summaryrefslogtreecommitdiff
path: root/src/libs/cplusplus/LookupContext.cpp
diff options
context:
space:
mode:
authorOrgad Shaneh <orgad.shaneh@audiocodes.com>2015-03-30 22:13:44 +0300
committerOrgad Shaneh <orgads@gmail.com>2015-04-28 13:54:25 +0000
commitad4cb444fbfd1f3f4747a0988a196120d3a0c208 (patch)
tree966257fbdeb49f3a5ed1e445fb3cf62886159515 /src/libs/cplusplus/LookupContext.cpp
parentaa893918c1a51cb20c909a4c32e401c6d2d254c0 (diff)
downloadqt-creator-ad4cb444fbfd1f3f4747a0988a196120d3a0c208.tar.gz
C++: Fix specialization resolution for nested types
Use-cases: template<typename T> struct Traits { typedef typename T::pointer pointer; }; template<typename _Tp> struct Traits<_Tp*> { typedef _Tp *pointer; }; struct Foo { int bar; }; // 1 template<typename T> class Temp { protected: typedef Traits<T> TraitsT; public: typedef typename TraitsT::pointer pointer; pointer p; }; void func() { Temp<Foo *> t; t.p-> // complete } // 2 class Temp2 { protected: typedef Foo *FooPtr; typedef Traits<FooPtr> TraitsT; public: typedef typename TraitsT::pointer pointer; pointer p; }; void func2() { Temp2 t; t.p-> // complete } Task-number: QTCREATORBUG-14141 Change-Id: Id3459671117c0c81bcde7c9714b42750634c0225 Reviewed-by: Nikolai Kosjar <nikolai.kosjar@theqtcompany.com>
Diffstat (limited to 'src/libs/cplusplus/LookupContext.cpp')
-rw-r--r--src/libs/cplusplus/LookupContext.cpp89
1 files changed, 70 insertions, 19 deletions
diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp
index ced7dc5e64..93b576ffc7 100644
--- a/src/libs/cplusplus/LookupContext.cpp
+++ b/src/libs/cplusplus/LookupContext.cpp
@@ -33,6 +33,7 @@
#include "ResolveExpression.h"
#include "Overview.h"
#include "CppRewriter.h"
+#include "TypeResolver.h"
#include <cplusplus/CoreTypes.h>
#include <cplusplus/Symbols.h>
@@ -525,6 +526,7 @@ public:
~LookupScopePrivate();
typedef std::map<const Name *, LookupScopePrivate *, Name::Compare> Table;
+ typedef std::map<const Name *, Declaration *, Name::Compare> TypedefTable;
typedef std::map<const TemplateNameId *,
LookupScopePrivate *,
TemplateNameId::Compare> TemplateNameIdTable;
@@ -546,6 +548,7 @@ public:
void addTodo(Symbol *symbol);
void addSymbol(Symbol *symbol);
void addUnscopedEnum(Enum *e);
+ void addTypedef(const Name *identifier, Declaration *d);
void addUsing(LookupScope *u);
void addNestedType(const Name *alias, LookupScope *e);
@@ -561,11 +564,16 @@ public:
LookupScope *findBlock_helper(Block *block, ProcessedSet *processed,
bool searchInEnclosingScope);
+private:
+ LookupScopePrivate *findNestedType(const Name *name, LookupScopePrivate *origin);
+
LookupScopePrivate *nestedType(const Name *name, LookupScopePrivate *origin);
LookupScopePrivate *findSpecialization(const TemplateNameId *templId,
- const TemplateNameIdTable &specializations);
+ const TemplateNameIdTable &specializations,
+ LookupScopePrivate *origin);
+public:
LookupScope *q;
CreateBindings *_factory;
@@ -573,6 +581,7 @@ public:
QList<Symbol *> _symbols;
QList<LookupScope *> _usings;
Table _nestedScopes;
+ TypedefTable _typedefs;
QHash<Block *, LookupScope *> _blocks;
QList<Enum *> _enums;
QList<Symbol *> _todo;
@@ -589,9 +598,11 @@ public:
AlreadyConsideredClassContainer<Class> _alreadyConsideredClasses;
AlreadyConsideredClassContainer<TemplateNameId> _alreadyConsideredTemplates;
+ QSet<const Declaration *> _alreadyConsideredTypedefs;
Class *_rootClass;
const Name *_name; // For debug
+ bool _hasTypedefs;
};
class Instantiator
@@ -702,6 +713,7 @@ LookupScopePrivate::LookupScopePrivate(LookupScope *q, CreateBindings *factory,
, _instantiationOrigin(0)
, _rootClass(0)
, _name(0)
+ , _hasTypedefs(false)
{
Q_ASSERT(factory);
}
@@ -1136,7 +1148,7 @@ static LookupScopePrivate *findSpecializationWithMatchingTemplateArgument(
}
LookupScopePrivate *LookupScopePrivate::findSpecialization(
- const TemplateNameId *templId, const TemplateNameIdTable &specializations)
+ const TemplateNameId *templId, 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();
@@ -1152,8 +1164,11 @@ LookupScopePrivate *LookupScopePrivate::findSpecialization(
for (unsigned i = 0; i < initializationTemplateArgumentCount; ++i) {
const FullySpecifiedType &specializationTemplateArgument
= specializationNameId->templateArgumentAt(i);
- const FullySpecifiedType &initializationTemplateArgument
+ 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
@@ -1197,8 +1212,33 @@ LookupScopePrivate *LookupScopePrivate::findOrCreateNestedAnonymousType(
}
}
-LookupScopePrivate *LookupScopePrivate::nestedType(
- const Name *name, LookupScopePrivate *origin)
+LookupScopePrivate *LookupScopePrivate::findNestedType(const Name *name, LookupScopePrivate *origin)
+{
+ TypedefTable::const_iterator typedefit = _typedefs.find(name);
+ if (typedefit != _typedefs.end()) {
+ Declaration *decl = typedefit->second;
+ if (_alreadyConsideredTypedefs.contains(decl))
+ return 0;
+ _alreadyConsideredTypedefs.insert(decl);
+ if (const NamedType *namedTy = decl->type()->asNamedType()) {
+ if (LookupScope *e = q->lookupType(namedTy->name()))
+ return e->d;
+ if (origin) {
+ if (LookupScope *e = origin->q->lookupType(namedTy->name()))
+ return e->d;
+ }
+ }
+ _alreadyConsideredTypedefs.remove(decl);
+ }
+
+ auto it = _nestedScopes.find(name);
+ if (it != _nestedScopes.end())
+ return it->second;
+
+ return 0;
+}
+
+LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScopePrivate *origin)
{
Q_ASSERT(name != 0);
Q_ASSERT(name->isNameId() || name->isTemplateNameId() || name->isAnonymousNameId());
@@ -1208,13 +1248,11 @@ LookupScopePrivate *LookupScopePrivate::nestedType(
if (const AnonymousNameId *anonymousNameId = name->asAnonymousNameId())
return findOrCreateNestedAnonymousType(anonymousNameId);
- Table::const_iterator it = _nestedScopes.find(name);
- if (it == _nestedScopes.end())
+ LookupScopePrivate *reference = findNestedType(name, origin);
+ if (!reference)
return 0;
-
- LookupScopePrivate *reference = it->second;
- LookupScopePrivate *baseTemplateClassReference = reference;
reference->flush();
+ LookupScopePrivate *baseTemplateClassReference = reference;
const TemplateNameId *templId = name->asTemplateNameId();
if (templId) {
@@ -1254,10 +1292,9 @@ LookupScopePrivate *LookupScopePrivate::nestedType(
reference = cit->second;
} else {
LookupScopePrivate *specializationWithPointer
- = findSpecialization(templId, specializations);
+ = findSpecialization(templId, specializations, origin);
if (specializationWithPointer)
reference = specializationWithPointer;
- // TODO: find the best specialization(probably partial) for this instantiation
}
// let's instantiation be instantiation
nonConstTemplId->setIsSpecialization(false);
@@ -1340,6 +1377,9 @@ LookupScopePrivate *LookupScopePrivate::nestedType(
templId->templateArgumentAt(i):
cloner.type(tParam->type(), &subst);
+ TypeResolver typeResolver(*_factory);
+ Scope *scope = 0;
+ typeResolver.resolve(&ty, &scope, origin ? origin->q : 0);
if (i < templSpecArgumentCount
&& templSpecId->templateArgumentAt(i)->isPointerType()) {
if (PointerType *pointerType = ty->asPointerType())
@@ -1353,6 +1393,7 @@ LookupScopePrivate *LookupScopePrivate::nestedType(
instantiator.instantiate(reference, instantiation);
} else {
instantiation->_symbols.append(reference->_symbols);
+ instantiation->_typedefs = reference->_typedefs;
}
QHash<const Name*, unsigned> templParams;
@@ -1427,6 +1468,7 @@ LookupScopePrivate *LookupScopePrivate::nestedType(
} else {
instantiation->_nestedScopes = reference->_nestedScopes;
instantiation->_symbols.append(reference->_symbols);
+ instantiation->_typedefs = reference->_typedefs;
}
_alreadyConsideredTemplates.clear(templId);
@@ -1472,6 +1514,13 @@ void Instantiator::instantiate(LookupScopePrivate *lookupScope,
return;
_alreadyConsideredInstantiations.insert(lookupScope);
if (instantiation != lookupScope) {
+ auto typedefend = lookupScope->_typedefs.end();
+ for (auto typedefit = lookupScope->_typedefs.begin();
+ typedefit != typedefend;
+ ++typedefit) {
+ instantiation->_typedefs[typedefit->first] =
+ _cloner.symbol(typedefit->second, &_subst)->asDeclaration();
+ }
foreach (Symbol *s, lookupScope->_symbols) {
Symbol *clone = _cloner.symbol(s, &_subst);
if (!clone->enclosingScope()) // Not from the cache but just cloned.
@@ -1560,6 +1609,11 @@ void LookupScopePrivate::addUnscopedEnum(Enum *e)
_enums.append(e);
}
+void LookupScopePrivate::addTypedef(const Name *identifier, Declaration *d)
+{
+ _typedefs[identifier] = d;
+}
+
void LookupScopePrivate::addUsing(LookupScope *u)
{
_usings.append(u);
@@ -1783,17 +1837,13 @@ bool CreateBindings::visit(Enum *e)
bool CreateBindings::visit(Declaration *decl)
{
if (decl->isTypedef()) {
+ _currentLookupScope->d->_hasTypedefs = true;
FullySpecifiedType ty = decl->type();
const Identifier *typedefId = decl->identifier();
if (typedefId && ! (ty.isConst() || ty.isVolatile())) {
- if (const NamedType *namedTy = ty->asNamedType()) {
- if (LookupScope *e = _currentLookupScope->lookupType(namedTy->name())) {
- _currentLookupScope->d->addNestedType(decl->name(), e);
- } else if (false) {
- Overview oo;
- qDebug() << "found entity not found for" << oo.prettyName(namedTy->name());
- }
+ if (ty->isNamedType()) {
+ _currentLookupScope->d->addTypedef(typedefId, decl);
} else if (Class *klass = ty->asClassType()) {
if (const Identifier *nameId = decl->name()->asNameId()) {
LookupScope *binding
@@ -1849,6 +1899,7 @@ bool CreateBindings::visit(Block *block)
if (! _currentLookupScope->d->_blocks.empty()
|| ! _currentLookupScope->d->_nestedScopes.empty()
|| ! _currentLookupScope->d->_enums.empty()
+ || _currentLookupScope->d->_hasTypedefs
|| ! _currentLookupScope->d->_anonymouses.empty()) {
previous->d->_blocks[block] = binding;
_entities.append(binding);