CplusPlus: Fix minimal name construction

... when using declarations are involved.
Second attempt.
I have a suspicion that this is not the "correct" approach, however:
    a) It appears to fix the problem.
    b) It does not break any tests.
    c) It's rather high in the call tree, so there's a low likelihood
       of breaking something else.
    d) Considering the hacky-looking pre-existing code dealing with
       using declarations (e.g. LookupContext::lookupByUsing()),
       it seems quite possible that there is no "correct" way with
       the current infrastructure.

Fixes: QTCREATORBUG-14524
Change-Id: I28c6e53137c21ce158bbd03b92b3db39146116d5
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
Christian Kandeler
2021-01-29 10:18:31 +01:00
parent fa260e00ed
commit aae3ce15aa
3 changed files with 49 additions and 15 deletions

View File

@@ -270,6 +270,27 @@ const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target,
{
const Name *n = nullptr;
QList<const Name *> names = LookupContext::fullyQualifiedName(symbol);
ClassOrNamespace *current = target;
const auto getNameFromItems = [symbol, target, control](const QList<LookupItem> &items,
const QList<const Name *> &names, bool checkSymbols) -> const Name * {
for (const LookupItem &item : items) {
if (checkSymbols && !symbolIdentical(item.declaration(), symbol))
continue;
// eliminate inline namespaces
QList<const Name *> minimal = names;
for (int i = minimal.size() - 2; i >= 0; --i) {
const Name *candidate = toName(minimal.mid(0, i + 1), control);
if (isInlineNamespace(target, candidate))
minimal.removeAt(i);
}
return toName(minimal, control);
}
return nullptr;
};
for (int i = names.size() - 1; i >= 0; --i) {
if (! n)
@@ -279,20 +300,24 @@ const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target,
// once we're qualified enough to get the same symbol, break
if (target) {
const QList<LookupItem> tresults = target->lookup(n);
foreach (const LookupItem &tr, tresults) {
if (symbolIdentical(tr.declaration(), symbol)) {
// eliminate inline namespaces
QList<const Name *> minimal = names.mid(i);
for (int i = minimal.size() - 2; i >= 0; --i) {
const Name *candidate = toName(minimal.mid(0, i + 1), control);
if (isInlineNamespace(target, candidate))
minimal.removeAt(i);
}
return toName(minimal, control);
const Name * const minimal = getNameFromItems(target->lookup(n), names.mid(i), true);
if (minimal)
return minimal;
}
if (current) {
const ClassOrNamespace * const nested = current->getNested(names.last());
if (nested) {
const QList<const Name *> nameList
= names.mid(0, names.size() - i - 1) << names.last();
const QList<ClassOrNamespace *> usings = nested->usings();
for (ClassOrNamespace * const u : usings) {
const Name * const minimal = getNameFromItems(u->lookup(symbol->name()),
nameList, false);
if (minimal)
return minimal;
}
}
current = current->getNested(names.at(names.size() - i - 1));
}
}
@@ -923,6 +948,15 @@ ClassOrNamespace *ClassOrNamespace::findBlock(Block *block)
return findBlock_helper(block, &processed, true);
}
ClassOrNamespace *ClassOrNamespace::getNested(const Name *name)
{
flush();
const auto it = _classOrNamespaces.find(name);
if (it != _classOrNamespaces.cend())
return it->second;
return nullptr;
}
Symbol *ClassOrNamespace::lookupInScope(const QList<const Name *> &fullName)
{
if (!_scopeLookupCache) {