aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2009-12-30 00:31:22 +0000
committerJohn McCall <rjmccall@apple.com>2009-12-30 00:31:22 +0000
commit5126fd0dd92c4ec211c837ee78d5ce59c68dcbd5 (patch)
treee3f7af19b0b305472616790777f3b87c6a08b0fb
parent4df6ec10e0e623168a8e34f16e2e986945ddd07d (diff)
Typedefs can be redeclared. That seems like something we should record in
the AST lest we run into some crazy canonicalization bug like PR5874. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92283 91177308-0d34-0410-b5e6-96231b3b80d8
-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;
+}