diff options
author | Douglas Gregor <dgregor@apple.com> | 2012-02-21 02:22:07 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2012-02-21 02:22:07 +0000 |
commit | 926410d2db727c5093bda792cb8b2025d7f02cc3 (patch) | |
tree | f6d079eb498c82377a23722e4091dc34450004a3 /clang | |
parent | 7d445e92c3206ab312b385202a6c81c59fd9599c (diff) | |
download | bcm5719-llvm-926410d2db727c5093bda792cb8b2025d7f02cc3.tar.gz bcm5719-llvm-926410d2db727c5093bda792cb8b2025d7f02cc3.zip |
Implement name mangling for lambda expressions that occur within the
initializers of data members (both static and non-static).
llvm-svn: 151017
Diffstat (limited to 'clang')
-rw-r--r-- | clang/include/clang/Parse/Parser.h | 2 | ||||
-rw-r--r-- | clang/lib/AST/ItaniumMangle.cpp | 40 | ||||
-rw-r--r-- | clang/lib/Parse/ParseCXXInlineMethods.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 17 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLambda.cpp | 27 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/mangle-lambdas.cpp | 47 |
7 files changed, 119 insertions, 24 deletions
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index a13b48a420a..242ef3857c7 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -2063,7 +2063,7 @@ private: bool SuppressDeclarations = false); void ParseCXXMemberSpecification(SourceLocation StartLoc, unsigned TagType, Decl *TagDecl); - ExprResult ParseCXXMemberInitializer(bool IsFunction, + ExprResult ParseCXXMemberInitializer(Decl *D, bool IsFunction, SourceLocation &EqualLoc); void ParseCXXClassMemberDeclaration(AccessSpecifier AS, AttributeList *Attr, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp index 93ebcc50cf2..47f50cf078e 100644 --- a/clang/lib/AST/ItaniumMangle.cpp +++ b/clang/lib/AST/ItaniumMangle.cpp @@ -1313,9 +1313,26 @@ void CXXNameMangler::mangleLocalName(const NamedDecl *ND) { } void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) { - // FIXME: Figure out if we're in a function body, default argument, - // or initializer for a class member. - + // If the context of a closure type is an initializer for a class member + // (static or nonstatic), it is encoded in a qualified name with a final + // <prefix> of the form: + // + // <data-member-prefix> := <member source-name> M + // + // Technically, the data-member-prefix is part of the <prefix>. However, + // since a closure type will always be mangled with a prefix, it's easier + // to emit that last part of the prefix here. + if (Decl *Context = Lambda->getLambdaContextDecl()) { + if ((isa<VarDecl>(Context) || isa<FieldDecl>(Context)) && + Context->getDeclContext()->isRecord()) { + if (const IdentifierInfo *Name + = cast<NamedDecl>(Context)->getIdentifier()) { + mangleSourceName(Name); + Out << 'M'; + } + } + } + Out << "Ul"; DeclarationName Name = getASTContext().DeclarationNames.getCXXOperatorName(OO_Call); @@ -1392,26 +1409,27 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { return; } - if (mangleSubstitution(cast<NamedDecl>(DC))) + const NamedDecl *ND = cast<NamedDecl>(DC); + if (mangleSubstitution(ND)) return; - + // Check if we have a template. const TemplateArgumentList *TemplateArgs = 0; - if (const TemplateDecl *TD = isTemplate(cast<NamedDecl>(DC), TemplateArgs)) { + if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { mangleTemplatePrefix(TD); TemplateParameterList *TemplateParameters = TD->getTemplateParameters(); mangleTemplateArgs(*TemplateParameters, *TemplateArgs); } - else if(NoFunction && (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC))) + else if(NoFunction && (isa<FunctionDecl>(ND) || isa<ObjCMethodDecl>(ND))) return; - else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) + else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND)) mangleObjCMethodName(Method); else { - manglePrefix(getEffectiveParentContext(DC), NoFunction); - mangleUnqualifiedName(cast<NamedDecl>(DC)); + manglePrefix(getEffectiveDeclContext(ND), NoFunction); + mangleUnqualifiedName(ND); } - addSubstitution(cast<NamedDecl>(DC)); + addSubstitution(ND); } void CXXNameMangler::mangleTemplatePrefix(TemplateName Template) { diff --git a/clang/lib/Parse/ParseCXXInlineMethods.cpp b/clang/lib/Parse/ParseCXXInlineMethods.cpp index 8ed058787e4..1294a4c79aa 100644 --- a/clang/lib/Parse/ParseCXXInlineMethods.cpp +++ b/clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -478,7 +478,8 @@ void Parser::ParseLexedMemberInitializer(LateParsedMemberInitializer &MI) { ConsumeAnyToken(); SourceLocation EqualLoc; - ExprResult Init = ParseCXXMemberInitializer(/*IsFunction=*/false, EqualLoc); + ExprResult Init = ParseCXXMemberInitializer(MI.Field, /*IsFunction=*/false, + EqualLoc); Actions.ActOnCXXInClassMemberInitializer(MI.Field, EqualLoc, Init.release()); diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 6213824cae3..5edc30be92b 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -2000,7 +2000,7 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, } else if (HasInitializer) { // Normal initializer. if (!Init.isUsable()) - Init = ParseCXXMemberInitializer( + Init = ParseCXXMemberInitializer(ThisDecl, DeclaratorInfo.isDeclarationOfFunction(), EqualLoc); if (Init.isInvalid()) @@ -2096,11 +2096,14 @@ void Parser::ParseCXXClassMemberDeclaration(AccessSpecifier AS, /// /// Prior to C++0x, the assignment-expression in an initializer-clause must /// be a constant-expression. -ExprResult Parser::ParseCXXMemberInitializer(bool IsFunction, +ExprResult Parser::ParseCXXMemberInitializer(Decl *D, bool IsFunction, SourceLocation &EqualLoc) { assert((Tok.is(tok::equal) || Tok.is(tok::l_brace)) && "Data member initializer not starting with '=' or '{'"); + EnterExpressionEvaluationContext Context(Actions, + Sema::PotentiallyEvaluated, + D); if (Tok.is(tok::equal)) { EqualLoc = ConsumeToken(); if (Tok.is(tok::kw_delete)) { diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index faf2c41853b..a1a952b833f 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -10394,6 +10394,14 @@ bool Sema::CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange) { return true; } +/// \brief Determine whether the given declaration is a static data member. +static bool isStaticDataMember(Decl *D) { + VarDecl *Var = dyn_cast_or_null<VarDecl>(D); + if (!Var) + return false; + + return Var->isStaticDataMember(); +} /// ActOnCXXEnterDeclInitializer - Invoked when we are about to parse /// an initializer for the out-of-line declaration 'Dcl'. The scope /// is a fresh scope pushed for just this purpose. @@ -10409,6 +10417,12 @@ void Sema::ActOnCXXEnterDeclInitializer(Scope *S, Decl *D) { // int foo::bar; assert(D->isOutOfLine()); EnterDeclaratorContext(S, D->getDeclContext()); + + // If we are parsing the initializer for a static data member, push a + // new expression evaluation context that is associated with this static + // data member. + if (isStaticDataMember(D)) + PushExpressionEvaluationContext(PotentiallyEvaluated, D); } /// ActOnCXXExitDeclInitializer - Invoked after we are finished parsing an @@ -10417,6 +10431,9 @@ void Sema::ActOnCXXExitDeclInitializer(Scope *S, Decl *D) { // If there is no declaration, there was an error parsing it. if (D == 0 || D->isInvalidDecl()) return; + if (isStaticDataMember(D)) + PopExpressionEvaluationContext(); + assert(D->isOutOfLine()); ExitDeclaratorContext(S); } diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index 047a28436f6..7b729e70181 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -641,20 +641,28 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, if (!ManglingNumber) { ContextDecl = ExprEvalContexts.back().LambdaContextDecl; - // FIXME: Data member initializers. enum ContextKind { Normal, - DefaultArgument + DefaultArgument, + DataMember } 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; - } + // 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 = DataMember; + } else if (isa<FieldDecl>(ContextDecl)) { + Kind = DataMember; + } + } switch (Kind) { case Normal: @@ -663,6 +671,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, break; case DefaultArgument: + case DataMember: ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext() .getManglingNumber(CallOperator); break; diff --git a/clang/test/CodeGenCXX/mangle-lambdas.cpp b/clang/test/CodeGenCXX/mangle-lambdas.cpp index de8360d730e..a4fb7cdc846 100644 --- a/clang/test/CodeGenCXX/mangle-lambdas.cpp +++ b/clang/test/CodeGenCXX/mangle-lambdas.cpp @@ -75,3 +75,50 @@ void test_ST(ST<double> st) { // CHECK-NEXT: ret void } + +template<typename T> +struct StaticMembers { + static T x; + static T y; + static T z; +}; + +template<typename T> int accept_lambda(T); + +template<typename T> +T StaticMembers<T>::x = []{return 1;}() + []{return 2;}(); + +template<typename T> +T StaticMembers<T>::y = []{return 3;}(); + +template<typename T> +T StaticMembers<T>::z = accept_lambda([]{return 4;}); + +// CHECK: define internal void @__cxx_global_var_init() +// CHECK: call i32 @_ZNK13StaticMembersIfE1xMUlvE_clEv +// CHECK-NEXT: call i32 @_ZNK13StaticMembersIfE1xMUlvE0_clEv +// CHECK-NEXT: add nsw +template float StaticMembers<float>::x; + +// CHECK: define internal void @__cxx_global_var_init1() +// CHECK: call i32 @_ZNK13StaticMembersIfE1yMUlvE_clEv +template float StaticMembers<float>::y; + +// CHECK: define internal void @__cxx_global_var_init2() +// CHECK: call i32 @_Z13accept_lambdaIN13StaticMembersIfE1zMUlvE_EEiT_ +template float StaticMembers<float>::z; + +struct Members { + int x = [] { return 1; }() + [] { return 2; }(); + int y = [] { return 3; }(); +}; + +void test_Members() { + // CHECK: define linkonce_odr void @_ZN7MembersC2Ev + // CHECK: call i32 @_ZNK7Members1xMUlvE_clEv + // CHECK-NEXT: call i32 @_ZNK7Members1xMUlvE0_clE + // CHECK-NEXT: add nsw i32 + // CHECK: call i32 @_ZNK7Members1yMUlvE_clEv + Members members; + // CHECK: ret void +} |