diff options
-rw-r--r-- | include/clang/AST/Decl.h | 13 | ||||
-rw-r--r-- | lib/CodeGen/Mangle.cpp | 30 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 10 | ||||
-rw-r--r-- | test/CodeGenCXX/mangle.cpp | 7 |
4 files changed, 37 insertions, 23 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 92dda70083..b7d9fd0263 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -871,7 +871,8 @@ protected: friend Decl* Decl::Create(llvm::Deserializer& D, ASTContext& C); }; - +class TypedefDecl; + /// TagDecl - Represents the declaration of a struct/union/class/enum. class TagDecl : public TypeDecl, public DeclContext { public: @@ -890,10 +891,15 @@ private: /// IsDefinition - True if this is a definition ("struct foo {};"), false if /// it is a declaration ("struct foo;"). bool IsDefinition : 1; + + /// TypedefForAnonDecl - If a TagDecl is anonymous and part of a typedef, + /// this points to the TypedefDecl. Used for mangling. + TypedefDecl *TypedefForAnonDecl; + protected: TagDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, IdentifierInfo *Id) - : TypeDecl(DK, DC, L, Id), DeclContext(DK) { + : TypeDecl(DK, DC, L, Id), DeclContext(DK), TypedefForAnonDecl(0) { assert((DK != Enum || TK == TK_enum) &&"EnumDecl not matched with TK_enum"); TagDeclKind = TK; IsDefinition = false; @@ -943,6 +949,9 @@ public: bool isUnion() const { return getTagKind() == TK_union; } bool isEnum() const { return getTagKind() == TK_enum; } + TypedefDecl *getTypedefForAnonDecl() const { return TypedefForAnonDecl; } + void setTypedefForAnonDecl(TypedefDecl *TDD) { TypedefForAnonDecl = TDD; } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return D->getKind() >= TagFirst && D->getKind() <= TagLast; diff --git a/lib/CodeGen/Mangle.cpp b/lib/CodeGen/Mangle.cpp index 34c88fbba5..92eeb5db14 100644 --- a/lib/CodeGen/Mangle.cpp +++ b/lib/CodeGen/Mangle.cpp @@ -43,7 +43,6 @@ namespace { void mangleOperatorName(OverloadedOperatorKind OO, unsigned Arity); void mangleCVQualifiers(unsigned Quals); void mangleType(QualType T); - void mangleType(const TypedefType *T); void mangleType(const BuiltinType *T); void mangleType(const FunctionType *T); void mangleBareFunctionType(const FunctionType *T, bool MangleReturnType); @@ -330,15 +329,16 @@ void CXXNameMangler::mangleCVQualifiers(unsigned Quals) { } void CXXNameMangler::mangleType(QualType T) { + // Only operate on the canonical type! + T = Context.getCanonicalType(T); + // FIXME: Should we have a TypeNodes.def to make this easier? (YES!) // <type> ::= <CV-qualifiers> <type> mangleCVQualifiers(T.getCVRQualifiers()); - if (const TypedefType *TT = dyn_cast<TypedefType>(T.getTypePtr())) - mangleType(TT); // ::= <builtin-type> - else if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) + if (const BuiltinType *BT = dyn_cast<BuiltinType>(T.getTypePtr())) mangleType(BT); // ::= <function-type> else if (const FunctionType *FT = dyn_cast<FunctionType>(T.getTypePtr())) @@ -382,27 +382,13 @@ void CXXNameMangler::mangleType(QualType T) { } else if (const ObjCInterfaceType *IT = dyn_cast<ObjCInterfaceType>(T.getTypePtr())) { mangleType(IT); - } + } // FIXME: ::= G <type> # imaginary (C 2000) // FIXME: ::= U <source-name> <type> # vendor extended type qualifier else assert(false && "Cannot mangle unknown type"); } -void CXXNameMangler::mangleType(const TypedefType *T) { - QualType DeclTy = T->getDecl()->getUnderlyingType(); - - if (const TagType *TT = dyn_cast<TagType>(DeclTy)) { - // If the tag type is anonymous, use the name of the typedef. - if (!TT->getDecl()->getIdentifier()) { - mangleName(T->getDecl()); - return; - } - } - - mangleType(DeclTy); -} - void CXXNameMangler::mangleType(const BuiltinType *T) { // <builtin-type> ::= v # void // ::= w # wchar_t @@ -488,7 +474,11 @@ void CXXNameMangler::mangleBareFunctionType(const FunctionType *T, void CXXNameMangler::mangleType(const TagType *T) { // <class-enum-type> ::= <name> - mangleName(T->getDecl()); + + if (!T->getDecl()->getIdentifier()) + mangleName(T->getDecl()->getTypedefForAnonDecl()); + else + mangleName(T->getDecl()); } void CXXNameMangler::mangleType(const ArrayType *T) { diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index fbdab591c3..049c939452 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -2867,6 +2867,16 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, D.getIdentifierLoc(), D.getIdentifier(), T); + + if (TagType *TT = dyn_cast<TagType>(T)) { + TagDecl *TD = TT->getDecl(); + + // If the TagDecl that the TypedefDecl points to is an anonymous decl + // keep track of the TypedefDecl. + if (!TD->getIdentifier() && !TD->getTypedefForAnonDecl()) + TD->setTypedefForAnonDecl(NewTD); + } + NewTD->setNextDeclarator(LastDeclarator); if (D.getInvalidType()) NewTD->setInvalidDecl(); diff --git a/test/CodeGenCXX/mangle.cpp b/test/CodeGenCXX/mangle.cpp index 1c98df590b..5c38d17211 100644 --- a/test/CodeGenCXX/mangle.cpp +++ b/test/CodeGenCXX/mangle.cpp @@ -16,6 +16,11 @@ void f(s) { } typedef enum { foo } e; void f(e) { } -// RUN: grep _Z1f1u %t | count 1 +// RUN: grep _Z1f1u %t | count 1 && typedef union { int a; } u; void f(u) { } + +// RUN: grep _Z1f1x %t | count 1 +typedef struct { int a; } x,y; +void f(y) { } + |