diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-02-21 00:37:24 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-02-21 00:37:24 +0000 |
commit | ccc1b5eebc6ca8a904c58c0468b9a71483b7c7cf (patch) | |
tree | e2665ec87aa0c270a52f40e66b19a6ca5b2f05f0 /lib/Sema | |
parent | ef7844666b36226521e459d18f2834dacaa039e3 (diff) |
Implement name mangling for lambda expressions that occur within the
default arguments of function parameters. This simple-sounding task is
complicated greatly by two issues:
(1) Default arguments aren't actually a real context, so we need to
maintain extra state within lambda expressions to track when a
lambda was actually in a default argument.
(2) At the time that we parse a default argument, the FunctionDecl
doesn't exist yet, so lambda closure types end up in the enclosing
context. It's not clear that we ever want to change that, so instead
we introduce the notion of the "effective" context of a declaration
for the purposes of name mangling.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@151011 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaLambda.cpp | 33 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 6 |
4 files changed, 40 insertions, 7 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 716ffd131b..6a83518bc0 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -111,7 +111,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, &Context); ExprEvalContexts.push_back( - ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0, false)); + ExpressionEvaluationContextRecord(PotentiallyEvaluated, 0, false, 0)); FunctionScopes.push_back(new FunctionScopeInfo(Diags)); } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 3f1fabcaa3..1008a3ab43 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -9275,11 +9275,13 @@ ExprResult Sema::TranformToPotentiallyEvaluated(Expr *E) { } void -Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext) { +Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, + Decl *LambdaContextDecl) { ExprEvalContexts.push_back( ExpressionEvaluationContextRecord(NewContext, ExprCleanupObjects.size(), - ExprNeedsCleanups)); + ExprNeedsCleanups, + LambdaContextDecl)); ExprNeedsCleanups = false; if (!MaybeODRUseExprs.empty()) std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs); diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 6d54d403aa..047a28436f 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -485,6 +485,7 @@ static void addBlockPointerConversion(Sema &S, ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, Scope *CurScope, llvm::Optional<unsigned> ManglingNumber, + Decl *ContextDecl, bool IsInstantiation) { // Leave the expression-evaluation context. DiscardCleanupsInEvaluationContext(); @@ -638,8 +639,34 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, // If we don't already have a mangling number for this lambda expression, // allocate one now. if (!ManglingNumber) { - // FIXME: Default arguments, data member initializers are special. - ManglingNumber = Context.getLambdaManglingNumber(CallOperator); + ContextDecl = ExprEvalContexts.back().LambdaContextDecl; + + // FIXME: Data member initializers. + enum ContextKind { + Normal, + DefaultArgument + } Kind = Normal; + + // Default arguments of member function parameters that appear in a class + // definition receive special treatment. Identify them. + if (ParmVarDecl *Param = dyn_cast_or_null<ParmVarDecl>(ContextDecl)) { + if (const DeclContext *LexicalDC + = Param->getDeclContext()->getLexicalParent()) + if (LexicalDC->isRecord()) + Kind = DefaultArgument; + } + + switch (Kind) { + case Normal: + ManglingNumber = Context.getLambdaManglingNumber(CallOperator); + ContextDecl = 0; + break; + + case DefaultArgument: + ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext() + .getManglingNumber(CallOperator); + break; + } } LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, @@ -647,7 +674,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, ExplicitParams, ExplicitResultType, CaptureInits, ArrayIndexVars, ArrayIndexStarts, Body->getLocEnd(), - *ManglingNumber); + *ManglingNumber, ContextDecl); // C++11 [expr.prim.lambda]p2: // A lambda-expression shall not appear in an unevaluated operand diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 7e095f7336..7e775f55e0 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -7768,10 +7768,14 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { /*IsInstantiation=*/true); return ExprError(); } - + + // Note: Once a lambda mangling number and context declaration have been + // assigned, they never change. unsigned ManglingNumber = E->getLambdaClass()->getLambdaManglingNumber(); + Decl *ContextDecl = E->getLambdaClass()->getLambdaContextDecl(); return getSema().ActOnLambdaExpr(E->getLocStart(), Body.take(), /*CurScope=*/0, ManglingNumber, + ContextDecl, /*IsInstantiation=*/true); } |