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)
|
: _cloner(cloner)
|
||||||
, _subst(subst)
|
, _subst(subst)
|
||||||
{}
|
{}
|
||||||
void instantiate(LookupScopePrivate *lookupScope, LookupScopePrivate *instantiation);
|
void instantiate(LookupScopePrivate *lookupScope,
|
||||||
|
LookupScopePrivate *instantiation,
|
||||||
|
bool includeSymbols);
|
||||||
|
LookupScopePrivate *maybeInstantiate(LookupScopePrivate *lookupScope);
|
||||||
private:
|
private:
|
||||||
bool isInstantiationNeeded(LookupScopePrivate *lookupScope) const;
|
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.
|
// The instantiation should have all symbols, enums, and usings from the reference.
|
||||||
instantiation->_enums = reference->_enums;
|
instantiation->_enums = reference->_enums;
|
||||||
instantiation->_usings = reference->_usings;
|
|
||||||
|
|
||||||
instantiation->_rootClass = reference->_rootClass;
|
instantiation->_rootClass = reference->_rootClass;
|
||||||
|
|
||||||
@@ -1400,8 +1402,9 @@ LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScope
|
|||||||
}
|
}
|
||||||
|
|
||||||
Instantiator instantiator(cloner, subst);
|
Instantiator instantiator(cloner, subst);
|
||||||
instantiator.instantiate(reference, instantiation);
|
instantiator.instantiate(reference, instantiation, true);
|
||||||
} else {
|
} else {
|
||||||
|
instantiation->_usings = reference->_usings;
|
||||||
instantiation->_symbols.append(reference->_symbols);
|
instantiation->_symbols.append(reference->_symbols);
|
||||||
instantiation->_typedefs = reference->_typedefs;
|
instantiation->_typedefs = reference->_typedefs;
|
||||||
}
|
}
|
||||||
@@ -1477,6 +1480,7 @@ LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScope
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
instantiation->_nestedScopes = reference->_nestedScopes;
|
instantiation->_nestedScopes = reference->_nestedScopes;
|
||||||
|
instantiation->_usings = reference->_usings;
|
||||||
instantiation->_symbols.append(reference->_symbols);
|
instantiation->_symbols.append(reference->_symbols);
|
||||||
instantiation->_typedefs = reference->_typedefs;
|
instantiation->_typedefs = reference->_typedefs;
|
||||||
}
|
}
|
||||||
@@ -1517,8 +1521,34 @@ LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScope
|
|||||||
return reference;
|
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,
|
void Instantiator::instantiate(LookupScopePrivate *lookupScope,
|
||||||
LookupScopePrivate *instantiation)
|
LookupScopePrivate *instantiation,
|
||||||
|
bool includeSymbols)
|
||||||
{
|
{
|
||||||
if (_alreadyConsideredInstantiations.contains(lookupScope))
|
if (_alreadyConsideredInstantiations.contains(lookupScope))
|
||||||
return;
|
return;
|
||||||
@@ -1531,6 +1561,9 @@ void Instantiator::instantiate(LookupScopePrivate *lookupScope,
|
|||||||
instantiation->_typedefs[typedefit->first] =
|
instantiation->_typedefs[typedefit->first] =
|
||||||
_cloner.symbol(typedefit->second, &_subst)->asDeclaration();
|
_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) {
|
foreach (Symbol *s, lookupScope->_symbols) {
|
||||||
Symbol *clone = _cloner.symbol(s, &_subst);
|
Symbol *clone = _cloner.symbol(s, &_subst);
|
||||||
if (!clone->enclosingScope()) // Not from the cache but just cloned.
|
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();
|
auto cit = lookupScope->_nestedScopes.begin();
|
||||||
for (; cit != lookupScope->_nestedScopes.end(); ++cit) {
|
for (; cit != lookupScope->_nestedScopes.end(); ++cit) {
|
||||||
const Name *nestedName = cit->first;
|
const Name *nestedName = cit->first;
|
||||||
LookupScopePrivate *nestedLookupScope = cit->second;
|
LookupScopePrivate *nestedLookupScope = cit->second;
|
||||||
LookupScopePrivate *nestedInstantiation = nestedLookupScope;
|
LookupScopePrivate *nestedInstantiation = maybeInstantiate(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;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isNestedInstantiationEnclosingTemplate(nestedInstantiation, lookupScope))
|
if (isNestedInstantiationEnclosingTemplate(nestedInstantiation, lookupScope))
|
||||||
nestedInstantiation->_parent = instantiation;
|
nestedInstantiation->_parent = instantiation;
|
||||||
instantiate(nestedLookupScope, nestedInstantiation);
|
|
||||||
|
|
||||||
instantiation->_nestedScopes[nestedName] = nestedInstantiation;
|
instantiation->_nestedScopes[nestedName] = nestedInstantiation;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -326,13 +326,13 @@ void CppToolsPlugin::test_completion()
|
|||||||
actualCompletions.sort();
|
actualCompletions.sort();
|
||||||
expectedCompletions.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", "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_cxx11", "QTCREATORBUG-13757", Abort);
|
||||||
QEXPECT_FAIL("enum_in_function_in_struct_in_function_anon", "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_cxx11", "QTCREATORBUG-13757", Abort);
|
||||||
QEXPECT_FAIL("enum_in_class_accessed_in_member_func_inline_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);
|
QEXPECT_FAIL("recursive_instantiation_of_template_type", "QTCREATORBUG-14237", Abort);
|
||||||
QCOMPARE(actualCompletions, expectedCompletions);
|
QCOMPARE(actualCompletions, expectedCompletions);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1203,7 +1203,6 @@ void tst_CheckSymbols::findField()
|
|||||||
source[position] = ' ';
|
source[position] = ' ';
|
||||||
BaseTestCase tc(source);
|
BaseTestCase tc(source);
|
||||||
Use use = tc.findUse(line, column);
|
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);
|
QEXPECT_FAIL("recursive_instantiation_of_template_type", "QTCREATORBUG-14237", Abort);
|
||||||
QVERIFY(use.isValid());
|
QVERIFY(use.isValid());
|
||||||
QVERIFY(use.kind == Highlighting::FieldUse);
|
QVERIFY(use.kind == Highlighting::FieldUse);
|
||||||
|
|||||||
Reference in New Issue
Block a user