]> granicus.if.org Git - clang/commitdiff
Add a sanity check in the Redeclarable::redecl_iterator to avoid infinite loop
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Sat, 17 Dec 2011 04:13:25 +0000 (04:13 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Sat, 17 Dec 2011 04:13:25 +0000 (04:13 +0000)
when we formed an invalid redeclaration chain due to a bug.

Thanks to Doug for the hint!

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@146816 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/AST/Redeclarable.h

index e87ca78d635adeab913aa78bb37e06b3fbac57fb..c223d768c65d40aa5001c1d6d7f01ea1c76e7114 100644 (file)
@@ -116,6 +116,7 @@ public:
     /// Current - The current declaration.
     decl_type *Current;
     decl_type *Starter;
+    bool PassedFirst;
 
   public:
     typedef decl_type*                value_type;
@@ -125,13 +126,24 @@ public:
     typedef std::ptrdiff_t            difference_type;
 
     redecl_iterator() : Current(0) { }
-    explicit redecl_iterator(decl_type *C) : Current(C), Starter(C) { }
+    explicit redecl_iterator(decl_type *C)
+      : Current(C), Starter(C), PassedFirst(false) { }
 
     reference operator*() const { return Current; }
     pointer operator->() const { return Current; }
 
     redecl_iterator& operator++() {
       assert(Current && "Advancing while iterator has reached end");
+      // Sanity check to avoid infinite loop on invalid redecl chain.
+      if (Current->isFirstDeclaration()) {
+        if (PassedFirst) {
+          assert(0 && "Passed first decl twice, invalid redecl chain!");
+          Current = 0;
+          return *this;
+        }
+        PassedFirst = true;
+      }
+
       // Get either previous decl or latest decl.
       decl_type *Next = Current->RedeclLink.getNext();
       Current = (Next != Starter ? Next : 0);