From 2e49aaf484ad69700e39de72a6abfb79fc836c27 Mon Sep 17 00:00:00 2001
From: Roberto Raggi <roberto.raggi@nokia.com>
Date: Mon, 13 Jul 2009 18:00:22 +0200
Subject: [PATCH] Fixed possible crashes when resolving namespace and class
 bindings.

---
 src/libs/cplusplus/CppBindings.cpp | 51 ++++++++++++++++++++++--------
 src/libs/cplusplus/CppBindings.h   | 12 +++----
 2 files changed, 43 insertions(+), 20 deletions(-)

diff --git a/src/libs/cplusplus/CppBindings.cpp b/src/libs/cplusplus/CppBindings.cpp
index ba5c37754ee..06d16a281ae 100644
--- a/src/libs/cplusplus/CppBindings.cpp
+++ b/src/libs/cplusplus/CppBindings.cpp
@@ -113,8 +113,13 @@ NamespaceBinding *NamespaceBinding::globalNamespaceBinding()
     return it;
 }
 
-Binding *NamespaceBinding::findClassOrNamespaceBinding(Identifier *id)
+Binding *NamespaceBinding::findClassOrNamespaceBinding(Identifier *id, QSet<Binding *> *processed)
 {
+    if (processed->contains(this))
+        return 0;
+
+    processed->insert(this);
+
     if (id->isEqualTo(identifier()))
         return const_cast<NamespaceBinding *>(this);
 
@@ -129,21 +134,26 @@ Binding *NamespaceBinding::findClassOrNamespaceBinding(Identifier *id)
     }
 
     foreach (NamespaceBinding *u, usings) {
-        if (Binding *b = u->findClassOrNamespaceBinding(id))
+        if (Binding *b = u->findClassOrNamespaceBinding(id, processed))
             return b;
     }
 
     if (parent)
-        return parent->findClassOrNamespaceBinding(id);
+        return parent->findClassOrNamespaceBinding(id, processed);
 
     return 0;
 }
 
-ClassBinding *NamespaceBinding::findClassBinding(Name *name)
+ClassBinding *NamespaceBinding::findClassBinding(Name *name, QSet<Binding *> *processed)
 {
     if (! name)
         return 0;
 
+    if (processed->contains(this))
+        return 0;
+
+    processed->insert(this);
+
     Identifier *id = name->identifier();
 
     foreach (ClassBinding *classBinding, classBindings) {
@@ -152,7 +162,12 @@ ClassBinding *NamespaceBinding::findClassBinding(Name *name)
     }
 
     if (parent)
-        return parent->findClassBinding(name);
+        return parent->findClassBinding(name, processed);
+
+    foreach (NamespaceBinding *u, usings) {
+        if (ClassBinding *classBinding = u->findClassBinding(name, processed))
+            return classBinding;
+    }
 
     return 0;
 }
@@ -384,7 +399,7 @@ QByteArray ClassBinding::qualifiedId() const
     return s;
 }
 
-Binding *ClassBinding::findClassOrNamespaceBinding(Identifier *id)
+Binding *ClassBinding::findClassOrNamespaceBinding(Identifier *id, QSet<Binding *> *processed)
 {
     if (id->isEqualTo(identifier()))
         return this;
@@ -397,21 +412,26 @@ Binding *ClassBinding::findClassOrNamespaceBinding(Identifier *id)
     foreach (ClassBinding *baseClassBinding, baseClassBindings) {
         if (! baseClassBinding)
             continue;
-        else if (Binding *b = baseClassBinding->findClassOrNamespaceBinding(id))
+        else if (Binding *b = baseClassBinding->findClassOrNamespaceBinding(id, processed))
             return b;
     }
 
     if (parent)
-        return parent->findClassOrNamespaceBinding(id);
+        return parent->findClassOrNamespaceBinding(id, processed);
 
     return 0;
 }
 
-ClassBinding *ClassBinding::findClassBinding(Name *name)
+ClassBinding *ClassBinding::findClassBinding(Name *name, QSet<Binding *> *processed)
 {
     if (! name)
         return 0;
 
+    if (processed->contains(this))
+        return 0;
+
+    processed->insert(this);
+
     if (const QualifiedNameId *q = name->asQualifiedNameId()) {
         Binding *currentBinding = this;
 
@@ -420,7 +440,7 @@ ClassBinding *ClassBinding::findClassBinding(Name *name)
             if (! id)
                 return 0;
 
-            Binding *classOrNamespaceBinding = currentBinding->findClassOrNamespaceBinding(id);
+            Binding *classOrNamespaceBinding = currentBinding->findClassOrNamespaceBinding(id, processed);
 
             if (! classOrNamespaceBinding)
                 return 0;
@@ -429,7 +449,7 @@ ClassBinding *ClassBinding::findClassBinding(Name *name)
         }
 
         if (currentBinding)
-            return currentBinding->findClassBinding(q->unqualifiedNameId());
+            return currentBinding->findClassBinding(q->unqualifiedNameId(), processed);
 
         return 0;
     }
@@ -446,7 +466,7 @@ ClassBinding *ClassBinding::findClassBinding(Name *name)
         }
 
         if (parent)
-            return parent->findClassBinding(name);
+            return parent->findClassBinding(name, processed);
     }
 
     return 0;
@@ -637,6 +657,7 @@ NamespaceBinding *Binder::switchNamespaceBinding(NamespaceBinding *binding)
 
 ClassBinding *Binder::findOrCreateClassBinding(Class *classSymbol)
 {
+    // ### FINISH ME
     ClassBinding *binding = 0;
 
     if (classBinding)
@@ -650,13 +671,15 @@ ClassBinding *Binder::findOrCreateClassBinding(Class *classSymbol)
 
 ClassBinding *Binder::findClassBinding(Name *name)
 {
+    QSet<Binding *> processed;
+
     if (classBinding) {
-        if (ClassBinding *k = classBinding->findClassBinding(name))
+        if (ClassBinding *k = classBinding->findClassBinding(name, &processed))
             return k;
     }
 
     if (namespaceBinding)
-        return namespaceBinding->findClassBinding(name);
+        return namespaceBinding->findClassBinding(name, &processed);
 
     return 0;
 }
diff --git a/src/libs/cplusplus/CppBindings.h b/src/libs/cplusplus/CppBindings.h
index be5933e2c20..d3c4fa2198f 100644
--- a/src/libs/cplusplus/CppBindings.h
+++ b/src/libs/cplusplus/CppBindings.h
@@ -84,8 +84,8 @@ public:
     virtual NamespaceBinding *asNamespaceBinding() { return 0; }
     virtual ClassBinding *asClassBinding() { return 0; }
 
-    virtual ClassBinding *findClassBinding(Name *name) = 0;
-    virtual Binding *findClassOrNamespaceBinding(Identifier *id) = 0;
+    virtual ClassBinding *findClassBinding(Name *name, QSet<Binding *> *processed) = 0;
+    virtual Binding *findClassOrNamespaceBinding(Identifier *id, QSet<Binding *> *processed) = 0;
 };
 
 class CPLUSPLUS_EXPORT NamespaceBinding: public Binding
@@ -116,8 +116,8 @@ public:
                                        Name *name,
                                        bool lookAtParent = true);
 
-    virtual ClassBinding *findClassBinding(Name *name);
-    virtual Binding *findClassOrNamespaceBinding(Identifier *id);
+    virtual ClassBinding *findClassBinding(Name *name, QSet<Binding *> *processed);
+    virtual Binding *findClassOrNamespaceBinding(Identifier *id, QSet<Binding *> *processed);
 
     /// Helpers.
     virtual QByteArray qualifiedId() const;
@@ -171,8 +171,8 @@ public:
     Identifier *identifier() const;
     virtual QByteArray qualifiedId() const;
 
-    virtual ClassBinding *findClassBinding(Name *name);
-    virtual Binding *findClassOrNamespaceBinding(Identifier *id);
+    virtual ClassBinding *findClassBinding(Name *name, QSet<Binding *> *processed);
+    virtual Binding *findClassOrNamespaceBinding(Identifier *id, QSet<Binding *> *processed);
 
     void dump();
 
-- 
GitLab