diff options
author | Orgad Shaneh <orgad.shaneh@audiocodes.com> | 2015-06-07 11:47:50 +0300 |
---|---|---|
committer | Orgad Shaneh <orgads@gmail.com> | 2015-06-09 14:18:17 +0000 |
commit | 97d3d9ac0946f3be0e036b70401352e3ddaeb8fc (patch) | |
tree | 3bba03e6e4aa9025e07cdfce94b52f45570b9c74 /src/libs/cplusplus/LookupContext.cpp | |
parent | 1c7e465c30bb0d46ec43fe571b9c6aa0e3499754 (diff) | |
download | qt-creator-97d3d9ac0946f3be0e036b70401352e3ddaeb8fc.tar.gz |
C++: Support default template argument lookup for specialization
This fixes std::vector, although it doesn't really resolve numeric
template arguments. It just picks the first specialization.
Use-case:
class Foo {};
template<class T1 = Foo> class Temp;
template<> class Temp<Foo> { int var; };
void func()
{
Temp<> t;
t.var; // var not highlighted
}
Task-number: QTCREATORBUG-8922
Change-Id: I593515beb3a6d901b6088db8bc1b8e16c39083d3
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com>
Diffstat (limited to 'src/libs/cplusplus/LookupContext.cpp')
-rw-r--r-- | src/libs/cplusplus/LookupContext.cpp | 94 |
1 files changed, 55 insertions, 39 deletions
diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 031afb4004..38093f8b47 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -569,7 +569,7 @@ private: LookupScopePrivate *nestedType(const Name *name, LookupScopePrivate *origin); - LookupScopePrivate *findSpecialization(const TemplateNameId *templId, + LookupScopePrivate *findSpecialization(const Template *baseTemplate, const TemplateNameId *templId, const TemplateNameIdTable &specializations, LookupScopePrivate *origin); @@ -1201,28 +1201,25 @@ static bool matchTypes(const FullySpecifiedType &instantiation, } LookupScopePrivate *LookupScopePrivate::findSpecialization( + const Template *baseTemplate, const TemplateNameId *templId, const TemplateNameIdTable &specializations, LookupScopePrivate *origin) { + Clone cloner(_factory->control().data()); for (TemplateNameIdTable::const_iterator cit = specializations.begin(); cit != specializations.end(); ++cit) { const TemplateNameId *specializationNameId = cit->first; const unsigned specializationTemplateArgumentCount = specializationNameId->templateArgumentCount(); - const unsigned initializationTemplateArgumentCount = templId->templateArgumentCount(); - // for now it works only when we have the same number of arguments in specialization - // and initialization(in future it should be more clever) - if (specializationTemplateArgumentCount != initializationTemplateArgumentCount) - continue; + Subst subst(_factory->control().data()); bool match = true; - for (unsigned i = 0; i < initializationTemplateArgumentCount && match; ++i) { + for (unsigned i = 0; i < specializationTemplateArgumentCount && match; ++i) { const FullySpecifiedType &specializationTemplateArgument = specializationNameId->templateArgumentAt(i); - FullySpecifiedType initializationTemplateArgument = templId->templateArgumentAt(i); - TypeResolver typeResolver(*_factory); - Scope *scope = 0; - typeResolver.resolve(&initializationTemplateArgument, &scope, origin ? origin->q : 0); + FullySpecifiedType initializationTemplateArgument = + _factory->resolveTemplateArgument(cloner, subst, origin ? origin->q : 0, + baseTemplate, templId, i); // specialization and initialization argument have to be a pointer // additionally type of pointer argument of specialization has to be namedType if (findTemplateArgument(dereference(specializationTemplateArgument), cit->second)) { @@ -1340,8 +1337,17 @@ LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScope // we found full specialization reference = cit->second; } else { + Template *baseTemplate = 0; + foreach (Symbol *s, reference->_symbols) { + if (Class *clazz = s->asClass()) + baseTemplate = clazz->enclosingTemplate(); + else if (ForwardClassDeclaration *forward = s->asForwardClassDeclaration()) + baseTemplate = forward->enclosingTemplate(); + if (baseTemplate) + break; + } if (LookupScopePrivate *specialization = - findSpecialization(templId, specializations, origin)) { + findSpecialization(baseTemplate, templId, specializations, origin)) { reference = specialization; if (Q_UNLIKELY(debug)) { Overview oo; @@ -2088,40 +2094,50 @@ bool CreateBindings::visit(ObjCMethod *) return false; } -void CreateBindings::initializeSubst(Clone &cloner, - Subst &subst, - LookupScope *origin, - Template *specialization, - const TemplateNameId *instantiation) +FullySpecifiedType CreateBindings::resolveTemplateArgument(Clone &cloner, + Subst &subst, + LookupScope *origin, + const Template *specialization, + const TemplateNameId *instantiation, + unsigned index) { - const unsigned argumentCountOfInitialization = instantiation->templateArgumentCount(); - const unsigned argumentCountOfSpecialization = specialization->templateParameterCount(); + FullySpecifiedType ty; + + const TypenameArgument *tParam + = specialization->templateParameterAt(index)->asTypenameArgument(); + if (!tParam) + return ty; + if (index < instantiation->templateArgumentCount()) + ty = instantiation->templateArgumentAt(index); + else + ty = cloner.type(tParam->type(), &subst); + + TypeResolver typeResolver(*this); + Scope *resolveScope = specialization->enclosingScope(); + typeResolver.resolve(&ty, &resolveScope, origin); const TemplateNameId *templSpecId = specialization->name()->asTemplateNameId(); const unsigned templSpecArgumentCount = templSpecId ? templSpecId->templateArgumentCount() : 0; - for (unsigned i = 0; i < argumentCountOfSpecialization; ++i) { - const TypenameArgument *tParam - = specialization->templateParameterAt(i)->asTypenameArgument(); - if (!tParam) - continue; - const Name *name = tParam->name(); - if (!name) - continue; + if (index < templSpecArgumentCount && templSpecId->templateArgumentAt(index)->isPointerType()) { + if (PointerType *pointerType = ty->asPointerType()) + ty = pointerType->elementType(); + } - FullySpecifiedType ty = (i < argumentCountOfInitialization) ? - instantiation->templateArgumentAt(i): - cloner.type(tParam->type(), &subst); + if (const Name *name = tParam->name()) + subst.bind(cloner.name(name, &subst), ty); + return ty; +} - TypeResolver typeResolver(*this); - Scope *resolveScope = specialization->enclosingScope(); - typeResolver.resolve(&ty, &resolveScope, origin); - if (i < templSpecArgumentCount && templSpecId->templateArgumentAt(i)->isPointerType()) { - if (PointerType *pointerType = ty->asPointerType()) - ty = pointerType->elementType(); - } +void CreateBindings::initializeSubst(Clone &cloner, + Subst &subst, + LookupScope *origin, + const Template *specialization, + const TemplateNameId *instantiation) +{ + const unsigned argumentCountOfSpecialization = specialization->templateParameterCount(); - subst.bind(cloner.name(name, &subst), ty); - } + for (unsigned i = 0; i < argumentCountOfSpecialization; ++i) + resolveTemplateArgument(cloner, subst, origin, specialization, instantiation, i); } } // namespace CPlusPlus |