From: Fariborz Jahanian Date: Wed, 3 Mar 2010 19:41:08 +0000 (+0000) Subject: Implements mangling of local class names to X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=570585307ef1e33490883b26b807cd2a5f88e99d;p=clang Implements mangling of local class names to fix a code gen crash. This is WIP as not all ABI cases are covered (there is a FIXME to this effect). Fixes radar 7696748. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@97658 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 64743c7696..e053f78008 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -37,7 +37,19 @@ using namespace clang; using namespace CodeGen; namespace { - + +static const DeclContext *GetLocalClassFunctionDeclContext( + const DeclContext *DC) { + if (isa(DC)) { + while (!DC->isNamespace() && !DC->isTranslationUnit() && + !isa(DC)) + DC = DC->getParent(); + if (isa(DC)) + return DC; + } + return 0; +} + static const CXXMethodDecl *getStructor(const CXXMethodDecl *MD) { assert((isa(MD) || isa(MD)) && "Passed in decl is not a ctor or dtor!"); @@ -53,6 +65,8 @@ static const CXXMethodDecl *getStructor(const CXXMethodDecl *MD) { } static const unsigned UnknownArity = ~0U; +static unsigned Discriminator = 0; +static llvm::DenseMap Uniquifier; /// CXXNameMangler - Manage the mangling of a single name. class CXXNameMangler { @@ -61,7 +75,7 @@ class CXXNameMangler { const CXXMethodDecl *Structor; unsigned StructorType; - + llvm::DenseMap Substitutions; ASTContext &getASTContext() const { return Context.getASTContext(); } @@ -128,11 +142,12 @@ private: void mangleUnscopedTemplateName(const TemplateDecl *ND); void mangleSourceName(const IdentifierInfo *II); void mangleLocalName(const NamedDecl *ND); - void mangleNestedName(const NamedDecl *ND, const DeclContext *DC); + void mangleNestedName(const NamedDecl *ND, const DeclContext *DC, + bool NoFunction=false); void mangleNestedName(const TemplateDecl *TD, const TemplateArgument *TemplateArgs, unsigned NumTemplateArgs); - void manglePrefix(const DeclContext *DC); + void manglePrefix(const DeclContext *DC, bool NoFunction=false); void mangleTemplatePrefix(const TemplateDecl *ND); void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity); void mangleQualifiers(Qualifiers Quals); @@ -342,7 +357,12 @@ void CXXNameMangler::mangleName(const NamedDecl *ND) { // ::= // const DeclContext *DC = ND->getDeclContext(); - + + if (GetLocalClassFunctionDeclContext(DC)) { + mangleLocalName(ND); + return; + } + // If this is an extern variable declared locally, the relevant DeclContext // is that of the containing namespace, or the translation unit. if (isa(DC) && ND->hasLinkage()) @@ -603,7 +623,8 @@ void CXXNameMangler::mangleSourceName(const IdentifierInfo *II) { } void CXXNameMangler::mangleNestedName(const NamedDecl *ND, - const DeclContext *DC) { + const DeclContext *DC, + bool NoFunction) { // ::= N [] E // ::= N [] E @@ -616,8 +637,9 @@ void CXXNameMangler::mangleNestedName(const NamedDecl *ND, if (const TemplateDecl *TD = isTemplate(ND, TemplateArgs)) { mangleTemplatePrefix(TD); mangleTemplateArgs(*TemplateArgs); - } else { - manglePrefix(DC); + } + else { + manglePrefix(DC, NoFunction); mangleUnqualifiedName(ND); } @@ -640,18 +662,38 @@ void CXXNameMangler::mangleLocalName(const NamedDecl *ND) { // := Z E [] // := Z E s [] // := _ + const DeclContext *DC = ND->getDeclContext(); Out << 'Z'; - if (const ObjCMethodDecl *MD = dyn_cast(ND->getDeclContext())) + if (const ObjCMethodDecl *MD = dyn_cast(DC)) mangleObjCMethodName(MD); + else if (const DeclContext *CDC = GetLocalClassFunctionDeclContext(DC)) { + mangleFunctionEncoding(cast(CDC)); + Out << 'E'; + mangleNestedName(ND, DC, true /*NoFunction*/); + + // FIXME. This still does not conform to ABI and does not cover all cases. + unsigned &discriminator = Uniquifier[ND]; + if (!discriminator) + discriminator = ++Discriminator; + if (discriminator == 1) + return; + unsigned disc = discriminator-2; + if (disc < 10) + Out << '_' << disc; + else + Out << "__" << disc << '_'; + + return; + } else - mangleFunctionEncoding(cast(ND->getDeclContext())); + mangleFunctionEncoding(cast(DC)); Out << 'E'; mangleUnqualifiedName(ND); } -void CXXNameMangler::manglePrefix(const DeclContext *DC) { +void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) { // ::= // ::= // ::= @@ -672,8 +714,11 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC) { if (const TemplateDecl *TD = isTemplate(cast(DC), TemplateArgs)) { mangleTemplatePrefix(TD); mangleTemplateArgs(*TemplateArgs); - } else { - manglePrefix(DC->getParent()); + } + else if(NoFunction && isa(DC)) + return; + else { + manglePrefix(DC->getParent(), NoFunction); mangleUnqualifiedName(cast(DC)); } diff --git a/test/CodeGenCXX/mangle-local-class-names.cpp b/test/CodeGenCXX/mangle-local-class-names.cpp new file mode 100644 index 0000000000..2726f5e04a --- /dev/null +++ b/test/CodeGenCXX/mangle-local-class-names.cpp @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - | FileCheck %s + +// CHECK: @_ZZ4FUNCvEN4SSSSC1ERKf +// CHECK: @_ZZ4FUNCvEN4SSSSC2E_0RKf + +void FUNC () +{ + { + float IVAR1 ; + + struct SSSS + { + float bv; + SSSS( const float& from): bv(from) { } + }; + + SSSS VAR1(IVAR1); + } + + { + float IVAR2 ; + + struct SSSS + { + SSSS( const float& from) {} + }; + + SSSS VAR2(IVAR2); + } +}