]> granicus.if.org Git - clang/commitdiff
Make sure redeclaration chains are properly linked, even through invalid decls. This...
authorSebastian Redl <sebastian.redl@getdesigned.at>
Tue, 24 Nov 2009 17:14:34 +0000 (17:14 +0000)
committerSebastian Redl <sebastian.redl@getdesigned.at>
Tue, 24 Nov 2009 17:14:34 +0000 (17:14 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@89777 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Redeclarable.h
test/SemaCXX/class.cpp

index 867932332d09748f994c6cefc7e426541b33abbf..35af8c766e97287e0f8ba1c238f1f5622053d6bf 100644 (file)
@@ -91,6 +91,11 @@ public:
     return D;
   }
 
+  /// \brief Returns the most recent (re)declaration of this declaration.
+  decl_type *getMostRecentDeclaration() {
+    return getFirstDeclaration()->RedeclLink.getNext();
+  }
+
   /// \brief Returns the most recent (re)declaration of this declaration.
   const decl_type *getMostRecentDeclaration() const {
     return getFirstDeclaration()->RedeclLink.getNext();
@@ -102,8 +107,11 @@ public:
     decl_type *First;
 
     if (PrevDecl) {
-      // Point to previous.
-      RedeclLink = PreviousDeclLink(PrevDecl);
+      // Point to previous. Make sure that this is actually the most recent
+      // redeclaration, or we can build invalid chains. If the most recent
+      // redeclaration is invalid, it won't be PrevDecl, but we want it anyway.
+      RedeclLink = PreviousDeclLink(cast<decl_type>(
+                                      PrevDecl->getMostRecentDeclaration()));
       First = PrevDecl->getFirstDeclaration();
       assert(First->RedeclLink.NextIsLatest() && "Expected first");
     } else {
index d2a8114f7b06f54e8076266da53eaedcf5af3dd5..302d1d58d39c7f03ec323d2162e89ed4cc1db495 100644 (file)
@@ -110,3 +110,12 @@ struct C4 {
   void f(); // expected-note{{previous declaration is here}}
   int f; // expected-error{{duplicate member 'f'}}
 };
+
+// PR5415 - don't hang!
+struct S
+{
+  void f(); // expected-note 2 {{previous declaration}}
+  // FIXME: the out-of-line error shouldn't be there
+  void S::f() {} // expected-error {{class member cannot be redeclared}} expected-error {{out-of-line}} expected-note {{previous definition}}
+  void f() {} // expected-error {{class member cannot be redeclared}} expected-error {{redefinition}}
+};