[cfe-commits] r151017 - in /cfe/trunk: include/clang/Parse/Parser.h lib/AST/ItaniumMangle.cpp lib/Parse/ParseCXXInlineMethods.cpp lib/Parse/ParseDeclCXX.cpp lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaLambda.cpp test/CodeGenCXX/mangle-lambdas.cpp

Douglas Gregor dgregor at apple.com
Mon Feb 20 18:22:08 PST 2012


Author: dgregor
Date: Mon Feb 20 20:22:07 2012
New Revision: 151017

URL: http://llvm.org/viewvc/llvm-project?rev=151017&view=rev
Log:
Implement name mangling for lambda expressions that occur within the
initializers of data members (both static and non-static).

Modified:
    cfe/trunk/include/clang/Parse/Parser.h
    cfe/trunk/lib/AST/ItaniumMangle.cpp
    cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
    cfe/trunk/lib/Parse/ParseDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaLambda.cpp
    cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp

Modified: cfe/trunk/include/clang/Parse/Parser.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Parse/Parser.h?rev=151017&r1=151016&r2=151017&view=diff
==============================================================================
--- cfe/trunk/include/clang/Parse/Parser.h (original)
+++ cfe/trunk/include/clang/Parse/Parser.h Mon Feb 20 20:22:07 2012
@@ -2063,7 +2063,7 @@
                            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(),

Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=151017&r1=151016&r2=151017&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Mon Feb 20 20:22:07 2012
@@ -1313,9 +1313,26 @@
 }
 
 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 @@
     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) {

Modified: cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp?rev=151017&r1=151016&r2=151017&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp (original)
+++ cfe/trunk/lib/Parse/ParseCXXInlineMethods.cpp Mon Feb 20 20:22:07 2012
@@ -478,7 +478,8 @@
   ConsumeAnyToken();
 
   SourceLocation EqualLoc;
-  ExprResult Init = ParseCXXMemberInitializer(/*IsFunction=*/false, EqualLoc);
+  ExprResult Init = ParseCXXMemberInitializer(MI.Field, /*IsFunction=*/false, 
+                                              EqualLoc);
 
   Actions.ActOnCXXInClassMemberInitializer(MI.Field, EqualLoc, Init.release());
 

Modified: cfe/trunk/lib/Parse/ParseDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDeclCXX.cpp?rev=151017&r1=151016&r2=151017&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDeclCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDeclCXX.cpp Mon Feb 20 20:22:07 2012
@@ -2000,7 +2000,7 @@
     } else if (HasInitializer) {
       // Normal initializer.
       if (!Init.isUsable())
-        Init = ParseCXXMemberInitializer(
+        Init = ParseCXXMemberInitializer(ThisDecl,
                  DeclaratorInfo.isDeclarationOfFunction(), EqualLoc);
       
       if (Init.isInvalid())
@@ -2096,11 +2096,14 @@
 ///
 /// 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)) {

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=151017&r1=151016&r2=151017&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Mon Feb 20 20:22:07 2012
@@ -10394,6 +10394,14 @@
   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 @@
   //   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 @@
   // 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);
 }

Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=151017&r1=151016&r2=151017&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Mon Feb 20 20:22:07 2012
@@ -641,20 +641,28 @@
   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 @@
       break;
       
     case DefaultArgument:
+    case DataMember:
       ManglingNumber = ExprEvalContexts.back().getLambdaMangleContext()
                          .getManglingNumber(CallOperator);
       break;

Modified: cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp?rev=151017&r1=151016&r2=151017&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp Mon Feb 20 20:22:07 2012
@@ -75,3 +75,50 @@
 
   // 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
+}





More information about the cfe-commits mailing list