summaryrefslogtreecommitdiff
path: root/src/libs/cplusplus/LookupContext.cpp
diff options
context:
space:
mode:
authorOrgad Shaneh <orgad.shaneh@audiocodes.com>2015-06-05 17:08:44 +0300
committerOrgad Shaneh <orgads@gmail.com>2015-06-09 14:17:38 +0000
commit997ab425ce5cb0797101acadcfe9217ea1aa6813 (patch)
tree26afdc648e7d51e50f7ab3bfb18544edf755d6a6 /src/libs/cplusplus/LookupContext.cpp
parentb61413fe0c4eb6048b6f924e2db68d670e3a5348 (diff)
downloadqt-creator-997ab425ce5cb0797101acadcfe9217ea1aa6813.tar.gz
C++: Improve accuracy in findSpecialization
* If a template type is specialized as a pointer, accept only pointers (of any type) * Same for references and arrays * Only if the specialized type is not part of the template, match it against the input. Fixes resolving of partial specialization with pointers. Use-cases: // 1 struct b {}; struct a : b {}; template<class X, class Y> struct s { float f; }; template<class X> struct s<X, b*> { int i; }; template<class X> struct s<X, a*> { char j; }; void f() { s<int, a*> var; var.j; // j not highlighted } // 2 template <typename T> struct Temp { T variable; }; template <typename T> struct Temp<T &> { T reference; }; void func() { Temp<int&> templ; templ.reference; // reference not highlighted } // 3 class false_type {}; class true_type {}; template<class T1, class T2> class and_type { false_type f; }; template<> class and_type<true_type, true_type> { true_type t; }; void func2() { and_type<true_type, false_type> a; a.f; // f not highlighted } Task-number: QTCREATORBUG-14036 Change-Id: Idee5e3f41d15c0772318d3837cbcd442cb80293a Reviewed-by: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com>
Diffstat (limited to 'src/libs/cplusplus/LookupContext.cpp')
-rw-r--r--src/libs/cplusplus/LookupContext.cpp87
1 files changed, 53 insertions, 34 deletions
diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp
index 574f7f6359..82e9186feb 100644
--- a/src/libs/cplusplus/LookupContext.cpp
+++ b/src/libs/cplusplus/LookupContext.cpp
@@ -1144,9 +1144,29 @@ LookupScope *LookupScopePrivate::lookupType_helper(
return 0;
}
-static LookupScopePrivate *findSpecializationWithMatchingTemplateArgument(
- const Name *argumentName, LookupScopePrivate *reference)
+static const NamedType *dereference(const FullySpecifiedType &type)
+{
+ FullySpecifiedType ty = type;
+ forever {
+ if (PointerType *pointer = ty->asPointerType())
+ ty = pointer->elementType();
+ else if (ReferenceType *reference = ty->asReferenceType())
+ ty = reference->elementType();
+ else if (ArrayType *array = ty->asArrayType())
+ ty = array->elementType();
+ else if (const NamedType *namedType = ty->asNamedType())
+ return namedType;
+ else
+ break;
+ }
+ return 0;
+}
+
+static bool findTemplateArgument(const NamedType *namedType, LookupScopePrivate *reference)
{
+ if (!namedType)
+ return false;
+ const Name *argumentName = namedType->name();
foreach (Symbol *s, reference->_symbols) {
if (Class *clazz = s->asClass()) {
if (Template *templateSpecialization = clazz->enclosingTemplate()) {
@@ -1157,14 +1177,28 @@ static LookupScopePrivate *findSpecializationWithMatchingTemplateArgument(
= templateSpecialization->templateParameterAt(i)->asTypenameArgument()) {
if (const Name *name = tParam->name()) {
if (compareName(name, argumentName))
- return reference;
+ return true;
}
}
}
}
}
}
- return 0;
+ return false;
+}
+
+static bool matchTypes(const FullySpecifiedType &instantiation,
+ const FullySpecifiedType &specialization)
+{
+ if (specialization.match(instantiation))
+ return true;
+ if (const NamedType *specName = specialization->asNamedType()) {
+ if (const NamedType *initName = instantiation->asNamedType()) {
+ if (specName->name()->identifier()->match(initName->name()->identifier()))
+ return true;
+ }
+ }
+ return false;
}
LookupScopePrivate *LookupScopePrivate::findSpecialization(
@@ -1172,7 +1206,6 @@ LookupScopePrivate *LookupScopePrivate::findSpecialization(
const TemplateNameIdTable &specializations,
LookupScopePrivate *origin)
{
- // we go through all specialization and try to find that one with template argument as pointer
for (TemplateNameIdTable::const_iterator cit = specializations.begin();
cit != specializations.end(); ++cit) {
const TemplateNameId *specializationNameId = cit->first;
@@ -1183,45 +1216,31 @@ LookupScopePrivate *LookupScopePrivate::findSpecialization(
// and initialization(in future it should be more clever)
if (specializationTemplateArgumentCount != initializationTemplateArgumentCount)
continue;
- for (unsigned i = 0; i < initializationTemplateArgumentCount; ++i) {
+ bool match = true;
+ for (unsigned i = 0; i < initializationTemplateArgumentCount && 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);
- PointerType *specPointer = specializationTemplateArgument.type()->asPointerType();
// specialization and initialization argument have to be a pointer
// additionally type of pointer argument of specialization has to be namedType
- if (specPointer && initializationTemplateArgument.type()->isPointerType()
- && specPointer->elementType().type()->isNamedType()) {
- return cit->second;
- }
-
- ArrayType *specArray = specializationTemplateArgument.type()->asArrayType();
- if (specArray && initializationTemplateArgument.type()->isArrayType()) {
- if (const NamedType *argumentNamedType
- = specArray->elementType().type()->asNamedType()) {
- if (const Name *argumentName = argumentNamedType->name()) {
- if (LookupScopePrivate *reference
- = findSpecializationWithMatchingTemplateArgument(
- argumentName, cit->second)) {
- return reference;
- }
- }
- }
- }
-
- if (specializationTemplateArgument == initializationTemplateArgument)
- return cit->second;
-
- if (const NamedType *specName = specializationTemplateArgument->asNamedType()) {
- if (const NamedType *initName = initializationTemplateArgument->asNamedType()) {
- if (specName->name()->identifier() == initName->name()->identifier())
- return cit->second;
- }
+ if (findTemplateArgument(dereference(specializationTemplateArgument), cit->second)) {
+ if (specializationTemplateArgument->isPointerType())
+ match = initializationTemplateArgument->isPointerType();
+ else if (specializationTemplateArgument->isReferenceType())
+ match = initializationTemplateArgument->isReferenceType();
+ else if (specializationTemplateArgument->isArrayType())
+ match = initializationTemplateArgument->isArrayType();
+ // Do not try exact match (typename T != class T {};)
+ } else {
+ // Real type specialization
+ match = matchTypes(initializationTemplateArgument, specializationTemplateArgument);
}
}
+ if (match)
+ return cit->second;
}
return 0;