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 | |
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')
-rw-r--r-- | lib/AST/ExprCXX.cpp | 15 | ||||
-rw-r--r-- | lib/AST/ItaniumMangle.cpp | 12 | ||||
-rw-r--r-- | lib/Sema/SemaLambda.cpp | 156 | ||||
-rw-r--r-- | lib/Sema/TreeTransform.h | 17 |
4 files changed, 100 insertions, 100 deletions
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp index 039d70cfc5..8cf519c93d 100644 --- a/lib/AST/ExprCXX.cpp +++ b/lib/AST/ExprCXX.cpp @@ -796,9 +796,7 @@ LambdaExpr::LambdaExpr(QualType T, ArrayRef<Expr *> CaptureInits, ArrayRef<VarDecl *> ArrayIndexVars, ArrayRef<unsigned> ArrayIndexStarts, - SourceLocation ClosingBrace, - unsigned ManglingNumber, - Decl *ContextDecl) + SourceLocation ClosingBrace) : Expr(LambdaExprClass, T, VK_RValue, OK_Ordinary, T->isDependentType(), T->isDependentType(), T->isDependentType(), /*ContainsUnexpandedParameterPack=*/false), @@ -819,8 +817,6 @@ LambdaExpr::LambdaExpr(QualType T, ASTContext &Context = Class->getASTContext(); Data.NumCaptures = NumCaptures; Data.NumExplicitCaptures = 0; - Data.ManglingNumber = ManglingNumber; - Data.ContextDecl = ContextDecl; Data.Captures = (Capture *)Context.Allocate(sizeof(Capture) * NumCaptures); Capture *ToCapture = Data.Captures; for (unsigned I = 0, N = Captures.size(); I != N; ++I) { @@ -848,9 +844,6 @@ LambdaExpr::LambdaExpr(QualType T, sizeof(unsigned) * Captures.size()); getArrayIndexStarts()[Captures.size()] = ArrayIndexVars.size(); } - - if (ManglingNumber) - Class->ClearLinkageCache(); } LambdaExpr *LambdaExpr::Create(ASTContext &Context, @@ -863,9 +856,7 @@ LambdaExpr *LambdaExpr::Create(ASTContext &Context, ArrayRef<Expr *> CaptureInits, ArrayRef<VarDecl *> ArrayIndexVars, ArrayRef<unsigned> ArrayIndexStarts, - SourceLocation ClosingBrace, - unsigned ManglingNumber, - Decl *ContextDecl) { + SourceLocation ClosingBrace) { // Determine the type of the expression (i.e., the type of the // function object we're creating). QualType T = Context.getTypeDeclType(Class); @@ -878,7 +869,7 @@ LambdaExpr *LambdaExpr::Create(ASTContext &Context, return new (Mem) LambdaExpr(T, IntroducerRange, CaptureDefault, Captures, ExplicitParams, ExplicitResultType, CaptureInits, ArrayIndexVars, ArrayIndexStarts, - ClosingBrace, ManglingNumber, ContextDecl); + ClosingBrace); } LambdaExpr *LambdaExpr::CreateDeserialized(ASTContext &C, unsigned NumCaptures, diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index a4676a6c39..5457036920 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -535,6 +535,14 @@ isTemplate(const NamedDecl *ND, const TemplateArgumentList *&TemplateArgs) { return 0; } +static bool isLambda(const NamedDecl *ND) { + const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(ND); + if (!Record) + return false; + + return Record->isLambda(); +} + void CXXNameMangler::mangleName(const NamedDecl *ND) { // <name> ::= <nested-name> // ::= <unscoped-name> @@ -545,7 +553,9 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) { // If this is an extern variable declared locally, the relevant DeclContext // is that of the containing namespace, or the translation unit. - if (isa<FunctionDecl>(DC) && ND->hasLinkage()) + // FIXME: This is a hack; extern variables declared locally should have + // a proper semantic declaration context! + if (isa<FunctionDecl>(DC) && ND->hasLinkage() && !isLambda(ND)) while (!DC->isNamespace() && !DC->isTranslationUnit()) DC = getEffectiveParentContext(DC); else if (GetLocalClassDecl(ND)) { 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 diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index c759e7a07a..f16b667a65 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -7815,7 +7815,8 @@ ExprResult TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { // Create the local class that will describe the lambda. CXXRecordDecl *Class - = getSema().createLambdaClosureType(E->getIntroducerRange()); + = getSema().createLambdaClosureType(E->getIntroducerRange(), + /*KnownDependent=*/false); getDerived().transformedLocalDecl(E->getLambdaClass(), Class); // Transform the type of the lambda parameters and start the definition of @@ -7836,11 +7837,15 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { Invalid = true; // Build the call operator. + // 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(); CXXMethodDecl *CallOperator = getSema().startLambdaDefinition(Class, E->getIntroducerRange(), MethodTy, E->getCallOperator()->getLocEnd(), - Params); + Params, ManglingNumber, ContextDecl); getDerived().transformAttrs(E->getCallOperator(), CallOperator); // FIXME: Instantiation-specific. @@ -7953,14 +7958,8 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { 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); + /*CurScope=*/0, /*IsInstantiation=*/true); } template<typename Derived> |