diff options
-rw-r--r-- | lib/CodeGen/Mangle.cpp | 44 | ||||
-rw-r--r-- | test/CodeGenCXX/mangle-unnamed.cpp | 34 |
2 files changed, 77 insertions, 1 deletions
diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index c246bb50c6..faa9a9e453 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -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()) { diff --git a/test/CodeGenCXX/mangle-unnamed.cpp b/test/CodeGenCXX/mangle-unnamed.cpp index 4aec7dbf4a..83b46d6945 100644 --- a/test/CodeGenCXX/mangle-unnamed.cpp +++ b/test/CodeGenCXX/mangle-unnamed.cpp @@ -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; +} |