aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/AST/Decl.h12
-rw-r--r--lib/AST/Decl.cpp3
-rw-r--r--lib/Sema/SemaDecl.cpp12
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp5
-rw-r--r--test/SemaCXX/typedef-redecl.cpp8
5 files changed, 35 insertions, 5 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index 961549c7a9..d0d94aafb8 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -1449,7 +1449,7 @@ public:
};
-class TypedefDecl : public TypeDecl {
+class TypedefDecl : public TypeDecl, public Redeclarable<TypedefDecl> {
/// UnderlyingType - This is the type the typedef is set to.
TypeSourceInfo *TInfo;
@@ -1457,7 +1457,7 @@ class TypedefDecl : public TypeDecl {
IdentifierInfo *Id, TypeSourceInfo *TInfo)
: TypeDecl(Typedef, DC, L, Id), TInfo(TInfo) {}
- virtual ~TypedefDecl() {}
+ virtual ~TypedefDecl();
public:
static TypedefDecl *Create(ASTContext &C, DeclContext *DC,
@@ -1468,6 +1468,14 @@ public:
return TInfo;
}
+ /// Retrieves the canonical declaration of this typedef.
+ TypedefDecl *getCanonicalDecl() {
+ return getFirstDeclaration();
+ }
+ const TypedefDecl *getCanonicalDecl() const {
+ return getFirstDeclaration();
+ }
+
QualType getUnderlyingType() const {
return TInfo->getType();
}
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 02a26d49f0..e112fa3928 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -212,6 +212,9 @@ TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC,
return new (C) TypedefDecl(DC, L, Id, TInfo);
}
+// Anchor TypedefDecl's vtable here.
+TypedefDecl::~TypedefDecl() {}
+
EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L,
IdentifierInfo *Id, SourceLocation TKL,
EnumDecl *PrevDecl) {
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 9ed4fba66e..0a80f45f43 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -696,9 +696,8 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) {
}
// Verify the old decl was also a type.
- TypeDecl *Old = 0;
- if (!OldDecls.isSingleResult() ||
- !(Old = dyn_cast<TypeDecl>(OldDecls.getFoundDecl()))) {
+ TypeDecl *Old = OldDecls.getAsSingle<TypeDecl>();
+ if (!Old) {
Diag(New->getLocation(), diag::err_redefinition_different_kind)
<< New->getDeclName();
@@ -733,6 +732,13 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) {
return New->setInvalidDecl();
}
+ // The types match. Link up the redeclaration chain if the old
+ // declaration was a typedef.
+ // FIXME: this is a potential source of wierdness if the type
+ // spellings don't match exactly.
+ if (isa<TypedefDecl>(Old))
+ New->setPreviousDeclaration(cast<TypedefDecl>(Old));
+
if (getLangOptions().Microsoft)
return;
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 1ec91bd55e..e909c4f0b9 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -145,6 +145,11 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) {
if (Invalid)
Typedef->setInvalidDecl();
+ if (TypedefDecl *Prev = D->getPreviousDeclaration()) {
+ NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(Prev, TemplateArgs);
+ Typedef->setPreviousDeclaration(cast<TypedefDecl>(InstPrev));
+ }
+
Owner->addDecl(Typedef);
return Typedef;
diff --git a/test/SemaCXX/typedef-redecl.cpp b/test/SemaCXX/typedef-redecl.cpp
index f9b438e88f..0d8dc8487b 100644
--- a/test/SemaCXX/typedef-redecl.cpp
+++ b/test/SemaCXX/typedef-redecl.cpp
@@ -29,3 +29,11 @@ typedef I I;
struct s { };
+// PR5874
+namespace test1 {
+ typedef int foo;
+ namespace a { using test1::foo; };
+ typedef int foo;
+ using namespace a;
+ foo x;
+}