]> granicus.if.org Git - clang/commitdiff
Correctly mangle static variables of anonymous struct/union type.
authorAnders Carlsson <andersca@mac.com>
Tue, 8 Jun 2010 14:49:03 +0000 (14:49 +0000)
committerAnders Carlsson <andersca@mac.com>
Tue, 8 Jun 2010 14:49:03 +0000 (14:49 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@105606 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/Mangle.cpp
test/CodeGenCXX/mangle-unnamed.cpp

index c246bb50c69ed106c47c2ab39ba5f231515733e6..faa9a9e4535652657e862f2f13adbecd5d31cce3 100644 (file)
@@ -598,6 +598,28 @@ void CXXNameMangler::mangleUnresolvedName(NestedNameSpecifier *Qualifier,
   mangleUnqualifiedName(0, Name, KnownArity);
 }
 
+static const FieldDecl *FindFirstNamedDataMember(const RecordDecl *RD) {
+  assert(RD->isAnonymousStructOrUnion() &&
+         "Expected anonymous struct or union!");
+  
+  for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
+       I != E; ++I) {
+    const FieldDecl *FD = *I;
+    
+    if (FD->getIdentifier())
+      return FD;
+    
+    if (const RecordType *RT = FD->getType()->getAs<RecordType>()) {
+      if (const FieldDecl *NamedDataMember = 
+          FindFirstNamedDataMember(RT->getDecl()))
+        return NamedDataMember;
+    }
+  }
+
+  // We didn't find a named data member.
+  return 0;
+}
+
 void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
                                            DeclarationName Name,
                                            unsigned KnownArity) {
@@ -630,6 +652,28 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
       }
     }
 
+    if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) {
+      // We must have an anonymous union or struct declaration.
+      const RecordDecl *RD = 
+        cast<RecordDecl>(VD->getType()->getAs<RecordType>()->getDecl());
+      
+      // Itanium C++ ABI 5.1.2:
+      //
+      //   For the purposes of mangling, the name of an anonymous union is
+      //   considered to be the name of the first named data member found by a
+      //   pre-order, depth-first, declaration-order walk of the data members of
+      //   the anonymous union. If there is no such data member (i.e., if all of
+      //   the data members in the union are unnamed), then there is no way for
+      //   a program to refer to the anonymous union, and there is therefore no
+      //   need to mangle its name.
+      const FieldDecl *FD = FindFirstNamedDataMember(RD);
+      assert(FD && "Didn't find a named data member!");
+      assert(FD->getIdentifier() && "Data member name isn't an identifier!");
+      
+      mangleSourceName(FD->getIdentifier());
+      break;
+    }
+    
     // We must have an anonymous struct.
     const TagDecl *TD = cast<TagDecl>(ND);
     if (const TypedefDecl *D = TD->getTypedefForAnonDecl()) {
index 4aec7dbf4a76fefcb2ca9bba5cb50cbc6758b108..83b46d69454eaac4dfc55d1855ed44f2494f7d36 100644 (file)
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -emit-llvm-only -verify %s
+// RUN: %clang_cc1 -emit-llvm %s -o - -triple=x86_64-apple-darwin10 | FileCheck %s
 
 struct S {
   virtual ~S() { }
@@ -37,3 +37,35 @@ struct A {
 };
 
 int f4() { return A().a(); }
+
+int f5() {
+  static union {
+    int a;
+  };
+  
+  // CHECK: _ZZ2f5vE1a
+  return a;
+}
+
+int f6() {
+  static union {
+    union {
+      int : 1;
+    };
+    int b;
+  };
+  
+  // CHECK: _ZZ2f6vE1b
+  return b;
+}
+
+int f7() {
+  static union {
+    union {
+      int b;
+    } a;
+  };
+  
+  // CHECK: _ZZ2f7vE1a
+  return a.b;
+}