From: Anders Carlsson Date: Wed, 7 Oct 2009 01:45:02 +0000 (+0000) Subject: Mangle anonymous structs/unions correctly. Fixes PR5139. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c4355b6883382b85cda3b7337587784dabf3450b;p=clang Mangle anonymous structs/unions correctly. Fixes PR5139. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83448 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 269c1130f7..aa017c9207 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -22,6 +22,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" #include "clang/Basic/SourceManager.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/ErrorHandling.h" @@ -404,8 +405,8 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) { // ::= DeclarationName Name = ND->getDeclName(); switch (Name.getNameKind()) { - case DeclarationName::Identifier: - if (const NamespaceDecl *NS = dyn_cast(ND)) + case DeclarationName::Identifier: { + if (const NamespaceDecl *NS = dyn_cast(ND)) { if (NS->isAnonymousNamespace()) { // This is how gcc mangles these names. It's apparently // always '1', no matter how many different anonymous @@ -413,8 +414,38 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND) { Out << "12_GLOBAL__N_1"; break; } - mangleSourceName(Name.getAsIdentifierInfo()); + } + + if (const IdentifierInfo *II = Name.getAsIdentifierInfo()) { + mangleSourceName(II); + break; + } + + // We must have an anonymous struct. + const TagDecl *TD = cast(ND); + if (const TypedefDecl *D = TD->getTypedefForAnonDecl()) { + assert(TD->getDeclContext() == D->getDeclContext() && + "Typedef should not be in another decl context!"); + assert(D->getDeclName().getAsIdentifierInfo() && + "Typedef was not named!"); + mangleSourceName(D->getDeclName().getAsIdentifierInfo()); + break; + } + + // Get a unique id for the anonymous struct. + uint64_t AnonStructId = Context.getAnonymousStructId(TD); + + // Mangle it as a source name in the form + // [n] $_ + // where n is the length of the string. + llvm::SmallString<8> Str; + Str += "$_"; + Str += llvm::utostr(AnonStructId); + + Out << Str.size(); + Out << Str.str(); break; + } case DeclarationName::ObjCZeroArgSelector: case DeclarationName::ObjCOneArgSelector: diff --git a/lib/CodeGen/Mangle.h b/lib/CodeGen/Mangle.h index 8ab5d5edf3..f05220c38b 100644 --- a/lib/CodeGen/Mangle.h +++ b/lib/CodeGen/Mangle.h @@ -20,6 +20,7 @@ #include "CGCXX.h" #include "clang/AST/Type.h" +#include "llvm/ADT/DenseMap.h" namespace llvm { class raw_ostream; @@ -35,11 +36,21 @@ namespace clang { class MangleContext { ASTContext &Context; + + llvm::DenseMap AnonStructIds; + public: explicit MangleContext(ASTContext &Context) : Context(Context) { } ASTContext &getASTContext() const { return Context; } + + uint64_t getAnonymousStructId(const TagDecl *TD) { + std::pair::iterator, bool> Result = + AnonStructIds.insert(std::make_pair(TD, AnonStructIds.size())); + return Result.first->second; + } }; bool mangleName(MangleContext &Context, const NamedDecl *D, diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp index a881a710d4..2ffbae71da 100644 --- a/test/CodeGenCXX/mangle.cpp +++ b/test/CodeGenCXX/mangle.cpp @@ -207,3 +207,17 @@ void extern_f(void); // CHECK: @extern_f void extern_f(void) { } +struct S7 { + struct S { S(); }; + + struct { + S s; + } a; +}; + +// PR5139 +// CHECK: @_ZN2S7C1Ev +// CHECK: @_ZN2S7C2Ev +// CHECK: @"_ZN2S73$_0C1Ev" +S7::S7() {} +