From adfdb51660f3d4251101283efa46b6617cbe43d4 Mon Sep 17 00:00:00 2001
From: Roberto Raggi <roberto.raggi@nokia.com>
Date: Mon, 12 Jul 2010 13:41:54 +0200
Subject: [PATCH] Recursive definition of CPlusPlus::QualifiedNameId.

Done-with: Erik Verbruggen
---
 .../DeprecatedGenTemplateInstance.cpp         | 53 +++++++++----
 src/libs/cplusplus/LookupContext.cpp          | 77 +++++++++----------
 src/libs/cplusplus/NamePrettyPrinter.cpp      | 12 +--
 src/libs/cplusplus/ResolveExpression.cpp      | 20 ++---
 .../cppeditor/cppcheckundefinedsymbols.cpp    |  4 +-
 src/plugins/cppeditor/cppeditor.cpp           |  2 +-
 src/plugins/cpptools/cppcodecompletion.cpp    |  2 +-
 src/plugins/cpptools/searchsymbols.cpp        |  7 +-
 src/shared/cplusplus/CheckDeclaration.cpp     | 46 +++++------
 src/shared/cplusplus/CheckName.cpp            | 25 +++---
 src/shared/cplusplus/Control.cpp              | 18 ++---
 src/shared/cplusplus/Control.h                |  4 +-
 src/shared/cplusplus/CoreTypes.cpp            |  4 +-
 src/shared/cplusplus/Names.cpp                | 43 +++--------
 src/shared/cplusplus/Names.h                  | 21 ++---
 src/shared/cplusplus/Symbol.cpp               | 64 +++------------
 src/shared/cplusplus/Symbol.h                 |  1 -
 17 files changed, 166 insertions(+), 237 deletions(-)

diff --git a/src/libs/cplusplus/DeprecatedGenTemplateInstance.cpp b/src/libs/cplusplus/DeprecatedGenTemplateInstance.cpp
index 9c8ebfe3b58..56b05e39a69 100644
--- a/src/libs/cplusplus/DeprecatedGenTemplateInstance.cpp
+++ b/src/libs/cplusplus/DeprecatedGenTemplateInstance.cpp
@@ -256,27 +256,48 @@ private:
             _type = control()->namedType(templId);
         }
 
-        virtual void visit(const QualifiedNameId *name)
+        const Name *instantiate(const Name *name)
         {
-            QVarLengthArray<const Name *, 8> names(name->nameCount());
-            for (unsigned i = 0; i < name->nameCount(); ++i) {
-                const Name *n = name->nameAt(i);
-
-                if (const TemplateNameId *templId = n->asTemplateNameId()) {
-                    QVarLengthArray<FullySpecifiedType, 8> arguments(templId->templateArgumentCount());
-                    for (unsigned templateArgIndex = 0; templateArgIndex < templId->templateArgumentCount(); ++templateArgIndex) {
-                        FullySpecifiedType argTy = templId->templateArgumentAt(templateArgIndex);
-                        arguments[templateArgIndex] = q->apply(argTy);
-                    }
-
-                    n = control()->templateNameId(templId->identifier(), arguments.data(), arguments.size());
+            if (! name)
+                return name;
+
+            else if (const Name *nameId = name->asNameId()) {
+                const Identifier *id = control()->findOrInsertIdentifier(nameId->identifier()->chars(),
+                                                                         nameId->identifier()->size());
+                return control()->nameId(id);
+
+            } else if (const TemplateNameId *templId = name->asTemplateNameId()) {
+                QVarLengthArray<FullySpecifiedType, 8> arguments(templId->templateArgumentCount());
+                for (unsigned templateArgIndex = 0; templateArgIndex < templId->templateArgumentCount(); ++templateArgIndex) {
+                    FullySpecifiedType argTy = templId->templateArgumentAt(templateArgIndex);
+                    arguments[templateArgIndex] = q->apply(argTy);
                 }
+                const Identifier *id = control()->findOrInsertIdentifier(templId->identifier()->chars(),
+                                                                         templId->identifier()->size());
+                return control()->templateNameId(id, arguments.data(), arguments.size());
+
+            } else if (const QualifiedNameId *qq = name->asQualifiedNameId()) {
+                const Name *base = instantiate(qq->base());
+                const Name *name = instantiate(qq->name());
+
+                return control()->qualifiedNameId(base, name);
+
+            } else if (const OperatorNameId *op = name->asOperatorNameId()) {
+                return control()->operatorNameId(op->kind());
+
+            } else if (const ConversionNameId *c = name->asConversionNameId()) {
+                FullySpecifiedType ty = q->apply(c->type());
+                return control()->conversionNameId(ty);
 
-                names[i] = n;
             }
 
-            const QualifiedNameId *q = control()->qualifiedNameId(names.data(), names.size(), name->isGlobal());
-            _type = control()->namedType(q);
+            return 0;
+        }
+
+        virtual void visit(const QualifiedNameId *name)
+        {
+            if (const Name *n = instantiate(name))
+                _type = control()->namedType(n);
         }
 
         virtual void visit(const DestructorNameId *name)
diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp
index 4d365ae0833..3bb6ea04586 100644
--- a/src/libs/cplusplus/LookupContext.cpp
+++ b/src/libs/cplusplus/LookupContext.cpp
@@ -47,6 +47,18 @@ namespace {
 
 using namespace CPlusPlus;
 
+static void addNames(const Name *name, QList<const Name *> *names)
+{
+    if (! name)
+        return;
+    else if (name->isNameId() || name->isTemplateNameId())
+        names->append(name);
+    else if (const QualifiedNameId *q = name->asQualifiedNameId()) {
+        addNames(q->base(), names);
+        addNames(q->name(), names);
+    }
+}
+
 static void fullyQualifiedName_helper(Symbol *symbol, QList<const Name *> *names)
 {
     if (! symbol)
@@ -56,23 +68,16 @@ static void fullyQualifiedName_helper(Symbol *symbol, QList<const Name *> *names
 
     if (symbol->name()) {
         if (symbol->isClass() || symbol->isNamespace()) {
-            if (const QualifiedNameId *q = symbol->name()->asQualifiedNameId()) {
-                for (unsigned i = 0; i < q->nameCount(); ++i)
-                    names->append(q->nameAt(i));
+            addNames(symbol->name(), names);
 
-            } else if (symbol->name()->isNameId() || symbol->name()->isTemplateNameId()) {
-                names->append(symbol->name());
-            }
         } else if (symbol->isObjCClass() || symbol->isObjCBaseClass() || symbol->isObjCProtocol()
                 || symbol->isObjCForwardClassDeclaration() || symbol->isObjCForwardProtocolDeclaration()
                 || symbol->isForwardClassDeclaration()) {
-            if (symbol->name())
-                names->append(symbol->name());
+            addNames(symbol->name(), names);
+
         } else if (symbol->isFunction()) {
-            if (const QualifiedNameId *q = symbol->name()->asQualifiedNameId()) {
-                for (unsigned i = 0; i < q->nameCount() - 1; ++i)
-                    names->append(q->nameAt(i));
-            }
+            if (const QualifiedNameId *q = symbol->name()->asQualifiedNameId())
+                addNames(q->base(), names);
         }
     }
 }
@@ -142,6 +147,9 @@ const Name *LookupContext::minimalName(const Name *name,
                                        Scope *source,
                                        ClassOrNamespace *target) const
 {
+    qWarning() << "TODO:" << Q_FUNC_INFO;
+
+#if 0
     Q_ASSERT(name);
     Q_ASSERT(source);
     Q_ASSERT(target);
@@ -153,7 +161,7 @@ const Name *LookupContext::minimalName(const Name *name,
     Symbol *canonicalSymbol = symbols.first();
     std::vector<const Name *> fqNames = fullyQualifiedName(canonicalSymbol).toVector().toStdVector();
     if (const QualifiedNameId *qId = name->asQualifiedNameId())
-        fqNames.push_back(qId->nameAt(qId->nameCount() - 1));
+        fqNames.push_back(qId->name());
     else
         fqNames.push_back(name);
 
@@ -172,6 +180,8 @@ const Name *LookupContext::minimalName(const Name *name,
         return lastWorking->nameAt(0);
     else
         return lastWorking;
+#endif
+    return 0;
 }
 
 
@@ -396,21 +406,11 @@ QList<Symbol *> ClassOrNamespace::lookup_helper(const Name *name, bool searchInE
 
     if (name) {
         if (const QualifiedNameId *q = name->asQualifiedNameId()) {
-            ClassOrNamespace *binding = this;
-
-            if (q->isGlobal())
-                binding = globalNamespace();
-
-            if (q->nameCount() == 1)
-                return binding->find(q->unqualifiedNameId());
-
-            binding = binding->lookupType(q->nameAt(0));
-
-            for (unsigned index = 1; binding && index < q->nameCount() - 1; ++index)
-                binding = binding->findType(q->nameAt(index));
+            if (! q->base())
+                result = globalNamespace()->find(q->name());
 
-            if (binding)
-                result = binding->find(q->unqualifiedNameId());
+            else if (ClassOrNamespace *binding = lookupType(q->base()))
+                result = binding->find(q->name());
 
             return result;
         }
@@ -533,17 +533,14 @@ ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name,
                                                       bool searchInEnclosingScope)
 {
     if (const QualifiedNameId *q = name->asQualifiedNameId()) {
-        ClassOrNamespace *e = this;
 
-        if (q->isGlobal())
-            e = globalNamespace();
+        if (! q->base())
+            return globalNamespace()->findType(q->name());
 
-        e = e->lookupType(q->nameAt(0));
+        else if (ClassOrNamespace *binding = lookupType(q->base()))
+            return binding->findType(q->name());
 
-        for (unsigned index = 1; e && index < q->nameCount(); ++index)
-            e = e->findType(q->nameAt(index));
-
-        return e;
+        return 0;
 
     } else if (! processed->contains(this)) {
         processed->insert(this);
@@ -653,12 +650,10 @@ ClassOrNamespace *ClassOrNamespace::findOrCreateType(const Name *name)
         return this;
 
     if (const QualifiedNameId *q = name->asQualifiedNameId()) {
-        ClassOrNamespace *e = this;
+        if (! q->base())
+            return globalNamespace()->findOrCreateType(q->name());
 
-        for (unsigned i = 0; e && i < q->nameCount(); ++i)
-            e = e->findOrCreateType(q->nameAt(i));
-
-        return e;
+        return findOrCreateType(q->base())->findOrCreateType(q->name());
 
     } else if (name->isNameId() || name->isTemplateNameId()) {
         ClassOrNamespace *e = nestedType(name);
@@ -871,7 +866,7 @@ bool CreateBindings::visit(UsingDeclaration *u)
 {
     if (u->name()) {
         if (const QualifiedNameId *q = u->name()->asQualifiedNameId()) {
-            if (const NameId *unqualifiedId = q->unqualifiedNameId()->asNameId()) {
+            if (const NameId *unqualifiedId = q->name()->asNameId()) {
                 if (ClassOrNamespace *delegate = _currentClassOrNamespace->lookupType(q)) {
                     ClassOrNamespace *b = _currentClassOrNamespace->findOrCreateType(unqualifiedId);
                     b->addUsing(delegate);
diff --git a/src/libs/cplusplus/NamePrettyPrinter.cpp b/src/libs/cplusplus/NamePrettyPrinter.cpp
index 89c6ddb4764..5c6146d0e98 100644
--- a/src/libs/cplusplus/NamePrettyPrinter.cpp
+++ b/src/libs/cplusplus/NamePrettyPrinter.cpp
@@ -246,14 +246,10 @@ void NamePrettyPrinter::visit(const ConversionNameId *name)
 
 void NamePrettyPrinter::visit(const QualifiedNameId *name)
 {
-    if (name->isGlobal())
-        _name += QLatin1String("::");
-
-    for (unsigned index = 0; index < name->nameCount(); ++index) {
-        if (index != 0)
-            _name += QLatin1String("::");
-        _name += operator()(name->nameAt(index));
-    }
+    if (name->base())
+        _name += operator()(name->base());
+    _name += QLatin1String("::");
+    _name += operator()(name->name());
 }
 
 void NamePrettyPrinter::visit(const SelectorNameId *name)
diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp
index 21fc815f031..b02b7ecf5d1 100644
--- a/src/libs/cplusplus/ResolveExpression.cpp
+++ b/src/libs/cplusplus/ResolveExpression.cpp
@@ -221,11 +221,10 @@ bool ResolveExpression::visit(NewExpressionAST *ast)
 
 bool ResolveExpression::visit(TypeidExpressionAST *)
 {
-    const Name *std_type_info[2];
-    std_type_info[0] = control()->nameId(control()->findOrInsertIdentifier("std"));
-    std_type_info[1] = control()->nameId(control()->findOrInsertIdentifier("type_info"));
+    const Name *stdName = control()->nameId(control()->findOrInsertIdentifier("std"));
+    const Name *tiName = control()->nameId(control()->findOrInsertIdentifier("type_info"));
+    const Name *q = control()->qualifiedNameId(control()->qualifiedNameId(/* :: */ 0, stdName), tiName);
 
-    const Name *q = control()->qualifiedNameId(std_type_info, 2, /*global=*/ true);
     FullySpecifiedType ty(control()->namedType(q));
     addResult(ty, _scope);
 
@@ -314,14 +313,11 @@ void ResolveExpression::thisObject()
                 addResult(ptrTy, fun->scope());
                 break;
             } else if (const QualifiedNameId *q = fun->name()->asQualifiedNameId()) {
-                const Name *nestedNameSpecifier = 0;
-                if (q->nameCount() == 1 && q->isGlobal())
-                    nestedNameSpecifier = q->nameAt(0);
-                else
-                    nestedNameSpecifier = control()->qualifiedNameId(q->names(), q->nameCount() - 1);
-                FullySpecifiedType classTy(control()->namedType(nestedNameSpecifier));
-                FullySpecifiedType ptrTy(control()->pointerType(classTy));
-                addResult(ptrTy, fun->scope());
+                if (q->base()) {
+                    FullySpecifiedType classTy(control()->namedType(q->base()));
+                    FullySpecifiedType ptrTy(control()->pointerType(classTy));
+                    addResult(ptrTy, fun->scope());
+                }
                 break;
             }
         }
diff --git a/src/plugins/cppeditor/cppcheckundefinedsymbols.cpp b/src/plugins/cppeditor/cppcheckundefinedsymbols.cpp
index 85998929568..e0b21007f7c 100644
--- a/src/plugins/cppeditor/cppcheckundefinedsymbols.cpp
+++ b/src/plugins/cppeditor/cppcheckundefinedsymbols.cpp
@@ -117,8 +117,8 @@ protected:
             return;
 
         } else if (const QualifiedNameId *q = name->asQualifiedNameId()) {
-            for (unsigned i = 0; i < q->nameCount(); ++i)
-                addType(q->nameAt(i));
+            addType(q->base());
+            addType(q->name());
 
         } else if (name->isNameId() || name->isTemplateNameId()) {
             addType(name->identifier());
diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp
index ec161dfa4ae..529a64f4042 100644
--- a/src/plugins/cppeditor/cppeditor.cpp
+++ b/src/plugins/cppeditor/cppeditor.cpp
@@ -535,7 +535,7 @@ protected:
     {
         const Name *name = function->name();
         if (const QualifiedNameId *q = name->asQualifiedNameId())
-            name = q->unqualifiedNameId();
+            name = q->name();
 
         if (_declarationName->isEqualTo(name))
             _functions->append(function);
diff --git a/src/plugins/cpptools/cppcodecompletion.cpp b/src/plugins/cpptools/cppcodecompletion.cpp
index 9ea8d987dc1..3f90f644c05 100644
--- a/src/plugins/cpptools/cppcodecompletion.cpp
+++ b/src/plugins/cpptools/cppcodecompletion.cpp
@@ -200,7 +200,7 @@ protected:
     { _item = newCompletionItem(name); }
 
     virtual void visit(const QualifiedNameId *name)
-    { _item = newCompletionItem(name->unqualifiedNameId()); }
+    { _item = newCompletionItem(name->name()); }
 };
 
 struct CompleteFunctionDeclaration
diff --git a/src/plugins/cpptools/searchsymbols.cpp b/src/plugins/cpptools/searchsymbols.cpp
index f66700bf30f..99c2616489d 100644
--- a/src/plugins/cpptools/searchsymbols.cpp
+++ b/src/plugins/cpptools/searchsymbols.cpp
@@ -96,10 +96,9 @@ bool SearchSymbols::visit(Function *symbol)
 
     QString extraScope;
     if (const Name *name = symbol->name()) {
-        if (const QualifiedNameId *nameId = name->asQualifiedNameId()) {
-            if (nameId->nameCount() > 1) {
-                extraScope = overview.prettyName(nameId->nameAt(nameId->nameCount() - 2));
-            }
+        if (const QualifiedNameId *q = name->asQualifiedNameId()) {
+            if (q->base())
+                extraScope = overview.prettyName(q->base());
         }
     }
     QString fullScope = _scope;
diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp
index d38aa0eeeed..f320296d284 100644
--- a/src/shared/cplusplus/CheckDeclaration.cpp
+++ b/src/shared/cplusplus/CheckDeclaration.cpp
@@ -870,35 +870,31 @@ bool CheckDeclaration::visit(QtPropertyDeclarationAST *ast)
     return false;
 }
 
-void CheckDeclaration::checkQEnumsQFlagsNames(NameListAST *nameListAst,
-                                              const char *declName)
+static bool checkEnumName(const Name *name)
 {
-    for (NameListAST *iter = nameListAst; iter; iter = iter->next) {
+    if (! name)
+        return false;
 
-        const Name *name = semantic()->check(iter->value, _scope);
-        if (!name)
-            continue;
+    else if (name->asNameId() != 0)
+        return true;
 
-        if (name->isNameId())
-            continue;
+    else if (const QualifiedNameId *q = name->asQualifiedNameId()) {
+        if (! q->base())
+            return false; // global qualified name
 
-        const QualifiedNameId *qName = name->asQualifiedNameId();
-        if (!qName)
-            translationUnit()->error(iter->firstToken(), "invalid name in %s",
-                                     declName);
-        else if (qName->isGlobal())
-                translationUnit()->error(iter->firstToken(),
-                                         "invalid name '%s' in %s",
-                                         qName->identifier()->chars(), declName);
-        else {
-            for (unsigned i = 0; i < qName->nameCount(); ++i) {
-                const Name *namePart = qName->nameAt(i);
-                if (!namePart || !namePart->isNameId()) {
-                    translationUnit()->error(iter->firstToken(),
-                                             "invalid name '%s' in %s",
-                                             qName->identifier()->chars(), declName);
-                }
-            }
+        if (checkEnumName(q->base()) && checkEnumName(q->name()))
+            return true;
+    }
+
+    return false;
+}
+
+void CheckDeclaration::checkQEnumsQFlagsNames(NameListAST *nameListAst, const char *declName)
+{
+    for (NameListAST *iter = nameListAst; iter; iter = iter->next) {
+        if (const Name *name = semantic()->check(iter->value, _scope)) {
+            if (! checkEnumName(name))
+                translationUnit()->error(iter->firstToken(), "invalid name in %s", declName);
         }
     }
 }
diff --git a/src/shared/cplusplus/CheckName.cpp b/src/shared/cplusplus/CheckName.cpp
index 4105268f93f..1161a8e0e0e 100644
--- a/src/shared/cplusplus/CheckName.cpp
+++ b/src/shared/cplusplus/CheckName.cpp
@@ -87,15 +87,15 @@ const Name *CheckName::check(NestedNameSpecifierListAST *nested_name_specifier_l
     const Name *previousName = switchName(0);
     Scope *previousScope = switchScope(scope);
 
-    std::vector<const Name *> names;
     for (NestedNameSpecifierListAST *it = nested_name_specifier_list; it; it = it->next) {
         NestedNameSpecifierAST *nested_name_specifier = it->value;
-        names.push_back(semantic()->check(nested_name_specifier->class_or_namespace_name, _scope));
+        const Name *n = semantic()->check(nested_name_specifier->class_or_namespace_name, _scope);
+        if (! _name)
+            _name = n;
+        else
+            _name = control()->qualifiedNameId(_name, n);
     }
 
-    if (! names.empty())
-        _name = control()->qualifiedNameId(&names[0], names.size());
-
     (void) switchScope(previousScope);
     return switchName(previousName);
 }
@@ -127,13 +127,20 @@ Scope *CheckName::switchScope(Scope *scope)
 
 bool CheckName::visit(QualifiedNameAST *ast)
 {
-    std::vector<const Name *> names;
     for (NestedNameSpecifierListAST *it = ast->nested_name_specifier_list; it; it = it->next) {
         NestedNameSpecifierAST *nested_name_specifier = it->value;
-        names.push_back(semantic()->check(nested_name_specifier->class_or_namespace_name, _scope));
+        const Name *n = semantic()->check(nested_name_specifier->class_or_namespace_name, _scope);
+        if (_name || ast->global_scope_token)
+            _name = control()->qualifiedNameId(_name, n);
+        else
+            _name = n;
     }
-    names.push_back(semantic()->check(ast->unqualified_name, _scope));
-    _name = control()->qualifiedNameId(&names[0], names.size(), ast->global_scope_token != 0);
+
+    const Name *n = semantic()->check(ast->unqualified_name, _scope);
+    if (_name || ast->global_scope_token)
+        _name = control()->qualifiedNameId(_name, n);
+    else
+        _name = n;
 
     ast->name = _name;
     return false;
diff --git a/src/shared/cplusplus/Control.cpp b/src/shared/cplusplus/Control.cpp
index 93f77e3aae2..15b2c517871 100644
--- a/src/shared/cplusplus/Control.cpp
+++ b/src/shared/cplusplus/Control.cpp
@@ -177,11 +177,10 @@ template <> struct Compare<QualifiedNameId>
 {
     bool operator()(const QualifiedNameId &name, const QualifiedNameId &otherName) const
     {
-        if (name.isGlobal() == otherName.isGlobal())
-            return std::lexicographical_compare(name.firstName(), name.lastName(),
-                                                otherName.firstName(), otherName.lastName());
+        if (name.base() == otherName.base())
+            return name.name() < otherName.name();
 
-        return name.isGlobal() < otherName.isGlobal();
+        return name.base() < otherName.base();
     }
 };
 
@@ -285,10 +284,9 @@ public:
         return conversionNameIds.intern(ConversionNameId(type));
     }
 
-    template <typename _Iterator>
-    const QualifiedNameId *findOrInsertQualifiedNameId(_Iterator first, _Iterator last, bool isGlobal)
+    const QualifiedNameId *findOrInsertQualifiedNameId(const Name *base, const Name *name)
     {
-        return qualifiedNameIds.intern(QualifiedNameId(first, last, isGlobal));
+        return qualifiedNameIds.intern(QualifiedNameId(base, name));
     }
 
     template <typename _Iterator>
@@ -641,11 +639,9 @@ const OperatorNameId *Control::operatorNameId(int kind)
 const ConversionNameId *Control::conversionNameId(const FullySpecifiedType &type)
 { return d->findOrInsertConversionNameId(type); }
 
-const QualifiedNameId *Control::qualifiedNameId(const Name *const *names,
-                                                unsigned nameCount,
-                                                bool isGlobal)
+const QualifiedNameId *Control::qualifiedNameId(const Name *base, const Name *name)
 {
-    return d->findOrInsertQualifiedNameId(names, names + nameCount, isGlobal);
+    return d->findOrInsertQualifiedNameId(base, name);
 }
 
 const SelectorNameId *Control::selectorNameId(const Name *const *names,
diff --git a/src/shared/cplusplus/Control.h b/src/shared/cplusplus/Control.h
index 187dc10a0ef..7cd42e26145 100644
--- a/src/shared/cplusplus/Control.h
+++ b/src/shared/cplusplus/Control.h
@@ -83,9 +83,7 @@ public:
     const ConversionNameId *conversionNameId(const FullySpecifiedType &type);
 
     /// Returns the canonical qualified name id.
-    const QualifiedNameId *qualifiedNameId(const Name *const *names,
-                                           unsigned nameCount,
-                                           bool isGlobal = false);
+    const QualifiedNameId *qualifiedNameId(const Name *base, const Name *name);
 
     const SelectorNameId *selectorNameId(const Name *const *names,
                                          unsigned nameCount,
diff --git a/src/shared/cplusplus/CoreTypes.cpp b/src/shared/cplusplus/CoreTypes.cpp
index 6c5501b24ef..e53c665e667 100644
--- a/src/shared/cplusplus/CoreTypes.cpp
+++ b/src/shared/cplusplus/CoreTypes.cpp
@@ -298,11 +298,11 @@ bool NamedType::isEqualTo(const Type *other) const
 
     const Name *name = _name;
     if (const QualifiedNameId *q = name->asQualifiedNameId())
-        name = q->unqualifiedNameId();
+        name = q->name();
 
     const Name *otherName = o->name();
     if (const QualifiedNameId *q = otherName->asQualifiedNameId())
-        otherName = q->unqualifiedNameId();
+        otherName = q->name();
 
     return name->isEqualTo(otherName);
 }
diff --git a/src/shared/cplusplus/Names.cpp b/src/shared/cplusplus/Names.cpp
index 07667628e53..d73f98b3585 100644
--- a/src/shared/cplusplus/Names.cpp
+++ b/src/shared/cplusplus/Names.cpp
@@ -63,48 +63,29 @@ void QualifiedNameId::accept0(NameVisitor *visitor) const
 
 const Identifier *QualifiedNameId::identifier() const
 {
-    if (const Name *u = unqualifiedNameId())
+    if (const Name *u = name())
         return u->identifier();
 
     return 0;
 }
 
-unsigned QualifiedNameId::nameCount() const
-{ return _names.size(); }
-
-const Name *QualifiedNameId::nameAt(unsigned index) const
-{ return _names[index]; }
-
-bool QualifiedNameId::isGlobal() const
-{ return _isGlobal; }
-
-const Name *QualifiedNameId::unqualifiedNameId() const
-{
-    if (_names.empty())
-        return 0;
+const Name *QualifiedNameId::base() const
+{ return _base; }
 
-    return _names.back();
-}
+const Name *QualifiedNameId::name() const
+{ return _name; }
 
 bool QualifiedNameId::isEqualTo(const Name *other) const
 {
-    const QualifiedNameId *q = other->asQualifiedNameId();
-    if (! q)
-        return false;
-    else if (isGlobal() != q->isGlobal())
-        return false;
-    else {
-        const unsigned count = nameCount();
-        if (count != q->nameCount())
-            return false;
-        for (unsigned i = 0; i < count; ++i) {
-            const Name *l = nameAt(i);
-            const Name *r = q->nameAt(i);
-            if (! l->isEqualTo(r))
-                return false;
+    if (const QualifiedNameId *q = other->asQualifiedNameId()) {
+        if (_base == q->_base || (_base && _base->isEqualTo(q->_base))) {
+            if (_name == q->_name || (_name && _name->isEqualTo(q->_name))) {
+                return true;
+            }
         }
     }
-    return true;
+
+    return false;
 }
 
 NameId::NameId(const Identifier *identifier)
diff --git a/src/shared/cplusplus/Names.h b/src/shared/cplusplus/Names.h
index bd329060da8..050632a8b41 100644
--- a/src/shared/cplusplus/Names.h
+++ b/src/shared/cplusplus/Names.h
@@ -59,36 +59,27 @@ namespace CPlusPlus {
 class CPLUSPLUS_EXPORT QualifiedNameId: public Name
 {
 public:
-    template <typename _Iterator>
-    QualifiedNameId(_Iterator first, _Iterator last, bool isGlobal = false)
-        : _names(first, last), _isGlobal(isGlobal) {}
+    QualifiedNameId(const Name *base, const Name *name)
+        : _base(base), _name(name) {}
 
     virtual ~QualifiedNameId();
 
     virtual const Identifier *identifier() const;
 
-    unsigned nameCount() const;
-    const Name *nameAt(unsigned index) const;
-    const Name *unqualifiedNameId() const;
-    const Name *const *names() const { return &_names[0]; } // ### remove me
-    bool isGlobal() const;
+    const Name *base() const;
+    const Name *name() const;
 
     virtual bool isEqualTo(const Name *other) const;
 
     virtual const QualifiedNameId *asQualifiedNameId() const
     { return this; }
 
-    typedef std::vector<const Name *>::const_iterator NameIterator;
-
-    NameIterator firstName() const { return _names.begin(); }
-    NameIterator lastName() const { return _names.end(); }
-
 protected:
     virtual void accept0(NameVisitor *visitor) const;
 
 private:
-    std::vector<const Name *> _names;
-    bool _isGlobal;
+    const Name *_base;
+    const Name *_name;
 };
 
 class CPLUSPLUS_EXPORT NameId: public Name
diff --git a/src/shared/cplusplus/Symbol.cpp b/src/shared/cplusplus/Symbol.cpp
index 1b38da597be..af168982da4 100644
--- a/src/shared/cplusplus/Symbol.cpp
+++ b/src/shared/cplusplus/Symbol.cpp
@@ -101,7 +101,7 @@ protected:
     { _value = 0; } // ### TODO: implement me
 
     virtual void visit(const QualifiedNameId *name)
-    { _value = operator()(name->unqualifiedNameId()); }
+    { _value = operator()(name->name()); }
 
     virtual void visit(const SelectorNameId *name)
     { _value = name->identifier()->hashCode(); }
@@ -110,56 +110,6 @@ private:
     unsigned _value;
 };
 
-class Symbol::IdentityForName: protected NameVisitor
-{
-public:
-    IdentityForName()
-        : _identity(0)
-    { }
-
-    virtual ~IdentityForName()
-    { }
-
-    const Name *operator()(const Name *name)
-    {
-        const Name *previousIdentity = switchIdentity(0);
-        accept(name);
-        return switchIdentity(previousIdentity);
-    }
-
-protected:
-    const Name *switchIdentity(const Name *identity)
-    {
-        const Name *previousIdentity = _identity;
-        _identity = identity;
-        return previousIdentity;
-    }
-
-    virtual void visit(const NameId *name)
-    { _identity = name; }
-
-    virtual void visit(const TemplateNameId *name)
-    { _identity = name; }
-
-    virtual void visit(const DestructorNameId *name)
-    { _identity = name; }
-
-    virtual void visit(const OperatorNameId *name)
-    { _identity = name; }
-
-    virtual void visit(const ConversionNameId *name)
-    { _identity = name; }
-
-    virtual void visit(const QualifiedNameId *name)
-    { _identity = name->unqualifiedNameId(); }
-
-    virtual void visit(const SelectorNameId *name)
-    { _identity = name; }
-
-private:
-    const Name *_identity;
-};
-
 Symbol::Symbol(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name)
     : _startOffset(0),
       _endOffset(0),
@@ -265,8 +215,13 @@ void Symbol::setEndOffset(unsigned offset)
 
 const Name *Symbol::identity() const
 {
-    IdentityForName id;
-    return id(_name);
+    if (! _name)
+        return 0;
+
+    else if (const QualifiedNameId *q = _name->asQualifiedNameId())
+        return q->name();
+
+    return _name;
 }
 
 const Name *Symbol::name() const
@@ -279,9 +234,8 @@ void Symbol::setName(const Name *name)
     if (! _name)
         _hashCode = 0;
     else {
-        IdentityForName identityForName;
         HashCode hh;
-        _hashCode = hh(identityForName(_name));
+        _hashCode = hh(identity());
     }
 }
 
diff --git a/src/shared/cplusplus/Symbol.h b/src/shared/cplusplus/Symbol.h
index 98ce58bd8d4..c6ce1a64023 100644
--- a/src/shared/cplusplus/Symbol.h
+++ b/src/shared/cplusplus/Symbol.h
@@ -337,7 +337,6 @@ private:
     bool _isDeprecated: 1;
     bool _isUnavailable: 1;
 
-    class IdentityForName;
     class HashCode;
 
     friend class Scope;
-- 
GitLab