diff --git a/clang/include/clang/AST/DeclCXX.h b/clang/include/clang/AST/DeclCXX.h index a77c70c85983..7f3ec4c61656 100644 --- a/clang/include/clang/AST/DeclCXX.h +++ b/clang/include/clang/AST/DeclCXX.h @@ -621,7 +621,7 @@ class CXXRecordDecl : public RecordDecl { "queried lambda property of non-lambda class"); return static_cast(*DefinitionData); } - + /// \brief The template or declaration that this declaration /// describes or was instantiated from, respectively. /// @@ -1503,6 +1503,13 @@ public: return getLambdaData().ContextDecl; } + /// \brief Set the mangling number and context declaration for a lambda + /// class. + void setLambdaMangling(unsigned ManglingNumber, Decl *ContextDecl) { + getLambdaData().ManglingNumber = ManglingNumber; + getLambdaData().ContextDecl = ContextDecl; + } + /// \brief Determine whether this lambda expression was known to be dependent /// at the time it was created, even if its context does not appear to be /// dependent. diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 178a9ce3e2c7..b69693d7c6a3 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -1231,9 +1231,7 @@ private: ArrayRef CaptureInits, ArrayRef ArrayIndexVars, ArrayRef ArrayIndexStarts, - SourceLocation ClosingBrace, - unsigned ManglingNumber, - Decl *ContextDecl); + SourceLocation ClosingBrace); /// \brief Construct an empty lambda expression. LambdaExpr(EmptyShell Empty, unsigned NumCaptures, bool HasArrayIndexVars) @@ -1271,9 +1269,7 @@ public: ArrayRef CaptureInits, ArrayRef ArrayIndexVars, ArrayRef ArrayIndexStarts, - SourceLocation ClosingBrace, - unsigned ManglingNumber, - Decl *ContextDecl); + SourceLocation ClosingBrace); /// \brief Construct a new lambda expression that will be deserialized from /// an external source. diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index d45a14b5facc..b639332a4933 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -3700,7 +3700,10 @@ public: SourceRange IntroducerRange, TypeSourceInfo *MethodType, SourceLocation EndLoc, - llvm::ArrayRef Params); + llvm::ArrayRef Params, + llvm::Optional ManglingNumber + = llvm::Optional(), + Decl *ContextDecl = 0); /// \brief Introduce the scope for a lambda expression. sema::LambdaScopeInfo *enterLambdaScope(CXXMethodDecl *CallOperator, @@ -3733,9 +3736,6 @@ public: /// was successfully completed. ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, Scope *CurScope, - llvm::Optional ManglingNumber - = llvm::Optional(), - Decl *ContextDecl = 0, bool IsInstantiation = false); /// \brief Define the "body" of the conversion from a lambda object to a diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 039d70cfc56e..8cf519c93dc2 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -796,9 +796,7 @@ LambdaExpr::LambdaExpr(QualType T, ArrayRef CaptureInits, ArrayRef ArrayIndexVars, ArrayRef 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 CaptureInits, ArrayRef ArrayIndexVars, ArrayRef 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/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index a4676a6c3961..5457036920b7 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/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(ND); + if (!Record) + return false; + + return Record->isLambda(); +} + void CXXNameMangler::mangleName(const NamedDecl *ND) { // ::= // ::= @@ -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(DC) && ND->hasLinkage()) + // FIXME: This is a hack; extern variables declared locally should have + // a proper semantic declaration context! + if (isa(DC) && ND->hasLinkage() && !isLambda(ND)) while (!DC->isNamespace() && !DC->isTranslationUnit()) DC = getEffectiveParentContext(DC); else if (GetLocalClassDecl(ND)) { diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 2a09da0f94bf..6ef8d88bbe52 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/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(DC)) + if (FD->isInlined()) + return true; + + DC = DC->getLexicalParent(); + } + + return false; +} + CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, - SourceRange IntroducerRange, - TypeSourceInfo *MethodType, - SourceLocation EndLoc, - llvm::ArrayRef Params) { + SourceRange IntroducerRange, + TypeSourceInfo *MethodType, + SourceLocation EndLoc, + llvm::ArrayRef Params, + llvm::Optional 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(ContextDecl)) { + if (const DeclContext *LexicalDC + = Param->getDeclContext()->getLexicalParent()) + if (LexicalDC->isRecord()) + Kind = DefaultArgument; + } else if (VarDecl *Var = dyn_cast(ContextDecl)) { + if (Var->getDeclContext()->isRecord()) + Kind = StaticDataMember; + } else if (isa(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(DC)) - if (FD->isInlined()) - return true; - - DC = DC->getLexicalParent(); - } - - return false; -} ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, Scope *CurScope, - llvm::Optional ManglingNumber, - Decl *ContextDecl, bool IsInstantiation) { // Collect information from the lambda scope. llvm::SmallVector 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(ContextDecl)) { - if (const DeclContext *LexicalDC - = Param->getDeclContext()->getLexicalParent()) - if (LexicalDC->isRecord()) - Kind = DefaultArgument; - } else if (VarDecl *Var = dyn_cast(ContextDecl)) { - if (Var->getDeclContext()->isRecord()) - Kind = StaticDataMember; - } else if (isa(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/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index c759e7a07a01..f16b667a658d 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -7815,7 +7815,8 @@ ExprResult TreeTransform::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::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::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 diff --git a/clang/test/CodeGenCXX/mangle-lambdas.cpp b/clang/test/CodeGenCXX/mangle-lambdas.cpp index e8bd6ec47b7e..cc53b0105750 100644 --- a/clang/test/CodeGenCXX/mangle-lambdas.cpp +++ b/clang/test/CodeGenCXX/mangle-lambdas.cpp @@ -150,6 +150,8 @@ void use_func_template() { func_template(); } +// CHECK: define linkonce_odr void @_Z1fIZZNK23TestNestedInstantiationclEvENKUlvE_clEvEUlvE_EvT_ + struct Members { int x = [] { return 1; }() + [] { return 2; }(); int y = [] { return 3; }(); @@ -165,6 +167,20 @@ void test_Members() { // CHECK: ret void } +template void f(P) { } + +struct TestNestedInstantiation { + void operator()() const { + []() -> void { + return f([]{}); + }(); + } +}; + +void test_NestedInstantiation() { + TestNestedInstantiation()(); +} + // Check the linkage of the lambdas used in test_Members. // CHECK: define linkonce_odr i32 @_ZNK7Members1xMUlvE_clEv // CHECK: ret i32 1