From 2342fbb32cfe56533ebc8d87ed0134651e2c812a Mon Sep 17 00:00:00 2001 From: Leandro Melo Date: Tue, 28 Aug 2012 14:23:53 +0200 Subject: [PATCH] C++: Fix duplicate base classes in lookup Previously we detected the duplicates by name and then processed the missing ones, but this was not handling qualification properly. Now we process the bases and only after lookup (making sure we are talking about the *same* types) we add then if necessary. Change-Id: Ic318b174d2174e24c24a4f2f1b612fbcb3f20491 Reviewed-by: Orgad Shaneh Reviewed-by: Roberto Raggi --- src/libs/cplusplus/LookupContext.cpp | 26 +++++++++----------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 743e9a0fca1..d41846014ca 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -626,24 +626,14 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac // are templates. We need to collect them now. First, we track the bases which are already // part of the binding so we can identify the missings ones later. - QSet knownBases; - foreach (ClassOrNamespace *con, reference->usings()) { - foreach (Symbol *s, con->symbols()) { - if (Class *c = s->asClass()) { - knownBases.insert(c->name()); - break; - } - } - } - Class *referenceClass = 0; - QList missingBases; + QList allBases; foreach (Symbol *s, reference->symbols()) { if (Class *clazz = s->asClass()) { for (unsigned i = 0; i < clazz->baseClassCount(); ++i) { BaseClass *baseClass = clazz->baseClassAt(i); - if (baseClass->name() && !knownBases.contains(baseClass->name())) - missingBases.append(baseClass->name()); + if (baseClass->name()) + allBases.append(baseClass->name()); } referenceClass = clazz; break; @@ -653,6 +643,8 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac if (!referenceClass) return reference; + QSet knownUsings = reference->usings().toSet(); + // If we are dealling with a template type, more work is required, since we need to // construct all instantiation data. if (const TemplateNameId *templId = name->asTemplateNameId()) { @@ -673,7 +665,7 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac for (unsigned i = 0; i < templ->templateParameterCount(); ++i) templParams.insert(templ->templateParameterAt(i)->name(), i); - foreach (const Name *baseName, missingBases) { + foreach (const Name *baseName, allBases) { ClassOrNamespace *baseBinding = 0; if (const Identifier *nameId = baseName->asNameId()) { @@ -721,7 +713,7 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac } } - if (baseBinding) + if (baseBinding && !knownUsings.contains(baseBinding)) instantiation->addUsing(baseBinding); } } @@ -731,7 +723,7 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac // Find the missing bases for regular (non-template) types. // Ex.: class A : public B::Type {}; - foreach (const Name *baseName, missingBases) { + foreach (const Name *baseName, allBases) { ClassOrNamespace *binding = this; if (const QualifiedNameId *qBaseName = baseName->asQualifiedNameId()) { if (const Name *qualification = qBaseName->base()) @@ -741,7 +733,7 @@ ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespac if (binding) { ClassOrNamespace * baseBinding = binding->lookupType(baseName); - if (baseBinding) + if (baseBinding && !knownUsings.contains(baseBinding)) reference->addUsing(baseBinding); } }