summaryrefslogtreecommitdiff
path: root/src/libs/cplusplus/LookupContext.cpp
diff options
context:
space:
mode:
authorOrgad Shaneh <orgad.shaneh@audiocodes.com>2015-06-07 11:47:50 +0300
committerOrgad Shaneh <orgads@gmail.com>2015-06-09 14:18:17 +0000
commit97d3d9ac0946f3be0e036b70401352e3ddaeb8fc (patch)
tree3bba03e6e4aa9025e07cdfce94b52f45570b9c74 /src/libs/cplusplus/LookupContext.cpp
parent1c7e465c30bb0d46ec43fe571b9c6aa0e3499754 (diff)
downloadqt-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.cpp94
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