]> granicus.if.org Git - clang/commitdiff
Typedefs can be redeclared. That seems like something we should record in
authorJohn McCall <rjmccall@apple.com>
Wed, 30 Dec 2009 00:31:22 +0000 (00:31 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 30 Dec 2009 00:31:22 +0000 (00:31 +0000)
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

include/clang/AST/Decl.h
lib/AST/Decl.cpp
lib/Sema/SemaDecl.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/SemaCXX/typedef-redecl.cpp

index 961549c7a966908246dae7b2d0394ca4242794e5..d0d94aafb8d04a9a47cae9c2cc694bdf7414605d 100644 (file)
@@ -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();
   }
index 02a26d49f04f4097c0a195ec8c13f84f75fa9bac..e112fa3928deddbe9b2c9a6f0ee3a66ea79bf34d 100644 (file)
@@ -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) {
index 9ed4fba66e560abfc5284da32e621722854479e7..0a80f45f43ef11884495e1d1461c272d67252e34 100644 (file)
@@ -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;
 
index 1ec91bd55ec36bcd017e9444db546d6e624b6a82..e909c4f0b9b6761e99e5cae58942c3a229315755 100644 (file)
@@ -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;
index f9b438e88f3d33d48ad3cb54c9479bffb703cc49..0d8dc8487bf7199fd8ed48092eb5f9b1be92eadf 100644 (file)
@@ -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;
+}