forked from OSchip/llvm-project
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. llvm-svn: 97658
This commit is contained in:
parent
182eea8f81
commit
a529c25555
|
@ -38,6 +38,18 @@ using namespace CodeGen;
|
|||
|
||||
namespace {
|
||||
|
||||
static const DeclContext *GetLocalClassFunctionDeclContext(
|
||||
const DeclContext *DC) {
|
||||
if (isa<CXXRecordDecl>(DC)) {
|
||||
while (!DC->isNamespace() && !DC->isTranslationUnit() &&
|
||||
!isa<FunctionDecl>(DC))
|
||||
DC = DC->getParent();
|
||||
if (isa<FunctionDecl>(DC))
|
||||
return DC;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const CXXMethodDecl *getStructor(const CXXMethodDecl *MD) {
|
||||
assert((isa<CXXConstructorDecl>(MD) || isa<CXXDestructorDecl>(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<const NamedDecl*, unsigned> Uniquifier;
|
||||
|
||||
/// CXXNameMangler - Manage the mangling of a single name.
|
||||
class CXXNameMangler {
|
||||
|
@ -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);
|
||||
|
@ -343,6 +358,11 @@ 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<FunctionDecl>(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) {
|
||||
// <nested-name> ::= N [<CV-qualifiers>] <prefix> <unqualified-name> E
|
||||
// ::= N [<CV-qualifiers>] <template-prefix> <template-args> 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) {
|
|||
// <local-name> := Z <function encoding> E <entity name> [<discriminator>]
|
||||
// := Z <function encoding> E s [<discriminator>]
|
||||
// <discriminator> := _ <non-negative number>
|
||||
const DeclContext *DC = ND->getDeclContext();
|
||||
Out << 'Z';
|
||||
|
||||
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(ND->getDeclContext()))
|
||||
if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(DC))
|
||||
mangleObjCMethodName(MD);
|
||||
else if (const DeclContext *CDC = GetLocalClassFunctionDeclContext(DC)) {
|
||||
mangleFunctionEncoding(cast<FunctionDecl>(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<FunctionDecl>(ND->getDeclContext()));
|
||||
mangleFunctionEncoding(cast<FunctionDecl>(DC));
|
||||
|
||||
Out << 'E';
|
||||
mangleUnqualifiedName(ND);
|
||||
}
|
||||
|
||||
void CXXNameMangler::manglePrefix(const DeclContext *DC) {
|
||||
void CXXNameMangler::manglePrefix(const DeclContext *DC, bool NoFunction) {
|
||||
// <prefix> ::= <prefix> <unqualified-name>
|
||||
// ::= <template-prefix> <template-args>
|
||||
// ::= <template-param>
|
||||
|
@ -672,8 +714,11 @@ void CXXNameMangler::manglePrefix(const DeclContext *DC) {
|
|||
if (const TemplateDecl *TD = isTemplate(cast<NamedDecl>(DC), TemplateArgs)) {
|
||||
mangleTemplatePrefix(TD);
|
||||
mangleTemplateArgs(*TemplateArgs);
|
||||
} else {
|
||||
manglePrefix(DC->getParent());
|
||||
}
|
||||
else if(NoFunction && isa<FunctionDecl>(DC))
|
||||
return;
|
||||
else {
|
||||
manglePrefix(DC->getParent(), NoFunction);
|
||||
mangleUnqualifiedName(cast<NamedDecl>(DC));
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue