Address Doug's comments wrt the mangler and fix Eli's test case
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66549 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 92dda70..b7d9fd0 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -871,7 +871,8 @@
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 @@
/// 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 @@
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 34c88fb..92eeb5d 100644
--- a/lib/CodeGen/Mangle.cpp
+++ b/lib/CodeGen/Mangle.cpp
@@ -43,7 +43,6 @@
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::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 @@
} 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::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 fbdab59..049c939 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -2867,6 +2867,16 @@
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 1c98df5..5c38d17 100644
--- a/test/CodeGenCXX/mangle.cpp
+++ b/test/CodeGenCXX/mangle.cpp
@@ -16,6 +16,11 @@
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) { }
+