diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-07-22 23:45:10 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-07-22 23:45:10 +0000 |
commit | adb1d4c18ee83249d4cffc99ef902f98e846092a (patch) | |
tree | cbca6e015fb9aff01308060992f20d234c88cb00 /lib/Sema/SemaLambda.cpp | |
parent | b67e7fc607671ef3df64de63c38545197e9992b2 (diff) |
PR12917: Remove incorrect assumption that lambda mangling information cannot
change once it's been assigned. It can change in two ways:
1) In a template instantiation, the context declaration should be the
instantiated declaration, not the declaration in the template.
2) If a lambda appears in the pattern of a variadic pack expansion, the
mangling number will depend on the pack length.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@160614 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaLambda.cpp')
-rw-r--r-- | lib/Sema/SemaLambda.cpp | 126 |
1 files changed, 68 insertions, 58 deletions
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index ab5640c2be..25d27f44ee 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -54,9 +54,7 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, SourceRange IntroducerRange, TypeSourceInfo *MethodType, SourceLocation EndLoc, - llvm::ArrayRef<ParmVarDecl *> Params, - llvm::Optional<unsigned> ManglingNumber, - Decl *ContextDecl) { + llvm::ArrayRef<ParmVarDecl *> Params) { // 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 @@ -98,64 +96,76 @@ CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, P != PEnd; ++P) (*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; + + // Allocate a mangling number for this lambda expression, if the ABI + // requires one. + Decl *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; } } - Class->setLambdaMangling(*ManglingNumber, ContextDecl); + // Itanium ABI [5.1.7]: + // In the following contexts [...] the one-definition rule requires closure + // types in different translation units to "correspond": + bool IsInNonspecializedTemplate = + !ActiveTemplateInstantiations.empty() || CurContext->isDependentContext(); + unsigned ManglingNumber; + switch (Kind) { + case Normal: + // -- the bodies of non-exported nonspecialized template functions + // -- the bodies of inline functions + if ((IsInNonspecializedTemplate && + !(ContextDecl && isa<ParmVarDecl>(ContextDecl))) || + isInInlineFunction(CurContext)) + ManglingNumber = Context.getLambdaManglingNumber(Method); + else + ManglingNumber = 0; + + // There is no special context for this lambda. + ContextDecl = 0; + break; + + case StaticDataMember: + // -- the initializers of nonspecialized static members of template classes + if (!IsInNonspecializedTemplate) { + ManglingNumber = 0; + ContextDecl = 0; + break; + } + // Fall through to assign a mangling number. + + case DataMember: + // -- the in-class initializers of class members + case DefaultArgument: + // -- default arguments appearing in class definitions + ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext() + .getManglingNumber(Method); + break; + } + + Class->setLambdaMangling(ManglingNumber, ContextDecl); + return Method; } |