Commit 2342fbb3 authored by Leandro Melo's avatar Leandro Melo
Browse files

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's avatarOrgad Shaneh <orgads@gmail.com>
Reviewed-by: default avatarRoberto Raggi <roberto.raggi@nokia.com>
parent 04bc18ea
......@@ -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<const Name *> 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<const Name *> missingBases;
QList<const Name *> 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<ClassOrNamespace *> 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<Some>::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);
}
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment