r185450 - More fixes for block mangling.

Eli Friedman eli.friedman at gmail.com
Tue Jul 2 10:52:29 PDT 2013


Author: efriedma
Date: Tue Jul  2 12:52:28 2013
New Revision: 185450

URL: http://llvm.org/viewvc/llvm-project?rev=185450&view=rev
Log:
More fixes for block mangling.

Make sure we properly treat names defined inside a block as local
names.  There are basically three fixes here.  One, correctly
treat blocks as a context where we need to use local-name mangling using
the new isLocalContainerContext helper. Two, make
CXXNameMangler::manglePrefix handle local names in a consistent way.
Three, extend CXXNameMangler::mangleLocalName so it can mangle a block
correctly.

Modified:
    cfe/trunk/lib/AST/ItaniumMangle.cpp
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm
    cfe/trunk/test/CodeGenCXX/captured-statements.cpp
    cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp
    cfe/trunk/test/CodeGenObjCXX/mangle-blocks.mm

Modified: cfe/trunk/lib/AST/ItaniumMangle.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ItaniumMangle.cpp?rev=185450&r1=185449&r2=185450&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ItaniumMangle.cpp (original)
+++ cfe/trunk/lib/AST/ItaniumMangle.cpp Tue Jul  2 12:52:28 2013
@@ -57,17 +57,25 @@ static const DeclContext *getEffectiveDe
         return ContextParam->getDeclContext();
   }
   
-  return D->getDeclContext();
+  const DeclContext *DC = D->getDeclContext();
+  if (const CapturedDecl *CD = dyn_cast<CapturedDecl>(DC))
+    return getEffectiveDeclContext(CD);
+
+  return DC;
 }
 
 static const DeclContext *getEffectiveParentContext(const DeclContext *DC) {
   return getEffectiveDeclContext(cast<Decl>(DC));
 }
-  
+
+static bool isLocalContainerContext(const DeclContext *DC) {
+  return isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC) || isa<BlockDecl>(DC);
+}
+
 static const CXXRecordDecl *GetLocalClassDecl(const Decl *D) {
   const DeclContext *DC = getEffectiveDeclContext(D);
   while (!DC->isNamespace() && !DC->isTranslationUnit()) {
-    if (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC) || isa<BlockDecl>(DC))
+    if (isLocalContainerContext(DC))
       return dyn_cast<CXXRecordDecl>(D);
     D = cast<Decl>(DC);
     DC = getEffectiveDeclContext(D);
@@ -306,7 +314,9 @@ private:
   void mangleUnscopedTemplateName(const TemplateDecl *ND);
   void mangleUnscopedTemplateName(TemplateName);
   void mangleSourceName(const IdentifierInfo *II);
-  void mangleLocalName(const NamedDecl *ND);
+  void mangleLocalName(const Decl *D);
+  void mangleBlockForPrefix(const BlockDecl *Block);
+  void mangleUnqualifiedBlock(const BlockDecl *Block);
   void mangleLambda(const CXXRecordDecl *Lambda);
   void mangleNestedName(const NamedDecl *ND, const DeclContext *DC,
                         bool NoFunction=false);
@@ -551,8 +561,7 @@ void CXXNameMangler::mangleName(const Na
   // is that of the containing namespace, or the translation unit.
   // FIXME: This is a hack; extern variables declared locally should have
   // a proper semantic declaration context!
-  if ((isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)) &&
-      ND->hasLinkage() && !isLambda(ND))
+  if (isLocalContainerContext(DC) && ND->hasLinkage() && !isLambda(ND))
     while (!DC->isNamespace() && !DC->isTranslationUnit())
       DC = getEffectiveParentContext(DC);
   else if (GetLocalClassDecl(ND)) {
@@ -575,7 +584,7 @@ void CXXNameMangler::mangleName(const Na
     return;
   }
 
-  if (isa<FunctionDecl>(DC) || isa<ObjCMethodDecl>(DC)) {
+  if (isLocalContainerContext(DC)) {
     mangleLocalName(ND);
     return;
   }
@@ -1264,21 +1273,22 @@ void CXXNameMangler::mangleNestedName(co
   Out << 'E';
 }
 
-void CXXNameMangler::mangleLocalName(const NamedDecl *ND) {
+void CXXNameMangler::mangleLocalName(const Decl *D) {
   // <local-name> := Z <function encoding> E <entity name> [<discriminator>]
   //              := Z <function encoding> E s [<discriminator>]
   // <local-name> := Z <function encoding> E d [ <parameter number> ] 
   //                 _ <entity name>
   // <discriminator> := _ <non-negative number>
-  const CXXRecordDecl *RD = GetLocalClassDecl(ND);
-  const DeclContext *DC = getEffectiveDeclContext(RD ? RD : ND);
+  assert(isa<NamedDecl>(D) || isa<BlockDecl>(D));
+  const CXXRecordDecl *RD = GetLocalClassDecl(D);
+  const DeclContext *DC = getEffectiveDeclContext(RD ? RD : D);
 
   Out << 'Z';
 
   if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC))
     mangleObjCMethodName(MD);
   else if (const BlockDecl *BD = dyn_cast<BlockDecl>(DC))
-    manglePrefix(BD); // FIXME: This isn't right.
+    mangleBlockForPrefix(BD);
   else
     mangleFunctionEncoding(cast<FunctionDecl>(DC));
 
@@ -1307,10 +1317,16 @@ void CXXNameMangler::mangleLocalName(con
     }
     
     // Mangle the name relative to the closest enclosing function.
-    if (ND == RD) // equality ok because RD derived from ND above
-      mangleUnqualifiedName(ND);
-    else
+    // equality ok because RD derived from ND above
+    if (D == RD)  {
+      mangleUnqualifiedName(RD);
+    } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
+      manglePrefix(getEffectiveDeclContext(BD), true /*NoFunction*/);
+      mangleUnqualifiedBlock(BD);
+    } else {
+      const NamedDecl *ND = cast<NamedDecl>(D);
       mangleNestedName(ND, getEffectiveDeclContext(ND), true /*NoFunction*/);
+    }
 
     if (!SkipDiscriminator) {
       unsigned disc;
@@ -1325,7 +1341,48 @@ void CXXNameMangler::mangleLocalName(con
     return;
   }
 
-  mangleUnqualifiedName(ND);
+  if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
+    mangleUnqualifiedBlock(BD);
+  else
+    mangleUnqualifiedName(cast<NamedDecl>(D));
+}
+
+void CXXNameMangler::mangleBlockForPrefix(const BlockDecl *Block) {
+  if (GetLocalClassDecl(Block)) {
+    mangleLocalName(Block);
+    return;
+  }
+  const DeclContext *DC = getEffectiveDeclContext(Block);
+  if (isLocalContainerContext(DC)) {
+    mangleLocalName(Block);
+    return;
+  }
+  manglePrefix(getEffectiveDeclContext(Block));
+  mangleUnqualifiedBlock(Block);
+}
+
+void CXXNameMangler::mangleUnqualifiedBlock(const BlockDecl *Block) {
+  if (Decl *Context = Block->getBlockManglingContextDecl()) {
+    if ((isa<VarDecl>(Context) || isa<FieldDecl>(Context)) &&
+        Context->getDeclContext()->isRecord()) {
+      if (const IdentifierInfo *Name
+            = cast<NamedDecl>(Context)->getIdentifier()) {
+        mangleSourceName(Name);
+        Out << 'M';            
+      }
+    }
+  }
+
+  // If we have a block mangling number, use it.
+  unsigned Number = Block->getBlockManglingNumber();
+  // Otherwise, just make up a number. It doesn't matter what it is because
+  // the symbol in question isn't externally visible.
+  if (!Number)
+    Number = Context.getBlockId(Block, false);
+  Out << "Ub";
+  if (Number > 1)
+    Out << Number - 2;
+  Out << '_';
 }
 
 void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) {
@@ -1411,30 +1468,11 @@ void CXXNameMangler::manglePrefix(const
   if (DC->isTranslationUnit())
     return;
 
-  if (const BlockDecl *Block = dyn_cast<BlockDecl>(DC)) {
-    // Reflect the lambda mangling rules, except that we don't have an
-    // actual function declaration.
-    if (NoFunction)
-      return;
-
-    manglePrefix(getEffectiveParentContext(DC), NoFunction);
-    // If we have a block mangling number, use it.
-    unsigned Number = Block->getBlockManglingNumber();
-    // Otherwise, just make up a number. It doesn't matter what it is because
-    // the symbol in question isn't externally visible.
-    if (!Number)
-      Number = Context.getBlockId(Block, false);
-    Out << "Ub";
-    if (Number > 1)
-      Out << Number - 2;
-    Out << '_';
-    return;
-  } else if (isa<CapturedDecl>(DC)) {
-    // Skip CapturedDecl context.
-    manglePrefix(getEffectiveParentContext(DC), NoFunction);
+  if (NoFunction && isLocalContainerContext(DC))
     return;
-  }
-  
+
+  assert(!isLocalContainerContext(DC));
+
   const NamedDecl *ND = cast<NamedDecl>(DC);  
   if (mangleSubstitution(ND))
     return;
@@ -1444,12 +1482,7 @@ void CXXNameMangler::manglePrefix(const
   if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) {
     mangleTemplatePrefix(TD);
     mangleTemplateArgs(*TemplateArgs);
-  }
-  else if(NoFunction && (isa<FunctionDecl>(ND) || isa<ObjCMethodDecl>(ND)))
-    return;
-  else if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(ND))
-    mangleObjCMethodName(Method);
-  else {
+  } else {
     manglePrefix(getEffectiveDeclContext(ND), NoFunction);
     mangleUnqualifiedName(ND);
   }

Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm?rev=185450&r1=185449&r2=185450&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm (original)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/blocks-irgen.mm Tue Jul  2 12:52:28 2013
@@ -14,7 +14,7 @@ namespace PR12746 {
   }
 
   // CHECK: define internal zeroext i1 @___ZN7PR127462f1EPi_block_invoke
-  // CHECK: call zeroext i1 @"_ZZ7PR127462f1Ub_ENK3$_0clEv"
+  // CHECK: call zeroext i1 @"_ZZZN7PR127462f1EPiEUb_ENK3$_0clEv"
 
   bool f2(int *x) {
     auto outer = [&]() -> bool {

Modified: cfe/trunk/test/CodeGenCXX/captured-statements.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/captured-statements.cpp?rev=185450&r1=185449&r2=185450&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/captured-statements.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/captured-statements.cpp Tue Jul  2 12:52:28 2013
@@ -165,7 +165,7 @@ void template_capture_lambda() {
 }
 
 void test_capture_lambda() {
-  // CHECK-6: define {{.*}} void @_ZZ23template_capture_lambdaIiEvvENKS_IiEUlvE_clEv
+  // CHECK-6: define {{.*}} void @_ZZ23template_capture_lambdaIiEvvENKUlvE_clEv
   // CHECK-6-NOT: }
   // CHECK-6: store i32*
   // CHECK-6: store i32*
@@ -175,7 +175,7 @@ void test_capture_lambda() {
 }
 
 inline int test_captured_linkage() {
-  // CHECK-7: @_ZN21test_captured_linkage1iE = linkonce_odr global i32 0
+  // CHECK-7: @_ZZ21test_captured_linkagevE1i = linkonce_odr global i32 0
   int j;
   #pragma clang __debug captured
   {

Modified: cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp?rev=185450&r1=185449&r2=185450&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/mangle-lambdas.cpp Tue Jul  2 12:52:28 2013
@@ -160,7 +160,7 @@ void func_template(T = []{ return T(); }
 
 // CHECK: define void @_Z17use_func_templatev()
 void use_func_template() {
-  // CHECK: call i32 @"_ZZ13func_templateIiEvT_ENKS_IiE3$_3clEv"
+  // CHECK: call i32 @"_ZZ13func_templateIiEvT_ENK3$_3clEv"
   func_template<int>();
 }
 
@@ -205,8 +205,8 @@ namespace PR12808 {
   void f() {
     b<int>(1);
   }
-  // CHECK: define linkonce_odr void @_ZZN7PR128081bIiEEviENKS0_IiEUlvE_clEv
-  // CHECK: define linkonce_odr i32 @_ZZZN7PR128081bIiEEviENKS0_IiEUlvE_clEvENKUlvE_clEv
+  // CHECK: define linkonce_odr void @_ZZN7PR128081bIiEEviENKUlvE_clEv
+  // CHECK: define linkonce_odr i32 @_ZZZN7PR128081bIiEEviENKUlvE_clEvENKUlvE_clEv
 }
 
 // CHECK: define linkonce_odr void @_Z1fIZZNK23TestNestedInstantiationclEvENKUlvE_clEvEUlvE_EvT_

Modified: cfe/trunk/test/CodeGenObjCXX/mangle-blocks.mm
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenObjCXX/mangle-blocks.mm?rev=185450&r1=185449&r2=185450&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenObjCXX/mangle-blocks.mm (original)
+++ cfe/trunk/test/CodeGenObjCXX/mangle-blocks.mm Tue Jul  2 12:52:28 2013
@@ -1,14 +1,14 @@
 // RUN: %clang_cc1 -emit-llvm -fblocks -o - -triple x86_64-apple-darwin10 -fobjc-runtime=macosx-fragile-10.5 %s | FileCheck %s
 
-// CHECK: @_ZGVN3fooUb_5valueE = internal global i64 0
-// CHECK: @_ZN26externally_visible_statics1SUb_1jE = linkonce_odr global i32 0
-// CHECK: @_ZN26externally_visible_statics10inlinefuncUb_1iE = linkonce_odr global i32 0
+// CHECK: @_ZGVZZ3foovEUb_E5value = internal global i64 0
+// CHECK: @_ZZ26externally_visible_statics1S1xMUb_E1j = linkonce_odr global i32 0
+// CHECK: @_ZZZN26externally_visible_statics10inlinefuncEvEUb_E1i = linkonce_odr global i32 0
 
 int f();
 
 void foo() {
   // CHECK: define internal i32 @___Z3foov_block_invoke
-  // CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVN3fooUb_5valueE
+  // CHECK: call i32 @__cxa_guard_acquire(i64* @_ZGVZZ3foovEUb_E5value
   (void)^(int x) { 
     static int value = f();
     return x + value;
@@ -26,7 +26,7 @@ int i = ^(int x) { return x;}(i);
 - (void)method { 
   // CHECK: define internal signext i8 @"__11-[A method]_block_invoke"
   (void)^(int x) {
-    // CHECK: @"_ZN11-[A method]Ub0_4nameE"
+    // CHECK: @"_ZZZ11-[A method]EUb0_E4name"
     static const char *name = "hello";
     return name[x];
   };
@@ -44,7 +44,7 @@ namespace N {
   // CHECK: define internal signext i8 @___Z3fooi_block_invoke
   void bar() {
     (void)^(int x) { 
-      // CHECK: @_ZN1N3barUb2_4nameE
+      // CHECK: @_ZZZN1N3barEvEUb2_E4name
       static const char *name = "hello";
       return name[x];
     };
@@ -56,7 +56,7 @@ class C {
 };
 C::C() {
   (void)^(int x) { 
-    // CHECK: @_ZN1CC1Ub3_5namebE
+    // CHECK: @_ZZZN1CC1EvEUb3_E5nameb
     static const char *nameb = "hello";
     return nameb[x];
   };





More information about the cfe-commits mailing list