diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-04-04 17:40:10 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-04-04 17:40:10 +0000 |
commit | f54486acc1cadf2791c3916ece66fded1e57ba0b (patch) | |
tree | 50d408c6476749d089f753d8694cdf09a0c6eefe /lib/Sema/SemaLambda.cpp | |
parent | 8e86b2d03e6e58ef9a58d1d3ad70726ae7a3b4fd (diff) |
Move the computation of the lambda mangling information (mangling
number + context) to the point where we initially start defining the
lambda, so that the linkage won't change when that information is made
available. Fixes the assertion in <rdar://problem/11182962>.
Plus, actually mangle the context of lambdas properly.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154029 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaLambda.cpp')
-rw-r--r-- | lib/Sema/SemaLambda.cpp | 156 |
1 files changed, 78 insertions, 78 deletions
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 2a09da0f94..6ef8d88bbe 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -36,11 +36,27 @@ CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange, return Class; } +/// \brief Determine whether the given context is or is enclosed in an inline +/// function. +static bool isInInlineFunction(const DeclContext *DC) { + while (!DC->isFileContext()) { + if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC)) + if (FD->isInlined()) + return true; + + DC = DC->getLexicalParent(); + } + + return false; +} + CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, - SourceRange IntroducerRange, - TypeSourceInfo *MethodType, - SourceLocation EndLoc, - llvm::ArrayRef<ParmVarDecl *> Params) { + SourceRange IntroducerRange, + TypeSourceInfo *MethodType, + SourceLocation EndLoc, + llvm::ArrayRef<ParmVarDecl *> Params, + llvm::Optional<unsigned> ManglingNumber, + Decl *ContextDecl) { // C++11 [expr.prim.lambda]p5: // The closure type for a lambda-expression has a public inline function // call operator (13.5.4) whose parameters and return type are described by @@ -83,6 +99,63 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, (*P)->setOwningFunction(Method); } + // If we don't already have a mangling number for this lambda expression, + // allocate one now. + if (!ManglingNumber) { + ContextDecl = ExprEvalContexts.back().LambdaContextDecl; + + enum ContextKind { + Normal, + DefaultArgument, + DataMember, + StaticDataMember + } Kind = Normal; + + // Default arguments of member function parameters that appear in a class + // definition, as well as the initializers of data members, receive special + // treatment. Identify them. + if (ContextDecl) { + if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ContextDecl)) { + if (const DeclContext *LexicalDC + = Param->getDeclContext()->getLexicalParent()) + if (LexicalDC->isRecord()) + Kind = DefaultArgument; + } else if (VarDecl *Var = dyn_cast<VarDecl>(ContextDecl)) { + if (Var->getDeclContext()->isRecord()) + Kind = StaticDataMember; + } else if (isa<FieldDecl>(ContextDecl)) { + Kind = DataMember; + } + } + + switch (Kind) { + case Normal: + if (CurContext->isDependentContext() || isInInlineFunction(CurContext)) + ManglingNumber = Context.getLambdaManglingNumber(Method); + else + ManglingNumber = 0; + + // There is no special context for this lambda. + ContextDecl = 0; + break; + + case StaticDataMember: + if (!CurContext->isDependentContext()) { + ManglingNumber = 0; + ContextDecl = 0; + break; + } + // Fall through to assign a mangling number. + + case DataMember: + case DefaultArgument: + ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext() + .getManglingNumber(Method); + break; + } + } + + Class->setLambdaMangling(*ManglingNumber, ContextDecl); return Method; } @@ -491,25 +564,9 @@ static void addBlockPointerConversion(Sema &S, Conversion->setImplicit(true); Class->addDecl(Conversion); } - -/// \brief Determine whether the given context is or is enclosed in an inline -/// function. -static bool isInInlineFunction(const DeclContext *DC) { - while (!DC->isFileContext()) { - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(DC)) - if (FD->isInlined()) - return true; - - DC = DC->getLexicalParent(); - } - - return false; -} ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, Scope *CurScope, - llvm::Optional<unsigned> ManglingNumber, - Decl *ContextDecl, bool IsInstantiation) { // Collect information from the lambda scope. llvm::SmallVector<LambdaExpr::Capture, 4> Captures; @@ -655,69 +712,12 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, if (LambdaExprNeedsCleanups) ExprNeedsCleanups = true; - - // If we don't already have a mangling number for this lambda expression, - // allocate one now. - if (!ManglingNumber) { - ContextDecl = ExprEvalContexts.back().LambdaContextDecl; - - enum ContextKind { - Normal, - DefaultArgument, - DataMember, - StaticDataMember - } Kind = Normal; - - // Default arguments of member function parameters that appear in a class - // definition, as well as the initializers of data members, receive special - // treatment. Identify them. - if (ContextDecl) { - if (ParmVarDecl *Param = dyn_cast<ParmVarDecl>(ContextDecl)) { - if (const DeclContext *LexicalDC - = Param->getDeclContext()->getLexicalParent()) - if (LexicalDC->isRecord()) - Kind = DefaultArgument; - } else if (VarDecl *Var = dyn_cast<VarDecl>(ContextDecl)) { - if (Var->getDeclContext()->isRecord()) - Kind = StaticDataMember; - } else if (isa<FieldDecl>(ContextDecl)) { - Kind = DataMember; - } - } - - switch (Kind) { - case Normal: - if (CurContext->isDependentContext() || isInInlineFunction(CurContext)) - ManglingNumber = Context.getLambdaManglingNumber(CallOperator); - else - ManglingNumber = 0; - - // There is no special context for this lambda. - ContextDecl = 0; - break; - - case StaticDataMember: - if (!CurContext->isDependentContext()) { - ManglingNumber = 0; - ContextDecl = 0; - break; - } - // Fall through to assign a mangling number. - - case DataMember: - case DefaultArgument: - ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext() - .getManglingNumber(CallOperator); - break; - } - } LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, CaptureDefault, Captures, ExplicitParams, ExplicitResultType, CaptureInits, ArrayIndexVars, - ArrayIndexStarts, Body->getLocEnd(), - *ManglingNumber, ContextDecl); + ArrayIndexStarts, Body->getLocEnd()); // C++11 [expr.prim.lambda]p2: // A lambda-expression shall not appear in an unevaluated operand |