forked from qt-creator/qt-creator
C++: Fix explicit typedef from base type in templated class
Use-case:
struct Foo { int bar; };
template<typename T>
struct Base { typedef T F; };
template<typename T>
struct Derived : Base<T>
{
typedef typename Base<T>::F F;
F f;
};
void func()
{
Derived<Foo> d;
d.f.bar; // bar not highlighted
}
Task-number: QTCREATORBUG-14218
Change-Id: Ic0b22b2f8adf80ff88a2f8b7359c276a744f89e8
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com>
This commit is contained in:
committed by
Orgad Shaneh
parent
cf66beffb6
commit
372173331c
@@ -612,7 +612,10 @@ public:
|
||||
: _cloner(cloner)
|
||||
, _subst(subst)
|
||||
{}
|
||||
void instantiate(LookupScopePrivate *lookupScope, LookupScopePrivate *instantiation);
|
||||
void instantiate(LookupScopePrivate *lookupScope,
|
||||
LookupScopePrivate *instantiation,
|
||||
bool includeSymbols);
|
||||
LookupScopePrivate *maybeInstantiate(LookupScopePrivate *lookupScope);
|
||||
private:
|
||||
bool isInstantiationNeeded(LookupScopePrivate *lookupScope) const;
|
||||
|
||||
@@ -1356,7 +1359,6 @@ LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScope
|
||||
|
||||
// The instantiation should have all symbols, enums, and usings from the reference.
|
||||
instantiation->_enums = reference->_enums;
|
||||
instantiation->_usings = reference->_usings;
|
||||
|
||||
instantiation->_rootClass = reference->_rootClass;
|
||||
|
||||
@@ -1400,8 +1402,9 @@ LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScope
|
||||
}
|
||||
|
||||
Instantiator instantiator(cloner, subst);
|
||||
instantiator.instantiate(reference, instantiation);
|
||||
instantiator.instantiate(reference, instantiation, true);
|
||||
} else {
|
||||
instantiation->_usings = reference->_usings;
|
||||
instantiation->_symbols.append(reference->_symbols);
|
||||
instantiation->_typedefs = reference->_typedefs;
|
||||
}
|
||||
@@ -1477,6 +1480,7 @@ LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScope
|
||||
}
|
||||
} else {
|
||||
instantiation->_nestedScopes = reference->_nestedScopes;
|
||||
instantiation->_usings = reference->_usings;
|
||||
instantiation->_symbols.append(reference->_symbols);
|
||||
instantiation->_typedefs = reference->_typedefs;
|
||||
}
|
||||
@@ -1517,8 +1521,34 @@ LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScope
|
||||
return reference;
|
||||
}
|
||||
|
||||
LookupScopePrivate *Instantiator::maybeInstantiate(LookupScopePrivate *lookupScope)
|
||||
{
|
||||
lookupScope->flush();
|
||||
LookupScopePrivate *instantiation = lookupScope;
|
||||
|
||||
bool hasTemplateSymbols = isInstantiationNeeded(lookupScope);
|
||||
bool hasTemplateUsings = false;
|
||||
if (!hasTemplateSymbols) {
|
||||
foreach (LookupScope *usingLookupScope, lookupScope->_usings) {
|
||||
if (isInstantiationNeeded(usingLookupScope->d)) {
|
||||
hasTemplateUsings = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasTemplateSymbols || hasTemplateUsings) {
|
||||
instantiation = lookupScope->allocateChild(lookupScope->_name);
|
||||
instantiation->_enums = lookupScope->_enums;
|
||||
instantiation->_instantiationOrigin = lookupScope;
|
||||
instantiate(lookupScope, instantiation, hasTemplateSymbols);
|
||||
}
|
||||
|
||||
return instantiation;
|
||||
}
|
||||
|
||||
void Instantiator::instantiate(LookupScopePrivate *lookupScope,
|
||||
LookupScopePrivate *instantiation)
|
||||
LookupScopePrivate *instantiation,
|
||||
bool includeSymbols)
|
||||
{
|
||||
if (_alreadyConsideredInstantiations.contains(lookupScope))
|
||||
return;
|
||||
@@ -1531,6 +1561,9 @@ void Instantiator::instantiate(LookupScopePrivate *lookupScope,
|
||||
instantiation->_typedefs[typedefit->first] =
|
||||
_cloner.symbol(typedefit->second, &_subst)->asDeclaration();
|
||||
}
|
||||
foreach (LookupScope *usingLookupScope, lookupScope->_usings)
|
||||
instantiation->_usings.append(maybeInstantiate(usingLookupScope->d)->q);
|
||||
if (includeSymbols) {
|
||||
foreach (Symbol *s, lookupScope->_symbols) {
|
||||
Symbol *clone = _cloner.symbol(s, &_subst);
|
||||
if (!clone->enclosingScope()) // Not from the cache but just cloned.
|
||||
@@ -1558,25 +1591,18 @@ void Instantiator::instantiate(LookupScopePrivate *lookupScope,
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
instantiation->_symbols = lookupScope->_symbols;
|
||||
}
|
||||
}
|
||||
auto cit = lookupScope->_nestedScopes.begin();
|
||||
for (; cit != lookupScope->_nestedScopes.end(); ++cit) {
|
||||
const Name *nestedName = cit->first;
|
||||
LookupScopePrivate *nestedLookupScope = cit->second;
|
||||
LookupScopePrivate *nestedInstantiation = nestedLookupScope;
|
||||
nestedLookupScope->flush();
|
||||
|
||||
const bool instantiationNeeded = isInstantiationNeeded(nestedInstantiation);
|
||||
if (instantiationNeeded) {
|
||||
nestedInstantiation = nestedLookupScope->allocateChild(nestedName);
|
||||
nestedInstantiation->_enums = nestedLookupScope->_enums;
|
||||
nestedInstantiation->_usings = nestedLookupScope->_usings;
|
||||
nestedInstantiation->_instantiationOrigin = nestedLookupScope;
|
||||
}
|
||||
LookupScopePrivate *nestedInstantiation = maybeInstantiate(nestedLookupScope);
|
||||
|
||||
if (isNestedInstantiationEnclosingTemplate(nestedInstantiation, lookupScope))
|
||||
nestedInstantiation->_parent = instantiation;
|
||||
instantiate(nestedLookupScope, nestedInstantiation);
|
||||
|
||||
instantiation->_nestedScopes[nestedName] = nestedInstantiation;
|
||||
}
|
||||
|
||||
@@ -326,13 +326,13 @@ void CppToolsPlugin::test_completion()
|
||||
actualCompletions.sort();
|
||||
expectedCompletions.sort();
|
||||
|
||||
QEXPECT_FAIL("template_as_base: explicit typedef from base", "QTCREATORBUG-14218", Abort);
|
||||
QEXPECT_FAIL("template_as_base: typedef not available in derived",
|
||||
"We can live with that...", Abort);
|
||||
QEXPECT_FAIL("enum_in_function_in_struct_in_function", "QTCREATORBUG-13757", Abort);
|
||||
QEXPECT_FAIL("enum_in_function_in_struct_in_function_cxx11", "QTCREATORBUG-13757", Abort);
|
||||
QEXPECT_FAIL("enum_in_function_in_struct_in_function_anon", "QTCREATORBUG-13757", Abort);
|
||||
QEXPECT_FAIL("enum_in_class_accessed_in_member_func_cxx11", "QTCREATORBUG-13757", Abort);
|
||||
QEXPECT_FAIL("enum_in_class_accessed_in_member_func_inline_cxx11", "QTCREATORBUG-13757", Abort);
|
||||
QEXPECT_FAIL("pointer_indirect_specialization_double_indirection_with_base", "QTCREATORBUG-14141", Abort);
|
||||
QEXPECT_FAIL("recursive_instantiation_of_template_type", "QTCREATORBUG-14237", Abort);
|
||||
QCOMPARE(actualCompletions, expectedCompletions);
|
||||
}
|
||||
|
||||
@@ -1203,7 +1203,6 @@ void tst_CheckSymbols::findField()
|
||||
source[position] = ' ';
|
||||
BaseTestCase tc(source);
|
||||
Use use = tc.findUse(line, column);
|
||||
QEXPECT_FAIL("pointer_indirect_specialization_double_indirection_with_base", "QTCREATORBUG-14141", Abort);
|
||||
QEXPECT_FAIL("recursive_instantiation_of_template_type", "QTCREATORBUG-14237", Abort);
|
||||
QVERIFY(use.isValid());
|
||||
QVERIFY(use.kind == Highlighting::FieldUse);
|
||||
|
||||
Reference in New Issue
Block a user