From 0498fb68ff76adc39c8744ff354d5dcc5ab94da8 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Thu, 19 Nov 2015 13:49:26 +0100 Subject: C++: Revert lookup to 3.4.2 ...which was least buggy. The bugs fixed by the changes we revert here (highlighting/completion for code involving templates) were minor compared to ones we currently have. Those bugs will be addressed by the clang code model anyway. Relevant commits were collected via: $ cd ${QTC}/src/libs/cplusplus $ git log \ --no-merges \ --format=oneline \ v3.4.2..HEAD \ -- LookupContext.* ResolveExpression.* TypeResolver.* TypeOfExpression.* \ ../../plugins/cpptools/cppcompletion_test.cpp From this list the following were skipped due to irrelevance: 88c5b47e535d91f3db99882d5b50b263b46f223c # CppTools: Minor cleanup in completion tests e5255a1f5cac284c4f0d4a85203878c84da86e85 # CppTools: Add a test for ObjC not replacing dot with arrow 5b12c8d63a30e281274cdc267efabead2c736bd8 # CppTools: Support ObjC in member access operator tests 9fef4fb9ca4e65e20ff13b98bcf15e3c6232fdfb # CPlusPlus: Fix warnings about overriding visit(...) methods There were only minor conflicts while reverting those. This changes touches so many files because there were quite some cleanups and renames after the 3.4.2 release. Task-number: QTCREATORBUG-14889 Task-number: QTCREATORBUG-15211 Task-number: QTCREATORBUG-15213 Task-number: QTCREATORBUG-15257 Task-number: QTCREATORBUG-15264 Task-number: QTCREATORBUG-15291 Task-number: QTCREATORBUG-15329 Change-Id: I01f759f8f35ecb4228928a4f22086e279c1a5435 Reviewed-by: Marco Bubke --- src/libs/3rdparty/cplusplus/AST.h | 2 +- src/libs/3rdparty/cplusplus/Bind.cpp | 40 +- .../cplusplus/CPlusPlusForwardDeclarations.h | 1 - src/libs/3rdparty/cplusplus/Control.cpp | 16 +- src/libs/3rdparty/cplusplus/Control.h | 3 - src/libs/3rdparty/cplusplus/FullySpecifiedType.cpp | 6 - src/libs/3rdparty/cplusplus/FullySpecifiedType.h | 4 - src/libs/3rdparty/cplusplus/Matcher.cpp | 11 - src/libs/3rdparty/cplusplus/Matcher.h | 1 - src/libs/3rdparty/cplusplus/Names.h | 2 +- src/libs/3rdparty/cplusplus/Scope.cpp | 2 +- src/libs/3rdparty/cplusplus/Symbol.cpp | 3 - src/libs/3rdparty/cplusplus/Symbol.h | 7 +- src/libs/3rdparty/cplusplus/SymbolVisitor.h | 1 - src/libs/3rdparty/cplusplus/Symbols.cpp | 52 - src/libs/3rdparty/cplusplus/Symbols.h | 33 - src/libs/3rdparty/cplusplus/Templates.cpp | 20 +- src/libs/3rdparty/cplusplus/Templates.h | 2 - src/libs/3rdparty/cplusplus/Type.cpp | 3 - src/libs/3rdparty/cplusplus/Type.h | 3 - src/libs/3rdparty/cplusplus/TypeVisitor.h | 1 - src/libs/cplusplus/CppRewriter.cpp | 2 +- src/libs/cplusplus/CppRewriter.h | 4 +- .../cplusplus/DeprecatedGenTemplateInstance.cpp | 430 ++++++ src/libs/cplusplus/DeprecatedGenTemplateInstance.h | 63 + src/libs/cplusplus/FindUsages.cpp | 2 +- src/libs/cplusplus/LookupContext.cpp | 1363 +++++++++----------- src/libs/cplusplus/LookupContext.h | 209 ++- src/libs/cplusplus/LookupItem.cpp | 4 +- src/libs/cplusplus/LookupItem.h | 8 +- src/libs/cplusplus/ResolveExpression.cpp | 415 +++++- src/libs/cplusplus/ResolveExpression.h | 15 +- src/libs/cplusplus/TypeOfExpression.cpp | 8 +- src/libs/cplusplus/TypeOfExpression.h | 14 +- src/libs/cplusplus/TypeResolver.cpp | 262 ---- src/libs/cplusplus/TypeResolver.h | 68 - src/libs/cplusplus/cplusplus-lib.pri | 4 +- src/libs/cplusplus/cplusplus.qbs | 2 +- src/libs/qmljs/qmljsfindexportedcpptypes.cpp | 2 +- src/plugins/cppeditor/cppeditor.cpp | 2 +- src/plugins/cppeditor/cppelementevaluator.cpp | 12 +- .../cppeditor/cppfollowsymbolundercursor.cpp | 3 +- src/plugins/cppeditor/cppfunctiondecldeflink.cpp | 4 +- src/plugins/cppeditor/cppinsertvirtualmethods.cpp | 16 +- src/plugins/cppeditor/cppquickfixes.cpp | 24 +- .../cppeditor/cppvirtualfunctionassistprovider.cpp | 4 +- .../followsymbol_switchmethoddecldef_test.cpp | 16 +- src/plugins/cpptools/cppchecksymbols.cpp | 30 +- src/plugins/cpptools/cppchecksymbols.h | 6 +- src/plugins/cpptools/cppcompletion_test.cpp | 520 +------- src/plugins/cpptools/cppcompletionassist.cpp | 76 +- src/plugins/cpptools/cppcompletionassist.h | 8 +- src/plugins/cpptools/cpptoolsreuse.cpp | 2 +- src/plugins/cpptools/symbolfinder.cpp | 16 +- src/plugins/cpptools/symbolfinder.h | 3 +- .../cplusplus-mkvisitor/cplusplus-mkvisitor.cpp | 50 +- .../cplusplus/checksymbols/tst_checksymbols.cpp | 143 +- tests/auto/cplusplus/lookup/tst_lookup.cpp | 6 +- tests/auto/cplusplus/semantic/tst_semantic.cpp | 31 +- 59 files changed, 1836 insertions(+), 2224 deletions(-) create mode 100644 src/libs/cplusplus/DeprecatedGenTemplateInstance.cpp create mode 100644 src/libs/cplusplus/DeprecatedGenTemplateInstance.h delete mode 100644 src/libs/cplusplus/TypeResolver.cpp delete mode 100644 src/libs/cplusplus/TypeResolver.h diff --git a/src/libs/3rdparty/cplusplus/AST.h b/src/libs/3rdparty/cplusplus/AST.h index 8c3ceca968..bcdf043362 100644 --- a/src/libs/3rdparty/cplusplus/AST.h +++ b/src/libs/3rdparty/cplusplus/AST.h @@ -3349,7 +3349,7 @@ public: DeclarationAST *declaration; public: // annotations - Scope *symbol; + Template *symbol; public: TemplateDeclarationAST() diff --git a/src/libs/3rdparty/cplusplus/Bind.cpp b/src/libs/3rdparty/cplusplus/Bind.cpp index 0deb19dd54..63940d19dd 100644 --- a/src/libs/3rdparty/cplusplus/Bind.cpp +++ b/src/libs/3rdparty/cplusplus/Bind.cpp @@ -1917,19 +1917,9 @@ bool Bind::visit(SimpleDeclarationAST *ast) methodKey = methodKeyForInvokableToken(tokenKind(ast->qt_invokable_token)); // unsigned qt_invokable_token = ast->qt_invokable_token; - const ExpressionAST *declTypeExpression = 0; - bool isTypedef = false; FullySpecifiedType type; for (SpecifierListAST *it = ast->decl_specifier_list; it; it = it->next) { type = this->specifier(it->value, type); - if (type.isTypedef()) - isTypedef = true; - - type.setTypedef(isTypedef); - if (type.isDecltype()) { - if (DecltypeSpecifierAST *decltypeSpec = it->value->asDecltypeSpecifier()) - declTypeExpression = decltypeSpec->expression; - } } List **symbolTail = &ast->symbols; @@ -1985,8 +1975,6 @@ bool Bind::visit(SimpleDeclarationAST *ast) translationUnit()->error(location(declaratorId->name, ast->firstToken()), "auto-initialized variable must have an initializer"); else if (initializer) decl->setInitializer(asStringLiteral(initializer)); - } else if (declTy.isDecltype()) { - decl->setInitializer(asStringLiteral(declTypeExpression)); } if (_scope->isClass()) { @@ -2367,15 +2355,11 @@ bool Bind::visit(ParameterDeclarationAST *ast) bool Bind::visit(TemplateDeclarationAST *ast) { - Scope *scope = 0; - if (ast->less_token) - scope = control()->newTemplate(ast->firstToken(), 0); - else - scope = control()->newExplicitInstantiation(ast->firstToken(), 0); - scope->setStartOffset(tokenAt(ast->firstToken()).utf16charsBegin()); - scope->setEndOffset(tokenAt(ast->lastToken() - 1).utf16charsEnd()); - ast->symbol = scope; - Scope *previousScope = switchScope(scope); + Template *templ = control()->newTemplate(ast->firstToken(), 0); + templ->setStartOffset(tokenAt(ast->firstToken()).utf16charsBegin()); + templ->setEndOffset(tokenAt(ast->lastToken() - 1).utf16charsEnd()); + ast->symbol = templ; + Scope *previousScope = switchScope(templ); for (DeclarationListAST *it = ast->template_parameter_list; it; it = it->next) { this->declaration(it->value); @@ -2384,17 +2368,12 @@ bool Bind::visit(TemplateDeclarationAST *ast) this->declaration(ast->declaration); (void) switchScope(previousScope); - Symbol *decl = 0; - if (Template *templ = scope->asTemplate()) - decl = templ->declaration(); - else if (ExplicitInstantiation *inst = scope->asExplicitInstantiation()) - decl = inst->declaration(); - if (decl) { - scope->setSourceLocation(decl->sourceLocation(), translationUnit()); - scope->setName(decl->name()); + if (Symbol *decl = templ->declaration()) { + templ->setSourceLocation(decl->sourceLocation(), translationUnit()); + templ->setName(decl->name()); } - _scope->addMember(scope); + _scope->addMember(templ); return false; } @@ -3039,7 +3018,6 @@ bool Bind::visit(TypeofSpecifierAST *ast) bool Bind::visit(DecltypeSpecifierAST *ast) { _type = this->expression(ast->expression); - _type.setDecltype(true); return false; } diff --git a/src/libs/3rdparty/cplusplus/CPlusPlusForwardDeclarations.h b/src/libs/3rdparty/cplusplus/CPlusPlusForwardDeclarations.h index 54f9db96da..9b1c5a30cf 100644 --- a/src/libs/3rdparty/cplusplus/CPlusPlusForwardDeclarations.h +++ b/src/libs/3rdparty/cplusplus/CPlusPlusForwardDeclarations.h @@ -112,7 +112,6 @@ class Function; class Namespace; class NamespaceAlias; class Template; -class ExplicitInstantiation; class BaseClass; class Block; class Class; diff --git a/src/libs/3rdparty/cplusplus/Control.cpp b/src/libs/3rdparty/cplusplus/Control.cpp index 463a2f88f6..afdd679056 100644 --- a/src/libs/3rdparty/cplusplus/Control.cpp +++ b/src/libs/3rdparty/cplusplus/Control.cpp @@ -366,16 +366,9 @@ public: Template *newTemplate(unsigned sourceLocation, const Name *name) { - Template *templ = new Template(translationUnit, sourceLocation, name); - symbols.push_back(templ); - return templ; - } - - ExplicitInstantiation *newExplicitInstantiation(unsigned sourceLocation, const Name *name) - { - ExplicitInstantiation *inst = new ExplicitInstantiation(translationUnit, sourceLocation, name); - symbols.push_back(inst); - return inst; + Template *ns = new Template(translationUnit, sourceLocation, name); + symbols.push_back(ns); + return ns; } NamespaceAlias *newNamespaceAlias(unsigned sourceLocation, const Name *name) @@ -699,9 +692,6 @@ Namespace *Control::newNamespace(unsigned sourceLocation, const Name *name) Template *Control::newTemplate(unsigned sourceLocation, const Name *name) { return d->newTemplate(sourceLocation, name); } -ExplicitInstantiation *Control::newExplicitInstantiation(unsigned sourceLocation, const Name *name) -{ return d->newExplicitInstantiation(sourceLocation, name); } - NamespaceAlias *Control::newNamespaceAlias(unsigned sourceLocation, const Name *name) { return d->newNamespaceAlias(sourceLocation, name); } diff --git a/src/libs/3rdparty/cplusplus/Control.h b/src/libs/3rdparty/cplusplus/Control.h index bb2bf9cd10..85b8c3d3d7 100644 --- a/src/libs/3rdparty/cplusplus/Control.h +++ b/src/libs/3rdparty/cplusplus/Control.h @@ -120,9 +120,6 @@ public: /// Creates a new Template symbol. Template *newTemplate(unsigned sourceLocation, const Name *name = 0); - /// Creates a new ExplicitInstantiation symbol. - ExplicitInstantiation *newExplicitInstantiation(unsigned sourceLocation, const Name *name = 0); - /// Creates a new Namespace symbol. NamespaceAlias *newNamespaceAlias(unsigned sourceLocation, const Name *name = 0); diff --git a/src/libs/3rdparty/cplusplus/FullySpecifiedType.cpp b/src/libs/3rdparty/cplusplus/FullySpecifiedType.cpp index ea88140314..f78e4e9338 100644 --- a/src/libs/3rdparty/cplusplus/FullySpecifiedType.cpp +++ b/src/libs/3rdparty/cplusplus/FullySpecifiedType.cpp @@ -100,12 +100,6 @@ bool FullySpecifiedType::isAuto() const void FullySpecifiedType::setAuto(bool isAuto) { f._isAuto = isAuto; } -bool FullySpecifiedType::isDecltype() const -{ return f._isDecltype; } - -void FullySpecifiedType::setDecltype(bool isDecltype) -{ f._isDecltype = isDecltype; } - bool FullySpecifiedType::isRegister() const { return f._isRegister; } diff --git a/src/libs/3rdparty/cplusplus/FullySpecifiedType.h b/src/libs/3rdparty/cplusplus/FullySpecifiedType.h index 4c7a21ddc3..8f20018465 100644 --- a/src/libs/3rdparty/cplusplus/FullySpecifiedType.h +++ b/src/libs/3rdparty/cplusplus/FullySpecifiedType.h @@ -58,9 +58,6 @@ public: bool isAuto() const; void setAuto(bool isAuto); - bool isDecltype() const; - void setDecltype(bool isDecltype); - bool isRegister() const; void setRegister(bool isRegister); @@ -128,7 +125,6 @@ private: // storage class specifiers unsigned _isFriend: 1; unsigned _isAuto: 1; - unsigned _isDecltype: 1; unsigned _isRegister: 1; unsigned _isStatic: 1; unsigned _isExtern: 1; diff --git a/src/libs/3rdparty/cplusplus/Matcher.cpp b/src/libs/3rdparty/cplusplus/Matcher.cpp index 379ed59586..7a3c21cafc 100644 --- a/src/libs/3rdparty/cplusplus/Matcher.cpp +++ b/src/libs/3rdparty/cplusplus/Matcher.cpp @@ -218,17 +218,6 @@ bool Matcher::match(const Template *type, const Template *otherType) return true; } -bool Matcher::match(const ExplicitInstantiation *type, const ExplicitInstantiation *otherType) -{ - if (type == otherType) - return true; - - if (! Matcher::match(type->name(), otherType->name(), this)) - return false; - - return true; -} - bool Matcher::match(const ForwardClassDeclaration *type, const ForwardClassDeclaration *otherType) { if (type == otherType) diff --git a/src/libs/3rdparty/cplusplus/Matcher.h b/src/libs/3rdparty/cplusplus/Matcher.h index 4d2b40b64d..1a9d9d3511 100644 --- a/src/libs/3rdparty/cplusplus/Matcher.h +++ b/src/libs/3rdparty/cplusplus/Matcher.h @@ -61,7 +61,6 @@ public: virtual bool match(const Enum *type, const Enum *otherType); virtual bool match(const Namespace *type, const Namespace *otherType); virtual bool match(const Template *type, const Template *otherType); - virtual bool match(const ExplicitInstantiation *type, const ExplicitInstantiation *otherType); virtual bool match(const ForwardClassDeclaration *type, const ForwardClassDeclaration *otherType); virtual bool match(const Class *type, const Class *otherType); virtual bool match(const ObjCClass *type, const ObjCClass *otherType); diff --git a/src/libs/3rdparty/cplusplus/Names.h b/src/libs/3rdparty/cplusplus/Names.h index 7b49190f8e..33f40d523d 100644 --- a/src/libs/3rdparty/cplusplus/Names.h +++ b/src/libs/3rdparty/cplusplus/Names.h @@ -100,7 +100,7 @@ public: TemplateArgumentIterator firstTemplateArgument() const { return _templateArguments.begin(); } TemplateArgumentIterator lastTemplateArgument() const { return _templateArguments.end(); } bool isSpecialization() const { return _isSpecialization; } - // this is temporary solution needed in LookupScope::nestedType + // this is temporary solution needed in ClassOrNamespace::nestedType // when we try to find correct specialization for instantiation void setIsSpecialization(bool isSpecialization) { _isSpecialization = isSpecialization; } diff --git a/src/libs/3rdparty/cplusplus/Scope.cpp b/src/libs/3rdparty/cplusplus/Scope.cpp index 783eff77ae..406a794c7e 100644 --- a/src/libs/3rdparty/cplusplus/Scope.cpp +++ b/src/libs/3rdparty/cplusplus/Scope.cpp @@ -215,7 +215,7 @@ unsigned SymbolTable::symbolCount() const Symbol *SymbolTable::symbolAt(unsigned index) const { - if (! _symbols || index >= symbolCount()) + if (! _symbols) return 0; return _symbols[index]; } diff --git a/src/libs/3rdparty/cplusplus/Symbol.cpp b/src/libs/3rdparty/cplusplus/Symbol.cpp index 0ddd4ffbb2..ae20b14bb7 100644 --- a/src/libs/3rdparty/cplusplus/Symbol.cpp +++ b/src/libs/3rdparty/cplusplus/Symbol.cpp @@ -361,9 +361,6 @@ bool Symbol::isNamespace() const bool Symbol::isTemplate() const { return asTemplate() != 0; } -bool Symbol::isExplicitInstantiation() const -{ return asExplicitInstantiation() != 0; } - bool Symbol::isClass() const { return asClass() != 0; } diff --git a/src/libs/3rdparty/cplusplus/Symbol.h b/src/libs/3rdparty/cplusplus/Symbol.h index cbed45f461..919268b14b 100644 --- a/src/libs/3rdparty/cplusplus/Symbol.h +++ b/src/libs/3rdparty/cplusplus/Symbol.h @@ -135,7 +135,7 @@ public: /// Returns true if this Symbol is an Enum. bool isEnum() const; - /// Returns true if this Symbol is a Function. + /// Returns true if this Symbol is an Function. bool isFunction() const; /// Returns true if this Symbol is a Namespace. @@ -144,9 +144,6 @@ public: /// Returns true if this Symbol is a Template. bool isTemplate() const; - /// Returns true if this Symbol is an ExplicitInstantiation. - bool isExplicitInstantiation() const; - /// Returns true if this Symbol is a Class. bool isClass() const; @@ -206,7 +203,6 @@ public: virtual const Function *asFunction() const { return 0; } virtual const Namespace *asNamespace() const { return 0; } virtual const Template *asTemplate() const { return 0; } - virtual const ExplicitInstantiation *asExplicitInstantiation() const { return 0; } virtual const NamespaceAlias *asNamespaceAlias() const { return 0; } virtual const Class *asClass() const { return 0; } virtual const Block *asBlock() const { return 0; } @@ -233,7 +229,6 @@ public: virtual Function *asFunction() { return 0; } virtual Namespace *asNamespace() { return 0; } virtual Template *asTemplate() { return 0; } - virtual ExplicitInstantiation *asExplicitInstantiation() { return 0; } virtual NamespaceAlias *asNamespaceAlias() { return 0; } virtual Class *asClass() { return 0; } virtual Block *asBlock() { return 0; } diff --git a/src/libs/3rdparty/cplusplus/SymbolVisitor.h b/src/libs/3rdparty/cplusplus/SymbolVisitor.h index 5331525e9f..4311672eca 100644 --- a/src/libs/3rdparty/cplusplus/SymbolVisitor.h +++ b/src/libs/3rdparty/cplusplus/SymbolVisitor.h @@ -51,7 +51,6 @@ public: virtual bool visit(Function *) { return true; } virtual bool visit(Namespace *) { return true; } virtual bool visit(Template *) { return true; } - virtual bool visit(ExplicitInstantiation *) { return true; } virtual bool visit(Class *) { return true; } virtual bool visit(Block *) { return true; } virtual bool visit(ForwardClassDeclaration *) { return true; } diff --git a/src/libs/3rdparty/cplusplus/Symbols.cpp b/src/libs/3rdparty/cplusplus/Symbols.cpp index 3c632f1cd7..f8a8440c09 100644 --- a/src/libs/3rdparty/cplusplus/Symbols.cpp +++ b/src/libs/3rdparty/cplusplus/Symbols.cpp @@ -481,12 +481,10 @@ void Enum::visitSymbol0(SymbolVisitor *visitor) Template::Template(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name) : Scope(translationUnit, sourceLocation, name) - , _isExplicitInstantiation(false) { } Template::Template(Clone *clone, Subst *subst, Template *original) : Scope(clone, subst, original) - , _isExplicitInstantiation(original->_isExplicitInstantiation) { } Template::~Template() @@ -539,56 +537,6 @@ bool Template::match0(const Type *otherType, Matcher *matcher) const return false; } -ExplicitInstantiation::ExplicitInstantiation(TranslationUnit *translationUnit, - unsigned sourceLocation, const Name *name) - : Scope(translationUnit, sourceLocation, name) -{ } - -ExplicitInstantiation::ExplicitInstantiation(Clone *clone, Subst *subst, ExplicitInstantiation *original) - : Scope(clone, subst, original) -{ } - -ExplicitInstantiation::~ExplicitInstantiation() -{ } - -Symbol *ExplicitInstantiation::declaration() const -{ - if (isEmpty()) - return 0; - - if (Symbol *s = memberAt(memberCount() - 1)) { - if (s->isClass() || s->isForwardClassDeclaration() || - s->isTemplate() || s->isExplicitInstantiation() || - s->isFunction() || s->isDeclaration()) { - return s; - } - } - - return 0; -} - -FullySpecifiedType ExplicitInstantiation::type() const -{ return FullySpecifiedType(const_cast(this)); } - -void ExplicitInstantiation::visitSymbol0(SymbolVisitor *visitor) -{ - if (visitor->visit(this)) { - for (unsigned i = 0; i < memberCount(); ++i) { - visitSymbol(memberAt(i), visitor); - } - } -} - -void ExplicitInstantiation::accept0(TypeVisitor *visitor) -{ visitor->visit(this); } - -bool ExplicitInstantiation::match0(const Type *otherType, Matcher *matcher) const -{ - if (const ExplicitInstantiation *otherTy = otherType->asExplicitInstantiationType()) - return matcher->match(this, otherTy); - return false; -} - Namespace::Namespace(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name) : Scope(translationUnit, sourceLocation, name) , _isInline(false) diff --git a/src/libs/3rdparty/cplusplus/Symbols.h b/src/libs/3rdparty/cplusplus/Symbols.h index f2d92c23f2..257bdb8682 100644 --- a/src/libs/3rdparty/cplusplus/Symbols.h +++ b/src/libs/3rdparty/cplusplus/Symbols.h @@ -423,41 +423,8 @@ protected: virtual void visitSymbol0(SymbolVisitor *visitor); virtual void accept0(TypeVisitor *visitor); virtual bool match0(const Type *otherType, Matcher *matcher) const; - -private: - bool _isExplicitInstantiation; }; -class CPLUSPLUS_EXPORT ExplicitInstantiation : public Scope, public Type -{ -public: - ExplicitInstantiation(TranslationUnit *translationUnit, unsigned sourceLocation, const Name *name); - ExplicitInstantiation(Clone *clone, Subst *subst, ExplicitInstantiation *original); - virtual ~ExplicitInstantiation(); - - Symbol *declaration() const; - - // Symbol's interface - virtual FullySpecifiedType type() const; - - virtual const ExplicitInstantiation *asExplicitInstantiation() const - { return this; } - - virtual ExplicitInstantiation *asExplicitInstantiation() - { return this; } - - // Type's interface - virtual const ExplicitInstantiation *asExplicitInstantiationType() const - { return this; } - - virtual ExplicitInstantiation *asExplicitInstantiationType() - { return this; } - -protected: - virtual void visitSymbol0(SymbolVisitor *visitor); - virtual void accept0(TypeVisitor *visitor); - virtual bool match0(const Type *otherType, Matcher *matcher) const; -}; class CPLUSPLUS_EXPORT Namespace: public Scope, public Type { diff --git a/src/libs/3rdparty/cplusplus/Templates.cpp b/src/libs/3rdparty/cplusplus/Templates.cpp index 41e462a3b8..3b8ae9a23f 100644 --- a/src/libs/3rdparty/cplusplus/Templates.cpp +++ b/src/libs/3rdparty/cplusplus/Templates.cpp @@ -125,12 +125,6 @@ void CloneType::visit(Template *type) _type = templ; } -void CloneType::visit(ExplicitInstantiation *type) -{ - ExplicitInstantiation *inst = _clone->symbol(type, _subst)->asExplicitInstantiation(); - _type = inst; -} - void CloneType::visit(Class *type) { Class *klass = _clone->symbol(type, _subst)->asClass(); @@ -194,8 +188,10 @@ Symbol *CloneSymbol::cloneSymbol(Symbol *symbol, Subst *subst) SymbolSubstPair symbolSubstPair = std::make_pair(symbol, subst); auto it = _cache.find(symbolSubstPair); - if (it != _cache.end()) - return it->second; + if (it != _cache.end()) { + if (it->second->enclosingScope() == symbol->enclosingScope()) + return it->second; + } Symbol *r = 0; std::swap(_subst, subst); @@ -297,14 +293,6 @@ bool CloneSymbol::visit(Template *symbol) return false; } -bool CloneSymbol::visit(ExplicitInstantiation *symbol) -{ - ExplicitInstantiation *inst = new ExplicitInstantiation(_clone, _subst, symbol); - _symbol = inst; - _control->addSymbol(inst); - return false; -} - bool CloneSymbol::visit(Class *symbol) { Class *klass = new Class(_clone, _subst, symbol); diff --git a/src/libs/3rdparty/cplusplus/Templates.h b/src/libs/3rdparty/cplusplus/Templates.h index e39f79a7a6..9db69084f7 100644 --- a/src/libs/3rdparty/cplusplus/Templates.h +++ b/src/libs/3rdparty/cplusplus/Templates.h @@ -85,7 +85,6 @@ protected: virtual void visit(Function *type); virtual void visit(Namespace *type); virtual void visit(Template *type); - virtual void visit(ExplicitInstantiation *type); virtual void visit(Class *type); virtual void visit(Enum *type); virtual void visit(ForwardClassDeclaration *type); @@ -153,7 +152,6 @@ protected: virtual bool visit(Function *symbol); virtual bool visit(Namespace *symbol); virtual bool visit(Template *symbol); - virtual bool visit(ExplicitInstantiation *symbol); virtual bool visit(Class *symbol); virtual bool visit(Block *symbol); virtual bool visit(ForwardClassDeclaration *symbol); diff --git a/src/libs/3rdparty/cplusplus/Type.cpp b/src/libs/3rdparty/cplusplus/Type.cpp index 69ffb5030a..bad4d42eeb 100644 --- a/src/libs/3rdparty/cplusplus/Type.cpp +++ b/src/libs/3rdparty/cplusplus/Type.cpp @@ -68,9 +68,6 @@ bool Type::isNamespaceType() const bool Type::isTemplateType() const { return asTemplateType() != 0; } -bool Type::isExplicitInstantiationType() const -{ return asExplicitInstantiationType() != 0; } - bool Type::isClassType() const { return asClassType() != 0; } diff --git a/src/libs/3rdparty/cplusplus/Type.h b/src/libs/3rdparty/cplusplus/Type.h index 2661628f76..958ba15efd 100644 --- a/src/libs/3rdparty/cplusplus/Type.h +++ b/src/libs/3rdparty/cplusplus/Type.h @@ -43,7 +43,6 @@ public: bool isFunctionType() const; bool isNamespaceType() const; bool isTemplateType() const; - bool isExplicitInstantiationType() const; bool isClassType() const; bool isEnumType() const; bool isForwardClassDeclarationType() const; @@ -65,7 +64,6 @@ public: virtual const Function *asFunctionType() const { return 0; } virtual const Namespace *asNamespaceType() const { return 0; } virtual const Template *asTemplateType() const { return 0; } - virtual const ExplicitInstantiation *asExplicitInstantiationType() const { return 0; } virtual const Class *asClassType() const { return 0; } virtual const Enum *asEnumType() const { return 0; } virtual const ForwardClassDeclaration *asForwardClassDeclarationType() const { return 0; } @@ -87,7 +85,6 @@ public: virtual Function *asFunctionType() { return 0; } virtual Namespace *asNamespaceType() { return 0; } virtual Template *asTemplateType() { return 0; } - virtual ExplicitInstantiation *asExplicitInstantiationType() { return 0; } virtual Class *asClassType() { return 0; } virtual Enum *asEnumType() { return 0; } virtual ForwardClassDeclaration *asForwardClassDeclarationType() { return 0; } diff --git a/src/libs/3rdparty/cplusplus/TypeVisitor.h b/src/libs/3rdparty/cplusplus/TypeVisitor.h index 86568dcebc..b3a24b1572 100644 --- a/src/libs/3rdparty/cplusplus/TypeVisitor.h +++ b/src/libs/3rdparty/cplusplus/TypeVisitor.h @@ -51,7 +51,6 @@ public: virtual void visit(Function *) {} virtual void visit(Namespace *) {} virtual void visit(Template *) {} - virtual void visit(ExplicitInstantiation *) {} virtual void visit(Class *) {} virtual void visit(Enum *) {} virtual void visit(ForwardClassDeclaration *) {} diff --git a/src/libs/cplusplus/CppRewriter.cpp b/src/libs/cplusplus/CppRewriter.cpp index fa66e3b4e3..63eadd912c 100644 --- a/src/libs/cplusplus/CppRewriter.cpp +++ b/src/libs/cplusplus/CppRewriter.cpp @@ -379,7 +379,7 @@ FullySpecifiedType SubstitutionMap::apply(const Name *name, Rewrite *) const } -UseMinimalNames::UseMinimalNames(LookupScope *target) +UseMinimalNames::UseMinimalNames(ClassOrNamespace *target) : _target(target) { diff --git a/src/libs/cplusplus/CppRewriter.h b/src/libs/cplusplus/CppRewriter.h index cb307a9401..cc68f662a5 100644 --- a/src/libs/cplusplus/CppRewriter.h +++ b/src/libs/cplusplus/CppRewriter.h @@ -89,13 +89,13 @@ private: class CPLUSPLUS_EXPORT UseMinimalNames: public Substitution { public: - UseMinimalNames(LookupScope *target); + UseMinimalNames(ClassOrNamespace *target); virtual ~UseMinimalNames(); virtual FullySpecifiedType apply(const Name *name, Rewrite *rewrite) const; private: - LookupScope *_target; + ClassOrNamespace *_target; }; class CPLUSPLUS_EXPORT UseQualifiedNames: public UseMinimalNames diff --git a/src/libs/cplusplus/DeprecatedGenTemplateInstance.cpp b/src/libs/cplusplus/DeprecatedGenTemplateInstance.cpp new file mode 100644 index 0000000000..e037f87c58 --- /dev/null +++ b/src/libs/cplusplus/DeprecatedGenTemplateInstance.cpp @@ -0,0 +1,430 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "DeprecatedGenTemplateInstance.h" +#include "Overview.h" + +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace CPlusPlus; + +namespace { + +class ApplySubstitution +{ +public: + ApplySubstitution(Control *control, Symbol *symbol, const DeprecatedGenTemplateInstance::Substitution &substitution); + ~ApplySubstitution(); + + inline Control *control() const { return _control; } + + FullySpecifiedType apply(const Name *name); + FullySpecifiedType apply(const FullySpecifiedType &type); + + int findSubstitution(const Identifier *id) const; + FullySpecifiedType applySubstitution(int index) const; + +private: + class ApplyToType: protected TypeVisitor + { + public: + ApplyToType(ApplySubstitution *q) + : q(q) {} + + FullySpecifiedType operator()(const FullySpecifiedType &ty) + { + FullySpecifiedType previousType = switchType(ty); + accept(ty.type()); + return switchType(previousType); + } + + protected: + using TypeVisitor::visit; + + Control *control() const + { return q->control(); } + + FullySpecifiedType switchType(const FullySpecifiedType &type) + { + FullySpecifiedType previousType = _type; + _type = type; + return previousType; + } + + virtual void visit(VoidType *) + { + // nothing to do + } + + virtual void visit(IntegerType *) + { + // nothing to do + } + + virtual void visit(FloatType *) + { + // nothing to do + } + + virtual void visit(PointerToMemberType *) + { + qDebug() << Q_FUNC_INFO; // ### TODO + } + + virtual void visit(PointerType *ptrTy) + { + _type.setType(control()->pointerType(q->apply(ptrTy->elementType()))); + } + + virtual void visit(ReferenceType *refTy) + { + _type.setType(control()->referenceType(q->apply(refTy->elementType()), refTy->isRvalueReference())); + } + + virtual void visit(ArrayType *arrayTy) + { + _type.setType(control()->arrayType(q->apply(arrayTy->elementType()), arrayTy->size())); + } + + virtual void visit(NamedType *ty) + { + FullySpecifiedType n = q->apply(ty->name()); + _type.setType(n.type()); + } + + virtual void visit(Function *funTy) + { + Function *fun = control()->newFunction(/*sourceLocation=*/ 0, funTy->name()); + fun->setEnclosingScope(funTy->enclosingScope()); + fun->setConst(funTy->isConst()); + fun->setVolatile(funTy->isVolatile()); + fun->setVirtual(funTy->isVirtual()); + fun->setOverride(funTy->isOverride()); + fun->setFinal(funTy->isFinal()); + fun->setAmbiguous(funTy->isAmbiguous()); + fun->setVariadic(funTy->isVariadic()); + + fun->setReturnType(q->apply(funTy->returnType())); + + for (unsigned i = 0, argc = funTy->argumentCount(); i < argc; ++i) { + Argument *originalArgument = funTy->argumentAt(i)->asArgument(); + Argument *arg = control()->newArgument(/*sourceLocation*/ 0, + originalArgument->name()); + + arg->setType(q->apply(originalArgument->type())); + arg->setInitializer(originalArgument->initializer()); + fun->addMember(arg); + } + + _type.setType(fun); + } + + virtual void visit(Namespace *) + { + qDebug() << Q_FUNC_INFO; + } + + virtual void visit(Class *) + { + qDebug() << Q_FUNC_INFO; + } + + virtual void visit(Enum *) + { + qDebug() << Q_FUNC_INFO; + } + + virtual void visit(ForwardClassDeclaration *) + { + qDebug() << Q_FUNC_INFO; + } + + virtual void visit(ObjCClass *) + { + qDebug() << Q_FUNC_INFO; + } + + virtual void visit(ObjCProtocol *) + { + qDebug() << Q_FUNC_INFO; + } + + virtual void visit(ObjCMethod *) + { + qDebug() << Q_FUNC_INFO; + } + + virtual void visit(ObjCForwardClassDeclaration *) + { + qDebug() << Q_FUNC_INFO; + } + + virtual void visit(ObjCForwardProtocolDeclaration *) + { + qDebug() << Q_FUNC_INFO; + } + + private: + ApplySubstitution *q; + FullySpecifiedType _type; + QHash _processed; + }; + + class ApplyToName: protected NameVisitor + { + public: + ApplyToName(ApplySubstitution *q): q(q) {} + + FullySpecifiedType operator()(const Name *name) + { + FullySpecifiedType previousType = switchType(FullySpecifiedType()); + accept(name); + return switchType(previousType); + } + + protected: + Control *control() const + { return q->control(); } + + int findSubstitution(const Identifier *id) const + { return q->findSubstitution(id); } + + FullySpecifiedType applySubstitution(int index) const + { return q->applySubstitution(index); } + + FullySpecifiedType switchType(const FullySpecifiedType &type) + { + FullySpecifiedType previousType = _type; + _type = type; + return previousType; + } + + virtual void visit(const Identifier *name) + { + int index = findSubstitution(name->identifier()); + + if (index != -1) + _type = applySubstitution(index); + + else + _type = control()->namedType(name); + } + + virtual void visit(const TemplateNameId *name) + { + QVarLengthArray arguments(name->templateArgumentCount()); + for (unsigned i = 0; i < name->templateArgumentCount(); ++i) { + FullySpecifiedType argTy = name->templateArgumentAt(i); + arguments[i] = q->apply(argTy); + } + + const TemplateNameId *templId = control()->templateNameId(name->identifier(), + name->isSpecialization(), + arguments.data(), + arguments.size()); + _type = control()->namedType(templId); + } + + const Name *instantiate(const Name *name) + { + if (! name) + return name; + + if (const Identifier *nameId = name->asNameId()) { + const Identifier *id = control()->identifier(nameId->chars(), nameId->size()); + return id; + + } else if (const TemplateNameId *templId = name->asTemplateNameId()) { + QVarLengthArray arguments(templId->templateArgumentCount()); + for (unsigned templateArgIndex = 0; templateArgIndex < templId->templateArgumentCount(); + ++templateArgIndex) { + FullySpecifiedType argTy = templId->templateArgumentAt(templateArgIndex); + arguments[templateArgIndex] = q->apply(argTy); + } + const Identifier *id = control()->identifier(templId->identifier()->chars(), + templId->identifier()->size()); + return control()->templateNameId(id, templId->isSpecialization(), arguments.data(), + arguments.size()); + + } else if (const QualifiedNameId *qq = name->asQualifiedNameId()) { + const Name *base = instantiate(qq->base()); + const Name *name = instantiate(qq->name()); + + return control()->qualifiedNameId(base, name); + + } else if (const OperatorNameId *op = name->asOperatorNameId()) { + return control()->operatorNameId(op->kind()); + + } else if (const ConversionNameId *c = name->asConversionNameId()) { + FullySpecifiedType ty = q->apply(c->type()); + return control()->conversionNameId(ty); + + } + + return 0; + } + + virtual void visit(const QualifiedNameId *name) + { + if (const Name *n = instantiate(name)) + _type = control()->namedType(n); + } + + virtual void visit(const DestructorNameId *name) + { + Overview oo; + qWarning() << "ignored name:" << oo.prettyName(name); + } + + virtual void visit(const OperatorNameId *name) + { + Overview oo; + qWarning() << "ignored name:" << oo.prettyName(name); + } + + virtual void visit(const ConversionNameId *name) + { + Overview oo; + qWarning() << "ignored name:" << oo.prettyName(name); + } + + virtual void visit(const SelectorNameId *name) + { + Overview oo; + qWarning() << "ignored name:" << oo.prettyName(name); + } + + private: + ApplySubstitution *q; + FullySpecifiedType _type; + }; + +public: // attributes + Control *_control; + Symbol *symbol; + DeprecatedGenTemplateInstance::Substitution substitution; + ApplyToType applyToType; + ApplyToName applyToName; +}; + +ApplySubstitution::ApplySubstitution(Control *control, Symbol *symbol, + const DeprecatedGenTemplateInstance::Substitution &substitution) + : _control(control), symbol(symbol), + substitution(substitution), + applyToType(this), applyToName(this) +{ } + +ApplySubstitution::~ApplySubstitution() +{ +} + +FullySpecifiedType ApplySubstitution::apply(const Name *name) +{ + FullySpecifiedType ty = applyToName(name); + return ty; +} + +FullySpecifiedType ApplySubstitution::apply(const FullySpecifiedType &type) +{ + FullySpecifiedType ty = applyToType(type); + return ty; +} + +int ApplySubstitution::findSubstitution(const Identifier *id) const +{ + Q_ASSERT(id != 0); + + for (int index = 0; index < substitution.size(); ++index) { + QPair s = substitution.at(index); + + if (id->match(s.first)) + return index; + } + + return -1; +} + +FullySpecifiedType ApplySubstitution::applySubstitution(int index) const +{ + Q_ASSERT(index != -1); + Q_ASSERT(index < substitution.size()); + + return substitution.at(index).second; +} + +} // end of anonymous namespace + +DeprecatedGenTemplateInstance::DeprecatedGenTemplateInstance(QSharedPointer control, const Substitution &substitution) + : _control(control), + _substitution(substitution) +{ } + +FullySpecifiedType DeprecatedGenTemplateInstance::gen(Symbol *symbol) +{ + ApplySubstitution o(_control.data(), symbol, _substitution); + return o.apply(symbol->type()); +} + +FullySpecifiedType DeprecatedGenTemplateInstance::instantiate(const Name *className, Symbol *candidate, + QSharedPointer control) +{ + if (className) { + if (const TemplateNameId *templId = className->asTemplateNameId()) { + if (Template *templ = candidate->enclosingTemplate()) { + DeprecatedGenTemplateInstance::Substitution subst; + + for (unsigned i = 0; i < templId->templateArgumentCount(); ++i) { + FullySpecifiedType templArgTy = templId->templateArgumentAt(i); + + if (i < templ->templateParameterCount()) { + const Name *templArgName = templ->templateParameterAt(i)->name(); + + if (templArgName && templArgName->identifier()) { + const Identifier *templArgId = templArgName->identifier(); + subst.append(qMakePair(templArgId, templArgTy)); + } + } + } + + DeprecatedGenTemplateInstance inst(control, subst); + return inst.gen(candidate); + } + } + } + return candidate->type(); +} diff --git a/src/libs/cplusplus/DeprecatedGenTemplateInstance.h b/src/libs/cplusplus/DeprecatedGenTemplateInstance.h new file mode 100644 index 0000000000..9e488478c6 --- /dev/null +++ b/src/libs/cplusplus/DeprecatedGenTemplateInstance.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms and +** conditions see http://www.qt.io/terms-conditions. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef CPLUSPLUS_DEPRECATEDGENTEMPLATEINSTANCE_H +#define CPLUSPLUS_DEPRECATEDGENTEMPLATEINSTANCE_H + +#include +#include +#include + +#include +#include +#include + +namespace CPlusPlus { + +class CPLUSPLUS_EXPORT DeprecatedGenTemplateInstance +{ +public: + typedef QList< QPair > Substitution; + +public: + static FullySpecifiedType instantiate(const Name *className, Symbol *candidate, QSharedPointer control); + +private: + DeprecatedGenTemplateInstance(QSharedPointer control, const Substitution &substitution); + FullySpecifiedType gen(Symbol *symbol); + +private: + QSharedPointer _control; + const Substitution _substitution; +}; + +} // namespace CPlusPlus + +#endif // CPLUSPLUS_DEPRECATEDGENTEMPLATEINSTANCE_H diff --git a/src/libs/cplusplus/FindUsages.cpp b/src/libs/cplusplus/FindUsages.cpp index b9d34bd00c..0640fab537 100644 --- a/src/libs/cplusplus/FindUsages.cpp +++ b/src/libs/cplusplus/FindUsages.cpp @@ -532,7 +532,7 @@ void FindUsages::memInitializer(MemInitializerAST *ast) if (_currentScope->isFunction()) { Class *classScope = _currentScope->enclosingClass(); if (! classScope) { - if (LookupScope *binding = _context.lookupType(_currentScope)) { + if (ClassOrNamespace *binding = _context.lookupType(_currentScope)) { foreach (Symbol *s, binding->symbols()) { if (Class *k = s->asClass()) { classScope = k; diff --git a/src/libs/cplusplus/LookupContext.cpp b/src/libs/cplusplus/LookupContext.cpp index 401d54f48b..be1968733e 100644 --- a/src/libs/cplusplus/LookupContext.cpp +++ b/src/libs/cplusplus/LookupContext.cpp @@ -32,8 +32,8 @@ #include "ResolveExpression.h" #include "Overview.h" +#include "DeprecatedGenTemplateInstance.h" #include "CppRewriter.h" -#include "TypeResolver.h" #include #include @@ -41,18 +41,15 @@ #include #include #include -#include #include #include #include #include -static const bool debug = ! qgetenv("QTC_LOOKUPCONTEXT_DEBUG").isEmpty(); - -namespace CPlusPlus { +using namespace CPlusPlus; -typedef QSet ProcessedSet; +static const bool debug = ! qgetenv("QTC_LOOKUPCONTEXT_DEBUG").isEmpty(); static void addNames(const Name *name, QList *names, bool addAllNames = false) { @@ -92,6 +89,24 @@ static void path_helper(Symbol *symbol, QList *names) } } +static bool isNestedInstantiationEnclosingTemplate( + ClassOrNamespace *nestedClassOrNamespaceInstantiation, + ClassOrNamespace *enclosingTemplateClassInstantiation) +{ + QList processed; + while (enclosingTemplateClassInstantiation + && !processed.contains(enclosingTemplateClassInstantiation)) { + processed.append(enclosingTemplateClassInstantiation); + if (enclosingTemplateClassInstantiation == nestedClassOrNamespaceInstantiation) + return false; + enclosingTemplateClassInstantiation = enclosingTemplateClassInstantiation->parent(); + } + + return true; +} + +namespace CPlusPlus { + static inline bool compareName(const Name *name, const Name *other) { if (name == other) @@ -121,6 +136,9 @@ bool compareFullyQualifiedName(const QList &path, const QList bindings) : _expressionDocument(expressionDocument) , _thisDocument(thisDocument) , _snapshot(snapshot) @@ -216,7 +235,7 @@ static bool symbolIdentical(Symbol *s1, Symbol *s2) return QByteArray(s1->fileName()) == QByteArray(s2->fileName()); } -const Name *LookupContext::minimalName(Symbol *symbol, LookupScope *target, Control *control) +const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target, Control *control) { const Name *n = 0; QList names = LookupContext::fullyQualifiedName(symbol); @@ -241,7 +260,7 @@ const Name *LookupContext::minimalName(Symbol *symbol, LookupScope *target, Cont } QList LookupContext::lookupByUsing(const Name *name, - LookupScope *bindingScope) const + ClassOrNamespace *bindingScope) const { QList candidates; // if it is a nameId there can be a using declaration for it @@ -275,7 +294,7 @@ QList LookupContext::lookupByUsing(const Name *name, } else if (const QualifiedNameId *q = name->asQualifiedNameId()) { foreach (Symbol *s, bindingScope->symbols()) { if (Scope *scope = s->asScope()) { - LookupScope *base = lookupType(q->base(), scope); + ClassOrNamespace *base = lookupType(q->base(), scope); if (base) candidates = lookupByUsing(q->name(), base); if (!candidates.isEmpty()) @@ -299,14 +318,14 @@ Document::Ptr LookupContext::document(const QString &fileName) const Snapshot LookupContext::snapshot() const { return _snapshot; } -LookupScope *LookupContext::globalNamespace() const +ClassOrNamespace *LookupContext::globalNamespace() const { return bindings()->globalNamespace(); } -LookupScope *LookupContext::lookupType(const Name *name, Scope *scope, - LookupScope *enclosingBinding, - QSet typedefsBeingResolved) const +ClassOrNamespace *LookupContext::lookupType(const Name *name, Scope *scope, + ClassOrNamespace *enclosingBinding, + QSet typedefsBeingResolved) const { if (! scope || ! name) { return 0; @@ -314,8 +333,8 @@ LookupScope *LookupContext::lookupType(const Name *name, Scope *scope, for (unsigned i = 0; i < block->memberCount(); ++i) { Symbol *m = block->memberAt(i); if (UsingNamespaceDirective *u = m->asUsingNamespaceDirective()) { - if (LookupScope *uu = lookupType(u->name(), scope->enclosingNamespace())) { - if (LookupScope *r = uu->lookupType(name)) + if (ClassOrNamespace *uu = lookupType(u->name(), scope->enclosingNamespace())) { + if (ClassOrNamespace *r = uu->lookupType(name)) return r; } } else if (Declaration *d = m->asDeclaration()) { @@ -348,20 +367,20 @@ LookupScope *LookupContext::lookupType(const Name *name, Scope *scope, } // try to find it in block (rare case but has priority before enclosing scope) // e.g.: void foo() { struct S {}; S s; } - if (LookupScope *b = bindings()->lookupType(scope, enclosingBinding)) { - if (LookupScope *lookupScopeNestedInNestedBlock = b->lookupType(name, block)) - return lookupScopeNestedInNestedBlock; + if (ClassOrNamespace *b = bindings()->lookupType(scope, enclosingBinding)) { + if (ClassOrNamespace *classOrNamespaceNestedInNestedBlock = b->lookupType(name, block)) + return classOrNamespaceNestedInNestedBlock; } // try to find type in enclosing scope(typical case) - if (LookupScope *found = lookupType(name, scope->enclosingScope())) + if (ClassOrNamespace *found = lookupType(name, scope->enclosingScope())) return found; - } else if (LookupScope *b = bindings()->lookupType(scope, enclosingBinding)) { + } else if (ClassOrNamespace *b = bindings()->lookupType(scope, enclosingBinding)) { return b->lookupType(name); } else if (Class *scopeAsClass = scope->asClass()) { if (scopeAsClass->enclosingScope()->isBlock()) { - if (LookupScope *b = lookupType(scopeAsClass->name(), + if (ClassOrNamespace *b = lookupType(scopeAsClass->name(), scopeAsClass->enclosingScope(), enclosingBinding, typedefsBeingResolved)) { @@ -373,7 +392,8 @@ LookupScope *LookupContext::lookupType(const Name *name, Scope *scope, return 0; } -LookupScope *LookupContext::lookupType(Symbol *symbol, LookupScope *enclosingBinding) const +ClassOrNamespace *LookupContext::lookupType(Symbol *symbol, + ClassOrNamespace *enclosingBinding) const { return bindings()->lookupType(symbol, enclosingBinding); } @@ -387,7 +407,7 @@ QList LookupContext::lookup(const Name *name, Scope *scope) const for (; scope; scope = scope->enclosingScope()) { if (name->identifier() != 0 && scope->isBlock()) { - bindings()->lookupInScope(name, scope, &candidates); + bindings()->lookupInScope(name, scope, &candidates, /*templateId = */ 0, /*binding=*/ 0); if (! candidates.isEmpty()) { // it's a local. @@ -400,7 +420,7 @@ QList LookupContext::lookup(const Name *name, Scope *scope) const for (unsigned i = 0; i < scope->memberCount(); ++i) { if (UsingNamespaceDirective *u = scope->memberAt(i)->asUsingNamespaceDirective()) { - if (LookupScope *uu = lookupType(u->name(), scope->enclosingNamespace())) { + if (ClassOrNamespace *uu = lookupType(u->name(), scope->enclosingNamespace())) { candidates = uu->find(name); if (! candidates.isEmpty()) @@ -409,8 +429,8 @@ QList LookupContext::lookup(const Name *name, Scope *scope) const } } - if (LookupScope *bindingScope = bindings()->lookupType(scope)) { - if (LookupScope *bindingBlock = bindingScope->findBlock(scope->asBlock())) { + if (ClassOrNamespace *bindingScope = bindings()->lookupType(scope)) { + if (ClassOrNamespace *bindingBlock = bindingScope->findBlock(scope->asBlock())) { candidates = lookupByUsing(name, bindingBlock); if (! candidates.isEmpty()) return candidates; @@ -423,7 +443,7 @@ QList LookupContext::lookup(const Name *name, Scope *scope) const } } else if (Function *fun = scope->asFunction()) { - bindings()->lookupInScope(name, fun, &candidates); + bindings()->lookupInScope(name, fun, &candidates, /*templateId = */ 0, /*binding=*/ 0); if (! candidates.isEmpty()) { // it's an argument or a template parameter. @@ -435,7 +455,7 @@ QList LookupContext::lookup(const Name *name, Scope *scope) const } if (fun->name() && fun->name()->isQualifiedNameId()) { - if (LookupScope *binding = bindings()->lookupType(fun)) { + if (ClassOrNamespace *binding = bindings()->lookupType(fun)) { candidates = binding->find(name); // try find this name in parent class @@ -450,13 +470,13 @@ QList LookupContext::lookup(const Name *name, Scope *scope) const // continue, and look at the enclosing scope. } else if (ObjCMethod *method = scope->asObjCMethod()) { - bindings()->lookupInScope(name, method, &candidates); + bindings()->lookupInScope(name, method, &candidates, /*templateId = */ 0, /*binding=*/ 0); if (! candidates.isEmpty()) break; // it's a formal argument. } else if (Template *templ = scope->asTemplate()) { - bindings()->lookupInScope(name, templ, &candidates); + bindings()->lookupInScope(name, templ, &candidates, /*templateId = */ 0, /*binding=*/ 0); if (! candidates.isEmpty()) { // it's a template parameter. @@ -471,7 +491,7 @@ QList LookupContext::lookup(const Name *name, Scope *scope) const || scope->asClass() || (scope->asEnum() && scope->asEnum()->isScoped())) { - if (LookupScope *bindingScope = bindings()->lookupType(scope)) { + if (ClassOrNamespace *bindingScope = bindings()->lookupType(scope)) { candidates = bindingScope->find(name); if (! candidates.isEmpty()) @@ -484,9 +504,9 @@ QList LookupContext::lookup(const Name *name, Scope *scope) const // the scope can be defined inside a block, try to find it if (Block *block = scope->enclosingBlock()) { - if (LookupScope *b = bindings()->lookupType(block)) { - if (LookupScope *lookupScopeNestedInNestedBlock = b->lookupType(scope->name(), block)) - candidates = lookupScopeNestedInNestedBlock->find(name); + if (ClassOrNamespace *b = bindings()->lookupType(block)) { + if (ClassOrNamespace *classOrNamespaceNestedInNestedBlock = b->lookupType(scope->name(), block)) + candidates = classOrNamespaceNestedInNestedBlock->find(name); } } @@ -494,7 +514,7 @@ QList LookupContext::lookup(const Name *name, Scope *scope) const return candidates; } else if (scope->isObjCClass() || scope->isObjCProtocol()) { - if (LookupScope *binding = bindings()->lookupType(scope)) + if (ClassOrNamespace *binding = bindings()->lookupType(scope)) candidates = binding->find(name); if (! candidates.isEmpty()) @@ -505,10 +525,10 @@ QList LookupContext::lookup(const Name *name, Scope *scope) const return candidates; } -LookupScope *LookupContext::lookupParent(Symbol *symbol) const +ClassOrNamespace *LookupContext::lookupParent(Symbol *symbol) const { QList fqName = path(symbol); - LookupScope *binding = globalNamespace(); + ClassOrNamespace *binding = globalNamespace(); foreach (const Name *name, fqName) { binding = binding->findType(name); if (!binding) @@ -518,193 +538,59 @@ LookupScope *LookupContext::lookupParent(Symbol *symbol) const return binding; } -namespace Internal { - -class LookupScopePrivate -{ -public: - LookupScopePrivate(LookupScope *q, CreateBindings *factory, LookupScope *parent); - ~LookupScopePrivate(); - - typedef std::map Table; - typedef std::map TypedefTable; - typedef std::map TemplateNameIdTable; - typedef QHash Anonymouses; - - LookupScopePrivate *allocateChild(const Name *name); - - void flush(); - - LookupScope *globalNamespace() const; - - Symbol *lookupInScope(const QList &fullName); - - LookupScope *findOrCreateType(const Name *name, LookupScopePrivate *origin = 0, - Class *clazz = 0); - - LookupScopePrivate *findOrCreateNestedAnonymousType(const AnonymousNameId *anonymousNameId); - - 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); - - QList lookup_helper(const Name *name, bool searchInEnclosingScope); - - void lookup_helper(const Name *name, LookupScopePrivate *binding, - QList *result, - ProcessedSet *processed); - - LookupScope *lookupType_helper(const Name *name, ProcessedSet *processed, - bool searchInEnclosingScope, LookupScopePrivate *origin); - - 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, - LookupScopePrivate *origin); - -public: - LookupScope *q; - - CreateBindings *_factory; - LookupScopePrivate *_parent; - QList _symbols; - QList _usings; - Table _nestedScopes; - TypedefTable _typedefs; - QHash _blocks; - QList _enums; - QList _todo; - QSharedPointer _control; - TemplateNameIdTable _specializations; - QMap _instantiations; - Anonymouses _anonymouses; - QSet _declaredOrTypedefedAnonymouses; - - QHash *_scopeLookupCache; - - // it's an instantiation. - LookupScopePrivate *_instantiationOrigin; - - AlreadyConsideredClassContainer _alreadyConsideredClasses; - AlreadyConsideredClassContainer _alreadyConsideredTemplates; - QSet _alreadyConsideredTypedefs; - - Class *_rootClass; - const Name *_name; - bool _hasTypedefs; -}; - -class Instantiator -{ -public: - Instantiator(Clone &cloner, Subst &subst) - : _cloner(cloner) - , _subst(subst) - {} - void doInstantiate(LookupScopePrivate *lookupScope, LookupScopePrivate *instantiation); - LookupScopePrivate *instantiate(LookupScopePrivate *lookupScope, LookupScopePrivate *origin); - -private: - ProcessedSet _alreadyConsideredInstantiations; - Clone &_cloner; - Subst &_subst; -}; - -LookupScopePrivate::LookupScopePrivate(LookupScope *q, CreateBindings *factory, LookupScope *parent) - : q(q) - , _factory(factory) - , _parent(parent ? parent->d : 0) +ClassOrNamespace::ClassOrNamespace(CreateBindings *factory, ClassOrNamespace *parent) + : _factory(factory) + , _parent(parent) , _scopeLookupCache(0) + , _templateId(0) , _instantiationOrigin(0) , _rootClass(0) , _name(0) - , _hasTypedefs(false) { Q_ASSERT(factory); } -LookupScopePrivate::~LookupScopePrivate() +ClassOrNamespace::~ClassOrNamespace() { delete _scopeLookupCache; } -LookupScopePrivate *LookupScopePrivate::allocateChild(const Name *name) +const TemplateNameId *ClassOrNamespace::templateId() const { - LookupScope *e = _factory->allocLookupScope(q, name); - return e->d; + return _templateId; } -} // namespace Internal - -LookupScope::LookupScope(CreateBindings *factory, LookupScope *parent) - : d(new Internal::LookupScopePrivate(this, factory, parent)) +ClassOrNamespace *ClassOrNamespace::instantiationOrigin() const { + return _instantiationOrigin; } -LookupScope::~LookupScope() +ClassOrNamespace *ClassOrNamespace::parent() const { - delete d; + return _parent; } -LookupScope *LookupScope::instantiationOrigin() const +QList ClassOrNamespace::usings() const { - if (Internal::LookupScopePrivate *i = d->_instantiationOrigin) - return i->q; - return 0; + const_cast(this)->flush(); + return _usings; } -LookupScope *LookupScope::parent() const +QList ClassOrNamespace::unscopedEnums() const { - if (Internal::LookupScopePrivate *p = d->_parent) - return p->q; - return 0; + const_cast(this)->flush(); + return _enums; } -QList LookupScope::usings() const +QList ClassOrNamespace::symbols() const { - const_cast(this)->d->flush(); - return d->_usings; + const_cast(this)->flush(); + return _symbols; } -QList LookupScope::unscopedEnums() const +ClassOrNamespace *ClassOrNamespace::globalNamespace() const { - const_cast(this)->d->flush(); - return d->_enums; -} - -QList LookupScope::symbols() const -{ - const_cast(this)->d->flush(); - return d->_symbols; -} - -QList LookupScope::find(const Name *name) -{ - return d->lookup_helper(name, false); -} - -QList LookupScope::lookup(const Name *name) -{ - return d->lookup_helper(name, true); -} - -namespace Internal { - -LookupScope *LookupScopePrivate::globalNamespace() const -{ - const LookupScopePrivate *e = this; + ClassOrNamespace *e = const_cast(this); do { if (! e->_parent) @@ -713,20 +599,30 @@ LookupScope *LookupScopePrivate::globalNamespace() const e = e->_parent; } while (e); - return e ? e->q : 0; + return e; } -QList LookupScopePrivate::lookup_helper(const Name *name, bool searchInEnclosingScope) +QList ClassOrNamespace::find(const Name *name) +{ + return lookup_helper(name, false); +} + +QList ClassOrNamespace::lookup(const Name *name) +{ + return lookup_helper(name, true); +} + +QList ClassOrNamespace::lookup_helper(const Name *name, bool searchInEnclosingScope) { QList result; if (name) { - if (const QualifiedNameId *qName = name->asQualifiedNameId()) { - if (! qName->base()) { // e.g. ::std::string - result = globalNamespace()->find(qName->name()); - } else if (LookupScope *binding = q->lookupType(qName->base())) { - result = binding->find(qName->name()); + if (const QualifiedNameId *q = name->asQualifiedNameId()) { + if (! q->base()) { // e.g. ::std::string + result = globalNamespace()->find(q->name()); + } else if (ClassOrNamespace *binding = lookupType(q->base())) { + result = binding->find(q->name()); QList fullName; addNames(name, &fullName); @@ -735,10 +631,10 @@ QList LookupScopePrivate::lookup_helper(const Name *name, bool searc // a qualified name. For instance, a nested class which is forward declared // in the class but defined outside it - we should capture both. Symbol *match = 0; - ProcessedSet processed; - for (LookupScopePrivate *parentBinding = binding->d->_parent; + QSet processed; + for (ClassOrNamespace *parentBinding = binding->parent(); parentBinding && !match; - parentBinding = parentBinding->_parent) { + parentBinding = parentBinding->parent()) { if (processed.contains(parentBinding)) break; processed.insert(parentBinding); @@ -756,14 +652,14 @@ QList LookupScopePrivate::lookup_helper(const Name *name, bool searc return result; } - ProcessedSet processed; - ProcessedSet processedOwnParents; - LookupScopePrivate *binding = this; + QSet processed; + QSet processedOwnParents; + ClassOrNamespace *binding = this; do { if (processedOwnParents.contains(binding)) break; processedOwnParents.insert(binding); - lookup_helper(name, binding, &result, &processed); + lookup_helper(name, binding, &result, &processed, /*templateId = */ 0); binding = binding->_parent; } while (searchInEnclosingScope && binding); } @@ -771,60 +667,59 @@ QList LookupScopePrivate::lookup_helper(const Name *name, bool searc return result; } -void LookupScopePrivate::lookup_helper( - const Name *name, LookupScopePrivate *binding, QList *result, - ProcessedSet *processed) +void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding, + QList *result, + QSet *processed, + const TemplateNameId *templateId) { - if (!binding || processed->contains(binding)) - return; - processed->insert(binding); + if (binding && ! processed->contains(binding)) { + processed->insert(binding); - binding->flush(); - const Identifier *nameId = name->identifier(); + const Identifier *nameId = name->identifier(); - foreach (Symbol *s, binding->_symbols) { - if (s->isFriend()) - continue; - else if (s->isUsingNamespaceDirective()) - continue; + foreach (Symbol *s, binding->symbols()) { + if (s->isFriend()) + continue; + else if (s->isUsingNamespaceDirective()) + continue; - if (Scope *scope = s->asScope()) { - if (Class *klass = scope->asClass()) { - if (const Identifier *id = klass->identifier()) { - if (nameId && nameId->match(id)) { - LookupItem item; - item.setDeclaration(klass); - item.setBinding(binding->q); - result->append(item); + if (Scope *scope = s->asScope()) { + if (Class *klass = scope->asClass()) { + if (const Identifier *id = klass->identifier()) { + if (nameId && nameId->match(id)) { + LookupItem item; + item.setDeclaration(klass); + item.setBinding(binding); + result->append(item); + } } } + _factory->lookupInScope(name, scope, result, templateId, binding); } - _factory->lookupInScope(name, scope, result, binding->q); } - } - foreach (Enum *e, binding->_enums) - _factory->lookupInScope(name, e, result, binding->q); + foreach (Enum *e, binding->unscopedEnums()) + _factory->lookupInScope(name, e, result, templateId, binding); - foreach (LookupScope *u, binding->_usings) - lookup_helper(name, u->d, result, processed); + foreach (ClassOrNamespace *u, binding->usings()) + lookup_helper(name, u, result, processed, binding->_templateId); - Anonymouses::const_iterator cit = binding->_anonymouses.constBegin(); - Anonymouses::const_iterator citEnd = binding->_anonymouses.constEnd(); - for (; cit != citEnd; ++cit) { - const AnonymousNameId *anonymousNameId = cit.key(); - LookupScopePrivate *a = cit.value(); - if (!binding->_declaredOrTypedefedAnonymouses.contains(anonymousNameId)) - lookup_helper(name, a, result, processed); + Anonymouses::const_iterator cit = binding->_anonymouses.constBegin(); + Anonymouses::const_iterator citEnd = binding->_anonymouses.constEnd(); + for (; cit != citEnd; ++cit) { + const AnonymousNameId *anonymousNameId = cit.key(); + ClassOrNamespace *a = cit.value(); + if (!binding->_declaredOrTypedefedAnonymouses.contains(anonymousNameId)) + lookup_helper(name, a, result, processed, binding->_templateId); + } } } -} - void CreateBindings::lookupInScope(const Name *name, Scope *scope, QList *result, - LookupScope *binding) + const TemplateNameId *templateId, + ClassOrNamespace *binding) { if (! name) { return; @@ -858,7 +753,7 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope, if (Q_UNLIKELY(debug)) { Overview oo; qDebug() << "Found" << id->chars() << "in" - << (binding ? oo(binding->d->_name) : QString::fromLatin1("")); + << (binding ? oo(binding->_name) : QString::fromLatin1("")); } LookupItem item; @@ -866,7 +761,7 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope, item.setBinding(binding); if (s->asNamespaceAlias() && binding) { - LookupScope *targetNamespaceBinding = binding->lookupType(name); + ClassOrNamespace *targetNamespaceBinding = binding->lookupType(name); //there can be many namespace definitions if (targetNamespaceBinding && targetNamespaceBinding->symbols().size() > 0) { Symbol *resolvedSymbol = targetNamespaceBinding->symbols().first(); @@ -874,19 +769,19 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope, } } + if (templateId && (s->isDeclaration() || s->isFunction())) { + FullySpecifiedType ty = DeprecatedGenTemplateInstance::instantiate(templateId, s, control()); + item.setType(ty); // override the type. + } + // instantiate function template - if (const TemplateNameId *instantiation = name->asTemplateNameId()) { - if (Template *specialization = s->asTemplate()) { - if (Symbol *decl = specialization->declaration()) { - if (decl->isFunction() || decl->isDeclaration()) { - Clone cloner(_control.data()); - Subst subst(_control.data()); - initializeSubst(cloner, subst, binding, specialization, instantiation); - Symbol *instantiatedFunctionTemplate = cloner.symbol(decl, &subst); - item.setType(instantiatedFunctionTemplate->type()); // override the type - } - } - } + if (name->isTemplateNameId() && s->isTemplate() && s->asTemplate()->declaration() + && s->asTemplate()->declaration()->isFunction()) { + const TemplateNameId *instantiation = name->asTemplateNameId(); + Template *specialization = s->asTemplate(); + Symbol *instantiatedFunctionTemplate = instantiateTemplateFunction(instantiation, + specialization); + item.setType(instantiatedFunctionTemplate->type()); // override the type. } result->append(item); @@ -894,50 +789,51 @@ void CreateBindings::lookupInScope(const Name *name, Scope *scope, } } -LookupScope *LookupScope::lookupType(const Name *name) +ClassOrNamespace *ClassOrNamespace::lookupType(const Name *name) { if (! name) return 0; - ProcessedSet processed; - return d->lookupType_helper(name, &processed, /*searchInEnclosingScope =*/ true, d); + QSet processed; + return lookupType_helper(name, &processed, /*searchInEnclosingScope =*/ true, this); } -LookupScope *LookupScope::lookupType(const Name *name, Block *block) +ClassOrNamespace *ClassOrNamespace::lookupType(const Name *name, Block *block) { - d->flush(); + flush(); - QHash::const_iterator citBlock = d->_blocks.constFind(block); - if (citBlock != d->_blocks.constEnd()) { - LookupScope *nestedBlock = citBlock.value(); - ProcessedSet processed; - if (LookupScope *foundInNestedBlock - = nestedBlock->d->lookupType_helper(name, - &processed, - /*searchInEnclosingScope = */ true, - nestedBlock->d)) { + QHash::const_iterator citBlock = _blocks.constFind(block); + if (citBlock != _blocks.constEnd()) { + ClassOrNamespace *nestedBlock = citBlock.value(); + QSet processed; + if (ClassOrNamespace *foundInNestedBlock + = nestedBlock->lookupType_helper(name, + &processed, + /*searchInEnclosingScope = */ true, + this)) { return foundInNestedBlock; } } - for (citBlock = d->_blocks.constBegin(); citBlock != d->_blocks.constEnd(); ++citBlock) { - if (LookupScope *foundNestedBlock = citBlock.value()->lookupType(name, block)) + for (citBlock = _blocks.constBegin(); citBlock != _blocks.constEnd(); ++citBlock) { + if (ClassOrNamespace *foundNestedBlock = citBlock.value()->lookupType(name, block)) return foundNestedBlock; } return 0; } -LookupScope *LookupScope::findType(const Name *name) +ClassOrNamespace *ClassOrNamespace::findType(const Name *name) { - ProcessedSet processed; - return d->lookupType_helper(name, &processed, /*searchInEnclosingScope =*/ true, d); + QSet processed; + return lookupType_helper(name, &processed, /*searchInEnclosingScope =*/ false, this); } -LookupScope *Internal::LookupScopePrivate::findBlock_helper( - Block *block, ProcessedSet *processed, bool searchInEnclosingScope) +ClassOrNamespace *ClassOrNamespace::findBlock_helper(Block *block, + QSet *processed, + bool searchInEnclosingScope) { - for (LookupScopePrivate *binding = this; binding; binding = binding->_parent) { + for (ClassOrNamespace *binding = this; binding; binding = binding->_parent) { if (processed->contains(binding)) break; processed->insert(binding); @@ -948,8 +844,8 @@ LookupScope *Internal::LookupScopePrivate::findBlock_helper( return citBlock.value(); for (citBlock = binding->_blocks.begin(); citBlock != end; ++citBlock) { - if (LookupScope *foundNestedBlock = - citBlock.value()->d->findBlock_helper(block, processed, false)) { + if (ClassOrNamespace *foundNestedBlock = + citBlock.value()->findBlock_helper(block, processed, false)) { return foundNestedBlock; } } @@ -959,20 +855,19 @@ LookupScope *Internal::LookupScopePrivate::findBlock_helper( return 0; } -LookupScope *LookupScope::findBlock(Block *block) +ClassOrNamespace *ClassOrNamespace::findBlock(Block *block) { - ProcessedSet processed; - return d->findBlock_helper(block, &processed, true); + QSet processed; + return findBlock_helper(block, &processed, true); } -Symbol *Internal::LookupScopePrivate::lookupInScope(const QList &fullName) +Symbol *ClassOrNamespace::lookupInScope(const QList &fullName) { if (!_scopeLookupCache) { _scopeLookupCache = new QHash; - flush(); - for (int j = 0; j < _symbols.size(); ++j) { - if (Scope *scope = _symbols.at(j)->asScope()) { + for (int j = 0; j < symbols().size(); ++j) { + if (Scope *scope = symbols().at(j)->asScope()) { for (unsigned i = 0; i < scope->memberCount(); ++i) { Symbol *s = scope->memberAt(i); _scopeLookupCache->insert(LookupContext::fullyQualifiedName(s), s); @@ -984,30 +879,24 @@ Symbol *Internal::LookupScopePrivate::lookupInScope(const QList &f return _scopeLookupCache->value(fullName, 0); } -Class *LookupScope::rootClass() const -{ - return d->_rootClass; -} - -namespace Internal { - -LookupScope *LookupScopePrivate::lookupType_helper( - const Name *name, ProcessedSet *processed, - bool searchInEnclosingScope, LookupScopePrivate *origin) +ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name, + QSet *processed, + bool searchInEnclosingScope, + ClassOrNamespace *origin) { if (Q_UNLIKELY(debug)) { Overview oo; qDebug() << "Looking up" << oo(name) << "in" << oo(_name); } - if (const QualifiedNameId *qName = name->asQualifiedNameId()) { + if (const QualifiedNameId *q = name->asQualifiedNameId()) { - ProcessedSet innerProcessed; - if (! qName->base()) - return globalNamespace()->d->lookupType_helper(qName->name(), &innerProcessed, true, origin); + QSet innerProcessed; + if (! q->base()) + return globalNamespace()->lookupType_helper(q->name(), &innerProcessed, true, origin); - if (LookupScope *binding = lookupType_helper(qName->base(), processed, true, origin)) - return binding->d->lookupType_helper(qName->name(), &innerProcessed, false, origin); + if (ClassOrNamespace *binding = lookupType_helper(q->base(), processed, true, origin)) + return binding->lookupType_helper(q->name(), &innerProcessed, false, origin); return 0; @@ -1017,32 +906,41 @@ LookupScope *LookupScopePrivate::lookupType_helper( if (name->isNameId() || name->isTemplateNameId() || name->isAnonymousNameId()) { flush(); - foreach (Symbol *s, _symbols) { + foreach (Symbol *s, symbols()) { if (Class *klass = s->asClass()) { if (klass->identifier() && klass->identifier()->match(name->identifier())) - return q; + return this; } } - foreach (Enum *e, _enums) { + foreach (Enum *e, unscopedEnums()) { if (e->identifier() && e->identifier()->match(name->identifier())) - return q; + return this; } - if (LookupScopePrivate *e = nestedType(name, origin)) - return e->q; + if (ClassOrNamespace *e = nestedType(name, origin)) + return e; - foreach (LookupScope *u, _usings) { - if (LookupScope *r = u->d->lookupType_helper( - name, processed, /*searchInEnclosingScope =*/ false, origin)) { - return r; + if (_templateId) { + if (_usings.size() == 1) { + ClassOrNamespace *delegate = _usings.first(); + + if (ClassOrNamespace *r = delegate->lookupType_helper(name, + processed, + /*searchInEnclosingScope = */ true, + origin)) + return r; + } else if (Q_UNLIKELY(debug)) { + qWarning() << "expected one using declaration. Number of using declarations is:" + << _usings.size(); } } - if (_instantiationOrigin) { - if (LookupScope *o = _instantiationOrigin->lookupType_helper( - name, processed, /*searchInEnclosingScope =*/ true, origin)) { - return o; - } + foreach (ClassOrNamespace *u, usings()) { + if (ClassOrNamespace *r = u->lookupType_helper(name, + processed, + /*searchInEnclosingScope =*/ false, + origin)) + return r; } } @@ -1053,10 +951,10 @@ LookupScope *LookupScopePrivate::lookupType_helper( return 0; } -static LookupScopePrivate *findSpecializationWithMatchingTemplateArgument( - const Name *argumentName, LookupScopePrivate *reference) +static ClassOrNamespace *findSpecializationWithMatchingTemplateArgument(const Name *argumentName, + ClassOrNamespace *reference) { - foreach (Symbol *s, reference->_symbols) { + foreach (Symbol *s, reference->symbols()) { if (Class *clazz = s->asClass()) { if (Template *templateSpecialization = clazz->enclosingTemplate()) { const unsigned argumentCountOfSpecialization @@ -1076,127 +974,95 @@ static LookupScopePrivate *findSpecializationWithMatchingTemplateArgument( return 0; } -LookupScopePrivate *LookupScopePrivate::findSpecialization( - const TemplateNameId *templId, - const TemplateNameIdTable &specializations, - LookupScopePrivate *origin) +ClassOrNamespace *ClassOrNamespace::findSpecialization(const TemplateNameId *templId, + const TemplateNameIdTable &specializations) { + // 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; const unsigned specializationTemplateArgumentCount = specializationNameId->templateArgumentCount(); - const unsigned initializationTemplateArgumentCount = templId->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; - for (unsigned i = 0; i < initializationTemplateArgumentCount; ++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; - } + if (specializationTemplateArgumentCount == initializationTemplateArgumentCount) { + for (unsigned i = 0; i < initializationTemplateArgumentCount; ++i) { + const FullySpecifiedType &specializationTemplateArgument + = specializationNameId->templateArgumentAt(i); + const FullySpecifiedType &initializationTemplateArgument + = templId->templateArgumentAt(i); + 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; + 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 (ClassOrNamespace *reference + = findSpecializationWithMatchingTemplateArgument( + argumentName, cit->second)) { + return reference; + } } } } } - - if (const NamedType *specName = specializationTemplateArgument->asNamedType()) { - if (const NamedType *initName = initializationTemplateArgument->asNamedType()) { - if (specName->name()->identifier() == initName->name()->identifier()) - return cit->second; - } - } } } return 0; } -LookupScopePrivate *LookupScopePrivate::findOrCreateNestedAnonymousType( +ClassOrNamespace *ClassOrNamespace::findOrCreateNestedAnonymousType( const AnonymousNameId *anonymousNameId) { - auto cit = _anonymouses.constFind(anonymousNameId); + QHash::const_iterator cit + = _anonymouses.constFind(anonymousNameId); if (cit != _anonymouses.constEnd()) { return cit.value(); } else { - LookupScopePrivate *newAnonymous = allocateChild(anonymousNameId); + ClassOrNamespace *newAnonymous = _factory->allocClassOrNamespace(this); + if (Q_UNLIKELY(debug)) + newAnonymous->_name = anonymousNameId; _anonymouses[anonymousNameId] = newAnonymous; return newAnonymous; } } -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; - LookupScopePrivate *binding = 0; - _alreadyConsideredTypedefs.insert(decl); - if (const NamedType *namedTy = decl->type()->asNamedType()) { - if (LookupScope *e = q->lookupType(namedTy->name())) { - binding = e->d; - } else if (origin) { - if (LookupScope *e = origin->q->lookupType(namedTy->name())) - binding = e->d; - } - } - _alreadyConsideredTypedefs.remove(decl); - if (binding) - return binding; - } - - auto it = _nestedScopes.find(name); - if (it != _nestedScopes.end()) - return it->second; - - return 0; -} - -LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScopePrivate *origin) +ClassOrNamespace *ClassOrNamespace::nestedType(const Name *name, ClassOrNamespace *origin) { Q_ASSERT(name != 0); Q_ASSERT(name->isNameId() || name->isTemplateNameId() || name->isAnonymousNameId()); - const_cast(this)->flush(); + const_cast(this)->flush(); if (const AnonymousNameId *anonymousNameId = name->asAnonymousNameId()) return findOrCreateNestedAnonymousType(anonymousNameId); - LookupScopePrivate *reference = findNestedType(name, origin); - if (!reference) + Table::const_iterator it = _classOrNamespaces.find(name); + if (it == _classOrNamespaces.end()) return 0; - reference->flush(); - LookupScopePrivate *baseTemplateClassReference = reference; + + ClassOrNamespace *reference = it->second; + ClassOrNamespace *baseTemplateClassReference = reference; const TemplateNameId *templId = name->asTemplateNameId(); if (templId) { - // for "using" we should use the real one LookupScope(it should be the first + // for "using" we should use the real one ClassOrNamespace(it should be the first // one item from usings list) // we indicate that it is a 'using' by checking number of symbols(it should be 0) - if (reference->_symbols.count() == 0 && reference->_usings.count() != 0) - reference = reference->_usings[0]->d; + if (reference->symbols().count() == 0 && reference->usings().count() != 0) + reference = reference->_usings[0]; // if it is a TemplateNameId it could be a specialization(full or partial) or // instantiation of one of the specialization(reference->_specialization) or @@ -1209,12 +1075,15 @@ LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScope if (cit != reference->_specializations.end()) { return cit->second; } else { - LookupScopePrivate *newSpecialization = reference->allocateChild(templId); + ClassOrNamespace *newSpecialization = _factory->allocClassOrNamespace(reference); + if (Q_UNLIKELY(debug)) + newSpecialization->_name = templId; reference->_specializations[templId] = newSpecialization; return newSpecialization; } } else { - auto citInstantiation = reference->_instantiations.constFind(templId); + QMap::const_iterator citInstantiation + = reference->_instantiations.constFind(templId); if (citInstantiation != reference->_instantiations.constEnd()) return citInstantiation.value(); TemplateNameId *nonConstTemplId = const_cast(templId); @@ -1227,14 +1096,11 @@ LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScope // we found full specialization reference = cit->second; } else { - if (LookupScopePrivate *specialization = - findSpecialization(templId, specializations, origin)) { - reference = specialization; - if (Q_UNLIKELY(debug)) { - Overview oo; - qDebug() << "picked specialization" << oo(specialization->_name); - } - } + ClassOrNamespace *specializationWithPointer + = findSpecialization(templId, specializations); + if (specializationWithPointer) + reference = specializationWithPointer; + // TODO: find the best specialization(probably partial) for this instantiation } // let's instantiation be instantiation nonConstTemplId->setIsSpecialization(false); @@ -1247,7 +1113,7 @@ LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScope Class *referenceClass = 0; QList allBases; - foreach (Symbol *s, reference->_symbols) { + foreach (Symbol *s, reference->symbols()) { if (Class *clazz = s->asClass()) { for (unsigned i = 0; i < clazz->baseClassCount(); ++i) { BaseClass *baseClass = clazz->baseClassAt(i); @@ -1271,106 +1137,163 @@ LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScope if (!name->isTemplateNameId()) _alreadyConsideredClasses.insert(referenceClass); - QSet knownUsings = reference->_usings.toSet(); + QSet knownUsings = reference->usings().toSet(); // If we are dealling with a template type, more work is required, since we need to // construct all instantiation data. if (templId) { - if (!_factory->expandTemplates()) - return reference; - Template *templateSpecialization = referenceClass->enclosingTemplate(); - if (!templateSpecialization) - return reference; - - // It gets a bit complicated if the reference is actually a class template because we - // now must worry about dependent names in base classes. _alreadyConsideredTemplates.insert(templId); - const unsigned argumentCountOfInitialization = templId->templateArgumentCount(); - const unsigned argumentCountOfSpecialization - = templateSpecialization->templateParameterCount(); + ClassOrNamespace *instantiation = _factory->allocClassOrNamespace(baseTemplateClassReference); + if (Q_UNLIKELY(debug)) + instantiation->_name = templId; + instantiation->_templateId = templId; - Clone cloner(_control.data()); - Subst subst(_control.data()); - _factory->initializeSubst(cloner, subst, origin ? origin->q : 0, - templateSpecialization, templId); - - LookupScopePrivate *instantiation = baseTemplateClassReference->allocateChild(templId); + while (!origin->_symbols.isEmpty() && origin->_symbols[0]->isBlock()) + origin = origin->parent(); instantiation->_instantiationOrigin = origin; - instantiation->_rootClass = reference->_rootClass; - Instantiator instantiator(cloner, subst); - instantiator.doInstantiate(reference, instantiation); - - QHash templParams; - for (unsigned i = 0; i < argumentCountOfSpecialization; ++i) - templParams.insert(templateSpecialization->templateParameterAt(i)->name(), i); - - foreach (const Name *baseName, allBases) { - LookupScope *baseBinding = 0; - - if (const Identifier *nameId = baseName->asNameId()) { - // This is the simple case in which a template parameter is itself a base. - // Ex.: template class A : public T {}; - if (templParams.contains(nameId)) { - const unsigned parameterIndex = templParams.value(nameId); - if (parameterIndex < argumentCountOfInitialization) { - const FullySpecifiedType &fullType = - templId->templateArgumentAt(parameterIndex); - if (fullType.isValid()) { - if (NamedType *namedType = fullType.type()->asNamedType()) - baseBinding = q->lookupType(namedType->name()); - } - } - } - if (!baseBinding && subst.contains(baseName)) { - const FullySpecifiedType &fullType = subst[baseName]; - if (fullType.isValid()) { - if (NamedType *namedType = fullType.type()->asNamedType()) - baseBinding = q->lookupType(namedType->name()); - } - } - } else { - SubstitutionMap map; + // The instantiation should have all symbols, enums, and usings from the reference. + instantiation->_enums.append(reference->unscopedEnums()); + instantiation->_usings.append(reference->usings()); + + instantiation->_rootClass = reference->rootClass(); + + // It gets a bit complicated if the reference is actually a class template because we + // now must worry about dependent names in base classes. + if (Template *templateSpecialization = referenceClass->enclosingTemplate()) { + const unsigned argumentCountOfInitialization = templId->templateArgumentCount(); + const unsigned argumentCountOfSpecialization + = templateSpecialization->templateParameterCount(); + + Subst subst(_control.data()); + if (_factory->expandTemplates()) { + const TemplateNameId *templSpecId + = templateSpecialization->name()->asTemplateNameId(); + const unsigned templSpecArgumentCount = templSpecId ? + templSpecId->templateArgumentCount() : 0; + Clone cloner(_control.data()); for (unsigned i = 0; i < argumentCountOfSpecialization; ++i) { - const Name *name = templateSpecialization->templateParameterAt(i)->name(); + const TypenameArgument *tParam + = templateSpecialization->templateParameterAt(i)->asTypenameArgument(); + if (!tParam) + continue; + const Name *name = tParam->name(); + if (!name) + continue; + FullySpecifiedType ty = (i < argumentCountOfInitialization) ? templId->templateArgumentAt(i): - templateSpecialization->templateParameterAt(i)->type(); + cloner.type(tParam->type(), &subst); + + if (i < templSpecArgumentCount + && templSpecId->templateArgumentAt(i)->isPointerType()) { + if (PointerType *pointerType = ty->asPointerType()) + ty = pointerType->elementType(); + } - map.bind(name, ty); + subst.bind(cloner.name(name, &subst), ty); } - SubstitutionEnvironment env; - env.enter(&map); - baseName = rewriteName(baseName, &env, _control.data()); + foreach (Symbol *s, reference->symbols()) { + Symbol *clone = cloner.symbol(s, &subst); + clone->setEnclosingScope(s->enclosingScope()); + instantiation->_symbols.append(clone); + if (Q_UNLIKELY(debug)) { + Overview oo; + oo.showFunctionSignatures = true; + oo.showReturnTypes = true; + oo.showTemplateParameters = true; + qDebug() << "cloned" << oo(clone->type()); + if (Class *klass = clone->asClass()) { + const unsigned klassMemberCount = klass->memberCount(); + for (unsigned i = 0; i < klassMemberCount; ++i){ + Symbol *klassMemberAsSymbol = klass->memberAt(i); + if (klassMemberAsSymbol->isTypedef()) { + if (Declaration *declaration = klassMemberAsSymbol->asDeclaration()) + qDebug() << "Member: " << oo(declaration->type(), declaration->name()); + } + } + } + } + } + instantiateNestedClasses(reference, cloner, subst, instantiation); + } else { + instantiation->_symbols.append(reference->symbols()); + } - if (const TemplateNameId *baseTemplId = baseName->asTemplateNameId()) { - // Another template that uses the dependent name. - // Ex.: template class A : public B {}; - if (baseTemplId->identifier() != templId->identifier()) { - if (LookupScopePrivate *nested = nestedType(baseName, origin)) - baseBinding = nested->q; + QHash templParams; + for (unsigned i = 0; i < argumentCountOfSpecialization; ++i) + templParams.insert(templateSpecialization->templateParameterAt(i)->name(), i); + + foreach (const Name *baseName, allBases) { + ClassOrNamespace *baseBinding = 0; + + if (const Identifier *nameId = baseName->asNameId()) { + // This is the simple case in which a template parameter is itself a base. + // Ex.: template class A : public T {}; + if (templParams.contains(nameId)) { + const unsigned parameterIndex = templParams.value(nameId); + if (parameterIndex < argumentCountOfInitialization) { + const FullySpecifiedType &fullType = + templId->templateArgumentAt(parameterIndex); + if (fullType.isValid()) { + if (NamedType *namedType = fullType.type()->asNamedType()) + baseBinding = lookupType(namedType->name()); + } + } } - } else if (const QualifiedNameId *qBaseName = baseName->asQualifiedNameId()) { - // Qualified names in general. - // Ex.: template class A : public B::Type {}; - LookupScope *binding = q; - if (const Name *qualification = qBaseName->base()) { - const TemplateNameId *baseTemplName = qualification->asTemplateNameId(); - if (!baseTemplName || !compareName(baseTemplName, templateSpecialization->name())) - binding = q->lookupType(qualification); + if (!baseBinding && subst.contains(baseName)) { + const FullySpecifiedType &fullType = subst[baseName]; + if (fullType.isValid()) { + if (NamedType *namedType = fullType.type()->asNamedType()) + baseBinding = lookupType(namedType->name()); + } } - baseName = qBaseName->name(); + } else { + SubstitutionMap map; + for (unsigned i = 0; i < argumentCountOfSpecialization; ++i) { + const Name *name = templateSpecialization->templateParameterAt(i)->name(); + FullySpecifiedType ty = (i < argumentCountOfInitialization) ? + templId->templateArgumentAt(i): + templateSpecialization->templateParameterAt(i)->type(); + + map.bind(name, ty); + } + SubstitutionEnvironment env; + env.enter(&map); + + baseName = rewriteName(baseName, &env, _control.data()); + + if (const TemplateNameId *baseTemplId = baseName->asTemplateNameId()) { + // Another template that uses the dependent name. + // Ex.: template class A : public B {}; + if (baseTemplId->identifier() != templId->identifier()) + baseBinding = nestedType(baseName, origin); + } else if (const QualifiedNameId *qBaseName = baseName->asQualifiedNameId()) { + // Qualified names in general. + // Ex.: template class A : public B::Type {}; + ClassOrNamespace *binding = this; + if (const Name *qualification = qBaseName->base()) { + const TemplateNameId *baseTemplName = qualification->asTemplateNameId(); + if (!baseTemplName || !compareName(baseTemplName, templateSpecialization->name())) + binding = lookupType(qualification); + } + baseName = qBaseName->name(); - if (binding) - baseBinding = binding->lookupType(baseName); + if (binding) + baseBinding = binding->lookupType(baseName); + } } - } - if (baseBinding && !knownUsings.contains(baseBinding)) - instantiation->addUsing(baseBinding); + if (baseBinding && !knownUsings.contains(baseBinding)) + instantiation->addUsing(baseBinding); + } + } else { + instantiation->_classOrNamespaces = reference->_classOrNamespaces; + instantiation->_symbols.append(reference->symbols()); } + _alreadyConsideredTemplates.clear(templId); baseTemplateClassReference->_instantiations[templId] = instantiation; return instantiation; @@ -1382,14 +1305,14 @@ LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScope // Find the missing bases for regular (non-template) types. // Ex.: class A : public B::Type {}; foreach (const Name *baseName, allBases) { - LookupScope *binding = q; + ClassOrNamespace *binding = this; if (const QualifiedNameId *qBaseName = baseName->asQualifiedNameId()) { if (const Name *qualification = qBaseName->base()) - binding = q->lookupType(qualification); + binding = lookupType(qualification); else if (binding->parent() != 0) //if this is global identifier we take global namespace //Ex: class A{}; namespace NS { class A: public ::A{}; } - binding = binding->d->globalNamespace(); + binding = binding->globalNamespace(); else //if we are in the global scope continue; @@ -1397,7 +1320,7 @@ LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScope } if (binding) { - LookupScope * baseBinding = binding->lookupType(baseName); + ClassOrNamespace * baseBinding = binding->lookupType(baseName); if (baseBinding && !knownUsings.contains(baseBinding)) reference->addUsing(baseBinding); } @@ -1407,152 +1330,176 @@ LookupScopePrivate *LookupScopePrivate::nestedType(const Name *name, LookupScope return reference; } -LookupScopePrivate *Instantiator::instantiate(LookupScopePrivate *lookupScope, - LookupScopePrivate *origin) + +void ClassOrNamespace::instantiateNestedClasses(ClassOrNamespace *enclosingTemplateClass, + Clone &cloner, + Subst &subst, + ClassOrNamespace *enclosingTemplateClassInstantiation) { - lookupScope->flush(); - LookupScopePrivate *instantiation = lookupScope->allocateChild(lookupScope->_name); - instantiation->_instantiationOrigin = origin; - doInstantiate(lookupScope, instantiation); - return instantiation; + NestedClassInstantiator nestedClassInstantiator(_factory, cloner, subst); + nestedClassInstantiator.instantiate(enclosingTemplateClass, enclosingTemplateClassInstantiation); } -void Instantiator::doInstantiate(LookupScopePrivate *lookupScope, LookupScopePrivate *instantiation) +void ClassOrNamespace::NestedClassInstantiator::instantiate(ClassOrNamespace *enclosingTemplateClass, + ClassOrNamespace *enclosingTemplateClassInstantiation) { - if (_alreadyConsideredInstantiations.contains(lookupScope)) + if (_alreadyConsideredNestedClassInstantiations.contains(enclosingTemplateClass)) return; - _alreadyConsideredInstantiations.insert(lookupScope); - // The instantiation should have all symbols, enums, and usings from the reference. - if (instantiation != lookupScope) { - instantiation->_enums = lookupScope->_enums; - 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 (LookupScope *usingLookupScope, lookupScope->_usings) - instantiation->_usings.append(instantiate(usingLookupScope->d, instantiation)->q); - foreach (Symbol *s, lookupScope->_symbols) { - Symbol *clone = _cloner.symbol(s, &_subst); - if (!clone->enclosingScope()) // Not from the cache but just cloned. - clone->setEnclosingScope(s->enclosingScope()); - instantiation->_symbols.append(clone); - if (s == instantiation->_rootClass) { - clone->setName(instantiation->_name); - instantiation->_rootClass = clone->asClass(); + _alreadyConsideredNestedClassInstantiations.insert(enclosingTemplateClass); + ClassOrNamespace::Table::const_iterator cit = enclosingTemplateClass->_classOrNamespaces.begin(); + for (; cit != enclosingTemplateClass->_classOrNamespaces.end(); ++cit) { + const Name *nestedName = cit->first; + ClassOrNamespace *nestedClassOrNamespace = cit->second; + ClassOrNamespace *nestedClassOrNamespaceInstantiation = nestedClassOrNamespace; + + if (isInstantiateNestedClassNeeded(nestedClassOrNamespace->_symbols)) { + nestedClassOrNamespaceInstantiation = _factory->allocClassOrNamespace(nestedClassOrNamespace); + nestedClassOrNamespaceInstantiation->_enums.append(nestedClassOrNamespace->unscopedEnums()); + nestedClassOrNamespaceInstantiation->_usings.append(nestedClassOrNamespace->usings()); + nestedClassOrNamespaceInstantiation->_instantiationOrigin = nestedClassOrNamespace; + + foreach (Symbol *s, nestedClassOrNamespace->_symbols) { + Symbol *clone = _cloner.symbol(s, &_subst); + if (!clone->enclosingScope()) // Not from the cache but just cloned. + clone->setEnclosingScope(s->enclosingScope()); + nestedClassOrNamespaceInstantiation->_symbols.append(clone); } - if (Q_UNLIKELY(debug)) { - Overview oo; - oo.showFunctionSignatures = true; - oo.showReturnTypes = true; - oo.showTemplateParameters = true; - qDebug() << "cloned" << oo(clone->type()); - if (Class *klass = clone->asClass()) { - const unsigned klassMemberCount = klass->memberCount(); - for (unsigned i = 0; i < klassMemberCount; ++i){ - Symbol *klassMemberAsSymbol = klass->memberAt(i); - if (klassMemberAsSymbol->isTypedef()) { - if (Declaration *declaration = klassMemberAsSymbol->asDeclaration()) - qDebug() << "Member: " << oo(declaration->type(), declaration->name()); - } - } + } + + if (isNestedInstantiationEnclosingTemplate(nestedClassOrNamespaceInstantiation, + enclosingTemplateClass)) { + nestedClassOrNamespaceInstantiation->_parent = enclosingTemplateClassInstantiation; + } + instantiate(nestedClassOrNamespace, nestedClassOrNamespaceInstantiation); + + enclosingTemplateClassInstantiation->_classOrNamespaces[nestedName] = + nestedClassOrNamespaceInstantiation; + } + _alreadyConsideredNestedClassInstantiations.remove(enclosingTemplateClass); +} + +bool ClassOrNamespace::NestedClassInstantiator::isInstantiateNestedClassNeeded(const QList &symbols) const +{ + foreach (Symbol *s, symbols) { + if (Class *klass = s->asClass()) { + int memberCount = klass->memberCount(); + for (int i = 0; i < memberCount; ++i) { + Symbol *memberAsSymbol = klass->memberAt(i); + if (Declaration *declaration = memberAsSymbol->asDeclaration()) { + if (containsTemplateType(declaration)) + return true; + } else if (Function *function = memberAsSymbol->asFunction()) { + if (containsTemplateType(function)) + return true; } } } } - auto cit = lookupScope->_nestedScopes.begin(); - for (; cit != lookupScope->_nestedScopes.end(); ++cit) { - const Name *nestedName = cit->first; - LookupScopePrivate *nestedLookupScope = cit->second; - LookupScopePrivate *nestedInstantiation = instantiate(nestedLookupScope, instantiation); - nestedInstantiation->_parent = instantiation; - instantiation->_nestedScopes[nestedName] = nestedInstantiation; - } - _alreadyConsideredInstantiations.remove(lookupScope); + + return false; +} + +bool ClassOrNamespace::NestedClassInstantiator::containsTemplateType(Declaration *declaration) const +{ + Type *memberType = declaration->type().type(); + NamedType *namedType = findNamedType(memberType); + return namedType && _subst.contains(namedType->name()); +} + +bool ClassOrNamespace::NestedClassInstantiator::containsTemplateType(Function *function) const +{ + Type *returnType = function->returnType().type(); + NamedType *namedType = findNamedType(returnType); + return namedType && _subst.contains(namedType->name()); + //TODO: in future we will need also check function arguments, for now returned value is enough } -void LookupScopePrivate::flush() +NamedType *ClassOrNamespace::NestedClassInstantiator::findNamedType(Type *memberType) const +{ + if (NamedType *namedType = memberType->asNamedType()) + return namedType; + else if (PointerType *pointerType = memberType->asPointerType()) + return findNamedType(pointerType->elementType().type()); + else if (ReferenceType *referenceType = memberType->asReferenceType()) + return findNamedType(referenceType->elementType().type()); + + return 0; +} + +void ClassOrNamespace::flush() { if (! _todo.isEmpty()) { const QList todo = _todo; _todo.clear(); foreach (Symbol *member, todo) - _factory->process(member, q); + _factory->process(member, this); } } -void LookupScopePrivate::addSymbol(Symbol *symbol) +void ClassOrNamespace::addSymbol(Symbol *symbol) { _symbols.append(symbol); } -void LookupScopePrivate::addTodo(Symbol *symbol) +void ClassOrNamespace::addTodo(Symbol *symbol) { _todo.append(symbol); } -void LookupScopePrivate::addUnscopedEnum(Enum *e) +void ClassOrNamespace::addUnscopedEnum(Enum *e) { _enums.append(e); } -void LookupScopePrivate::addTypedef(const Name *identifier, Declaration *d) -{ - _typedefs[identifier] = d; -} - -void LookupScopePrivate::addUsing(LookupScope *u) +void ClassOrNamespace::addUsing(ClassOrNamespace *u) { _usings.append(u); } -void LookupScopePrivate::addNestedType(const Name *alias, LookupScope *e) +void ClassOrNamespace::addNestedType(const Name *alias, ClassOrNamespace *e) { - _nestedScopes[alias] = e->d; + _classOrNamespaces[alias] = e; } -LookupScope *LookupScopePrivate::findOrCreateType( - const Name *name, LookupScopePrivate *origin, Class *clazz) +ClassOrNamespace *ClassOrNamespace::findOrCreateType(const Name *name, ClassOrNamespace *origin, + Class *clazz) { if (! name) - return q; + return this; if (! origin) origin = this; - if (const QualifiedNameId *qName = name->asQualifiedNameId()) { - if (! qName->base()) - return globalNamespace()->d->findOrCreateType(qName->name(), origin, clazz); + if (const QualifiedNameId *q = name->asQualifiedNameId()) { + if (! q->base()) + return globalNamespace()->findOrCreateType(q->name(), origin, clazz); - return findOrCreateType(qName->base(), origin)->d->findOrCreateType(qName->name(), origin, clazz); + return findOrCreateType(q->base(), origin)->findOrCreateType(q->name(), origin, clazz); } else if (name->isNameId() || name->isTemplateNameId() || name->isAnonymousNameId()) { - LookupScopePrivate *e = nestedType(name, origin); + ClassOrNamespace *e = nestedType(name, origin); if (! e) { - e = allocateChild(name); + e = _factory->allocClassOrNamespace(this); e->_rootClass = clazz; - _nestedScopes[name] = e; + if (Q_UNLIKELY(debug)) + e->_name = name; + _classOrNamespaces[name] = e; } - return e->q; + return e; } return 0; } -} // namespace Internal - CreateBindings::CreateBindings(Document::Ptr thisDocument, const Snapshot &snapshot) : _snapshot(snapshot) , _control(QSharedPointer(new Control)) , _expandTemplates(false) - , _depth(0) { - _globalNamespace = allocLookupScope(/*parent = */ 0, /*name = */ 0); - _currentLookupScope = _globalNamespace; + _globalNamespace = allocClassOrNamespace(/*parent = */ 0); + _currentClassOrNamespace = _globalNamespace; process(thisDocument); } @@ -1562,36 +1509,36 @@ CreateBindings::~CreateBindings() qDeleteAll(_entities); } -LookupScope *CreateBindings::switchCurrentLookupScope(LookupScope *lookupScope) +ClassOrNamespace *CreateBindings::switchCurrentClassOrNamespace(ClassOrNamespace *classOrNamespace) { - LookupScope *previous = _currentLookupScope; - _currentLookupScope = lookupScope; + ClassOrNamespace *previous = _currentClassOrNamespace; + _currentClassOrNamespace = classOrNamespace; return previous; } -LookupScope *CreateBindings::globalNamespace() const +ClassOrNamespace *CreateBindings::globalNamespace() const { return _globalNamespace; } -LookupScope *CreateBindings::lookupType(Symbol *symbol, LookupScope *enclosingBinding) +ClassOrNamespace *CreateBindings::lookupType(Symbol *symbol, ClassOrNamespace *enclosingBinding) { const QList path = LookupContext::path(symbol); return lookupType(path, enclosingBinding); } -LookupScope *CreateBindings::lookupType(const QList &path, - LookupScope *enclosingBinding) +ClassOrNamespace *CreateBindings::lookupType(const QList &path, + ClassOrNamespace *enclosingBinding) { if (path.isEmpty()) return _globalNamespace; if (enclosingBinding) { - if (LookupScope *b = enclosingBinding->lookupType(path.last())) + if (ClassOrNamespace *b = enclosingBinding->lookupType(path.last())) return b; } - LookupScope *b = _globalNamespace->lookupType(path.at(0)); + ClassOrNamespace *b = _globalNamespace->lookupType(path.at(0)); for (int i = 1; b && i < path.size(); ++i) b = b->findType(path.at(i)); @@ -1599,23 +1546,22 @@ LookupScope *CreateBindings::lookupType(const QList &path, return b; } -void CreateBindings::process(Symbol *s, LookupScope *lookupScope) +void CreateBindings::process(Symbol *s, ClassOrNamespace *classOrNamespace) { - LookupScope *previous = switchCurrentLookupScope(lookupScope); + ClassOrNamespace *previous = switchCurrentClassOrNamespace(classOrNamespace); accept(s); - (void) switchCurrentLookupScope(previous); + (void) switchCurrentClassOrNamespace(previous); } void CreateBindings::process(Symbol *symbol) { - _currentLookupScope->d->addTodo(symbol); + _currentClassOrNamespace->addTodo(symbol); } -LookupScope *CreateBindings::allocLookupScope(LookupScope *parent, const Name *name) +ClassOrNamespace *CreateBindings::allocClassOrNamespace(ClassOrNamespace *parent) { - LookupScope *e = new LookupScope(this, parent); - e->d->_control = control(); - e->d->_name = name; + ClassOrNamespace *e = new ClassOrNamespace(this, parent); + e->_control = control(); _entities.append(e); return e; } @@ -1639,22 +1585,22 @@ void CreateBindings::process(Document::Ptr doc) } } -LookupScope *CreateBindings::enterLookupScopeBinding(Symbol *symbol) +ClassOrNamespace *CreateBindings::enterClassOrNamespaceBinding(Symbol *symbol) { - LookupScope *entity = _currentLookupScope->d->findOrCreateType( - symbol->name(), 0, symbol->asClass()); - entity->d->addSymbol(symbol); + ClassOrNamespace *entity = _currentClassOrNamespace->findOrCreateType(symbol->name(), 0, + symbol->asClass()); + entity->addSymbol(symbol); - return switchCurrentLookupScope(entity); + return switchCurrentClassOrNamespace(entity); } -LookupScope *CreateBindings::enterGlobalLookupScope(Symbol *symbol) +ClassOrNamespace *CreateBindings::enterGlobalClassOrNamespace(Symbol *symbol) { - LookupScope *entity = _globalNamespace->d->findOrCreateType( - symbol->name(), 0, symbol->asClass()); - entity->d->addSymbol(symbol); + ClassOrNamespace *entity = _globalNamespace->findOrCreateType(symbol->name(), 0, + symbol->asClass()); + entity->addSymbol(symbol); - return switchCurrentLookupScope(entity); + return switchCurrentClassOrNamespace(entity); } bool CreateBindings::visit(Template *templ) @@ -1665,40 +1611,34 @@ bool CreateBindings::visit(Template *templ) return false; } -bool CreateBindings::visit(ExplicitInstantiation *inst) -{ - Q_UNUSED(inst); - return false; -} - bool CreateBindings::visit(Namespace *ns) { - LookupScope *previous = enterLookupScopeBinding(ns); + ClassOrNamespace *previous = enterClassOrNamespaceBinding(ns); for (unsigned i = 0; i < ns->memberCount(); ++i) process(ns->memberAt(i)); if (ns->isInline() && previous) - previous->d->addUsing(_currentLookupScope); + previous->addUsing(_currentClassOrNamespace); - _currentLookupScope = previous; + _currentClassOrNamespace = previous; return false; } bool CreateBindings::visit(Class *klass) { - LookupScope *previous = _currentLookupScope; - LookupScope *binding = 0; + ClassOrNamespace *previous = _currentClassOrNamespace; + ClassOrNamespace *binding = 0; if (klass->name() && klass->name()->isQualifiedNameId()) - binding = _currentLookupScope->lookupType(klass->name()); + binding = _currentClassOrNamespace->lookupType(klass->name()); if (! binding) - binding = _currentLookupScope->d->findOrCreateType(klass->name(), 0, klass); + binding = _currentClassOrNamespace->findOrCreateType(klass->name(), 0, klass); - _currentLookupScope = binding; - _currentLookupScope->d->addSymbol(klass); + _currentClassOrNamespace = binding; + _currentClassOrNamespace->addSymbol(klass); for (unsigned i = 0; i < klass->baseClassCount(); ++i) process(klass->baseClassAt(i)); @@ -1706,15 +1646,15 @@ bool CreateBindings::visit(Class *klass) for (unsigned i = 0; i < klass->memberCount(); ++i) process(klass->memberAt(i)); - _currentLookupScope = previous; + _currentClassOrNamespace = previous; return false; } bool CreateBindings::visit(ForwardClassDeclaration *klass) { if (! klass->isFriend()) { - LookupScope *previous = enterLookupScopeBinding(klass); - _currentLookupScope = previous; + ClassOrNamespace *previous = enterClassOrNamespaceBinding(klass); + _currentClassOrNamespace = previous; } return false; @@ -1723,10 +1663,10 @@ bool CreateBindings::visit(ForwardClassDeclaration *klass) bool CreateBindings::visit(Enum *e) { if (e->isScoped()) { - LookupScope *previous = enterLookupScopeBinding(e); - _currentLookupScope = previous; + ClassOrNamespace *previous = enterClassOrNamespaceBinding(e); + _currentClassOrNamespace = previous; } else { - _currentLookupScope->d->addUnscopedEnum(e); + _currentClassOrNamespace->addUnscopedEnum(e); } return false; } @@ -1734,18 +1674,22 @@ 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 (ty->isNamedType()) { - _currentLookupScope->d->addTypedef(typedefId, decl); + if (const NamedType *namedTy = ty->asNamedType()) { + if (ClassOrNamespace *e = _currentClassOrNamespace->lookupType(namedTy->name())) { + _currentClassOrNamespace->addNestedType(decl->name(), e); + } else if (false) { + Overview oo; + qDebug() << "found entity not found for" << oo.prettyName(namedTy->name()); + } } else if (Class *klass = ty->asClassType()) { if (const Identifier *nameId = decl->name()->asNameId()) { - LookupScope *binding - = _currentLookupScope->d->findOrCreateType(nameId, 0, klass); - binding->d->addSymbol(klass); + ClassOrNamespace *binding + = _currentClassOrNamespace->findOrCreateType(nameId, 0, klass); + binding->addSymbol(klass); } } } @@ -1753,7 +1697,7 @@ bool CreateBindings::visit(Declaration *decl) if (Class *clazz = decl->type()->asClassType()) { if (const Name *name = clazz->name()) { if (const AnonymousNameId *anonymousNameId = name->asAnonymousNameId()) - _currentLookupScope->d->_declaredOrTypedefedAnonymouses.insert(anonymousNameId); + _currentClassOrNamespace->_declaredOrTypedefedAnonymouses.insert(anonymousNameId); } } return false; @@ -1761,59 +1705,58 @@ bool CreateBindings::visit(Declaration *decl) bool CreateBindings::visit(Function *function) { - LookupScope *previous = _currentLookupScope; - LookupScope *binding = lookupType(function, previous); + ClassOrNamespace *previous = _currentClassOrNamespace; + ClassOrNamespace *binding = lookupType(function, previous); if (!binding) return false; - _currentLookupScope = binding; + _currentClassOrNamespace = binding; for (unsigned i = 0, count = function->memberCount(); i < count; ++i) { Symbol *s = function->memberAt(i); if (Block *b = s->asBlock()) visit(b); } - _currentLookupScope = previous; + _currentClassOrNamespace = previous; return false; } bool CreateBindings::visit(Block *block) { - LookupScope *previous = _currentLookupScope; + ClassOrNamespace *previous = _currentClassOrNamespace; - LookupScope *binding = new LookupScope(this, previous); - binding->d->_control = control(); + ClassOrNamespace *binding = new ClassOrNamespace(this, previous); + binding->_control = control(); - _currentLookupScope = binding; - _currentLookupScope->d->addSymbol(block); + _currentClassOrNamespace = binding; + _currentClassOrNamespace->addSymbol(block); for (unsigned i = 0; i < block->memberCount(); ++i) // we cannot use lazy processing here, because we have to know - // does this block contain any other blocks or LookupScopes - process(block->memberAt(i), _currentLookupScope); - - // we add this block to parent LookupScope only if it contains - // any nested LookupScopes or other blocks(which have to contain - // nested LookupScopes) - 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; + // does this block contain any other blocks or classOrNamespaces + process(block->memberAt(i), _currentClassOrNamespace); + + // we add this block to parent ClassOrNamespace only if it contains + // any nested ClassOrNamespaces or other blocks(which have to contain + // nested ClassOrNamespaces) + if (! _currentClassOrNamespace->_blocks.empty() + || ! _currentClassOrNamespace->_classOrNamespaces.empty() + || ! _currentClassOrNamespace->_enums.empty() + || ! _currentClassOrNamespace->_anonymouses.empty()) { + previous->_blocks[block] = binding; _entities.append(binding); } else { delete binding; binding = 0; } - _currentLookupScope = previous; + _currentClassOrNamespace = previous; return false; } bool CreateBindings::visit(BaseClass *b) { - if (LookupScope *base = _currentLookupScope->lookupType(b->name())) { - _currentLookupScope->d->addUsing(base); + if (ClassOrNamespace *base = _currentClassOrNamespace->lookupType(b->name())) { + _currentClassOrNamespace->addUsing(base); } else if (false) { Overview oo; qDebug() << "no entity for:" << oo.prettyName(b->name()); @@ -1826,9 +1769,9 @@ bool CreateBindings::visit(UsingDeclaration *u) if (u->name()) { if (const QualifiedNameId *q = u->name()->asQualifiedNameId()) { if (const Identifier *unqualifiedId = q->name()->asNameId()) { - if (LookupScope *delegate = _currentLookupScope->lookupType(q)) { - LookupScope *b = _currentLookupScope->d->findOrCreateType(unqualifiedId); - b->d->addUsing(delegate); + if (ClassOrNamespace *delegate = _currentClassOrNamespace->lookupType(q)) { + ClassOrNamespace *b = _currentClassOrNamespace->findOrCreateType(unqualifiedId); + b->addUsing(delegate); } } } @@ -1838,8 +1781,8 @@ bool CreateBindings::visit(UsingDeclaration *u) bool CreateBindings::visit(UsingNamespaceDirective *u) { - if (LookupScope *e = _currentLookupScope->lookupType(u->name())) { - _currentLookupScope->d->addUsing(e); + if (ClassOrNamespace *e = _currentClassOrNamespace->lookupType(u->name())) { + _currentClassOrNamespace->addUsing(e); } else if (false) { Overview oo; qDebug() << "no entity for namespace:" << oo.prettyName(u->name()); @@ -1852,9 +1795,9 @@ bool CreateBindings::visit(NamespaceAlias *a) if (! a->identifier()) { return false; - } else if (LookupScope *e = _currentLookupScope->lookupType(a->namespaceName())) { + } else if (ClassOrNamespace *e = _currentClassOrNamespace->lookupType(a->namespaceName())) { if (a->name()->isNameId() || a->name()->isTemplateNameId() || a->name()->isAnonymousNameId()) - _currentLookupScope->d->addNestedType(a->name(), e); + _currentClassOrNamespace->addNestedType(a->name(), e); } else if (false) { Overview oo; @@ -1866,7 +1809,7 @@ bool CreateBindings::visit(NamespaceAlias *a) bool CreateBindings::visit(ObjCClass *klass) { - LookupScope *previous = enterGlobalLookupScope(klass); + ClassOrNamespace *previous = enterGlobalClassOrNamespace(klass); process(klass->baseClass()); @@ -1876,14 +1819,14 @@ bool CreateBindings::visit(ObjCClass *klass) for (unsigned i = 0; i < klass->memberCount(); ++i) process(klass->memberAt(i)); - _currentLookupScope = previous; + _currentClassOrNamespace = previous; return false; } bool CreateBindings::visit(ObjCBaseClass *b) { - if (LookupScope *base = _globalNamespace->lookupType(b->name())) { - _currentLookupScope->d->addUsing(base); + if (ClassOrNamespace *base = _globalNamespace->lookupType(b->name())) { + _currentClassOrNamespace->addUsing(base); } else if (false) { Overview oo; qDebug() << "no entity for:" << oo.prettyName(b->name()); @@ -1893,14 +1836,14 @@ bool CreateBindings::visit(ObjCBaseClass *b) bool CreateBindings::visit(ObjCForwardClassDeclaration *klass) { - LookupScope *previous = enterGlobalLookupScope(klass); - _currentLookupScope = previous; + ClassOrNamespace *previous = enterGlobalClassOrNamespace(klass); + _currentClassOrNamespace = previous; return false; } bool CreateBindings::visit(ObjCProtocol *proto) { - LookupScope *previous = enterGlobalLookupScope(proto); + ClassOrNamespace *previous = enterGlobalClassOrNamespace(proto); for (unsigned i = 0; i < proto->protocolCount(); ++i) process(proto->protocolAt(i)); @@ -1908,14 +1851,14 @@ bool CreateBindings::visit(ObjCProtocol *proto) for (unsigned i = 0; i < proto->memberCount(); ++i) process(proto->memberAt(i)); - _currentLookupScope = previous; + _currentClassOrNamespace = previous; return false; } bool CreateBindings::visit(ObjCBaseProtocol *b) { - if (LookupScope *base = _globalNamespace->lookupType(b->name())) { - _currentLookupScope->d->addUsing(base); + if (ClassOrNamespace *base = _globalNamespace->lookupType(b->name())) { + _currentClassOrNamespace->addUsing(base); } else if (false) { Overview oo; qDebug() << "no entity for:" << oo.prettyName(b->name()); @@ -1925,8 +1868,8 @@ bool CreateBindings::visit(ObjCBaseProtocol *b) bool CreateBindings::visit(ObjCForwardProtocolDeclaration *proto) { - LookupScope *previous = enterGlobalLookupScope(proto); - _currentLookupScope = previous; + ClassOrNamespace *previous = enterGlobalClassOrNamespace(proto); + _currentClassOrNamespace = previous; return false; } @@ -1935,57 +1878,29 @@ bool CreateBindings::visit(ObjCMethod *) return false; } -FullySpecifiedType CreateBindings::resolveTemplateArgument(Clone &cloner, - Subst &subst, - LookupScope *origin, - const Template *specialization, - const TemplateNameId *instantiation, - unsigned index) -{ - FullySpecifiedType ty; - CPP_ASSERT(specialization && instantiation, return ty); - - const TypenameArgument *tParam = 0; - if (Symbol *tArgument = specialization->templateParameterAt(index)) - tParam = tArgument->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; - if (index < templSpecArgumentCount && templSpecId->templateArgumentAt(index)->isPointerType()) { - if (PointerType *pointerType = ty->asPointerType()) - ty = pointerType->elementType(); - } - - if (const Name *name = tParam->name()) - subst.bind(cloner.name(name, &subst), ty); - return ty; -} - -void CreateBindings::initializeSubst(Clone &cloner, - Subst &subst, - LookupScope *origin, - const Template *specialization, - const TemplateNameId *instantiation) +Symbol *CreateBindings::instantiateTemplateFunction(const TemplateNameId *instantiation, + Template *specialization) const { + const unsigned argumentCountOfInitialization = instantiation->templateArgumentCount(); const unsigned argumentCountOfSpecialization = specialization->templateParameterCount(); - if (_depth > 15) - return; + Clone cloner(_control.data()); + Subst subst(_control.data()); + 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; - ++_depth; - for (unsigned i = 0; i < argumentCountOfSpecialization; ++i) - resolveTemplateArgument(cloner, subst, origin, specialization, instantiation, i); - --_depth; + FullySpecifiedType ty = (i < argumentCountOfInitialization) ? + instantiation->templateArgumentAt(i): + cloner.type(tParam->type(), &subst); + + subst.bind(cloner.name(name, &subst), ty); + } + return cloner.symbol(specialization, &subst); } -} // namespace CPlusPlus diff --git a/src/libs/cplusplus/LookupContext.h b/src/libs/cplusplus/LookupContext.h index 8410c9000b..5858d80c95 100644 --- a/src/libs/cplusplus/LookupContext.h +++ b/src/libs/cplusplus/LookupContext.h @@ -41,7 +41,6 @@ #include #include -#include #include #include @@ -59,78 +58,158 @@ struct FullyQualifiedName : fqn(fqn) {} }; -class LookupScopePrivate; -class Instantiator; } // namespace Internal; class CreateBindings; -class CPLUSPLUS_EXPORT LookupScope +class CPLUSPLUS_EXPORT ClassOrNamespace { - Q_DISABLE_COPY(LookupScope) + Q_DISABLE_COPY(ClassOrNamespace) - LookupScope(CreateBindings *factory, LookupScope *parent); + ClassOrNamespace(CreateBindings *factory, ClassOrNamespace *parent); public: - ~LookupScope(); + ~ClassOrNamespace(); - LookupScope *instantiationOrigin() const; + const TemplateNameId *templateId() const; + ClassOrNamespace *instantiationOrigin() const; - LookupScope *parent() const; - QList usings() const; + ClassOrNamespace *parent() const; + QList usings() const; QList unscopedEnums() const; QList symbols() const; + ClassOrNamespace *globalNamespace() const; + QList lookup(const Name *name); QList find(const Name *name); - LookupScope *lookupType(const Name *name); - LookupScope *lookupType(const Name *name, Block *block); - LookupScope *findType(const Name *name); - LookupScope *findBlock(Block *block); + ClassOrNamespace *lookupType(const Name *name); + ClassOrNamespace *lookupType(const Name *name, Block *block); + ClassOrNamespace *findType(const Name *name); + ClassOrNamespace *findBlock(Block *block); + + Symbol *lookupInScope(const QList &fullName); - /// The class this LookupScope is based on. - Class *rootClass() const; + /// The class this ClassOrNamespace is based on. + Class *rootClass() const { return _rootClass; } private: - Internal::LookupScopePrivate *d; + typedef std::map Table; + typedef std::map TemplateNameIdTable; + typedef QHash Anonymouses; + + /// \internal + void flush(); + + /// \internal + ClassOrNamespace *findOrCreateType(const Name *name, ClassOrNamespace *origin = 0, + Class *clazz = 0); + + ClassOrNamespace *findOrCreateNestedAnonymousType(const AnonymousNameId *anonymousNameId); + + void addTodo(Symbol *symbol); + void addSymbol(Symbol *symbol); + void addUnscopedEnum(Enum *e); + void addUsing(ClassOrNamespace *u); + void addNestedType(const Name *alias, ClassOrNamespace *e); + + QList lookup_helper(const Name *name, bool searchInEnclosingScope); + + void lookup_helper(const Name *name, ClassOrNamespace *binding, + QList *result, + QSet *processed, + const TemplateNameId *templateId); + + ClassOrNamespace *lookupType_helper(const Name *name, QSet *processed, + bool searchInEnclosingScope, ClassOrNamespace *origin); + + ClassOrNamespace *findBlock_helper(Block *block, QSet *processed, + bool searchInEnclosingScope); + + ClassOrNamespace *nestedType(const Name *name, ClassOrNamespace *origin); + + void instantiateNestedClasses(ClassOrNamespace *enclosingTemplateClass, + Clone &cloner, + Subst &subst, + ClassOrNamespace *enclosingTemplateClassInstantiation); + ClassOrNamespace *findSpecialization(const TemplateNameId *templId, + const TemplateNameIdTable &specializations); + + CreateBindings *_factory; + ClassOrNamespace *_parent; + QList _symbols; + QList _usings; + Table _classOrNamespaces; + QHash _blocks; + QList _enums; + QList _todo; + QSharedPointer _control; + TemplateNameIdTable _specializations; + QMap _instantiations; + Anonymouses _anonymouses; + QSet _declaredOrTypedefedAnonymouses; + + QHash *_scopeLookupCache; + + // it's an instantiation. + const TemplateNameId *_templateId; + ClassOrNamespace *_instantiationOrigin; + + AlreadyConsideredClassContainer _alreadyConsideredClasses; + AlreadyConsideredClassContainer _alreadyConsideredTemplates; + + Class *_rootClass; + + class NestedClassInstantiator + { + public: + NestedClassInstantiator(CreateBindings *factory, Clone &cloner, Subst &subst) + : _factory(factory) + , _cloner(cloner) + , _subst(subst) + {} + void instantiate(ClassOrNamespace *enclosingTemplateClass, + ClassOrNamespace *enclosingTemplateClassInstantiation); + private: + bool isInstantiateNestedClassNeeded(const QList &symbols) const; + bool containsTemplateType(Declaration *declaration) const; + bool containsTemplateType(Function *function) const; + NamedType *findNamedType(Type *memberType) const; + + QSet _alreadyConsideredNestedClassInstantiations; + CreateBindings *_factory; + Clone &_cloner; + Subst &_subst; + }; + +public: + const Name *_name; // For debug - friend class Internal::LookupScopePrivate; - friend class Internal::Instantiator; friend class CreateBindings; }; -class CPLUSPLUS_EXPORT CreateBindings - : protected SymbolVisitor - , public QEnableSharedFromThis +class CPLUSPLUS_EXPORT CreateBindings: protected SymbolVisitor { Q_DISABLE_COPY(CreateBindings) public: - typedef QSharedPointer Ptr; - CreateBindings(Document::Ptr thisDocument, const Snapshot &snapshot); virtual ~CreateBindings(); /// Returns the binding for the global namespace. - LookupScope *globalNamespace() const; + ClassOrNamespace *globalNamespace() const; /// Finds the binding associated to the given symbol. - LookupScope *lookupType(Symbol *symbol, LookupScope *enclosingBinding = 0); - LookupScope *lookupType(const QList &path, LookupScope *enclosingBinding = 0); + ClassOrNamespace *lookupType(Symbol *symbol, ClassOrNamespace *enclosingBinding = 0); + ClassOrNamespace *lookupType(const QList &path, + ClassOrNamespace *enclosingBinding = 0); /// Returns the Control that must be used to create temporary symbols. /// \internal QSharedPointer control() const { return _control; } - Snapshot &snapshot() - { return _snapshot; } - - /// Adds an expression document in order to keep their symbols and names alive - void addExpressionDocument(Document::Ptr document) - { _expressionDocuments.append(document); } - bool expandTemplates() const { return _expandTemplates; } void setExpandTemplates(bool expandTemplates) @@ -140,36 +219,28 @@ public: /// Store the result in \a results. /// \internal void lookupInScope(const Name *name, Scope *scope, QList *result, - LookupScope *binding = 0); + const TemplateNameId *templateId, ClassOrNamespace *binding); /// Create bindings for the symbols reachable from \a rootSymbol. /// \internal - void process(Symbol *rootSymbol, LookupScope *lookupScope); + void process(Symbol *rootSymbol, ClassOrNamespace *classOrNamespace); - /// Create an empty LookupScope binding with the given \a parent. + /// Create an empty ClassOrNamespace binding with the given \a parent. /// \internal - LookupScope *allocLookupScope(LookupScope *parent, const Name *name); - - FullySpecifiedType resolveTemplateArgument(Clone &cloner, Subst &subst, - LookupScope *origin, - const Template *specialization, - const TemplateNameId *instantiation, - unsigned index); - void initializeSubst(Clone &cloner, Subst &subst, LookupScope *origin, - const Template *specialization, const TemplateNameId *instantiation); + ClassOrNamespace *allocClassOrNamespace(ClassOrNamespace *parent); protected: using SymbolVisitor::visit; - /// Change the current LookupScope binding. - LookupScope *switchCurrentLookupScope(LookupScope *lookupScope); + /// Change the current ClassOrNamespace binding. + ClassOrNamespace *switchCurrentClassOrNamespace(ClassOrNamespace *classOrNamespace); - /// Enters the LookupScope binding associated with the given \a symbol. - LookupScope *enterLookupScopeBinding(Symbol *symbol); + /// Enters the ClassOrNamespace binding associated with the given \a symbol. + ClassOrNamespace *enterClassOrNamespaceBinding(Symbol *symbol); - /// Enters a LookupScope binding for the given \a symbol in the global + /// Enters a ClassOrNamespace binding for the given \a symbol in the global /// namespace binding. - LookupScope *enterGlobalLookupScope(Symbol *symbol); + ClassOrNamespace *enterGlobalClassOrNamespace(Symbol *symbol); /// Creates bindings for the given \a document. void process(Document::Ptr document); @@ -178,7 +249,6 @@ protected: void process(Symbol *root); virtual bool visit(Template *templ); - virtual bool visit(ExplicitInstantiation *inst); virtual bool visit(Namespace *ns); virtual bool visit(Class *klass); virtual bool visit(ForwardClassDeclaration *klass); @@ -201,15 +271,16 @@ protected: virtual bool visit(ObjCMethod *); private: + Symbol *instantiateTemplateFunction(const TemplateNameId *instantiation, + Template *specialization) const; + Snapshot _snapshot; QSharedPointer _control; - QList _expressionDocuments; QSet _processed; - QList _entities; - LookupScope *_globalNamespace; - LookupScope *_currentLookupScope; + QList _entities; + ClassOrNamespace *_globalNamespace; + ClassOrNamespace *_currentClassOrNamespace; bool _expandTemplates; - int _depth; }; class CPLUSPLUS_EXPORT LookupContext @@ -223,7 +294,7 @@ public: LookupContext(Document::Ptr expressionDocument, Document::Ptr thisDocument, const Snapshot &snapshot, - CreateBindings::Ptr bindings = CreateBindings::Ptr()); + QSharedPointer bindings = QSharedPointer()); LookupContext(const LookupContext &other); LookupContext &operator = (const LookupContext &other); @@ -233,25 +304,25 @@ public: Document::Ptr document(const QString &fileName) const; Snapshot snapshot() const; - LookupScope *globalNamespace() const; + ClassOrNamespace *globalNamespace() const; QList lookup(const Name *name, Scope *scope) const; - LookupScope *lookupType(const Name *name, Scope *scope, - LookupScope *enclosingBinding = 0, + ClassOrNamespace *lookupType(const Name *name, Scope *scope, + ClassOrNamespace *enclosingBinding = 0, QSet typedefsBeingResolved = QSet()) const; - LookupScope *lookupType(Symbol *symbol, - LookupScope *enclosingBinding = 0) const; - LookupScope *lookupParent(Symbol *symbol) const; + ClassOrNamespace *lookupType(Symbol *symbol, + ClassOrNamespace *enclosingBinding = 0) const; + ClassOrNamespace *lookupParent(Symbol *symbol) const; /// \internal - CreateBindings::Ptr bindings() const + QSharedPointer bindings() const { return _bindings; } static QList fullyQualifiedName(Symbol *symbol); static QList path(Symbol *symbol); - static const Name *minimalName(Symbol *symbol, LookupScope *target, Control *control); + static const Name *minimalName(Symbol *symbol, ClassOrNamespace *target, Control *control); void setExpandTemplates(bool expandTemplates) { @@ -261,7 +332,7 @@ public: } private: - QList lookupByUsing(const Name *name, LookupScope *bindingScope) const; + QList lookupByUsing(const Name *name, ClassOrNamespace *bindingScope) const; // The current expression. Document::Ptr _expressionDocument; @@ -273,7 +344,7 @@ private: Snapshot _snapshot; // Bindings - CreateBindings::Ptr _bindings; + QSharedPointer _bindings; bool m_expandTemplates; }; diff --git a/src/libs/cplusplus/LookupItem.cpp b/src/libs/cplusplus/LookupItem.cpp index 4e22389503..0621c1f6e9 100644 --- a/src/libs/cplusplus/LookupItem.cpp +++ b/src/libs/cplusplus/LookupItem.cpp @@ -77,10 +77,10 @@ Scope *LookupItem::scope() const void LookupItem::setScope(Scope *scope) { _scope = scope; } -LookupScope *LookupItem::binding() const +ClassOrNamespace *LookupItem::binding() const { return _binding; } -void LookupItem::setBinding(LookupScope *binding) +void LookupItem::setBinding(ClassOrNamespace *binding) { _binding = binding; } bool LookupItem::operator == (const LookupItem &other) const diff --git a/src/libs/cplusplus/LookupItem.h b/src/libs/cplusplus/LookupItem.h index 13963b7064..46c7b34716 100644 --- a/src/libs/cplusplus/LookupItem.h +++ b/src/libs/cplusplus/LookupItem.h @@ -37,7 +37,7 @@ namespace CPlusPlus { -class LookupScope; +class ClassOrNamespace; class CPLUSPLUS_EXPORT LookupItem { @@ -63,8 +63,8 @@ public: /// Sets this item's scope. void setScope(Scope *scope); - LookupScope *binding() const; - void setBinding(LookupScope *binding); + ClassOrNamespace *binding() const; + void setBinding(ClassOrNamespace *binding); bool operator == (const LookupItem &other) const; bool operator != (const LookupItem &other) const; @@ -73,7 +73,7 @@ private: FullySpecifiedType _type; Scope *_scope; Symbol *_declaration; - LookupScope *_binding; + ClassOrNamespace *_binding; }; uint qHash(const CPlusPlus::LookupItem &result); diff --git a/src/libs/cplusplus/ResolveExpression.cpp b/src/libs/cplusplus/ResolveExpression.cpp index 43887b2995..adaac12ab5 100644 --- a/src/libs/cplusplus/ResolveExpression.cpp +++ b/src/libs/cplusplus/ResolveExpression.cpp @@ -32,9 +32,9 @@ #include "LookupContext.h" #include "Overview.h" +#include "DeprecatedGenTemplateInstance.h" #include "CppRewriter.h" #include "TypeOfExpression.h" -#include "TypeResolver.h" #include #include @@ -75,6 +75,131 @@ static QList removeDuplicates(const QList &results) return uniqueList; } +class TypedefsResolver +{ +public: + TypedefsResolver(const LookupContext &context) : _context(context) {} + void resolve(FullySpecifiedType *type, Scope **scope, ClassOrNamespace *binding) + { + QSet visited; + _binding = binding; + // Use a hard limit when trying to resolve typedefs. Typedefs in templates can refer to + // each other, each time enhancing the template argument and thus making it impossible to + // use an "alreadyResolved" container. FIXME: We might overcome this by resolving the + // template parameters. + unsigned maxDepth = 15; + for (NamedType *namedTy = 0; maxDepth && (namedTy = getNamedType(*type)); --maxDepth) { + QList namedTypeItems = getNamedTypeItems(namedTy->name(), *scope, _binding); + + if (Q_UNLIKELY(debug)) + qDebug() << "-- we have" << namedTypeItems.size() << "candidates"; + + if (!findTypedef(namedTypeItems, type, scope, visited)) + break; + } + } + +private: + NamedType *getNamedType(FullySpecifiedType& type) const + { + NamedType *namedTy = type->asNamedType(); + if (! namedTy) { + if (PointerType *pointerTy = type->asPointerType()) + namedTy = pointerTy->elementType()->asNamedType(); + } + return namedTy; + } + + QList getNamedTypeItems(const Name *name, Scope *scope, + ClassOrNamespace *binding) const + { + QList namedTypeItems = typedefsFromScopeUpToFunctionScope(name, scope); + if (namedTypeItems.isEmpty()) { + if (binding) + namedTypeItems = binding->lookup(name); + if (ClassOrNamespace *scopeCon = _context.lookupType(scope)) + namedTypeItems += scopeCon->lookup(name); + } + + return namedTypeItems; + } + + /// Return all typedefs with given name from given scope up to function scope. + static QList typedefsFromScopeUpToFunctionScope(const Name *name, Scope *scope) + { + QList results; + if (!scope) + return results; + Scope *enclosingBlockScope = 0; + for (Block *block = scope->asBlock(); block; + block = enclosingBlockScope ? enclosingBlockScope->asBlock() : 0) { + const unsigned memberCount = block->memberCount(); + for (unsigned i = 0; i < memberCount; ++i) { + Symbol *symbol = block->memberAt(i); + if (Declaration *declaration = symbol->asDeclaration()) { + if (isTypedefWithName(declaration, name)) { + LookupItem item; + item.setDeclaration(declaration); + item.setScope(block); + item.setType(declaration->type()); + results.append(item); + } + } + } + enclosingBlockScope = block->enclosingScope(); + } + return results; + } + + static bool isTypedefWithName(const Declaration *declaration, const Name *name) + { + if (declaration->isTypedef()) { + const Identifier *identifier = declaration->name()->identifier(); + if (name->identifier()->match(identifier)) + return true; + } + return false; + } + + bool findTypedef(const QList& namedTypeItems, FullySpecifiedType *type, + Scope **scope, QSet& visited) + { + bool foundTypedef = false; + foreach (const LookupItem &it, namedTypeItems) { + Symbol *declaration = it.declaration(); + if (declaration && declaration->isTypedef()) { + if (visited.contains(declaration)) + break; + visited.insert(declaration); + + // continue working with the typedefed type and scope + if (type->type()->isPointerType()) { + *type = FullySpecifiedType( + _context.bindings()->control()->pointerType(declaration->type())); + } else if (type->type()->isReferenceType()) { + *type = FullySpecifiedType( + _context.bindings()->control()->referenceType( + declaration->type(), + declaration->type()->asReferenceType()->isRvalueReference())); + } else { + *type = declaration->type(); + } + + *scope = it.scope(); + _binding = it.binding(); + foundTypedef = true; + break; + } + } + + return foundTypedef; + } + + const LookupContext &_context; + // binding has to be remembered in case of resolving typedefs for templates + ClassOrNamespace *_binding; +}; + static int evaluateFunctionArgument(const FullySpecifiedType &actualTy, const FullySpecifiedType &formalTy) { @@ -176,7 +301,7 @@ void ResolveExpression::addResults(const QList &items) } void ResolveExpression::addResult(const FullySpecifiedType &ty, Scope *scope, - LookupScope *binding) + ClassOrNamespace *binding) { LookupItem item; item.setType(ty); @@ -206,7 +331,7 @@ bool ResolveExpression::visit(BinaryExpressionAST *ast) if (d->core_declarator) { if (DeclaratorIdAST *declaratorId = d->core_declarator->asDeclaratorId()) { if (NameAST *nameAST = declaratorId->name) { - if (LookupScope *binding = baseExpression(_results, T_ARROW)) { + if (ClassOrNamespace *binding = baseExpression(_results, T_ARROW)) { _results.clear(); addResults(binding->lookup(nameAST->name)); } @@ -487,17 +612,19 @@ bool ResolveExpression::visit(UnaryExpressionAST *ast) added = true; } else if (namedTy != 0) { const Name *starOp = control()->operatorNameId(OperatorNameId::StarOp); - if (LookupScope *b = _context.lookupType(namedTy->name(), p.scope(), p.binding())) { + if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), p.scope(), p.binding())) { foreach (const LookupItem &r, b->find(starOp)) { Symbol *overload = r.declaration(); if (Function *funTy = overload->type()->asFunctionType()) { if (maybeValidPrototype(funTy, 0)) { - FullySpecifiedType retTy = funTy->returnType().simplified(); - p.setType(retTy); - p.setScope(funTy->enclosingScope()); - it.setValue(p); - added = true; - break; + if (Function *proto = instantiate(b->templateId(), funTy)->asFunctionType()) { + FullySpecifiedType retTy = proto->returnType().simplified(); + p.setType(retTy); + p.setScope(proto->enclosingScope()); + it.setValue(p); + added = true; + break; + } } } } @@ -526,6 +653,48 @@ bool ResolveExpression::visit(QualifiedNameAST *ast) return false; } +namespace { + +class DeduceAutoCheck : public ASTVisitor +{ +public: + DeduceAutoCheck(const Identifier *id, TranslationUnit *tu) + : ASTVisitor(tu), _id(id), _block(false) + { + accept(tu->ast()); + } + + virtual bool preVisit(AST *) + { + if (_block) + return false; + + return true; + } + + virtual bool visit(SimpleNameAST *ast) + { + if (ast->name + && ast->name->identifier() + && strcmp(ast->name->identifier()->chars(), _id->chars()) == 0) { + _block = true; + } + + return false; + } + + virtual bool visit(MemberAccessAST *ast) + { + accept(ast->base_expression); + return false; + } + + const Identifier *_id; + bool _block; +}; + +} // namespace anonymous + bool ResolveExpression::visit(SimpleNameAST *ast) { QList candidates = _context.lookup(ast->name, _scope); @@ -539,7 +708,7 @@ bool ResolveExpression::visit(SimpleNameAST *ast) if (item.declaration() == 0) continue; - if (item.type().isAuto() || item.type().isDecltype()) { + if (item.type().isAuto()) { const Declaration *decl = item.declaration()->asDeclaration(); if (!decl) continue; @@ -548,10 +717,53 @@ bool ResolveExpression::visit(SimpleNameAST *ast) if (_autoDeclarationsBeingResolved.contains(decl)) continue; - newCandidates += - TypeResolver::resolveDeclInitializer(*_context.bindings(), decl, - _autoDeclarationsBeingResolved << decl, - ast->name->identifier()); + const StringLiteral *initializationString = decl->getInitializer(); + if (initializationString == 0) + continue; + + const QByteArray &initializer = + QByteArray::fromRawData(initializationString->chars(), + initializationString->size()).trimmed(); + + // Skip lambda-function initializers + if (initializer.length() > 0 && initializer[0] == '[') + continue; + + TypeOfExpression exprTyper; + exprTyper.setExpandTemplates(true); + Document::Ptr doc = _context.snapshot().document(QString::fromLocal8Bit(decl->fileName())); + exprTyper.init(doc, _context.snapshot(), _context.bindings(), + QSet(_autoDeclarationsBeingResolved) << decl); + + Document::Ptr exprDoc = + documentForExpression(exprTyper.preprocessedExpression(initializer)); + exprDoc->check(); + + DeduceAutoCheck deduceAuto(ast->name->identifier(), exprDoc->translationUnit()); + if (deduceAuto._block) + continue; + + const QList &typeItems = exprTyper(extractExpressionAST(exprDoc), exprDoc, + decl->enclosingScope()); + if (typeItems.empty()) + continue; + + Clone cloner(_context.bindings()->control().data()); + + for (int n = 0; n < typeItems.size(); ++ n) { + FullySpecifiedType newType = cloner.type(typeItems[n].type(), 0); + if (n == 0) { + item.setType(newType); + item.setScope(typeItems[n].scope()); + item.setBinding(typeItems[n].binding()); + } else { + LookupItem newItem(item); + newItem.setType(newType); + newItem.setScope(typeItems[n].scope()); + newItem.setBinding(typeItems[n].binding()); + newCandidates.push_back(newItem); + } + } } else { item.setType(item.declaration()->type()); item.setScope(item.declaration()->enclosingScope()); @@ -661,12 +873,14 @@ bool ResolveExpression::visit(CallAST *ast) Scope *scope = result.scope(); if (NamedType *namedTy = ty->asNamedType()) { - if (LookupScope *b = _context.lookupType(namedTy->name(), scope)) { + if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), scope)) { foreach (const LookupItem &r, b->find(functionCallOp)) { Symbol *overload = r.declaration(); if (Function *funTy = overload->type()->asFunctionType()) { - if (maybeValidPrototype(funTy, actualArgumentCount)) - addResult(funTy->returnType().simplified(), scope); + if (maybeValidPrototype(funTy, actualArgumentCount)) { + if (Function *proto = instantiate(namedTy->name(), funTy)->asFunctionType()) + addResult(proto->returnType().simplified(), scope); + } } } } @@ -679,6 +893,14 @@ bool ResolveExpression::visit(CallAST *ast) // Constructor call FullySpecifiedType ctorTy = control()->namedType(classTy->name()); addResult(ctorTy, scope); + } else if (Template *templateTy = ty->asTemplateType()) { + // template function + if (Symbol *declaration = templateTy->declaration()) { + if (Function *funTy = declaration->asFunction()) { + if (maybeValidPrototype(funTy, actualArgumentCount)) + addResult(funTy->returnType().simplified(), scope); + } + } } } @@ -694,8 +916,8 @@ bool ResolveExpression::visit(ArrayAccessAST *ast) FullySpecifiedType ty = result.type().simplified(); Scope *scope = result.scope(); - TypeResolver typeResolver(*_context.bindings()); - typeResolver.resolve(&ty, &scope, result.binding()); + TypedefsResolver typedefsResolver(_context); + typedefsResolver.resolve(&ty, &scope, result.binding()); if (PointerType *ptrTy = ty->asPointerType()) { addResult(ptrTy->elementType().simplified(), scope); @@ -704,12 +926,13 @@ bool ResolveExpression::visit(ArrayAccessAST *ast) addResult(arrTy->elementType().simplified(), scope); } else if (NamedType *namedTy = ty->asNamedType()) { - if (LookupScope *b = _context.lookupType(namedTy->name(), scope)) { + if (ClassOrNamespace *b = _context.lookupType(namedTy->name(), scope)) { foreach (const LookupItem &r, b->find(arrayAccessOp)) { Symbol *overload = r.declaration(); if (Function *funTy = overload->type()->asFunctionType()) { - // ### TODO: check the actual arguments - addResult(funTy->returnType().simplified(), scope); + if (Function *proto = instantiate(namedTy->name(), funTy)->asFunctionType()) + // ### TODO: check the actual arguments + addResult(proto->returnType().simplified(), scope); } } @@ -719,7 +942,7 @@ bool ResolveExpression::visit(ArrayAccessAST *ast) return false; } -QList ResolveExpression::getMembers(LookupScope *binding, const Name *memberName) const +QList ResolveExpression::getMembers(ClassOrNamespace *binding, const Name *memberName) const { Q_UNUSED(binding); Q_UNUSED(memberName); @@ -788,17 +1011,17 @@ bool ResolveExpression::visit(MemberAccessAST *ast) // Remember the access operator. const int accessOp = tokenKind(ast->access_token); - if (LookupScope *binding = baseExpression(baseResults, accessOp)) + if (ClassOrNamespace *binding = baseExpression(baseResults, accessOp)) addResults(binding->find(memberName)); return false; } -LookupScope *ResolveExpression::findClass(const FullySpecifiedType &originalTy, Scope *scope, - LookupScope *enclosingBinding) const +ClassOrNamespace *ResolveExpression::findClass(const FullySpecifiedType &originalTy, Scope *scope, + ClassOrNamespace *enclosingBinding) const { FullySpecifiedType ty = originalTy.simplified(); - LookupScope *binding = 0; + ClassOrNamespace *binding = 0; if (Class *klass = ty->asClassType()) { if (scope->isBlock()) @@ -816,14 +1039,15 @@ LookupScope *ResolveExpression::findClass(const FullySpecifiedType &originalTy, return binding; } -LookupScope *ResolveExpression::baseExpression(const QList &baseResults, - int accessOp, - bool *replacedDotOperator) const +ClassOrNamespace *ResolveExpression::baseExpression(const QList &baseResults, + int accessOp, + bool *replacedDotOperator) const { if (Q_UNLIKELY(debug)) qDebug() << "In ResolveExpression::baseExpression with" << baseResults.size() << "results..."; int i = 0; - TypeResolver typeResolver(*_context.bindings()); + Overview oo; + TypedefsResolver typedefsResolver(_context); foreach (const LookupItem &r, baseResults) { if (!r.type().type() || !r.scope()) @@ -832,55 +1056,80 @@ LookupScope *ResolveExpression::baseExpression(const QList &baseResu FullySpecifiedType originalType = ty; Scope *scope = r.scope(); - if (Q_UNLIKELY(debug)) + if (Q_UNLIKELY(debug)) { qDebug("trying result #%d", ++i); + qDebug() << "- before typedef resolving we have:" << oo(ty); + } + + typedefsResolver.resolve(&ty, &scope, r.binding()); - typeResolver.resolve(&ty, &scope, r.binding()); + if (Q_UNLIKELY(debug)) + qDebug() << "- after typedef resolving:" << oo(ty); if (accessOp == T_ARROW) { if (PointerType *ptrTy = ty->asPointerType()) { FullySpecifiedType type = ptrTy->elementType(); - if (LookupScope *binding = findClass(type, scope)) + if (ClassOrNamespace *binding + = findClassForTemplateParameterInExpressionScope(r.binding(), + type)) { + return binding; + } + if (ClassOrNamespace *binding = findClass(type, scope)) return binding; - } else if (LookupScope *binding = findClass(ty, scope, r.binding())) { - // lookup for overloads of operator-> - - const OperatorNameId *arrowOp - = control()->operatorNameId(OperatorNameId::ArrowOp); - foreach (const LookupItem &r, binding->find(arrowOp)) { - Symbol *overload = r.declaration(); - if (! overload) - continue; - Scope *functionScope = overload->enclosingScope(); + } else { + ClassOrNamespace *binding + = findClassForTemplateParameterInExpressionScope(r.binding(), + ty); - if (Function *funTy = overload->type()->asFunctionType()) { - FullySpecifiedType retTy = funTy->returnType().simplified(); + if (! binding) + binding = findClass(ty, scope, r.binding()); - typeResolver.resolve(&retTy, &functionScope, r.binding()); + if (binding){ + // lookup for overloads of operator-> - if (! retTy->isPointerType() && ! retTy->isNamedType()) + const OperatorNameId *arrowOp + = control()->operatorNameId(OperatorNameId::ArrowOp); + foreach (const LookupItem &r, binding->find(arrowOp)) { + Symbol *overload = r.declaration(); + if (! overload) continue; + Scope *functionScope = overload->enclosingScope(); + + if (overload->type()->isFunctionType()) { + FullySpecifiedType overloadTy + = instantiate(binding->templateId(), overload); + Function *instantiatedFunction = overloadTy->asFunctionType(); + Q_ASSERT(instantiatedFunction != 0); + + FullySpecifiedType retTy + = instantiatedFunction->returnType().simplified(); + + typedefsResolver.resolve(&retTy, &functionScope, r.binding()); - if (PointerType *ptrTy = retTy->asPointerType()) - retTy = ptrTy->elementType(); + if (! retTy->isPointerType() && ! retTy->isNamedType()) + continue; - if (LookupScope *retBinding = findClass(retTy, functionScope)) - return retBinding; + if (PointerType *ptrTy = retTy->asPointerType()) + retTy = ptrTy->elementType(); - if (scope != functionScope) { - if (LookupScope *retBinding = findClass(retTy, scope)) + if (ClassOrNamespace *retBinding = findClass(retTy, functionScope)) return retBinding; - } - if (LookupScope *origin = binding->instantiationOrigin()) { - foreach (Symbol *originSymbol, origin->symbols()) { - Scope *originScope = originSymbol->asScope(); - if (originScope && originScope != scope - && originScope != functionScope) { - if (LookupScope *retBinding - = findClass(retTy, originScope)) - return retBinding; + if (scope != functionScope) { + if (ClassOrNamespace *retBinding = findClass(retTy, scope)) + return retBinding; + } + + if (ClassOrNamespace *origin = binding->instantiationOrigin()) { + foreach (Symbol *originSymbol, origin->symbols()) { + Scope *originScope = originSymbol->asScope(); + if (originScope && originScope != scope + && originScope != functionScope) { + if (ClassOrNamespace *retBinding + = findClass(retTy, originScope)) + return retBinding; + } } } } @@ -894,13 +1143,19 @@ LookupScope *ResolveExpression::baseExpression(const QList &baseResu ty = ptrTy->elementType(); } - LookupScope *enclosingBinding = 0; - if (LookupScope *binding = r.binding()) { + if (ClassOrNamespace *binding + = findClassForTemplateParameterInExpressionScope(r.binding(), + ty)) { + return binding; + } + + ClassOrNamespace *enclosingBinding = 0; + if (ClassOrNamespace *binding = r.binding()) { if (binding->instantiationOrigin()) enclosingBinding = binding; } - if (LookupScope *binding = findClass(ty, scope, enclosingBinding)) + if (ClassOrNamespace *binding = findClass(ty, scope, enclosingBinding)) return binding; } } @@ -908,6 +1163,30 @@ LookupScope *ResolveExpression::baseExpression(const QList &baseResu return 0; } +ClassOrNamespace *ResolveExpression::findClassForTemplateParameterInExpressionScope( + ClassOrNamespace *resultBinding, + const FullySpecifiedType &ty) const +{ + if (resultBinding) { + if (ClassOrNamespace *origin = resultBinding->instantiationOrigin()) { + foreach (Symbol *originSymbol, origin->symbols()) { + if (Scope *originScope = originSymbol->asScope()) { + if (ClassOrNamespace *retBinding = findClass(ty, originScope)) + return retBinding; + } + } + } + } + + return 0; +} + +FullySpecifiedType ResolveExpression::instantiate(const Name *className, Symbol *candidate) const +{ + return DeprecatedGenTemplateInstance::instantiate(className, candidate, + _context.bindings()->control()); +} + bool ResolveExpression::visit(PostIncrDecrAST *ast) { const QList baseResults = resolve(ast->base_expression, _scope); @@ -921,7 +1200,7 @@ bool ResolveExpression::visit(ObjCMessageExpressionAST *ast) foreach (const LookupItem &result, receiverResults) { FullySpecifiedType ty = result.type().simplified(); - LookupScope *binding = 0; + ClassOrNamespace *binding = 0; if (ObjCClass *clazz = ty->asObjCClassType()) { // static access, e.g.: diff --git a/src/libs/cplusplus/ResolveExpression.h b/src/libs/cplusplus/ResolveExpression.h index df9ea22020..aee53c40fa 100644 --- a/src/libs/cplusplus/ResolveExpression.h +++ b/src/libs/cplusplus/ResolveExpression.h @@ -53,25 +53,26 @@ public: QList resolve(ExpressionAST *ast, Scope *scope, bool ref = false); QList reference(ExpressionAST *ast, Scope *scope); - LookupScope *baseExpression(const QList &baseResults, + ClassOrNamespace *baseExpression(const QList &baseResults, int accessOp, bool *replacedDotOperator = 0) const; const LookupContext &context() const; protected: - LookupScope *findClass(const FullySpecifiedType &ty, Scope *scope, - LookupScope *enclosingBinding = 0) const; + ClassOrNamespace *findClass(const FullySpecifiedType &ty, Scope *scope, + ClassOrNamespace *enclosingBinding = 0) const; QList expression(ExpressionAST *ast); QList switchResults(const QList &symbols); + FullySpecifiedType instantiate(const Name *className, Symbol *candidate) const; - QList getMembers(LookupScope *binding, const Name *memberName) const; + QList getMembers(ClassOrNamespace *binding, const Name *memberName) const; void thisObject(); - void addResult(const FullySpecifiedType &ty, Scope *scope, LookupScope *binding = 0); + void addResult(const FullySpecifiedType &ty, Scope *scope, ClassOrNamespace *binding = 0); void addResults(const QList &symbols); void addResults(const QList &items); @@ -125,6 +126,10 @@ protected: private: + ClassOrNamespace *findClassForTemplateParameterInExpressionScope( + ClassOrNamespace *resultBinding, + const FullySpecifiedType &ty) const; + Scope *_scope; const LookupContext& _context; Bind bind; diff --git a/src/libs/cplusplus/TypeOfExpression.cpp b/src/libs/cplusplus/TypeOfExpression.cpp index bc0792262a..8d5be1b251 100644 --- a/src/libs/cplusplus/TypeOfExpression.cpp +++ b/src/libs/cplusplus/TypeOfExpression.cpp @@ -50,7 +50,7 @@ TypeOfExpression::TypeOfExpression(): } void TypeOfExpression::init(Document::Ptr thisDocument, const Snapshot &snapshot, - CreateBindings::Ptr bindings, + QSharedPointer bindings, const QSet &autoDeclarationsBeingResolved) { m_thisDocument = thisDocument; @@ -62,7 +62,7 @@ void TypeOfExpression::init(Document::Ptr thisDocument, const Snapshot &snapshot Q_ASSERT(m_bindings.isNull()); m_bindings = bindings; if (m_bindings.isNull()) - m_bindings = CreateBindings::Ptr(new CreateBindings(thisDocument, snapshot)); + m_bindings = QSharedPointer(new CreateBindings(thisDocument, snapshot)); m_environment.clear(); m_autoDeclarationsBeingResolved = autoDeclarationsBeingResolved; @@ -105,7 +105,7 @@ QList TypeOfExpression::operator()(ExpressionAST *expression, m_scope = scope; - m_bindings->addExpressionDocument(document); + m_documents.append(document); m_lookupContext = LookupContext(document, m_thisDocument, m_snapshot, m_bindings); Q_ASSERT(!m_bindings.isNull()); m_lookupContext.setExpandTemplates(m_expandTemplates); @@ -122,7 +122,7 @@ QList TypeOfExpression::reference(ExpressionAST *expression, m_scope = scope; - m_bindings->addExpressionDocument(document); + m_documents.append(document); m_lookupContext = LookupContext(document, m_thisDocument, m_snapshot, m_bindings); Q_ASSERT(!m_bindings.isNull()); m_lookupContext.setExpandTemplates(m_expandTemplates); diff --git a/src/libs/cplusplus/TypeOfExpression.h b/src/libs/cplusplus/TypeOfExpression.h index 0308f9a45e..158b3e9815 100644 --- a/src/libs/cplusplus/TypeOfExpression.h +++ b/src/libs/cplusplus/TypeOfExpression.h @@ -62,7 +62,7 @@ public: */ void init(Document::Ptr thisDocument, const Snapshot &snapshot, - CreateBindings::Ptr bindings = CreateBindings::Ptr(), + QSharedPointer bindings = QSharedPointer(), const QSet &autoDeclarationsBeingResolved = QSet()); @@ -135,6 +135,7 @@ public: } private: + void processEnvironment(Document::Ptr doc, Environment *env, QSet *processed) const; @@ -142,13 +143,20 @@ private: private: Document::Ptr m_thisDocument; Snapshot m_snapshot; - CreateBindings::Ptr m_bindings; + QSharedPointer m_bindings; ExpressionAST *m_ast; Scope *m_scope; LookupContext m_lookupContext; mutable QSharedPointer m_environment; - QSet m_autoDeclarationsBeingResolved; + bool m_expandTemplates; + + // FIXME: This is a temporary hack to avoid dangling pointers. + // Keep the expression documents and thus all the symbols and + // their types alive until they are not needed any more. + QList m_documents; + + QSet m_autoDeclarationsBeingResolved; }; ExpressionAST CPLUSPLUS_EXPORT *extractExpressionAST(Document::Ptr doc); diff --git a/src/libs/cplusplus/TypeResolver.cpp b/src/libs/cplusplus/TypeResolver.cpp deleted file mode 100644 index 1be33f1410..0000000000 --- a/src/libs/cplusplus/TypeResolver.cpp +++ /dev/null @@ -1,262 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms and -** conditions see http://www.qt.io/terms-conditions. For further information -** use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "TypeResolver.h" -#include "Overview.h" -#include "TypeOfExpression.h" - -#include - -static const bool debug = ! qgetenv("QTC_LOOKUPCONTEXT_DEBUG").isEmpty(); - -namespace CPlusPlus { - -namespace { - -class DeduceAutoCheck : public ASTVisitor -{ -public: - DeduceAutoCheck(const Identifier *id, TranslationUnit *tu) - : ASTVisitor(tu), _id(id), _block(false) - { - accept(tu->ast()); - } - - virtual bool preVisit(AST *) - { - if (_block) - return false; - - return true; - } - - virtual bool visit(SimpleNameAST *ast) - { - if (ast->name - && ast->name->identifier() - && strcmp(ast->name->identifier()->chars(), _id->chars()) == 0) { - _block = true; - } - - return false; - } - - virtual bool visit(MemberAccessAST *ast) - { - accept(ast->base_expression); - return false; - } - - const Identifier *_id; - bool _block; -}; - -} // namespace anonymous - -void TypeResolver::resolve(FullySpecifiedType *type, Scope **scope, LookupScope *binding) -{ - QSet visited; - _binding = binding; - // Use a hard limit when trying to resolve typedefs. Typedefs in templates can refer to - // each other, each time enhancing the template argument and thus making it impossible to - // use an "alreadyResolved" container. FIXME: We might overcome this by resolving the - // template parameters. - unsigned maxDepth = 15; - Overview oo; - if (Q_UNLIKELY(debug)) - qDebug() << "- before typedef resolving we have:" << oo(*type); - for (NamedType *namedTy = 0; maxDepth && (namedTy = getNamedType(*type)); --maxDepth) { - QList namedTypeItems = getNamedTypeItems(namedTy->name(), *scope, _binding); - - if (Q_UNLIKELY(debug)) - qDebug() << "-- we have" << namedTypeItems.size() << "candidates"; - - if (!findTypedef(namedTypeItems, type, scope, visited)) - break; - } - if (Q_UNLIKELY(debug)) - qDebug() << "- after typedef resolving:" << oo(*type); -} - -NamedType *TypeResolver::getNamedType(FullySpecifiedType &type) const -{ - NamedType *namedTy = type->asNamedType(); - if (! namedTy) { - if (PointerType *pointerTy = type->asPointerType()) - namedTy = pointerTy->elementType()->asNamedType(); - } - return namedTy; -} - -QList TypeResolver::getNamedTypeItems(const Name *name, Scope *scope, - LookupScope *binding) const -{ - QList namedTypeItems = typedefsFromScopeUpToFunctionScope(name, scope); - if (namedTypeItems.isEmpty()) { - if (binding) - namedTypeItems = binding->lookup(name); - if (LookupScope *scopeCon = _factory.lookupType(scope)) { - if (scopeCon != binding) - namedTypeItems += scopeCon->lookup(name); - } - } - - return namedTypeItems; -} - -/// Return all typedefs with given name from given scope up to function scope. -QList TypeResolver::typedefsFromScopeUpToFunctionScope(const Name *name, Scope *scope) -{ - QList results; - if (!scope) - return results; - Scope *enclosingBlockScope = 0; - for (Block *block = scope->asBlock(); block; - block = enclosingBlockScope ? enclosingBlockScope->asBlock() : 0) { - const unsigned memberCount = block->memberCount(); - for (unsigned i = 0; i < memberCount; ++i) { - Symbol *symbol = block->memberAt(i); - if (Declaration *declaration = symbol->asDeclaration()) { - if (isTypedefWithName(declaration, name)) { - LookupItem item; - item.setDeclaration(declaration); - item.setScope(block); - item.setType(declaration->type()); - results.append(item); - } - } - } - enclosingBlockScope = block->enclosingScope(); - if (enclosingBlockScope) { - // For lambda, step beyond the function to its enclosing block - if (Function *enclosingFunction = enclosingBlockScope->asFunction()) { - if (!enclosingFunction->name()) - enclosingBlockScope = enclosingBlockScope->enclosingScope(); - } - } - } - return results; -} - -// Resolves auto and decltype initializer string -QList TypeResolver::resolveDeclInitializer( - CreateBindings &factory, const Declaration *decl, - const QSet &declarationsBeingResolved, - const Identifier *id) -{ - const StringLiteral *initializationString = decl->getInitializer(); - if (initializationString == 0) - return QList(); - - const QByteArray &initializer = - QByteArray::fromRawData(initializationString->chars(), - initializationString->size()).trimmed(); - - // Skip lambda-function initializers - if (initializer.length() > 0 && initializer[0] == '[') - return QList(); - - TypeOfExpression exprTyper; - exprTyper.setExpandTemplates(true); - Document::Ptr doc = factory.snapshot().document(QString::fromLocal8Bit(decl->fileName())); - exprTyper.init(doc, factory.snapshot(), factory.sharedFromThis(), declarationsBeingResolved); - - Document::Ptr exprDoc = - documentForExpression(exprTyper.preprocessedExpression(initializer)); - factory.addExpressionDocument(exprDoc); - exprDoc->check(); - - if (id) { - DeduceAutoCheck deduceAuto(id, exprDoc->translationUnit()); - if (deduceAuto._block) - return QList(); - } - - return exprTyper(extractExpressionAST(exprDoc), exprDoc, decl->enclosingScope()); -} - -bool TypeResolver::isTypedefWithName(const Declaration *declaration, const Name *name) -{ - if (declaration->isTypedef()) { - const Identifier *identifier = declaration->name()->identifier(); - if (name->identifier()->match(identifier)) - return true; - } - return false; -} - -bool TypeResolver::findTypedef(const QList &namedTypeItems, FullySpecifiedType *type, - Scope **scope, QSet &visited) -{ - foreach (const LookupItem &it, namedTypeItems) { - Symbol *declaration = it.declaration(); - if (!declaration) - continue; - if (Template *specialization = declaration->asTemplate()) - declaration = specialization->declaration(); - if (!declaration || (!declaration->isTypedef() && !declaration->type().isDecltype())) - continue; - if (visited.contains(declaration)) - break; - visited.insert(declaration); - - // continue working with the typedefed type and scope - if (type->type()->isPointerType()) { - *type = FullySpecifiedType( - _factory.control()->pointerType(declaration->type())); - } else if (type->type()->isReferenceType()) { - *type = FullySpecifiedType( - _factory.control()->referenceType( - declaration->type(), - declaration->type()->asReferenceType()->isRvalueReference())); - } else if (declaration->type().isDecltype()) { - Declaration *decl = declaration->asDeclaration(); - const QList resolved = - resolveDeclInitializer(_factory, decl, QSet() << decl); - if (!resolved.isEmpty()) { - LookupItem item = resolved.first(); - *type = item.type(); - *scope = item.scope(); - _binding = item.binding(); - return true; - } - } else { - *type = it.type(); - } - - *scope = it.scope(); - _binding = it.binding(); - return true; - } - - return false; -} - -} // namespace CPlusPlus diff --git a/src/libs/cplusplus/TypeResolver.h b/src/libs/cplusplus/TypeResolver.h deleted file mode 100644 index bf25e468c6..0000000000 --- a/src/libs/cplusplus/TypeResolver.h +++ /dev/null @@ -1,68 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms and -** conditions see http://www.qt.io/terms-conditions. For further information -** use the contact form at http://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef TYPERESOLVER_H -#define TYPERESOLVER_H - -#include "LookupContext.h" - -namespace CPlusPlus { - -class TypeResolver -{ -public: - TypeResolver(CreateBindings &factory) : _factory(factory) {} - void resolve(FullySpecifiedType *type, Scope **scope, LookupScope *binding); - static QList resolveDeclInitializer( - CreateBindings &factory, const Declaration *decl, - const QSet &declarationsBeingResolved, - const Identifier *id = 0); - -private: - NamedType *getNamedType(FullySpecifiedType& type) const; - - QList getNamedTypeItems(const Name *name, Scope *scope, - LookupScope *binding) const; - - static QList typedefsFromScopeUpToFunctionScope(const Name *name, Scope *scope); - - static bool isTypedefWithName(const Declaration *declaration, const Name *name); - - bool findTypedef(const QList& namedTypeItems, FullySpecifiedType *type, - Scope **scope, QSet& visited); - - CreateBindings &_factory; - // binding has to be remembered in case of resolving typedefs for templates - LookupScope *_binding; -}; - -} // namespace CPlusPlus - -#endif // TYPERESOLVER_H diff --git a/src/libs/cplusplus/cplusplus-lib.pri b/src/libs/cplusplus/cplusplus-lib.pri index ebb5ad07f1..0e5bed22e0 100644 --- a/src/libs/cplusplus/cplusplus-lib.pri +++ b/src/libs/cplusplus/cplusplus-lib.pri @@ -36,7 +36,6 @@ HEADERS += \ $$PWD/NamePrettyPrinter.h \ $$PWD/TypeOfExpression.h \ $$PWD/TypePrettyPrinter.h \ - $$PWD/TypeResolver.h \ $$PWD/ResolveExpression.h \ $$PWD/LookupItem.h \ $$PWD/AlreadyConsideredClassContainer.h \ @@ -45,6 +44,7 @@ HEADERS += \ $$PWD/ASTPath.h \ $$PWD/SnapshotSymbolVisitor.h \ $$PWD/SymbolNameVisitor.h \ + $$PWD/DeprecatedGenTemplateInstance.h \ $$PWD/FindUsages.h \ $$PWD/DependencyTable.h \ $$PWD/PreprocessorClient.h \ @@ -67,7 +67,6 @@ SOURCES += \ $$PWD/NamePrettyPrinter.cpp \ $$PWD/TypeOfExpression.cpp \ $$PWD/TypePrettyPrinter.cpp \ - $$PWD/TypeResolver.cpp \ $$PWD/ResolveExpression.cpp \ $$PWD/LookupItem.cpp \ $$PWD/LookupContext.cpp \ @@ -75,6 +74,7 @@ SOURCES += \ $$PWD/ASTPath.cpp \ $$PWD/SnapshotSymbolVisitor.cpp \ $$PWD/SymbolNameVisitor.cpp \ + $$PWD/DeprecatedGenTemplateInstance.cpp \ $$PWD/FindUsages.cpp \ $$PWD/DependencyTable.cpp \ $$PWD/PreprocessorClient.cpp \ diff --git a/src/libs/cplusplus/cplusplus.qbs b/src/libs/cplusplus/cplusplus.qbs index 8ac08217eb..dd4012d633 100644 --- a/src/libs/cplusplus/cplusplus.qbs +++ b/src/libs/cplusplus/cplusplus.qbs @@ -96,6 +96,7 @@ QtcLibrary { "CppRewriter.cpp", "CppRewriter.h", "cppmodelmanagerbase.cpp", "cppmodelmanagerbase.h", "DependencyTable.cpp", "DependencyTable.h", + "DeprecatedGenTemplateInstance.cpp", "DeprecatedGenTemplateInstance.h", "ExpressionUnderCursor.cpp", "ExpressionUnderCursor.h", "FastPreprocessor.cpp", "FastPreprocessor.h", "FindUsages.cpp", "FindUsages.h", @@ -116,7 +117,6 @@ QtcLibrary { "SymbolNameVisitor.cpp", "SymbolNameVisitor.h", "TypeOfExpression.cpp", "TypeOfExpression.h", "TypePrettyPrinter.cpp", "TypePrettyPrinter.h", - "TypeResolver.cpp", "TypeResolver.h", "cplusplus.qrc", "findcdbbreakpoint.cpp", "findcdbbreakpoint.h", "pp-cctype.h", diff --git a/src/libs/qmljs/qmljsfindexportedcpptypes.cpp b/src/libs/qmljs/qmljsfindexportedcpptypes.cpp index f7edb410d2..cf1dde0819 100644 --- a/src/libs/qmljs/qmljsfindexportedcpptypes.cpp +++ b/src/libs/qmljs/qmljsfindexportedcpptypes.cpp @@ -795,7 +795,7 @@ static void buildContextProperties( Scope *typeScope = result.scope(); if (!typeScope) typeScope = scope; // incorrect but may be an ok fallback - LookupScope *binding = typeOf.context().lookupType(namedType->name(), typeScope); + ClassOrNamespace *binding = typeOf.context().lookupType(namedType->name(), typeScope); if (binding && !binding->symbols().isEmpty()) { // find the best 'Class' symbol for (int i = binding->symbols().size() - 1; i >= 0; --i) { diff --git a/src/plugins/cppeditor/cppeditor.cpp b/src/plugins/cppeditor/cppeditor.cpp index 81c7dc7158..2abdef298b 100644 --- a/src/plugins/cppeditor/cppeditor.cpp +++ b/src/plugins/cppeditor/cppeditor.cpp @@ -387,7 +387,7 @@ void CppEditorWidget::switchDeclarationDefinition(bool inNextSplit) } else if (functionDefinitionSymbol) { const Snapshot snapshot = d->m_modelManager->snapshot(); LookupContext context(d->m_lastSemanticInfo.doc, snapshot); - LookupScope *binding = context.lookupType(functionDefinitionSymbol); + ClassOrNamespace *binding = context.lookupType(functionDefinitionSymbol); const QList declarations = context.lookup(functionDefinitionSymbol->name(), functionDefinitionSymbol->enclosingScope()); diff --git a/src/plugins/cppeditor/cppelementevaluator.cpp b/src/plugins/cppeditor/cppelementevaluator.cpp index 97b25d723f..6740b935cc 100644 --- a/src/plugins/cppeditor/cppelementevaluator.cpp +++ b/src/plugins/cppeditor/cppelementevaluator.cpp @@ -331,10 +331,10 @@ bool CppClass::operator==(const CppClass &other) void CppClass::lookupBases(Symbol *declaration, const LookupContext &context) { - typedef QPair Data; + typedef QPair Data; - if (LookupScope *clazz = context.lookupType(declaration)) { - QSet visited; + if (ClassOrNamespace *clazz = context.lookupType(declaration)) { + QSet visited; QQueue q; q.enqueue(qMakePair(clazz, this)); @@ -342,8 +342,8 @@ void CppClass::lookupBases(Symbol *declaration, const LookupContext &context) Data current = q.dequeue(); clazz = current.first; visited.insert(clazz); - const QList &bases = clazz->usings(); - foreach (LookupScope *baseClass, bases) { + const QList &bases = clazz->usings(); + foreach (ClassOrNamespace *baseClass, bases) { const QList &symbols = baseClass->symbols(); foreach (Symbol *symbol, symbols) { if (symbol->isClass() && ( @@ -433,7 +433,7 @@ CppVariable::CppVariable(Symbol *declaration, const LookupContext &context, Scop } if (typeName) { - if (LookupScope *clazz = context.lookupType(typeName, scope)) { + if (ClassOrNamespace *clazz = context.lookupType(typeName, scope)) { if (!clazz->symbols().isEmpty()) { Overview overview; Symbol *symbol = clazz->symbols().at(0); diff --git a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp index a166e8d641..407252ca50 100644 --- a/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp +++ b/src/plugins/cppeditor/cppfollowsymbolundercursor.cpp @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include @@ -184,7 +183,7 @@ Class *VirtualFunctionHelper::staticClassOfFunctionCallExpression_internal() con const QList items = m_typeOfExpression(memberAccessAST->base_expression, m_expressionDocument, m_scope); ResolveExpression resolveExpression(m_typeOfExpression.context()); - LookupScope *binding = resolveExpression.baseExpression(items, m_accessTokenKind); + ClassOrNamespace *binding = resolveExpression.baseExpression(items, m_accessTokenKind); if (binding) { if (Class *klass = binding->rootClass()) { result = klass; diff --git a/src/plugins/cppeditor/cppfunctiondecldeflink.cpp b/src/plugins/cppeditor/cppfunctiondecldeflink.cpp index dfb0b1018a..4c359ed9b6 100644 --- a/src/plugins/cppeditor/cppfunctiondecldeflink.cpp +++ b/src/plugins/cppeditor/cppfunctiondecldeflink.cpp @@ -607,7 +607,7 @@ ChangeSet FunctionDeclDefLink::changes(const Snapshot &snapshot, int targetOffse SubstitutionEnvironment env; env.setContext(sourceContext); env.switchScope(sourceFunction->enclosingScope()); - LookupScope *targetCoN = targetContext.lookupType(targetFunction->enclosingScope()); + ClassOrNamespace *targetCoN = targetContext.lookupType(targetFunction->enclosingScope()); if (!targetCoN) targetCoN = targetContext.globalNamespace(); UseMinimalNames q(targetCoN); @@ -653,7 +653,7 @@ ChangeSet FunctionDeclDefLink::changes(const Snapshot &snapshot, int targetOffse SubstitutionEnvironment env; env.setContext(sourceContext); env.switchScope(sourceFunction); - LookupScope *targetCoN = targetContext.lookupType(targetFunction); + ClassOrNamespace *targetCoN = targetContext.lookupType(targetFunction); if (!targetCoN) targetCoN = targetContext.globalNamespace(); UseMinimalNames q(targetCoN); diff --git a/src/plugins/cppeditor/cppinsertvirtualmethods.cpp b/src/plugins/cppeditor/cppinsertvirtualmethods.cpp index ab6d15ead4..222d8a90ff 100644 --- a/src/plugins/cppeditor/cppinsertvirtualmethods.cpp +++ b/src/plugins/cppeditor/cppinsertvirtualmethods.cpp @@ -566,15 +566,15 @@ public: // Determine base classes QList baseClasses; - QQueue baseClassQueue; - QSet visitedBaseClasses; - if (LookupScope *clazz = interface.context().lookupType(m_classAST->symbol)) + QQueue baseClassQueue; + QSet visitedBaseClasses; + if (ClassOrNamespace *clazz = interface.context().lookupType(m_classAST->symbol)) baseClassQueue.enqueue(clazz); while (!baseClassQueue.isEmpty()) { - LookupScope *clazz = baseClassQueue.dequeue(); + ClassOrNamespace *clazz = baseClassQueue.dequeue(); visitedBaseClasses.insert(clazz); - const QList bases = clazz->usings(); - foreach (LookupScope *baseClass, bases) { + const QList bases = clazz->usings(); + foreach (ClassOrNamespace *baseClass, bases) { foreach (Symbol *symbol, baseClass->symbols()) { Class *base = symbol->asClass(); if (base @@ -768,7 +768,7 @@ public: const LookupContext targetContext(headerFile->cppDocument(), snapshot()); const Class *targetClass = m_classAST->symbol; - LookupScope *targetCoN = targetContext.lookupType(targetClass->enclosingScope()); + ClassOrNamespace *targetCoN = targetContext.lookupType(targetClass->enclosingScope()); if (!targetCoN) targetCoN = targetContext.globalNamespace(); UseMinimalNames useMinimalNames(targetCoN); @@ -865,7 +865,7 @@ public: implementationDoc->translationUnit()->getPosition(insertPos, &line, &column); Scope *targetScope = implementationDoc->scopeAt(line, column); const LookupContext targetContext(implementationDoc, snapshot()); - LookupScope *targetCoN = targetContext.lookupType(targetScope); + ClassOrNamespace *targetCoN = targetContext.lookupType(targetScope); if (!targetCoN) targetCoN = targetContext.globalNamespace(); diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index 176afcb7f9..9ef84adad2 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -219,7 +219,7 @@ Class *isMemberFunction(const LookupContext &context, Function *function) if (!q->base()) return 0; - if (LookupScope *binding = context.lookupType(q->base(), enclosingScope)) { + if (ClassOrNamespace *binding = context.lookupType(q->base(), enclosingScope)) { foreach (Symbol *s, binding->symbols()) { if (Class *matchingClass = s->asClass()) return matchingClass; @@ -257,7 +257,7 @@ Namespace *isNamespaceFunction(const LookupContext &context, Function *function) if (!q->base()) return 0; - if (LookupScope *binding = context.lookupType(q->base(), enclosingScope)) { + if (ClassOrNamespace *binding = context.lookupType(q->base(), enclosingScope)) { foreach (Symbol *s, binding->symbols()) { if (Namespace *matchingNamespace = s->asNamespace()) return matchingNamespace; @@ -1331,7 +1331,7 @@ void TranslateStringLiteral::match(const CppQuickFixInterface &interface, for (int i = path.size() - 1; i >= 0; --i) { if (FunctionDefinitionAST *definition = path.at(i)->asFunctionDefinition()) { Function *function = definition->symbol; - LookupScope *b = interface.context().lookupType(function); + ClassOrNamespace *b = interface.context().lookupType(function); if (b) { // Do we have a tr function? foreach (const LookupItem &r, b->find(trName)) { @@ -1592,7 +1592,7 @@ public: SubstitutionEnvironment env; env.setContext(context()); env.switchScope(result.first().scope()); - LookupScope *con = typeOfExpression.context().lookupType(scope); + ClassOrNamespace *con = typeOfExpression.context().lookupType(scope); if (!con) con = typeOfExpression.context().globalNamespace(); UseMinimalNames q(con); @@ -2284,7 +2284,7 @@ Enum *findEnum(const QList &results, const LookupContext &ctxt) if (Enum *e = type->asEnumType()) return e; if (const NamedType *namedType = type->asNamedType()) { - if (LookupScope *con = ctxt.lookupType(namedType->name(), result.scope())) { + if (ClassOrNamespace *con = ctxt.lookupType(namedType->name(), result.scope())) { const QList enums = con->unscopedEnums(); const Name *referenceName = namedType->name(); if (const QualifiedNameId *qualifiedName = referenceName->asQualifiedNameId()) @@ -2581,7 +2581,7 @@ public: Document::Ptr targetDoc = targetFile->cppDocument(); Scope *targetScope = targetDoc->scopeAt(m_loc.line(), m_loc.column()); LookupContext targetContext(targetDoc, snapshot()); - LookupScope *targetCoN = targetContext.lookupType(targetScope); + ClassOrNamespace *targetCoN = targetContext.lookupType(targetScope); if (!targetCoN) targetCoN = targetContext.globalNamespace(); @@ -3215,7 +3215,7 @@ public: SubstitutionEnvironment env; env.setContext(context()); env.switchScope(refFunc); - LookupScope *targetCoN = context().lookupType(refFunc->enclosingScope()); + ClassOrNamespace *targetCoN = context().lookupType(refFunc->enclosingScope()); if (!targetCoN) targetCoN = context().globalNamespace(); UseMinimalNames subs(targetCoN); @@ -4644,7 +4644,7 @@ QString definitionSignature(const CppQuickFixInterface *assist, QTC_ASSERT(func, return QString()); LookupContext cppContext(targetFile->cppDocument(), assist->snapshot()); - LookupScope *cppCoN = cppContext.lookupType(scope); + ClassOrNamespace *cppCoN = cppContext.lookupType(scope); if (!cppCoN) cppCoN = cppContext.globalNamespace(); SubstitutionEnvironment env; @@ -5125,7 +5125,7 @@ public: SubstitutionEnvironment env; env.setContext(context()); env.switchScope(result.first().scope()); - LookupScope *con = typeOfExpression.context().lookupType(scope); + ClassOrNamespace *con = typeOfExpression.context().lookupType(scope); if (!con) con = typeOfExpression.context().globalNamespace(); UseMinimalNames q(con); @@ -5724,7 +5724,7 @@ PointerType *determineConvertedType(NamedType *namedType, const LookupContext &c { if (!namedType) return 0; - if (LookupScope *binding = context.lookupType(namedType->name(), scope)) { + if (ClassOrNamespace *binding = context.lookupType(namedType->name(), scope)) { if (Symbol *objectClassSymbol = skipForwardDeclarations(binding->symbols())) { if (Class *klass = objectClassSymbol->asClass()) { for (auto it = klass->memberBegin(), end = klass->memberEnd(); it != end; ++it) { @@ -5782,7 +5782,7 @@ Class *senderOrReceiverClass(const CppQuickFixInterface &interface, NamedType *objectType = objectTypeBase->asNamedType(); QTC_ASSERT(objectType, return 0); - LookupScope *objectClassCON = context.lookupType(objectType->name(), objectPointerScope); + ClassOrNamespace *objectClassCON = context.lookupType(objectType->name(), objectPointerScope); QTC_ASSERT(objectClassCON, return 0); QTC_ASSERT(!objectClassCON->symbols().isEmpty(), return 0); @@ -5834,7 +5834,7 @@ bool findConnectReplacement(const CppQuickFixInterface &interface, // Minimize qualification Control *control = context.bindings()->control().data(); - LookupScope *functionCON = context.lookupParent(scope); + ClassOrNamespace *functionCON = context.lookupParent(scope); const Name *shortName = LookupContext::minimalName(method, functionCON, control); if (!shortName->asQualifiedNameId()) shortName = control->qualifiedNameId(classOfMethod->name(), shortName); diff --git a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp index 61828f1631..3b4ba8baf5 100644 --- a/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp +++ b/src/plugins/cppeditor/cppvirtualfunctionassistprovider.cpp @@ -152,8 +152,8 @@ public: QTC_ASSERT(m_params.staticClass, return 0); QTC_ASSERT(!m_params.snapshot.isEmpty(), return 0); - Class *functionsClass = m_finder.findMatchingClassDeclaration( - m_params.function, m_params.snapshot, &m_params.typeOfExpression->context()); + Class *functionsClass = m_finder.findMatchingClassDeclaration(m_params.function, + m_params.snapshot); if (!functionsClass) return 0; diff --git a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp index 956b02b5d9..fbcda2628e 100644 --- a/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp +++ b/src/plugins/cppeditor/followsymbol_switchmethoddecldef_test.cpp @@ -972,20 +972,6 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_data() "template\n" "using Foo = Bar<@T>;\n" ); - - QTest::newRow("qualifiedNames") << _( - "struct C\n" - "{\n" - " struct Nested { int $member; };\n" - " void f();\n" - "};\n" - "\n" - "void C::f()\n" - "{\n" - " C::Nested object;\n" - " object.@member;\n" - "}\n" - ); } void CppEditorPlugin::test_FollowSymbolUnderCursor() @@ -1390,7 +1376,7 @@ void CppEditorPlugin::test_FollowSymbolUnderCursor_virtualFunctionCall_data() "template struct A { virtual void virt() {} };\n" "void f(A *l) { l->$@virt(); }\n") << (OverrideItemList() - << OverrideItem(QLatin1String("A::virt"), 1)); + << OverrideItem(QLatin1String("A::virt"), 1)); /// Check: Static type is nicely resolved, especially for QSharedPointers. QTest::newRow("QSharedPointer") << _( diff --git a/src/plugins/cpptools/cppchecksymbols.cpp b/src/plugins/cpptools/cppchecksymbols.cpp index acf3d5c86f..cbc6baf75e 100644 --- a/src/plugins/cpptools/cppchecksymbols.cpp +++ b/src/plugins/cpptools/cppchecksymbols.cpp @@ -669,7 +669,7 @@ bool CheckSymbols::visit(NewExpressionAST *ast) if (highlightCtorDtorAsType) { accept(ast->new_type_id); } else { - LookupScope *binding = 0; + ClassOrNamespace *binding = 0; NameAST *nameAST = 0; if (ast->new_type_id) { for (SpecifierListAST *it = ast->new_type_id->type_specifier_list; it; it = it->next) { @@ -735,7 +735,7 @@ void CheckSymbols::checkNamespace(NameAST *name) unsigned line, column; getTokenStartPosition(name->firstToken(), &line, &column); - if (LookupScope *b = _context.lookupType(name->name, enclosingScope())) { + if (ClassOrNamespace *b = _context.lookupType(name->name, enclosingScope())) { foreach (Symbol *s, b->symbols()) { if (s->isNamespace()) return; @@ -768,14 +768,14 @@ bool CheckSymbols::hasVirtualDestructor(Class *klass) const return false; } -bool CheckSymbols::hasVirtualDestructor(LookupScope *binding) const +bool CheckSymbols::hasVirtualDestructor(ClassOrNamespace *binding) const { - QSet processed; - QList todo; + QSet processed; + QList todo; todo.append(binding); while (!todo.isEmpty()) { - LookupScope *b = todo.takeFirst(); + ClassOrNamespace *b = todo.takeFirst(); if (b && !processed.contains(b)) { processed.insert(b); foreach (Symbol *s, b->symbols()) { @@ -857,7 +857,7 @@ bool CheckSymbols::visit(QualifiedNameAST *ast) { if (ast->name) { - LookupScope *binding = checkNestedName(ast); + ClassOrNamespace *binding = checkNestedName(ast); if (binding && ast->unqualified_name) { if (ast->unqualified_name->asDestructorName() != 0) { @@ -886,9 +886,9 @@ bool CheckSymbols::visit(QualifiedNameAST *ast) return false; } -LookupScope *CheckSymbols::checkNestedName(QualifiedNameAST *ast) +ClassOrNamespace *CheckSymbols::checkNestedName(QualifiedNameAST *ast) { - LookupScope *binding = 0; + ClassOrNamespace *binding = 0; if (ast->name) { if (NestedNameSpecifierListAST *it = ast->nested_name_specifier_list) { @@ -954,7 +954,7 @@ bool CheckSymbols::visit(MemInitializerAST *ast) { if (FunctionDefinitionAST *enclosingFunction = enclosingFunctionDefinition()) { if (ast->name && enclosingFunction->symbol) { - if (LookupScope *binding = _context.lookupType(enclosingFunction->symbol)) { + if (ClassOrNamespace *binding = _context.lookupType(enclosingFunction->symbol)) { foreach (Symbol *s, binding->symbols()) { if (Class *klass = s->asClass()) { NameAST *nameAST = ast->name; @@ -1157,7 +1157,7 @@ void CheckSymbols::addUse(const Result &use) _usages.append(use); } -void CheckSymbols::addType(LookupScope *b, NameAST *ast) +void CheckSymbols::addType(ClassOrNamespace *b, NameAST *ast) { unsigned startToken; if (!b || !acceptName(ast, &startToken)) @@ -1296,8 +1296,12 @@ bool CheckSymbols::maybeAddFunction(const QList &candidates, NameAST isConstructor = isConstructorDeclaration(c); Function *funTy = c->type()->asFunctionType(); - if (!funTy) // Template function has an overridden type - funTy = r.type()->asFunctionType(); + if (!funTy) { + //Try to find a template function + if (Template * t = r.type()->asTemplateType()) + if ((c = t->declaration())) + funTy = c->type()->asFunctionType(); + } if (!funTy || funTy->isAmbiguous()) continue; // TODO: add diagnostic messages and color call-operators calls too? diff --git a/src/plugins/cpptools/cppchecksymbols.h b/src/plugins/cpptools/cppchecksymbols.h index 11cde21146..f874c16323 100644 --- a/src/plugins/cpptools/cppchecksymbols.h +++ b/src/plugins/cpptools/cppchecksymbols.h @@ -105,7 +105,7 @@ protected: const QList &otherUses); bool hasVirtualDestructor(CPlusPlus::Class *klass) const; - bool hasVirtualDestructor(CPlusPlus::LookupScope *binding) const; + bool hasVirtualDestructor(CPlusPlus::ClassOrNamespace *binding) const; bool warning(unsigned line, unsigned column, const QString &text, unsigned length = 0); bool warning(CPlusPlus::AST *ast, const QString &text); @@ -119,13 +119,13 @@ protected: void checkNamespace(CPlusPlus::NameAST *name); void checkName(CPlusPlus::NameAST *ast, CPlusPlus::Scope *scope = 0); - CPlusPlus::LookupScope *checkNestedName(CPlusPlus::QualifiedNameAST *ast); + CPlusPlus::ClassOrNamespace *checkNestedName(CPlusPlus::QualifiedNameAST *ast); void addUse(const Result &use); void addUse(unsigned tokenIndex, Kind kind); void addUse(CPlusPlus::NameAST *name, Kind kind); - void addType(CPlusPlus::LookupScope *b, CPlusPlus::NameAST *ast); + void addType(CPlusPlus::ClassOrNamespace *b, CPlusPlus::NameAST *ast); bool maybeAddTypeOrStatic(const QList &candidates, CPlusPlus::NameAST *ast); diff --git a/src/plugins/cpptools/cppcompletion_test.cpp b/src/plugins/cpptools/cppcompletion_test.cpp index 02cc06848f..7deb309f58 100644 --- a/src/plugins/cpptools/cppcompletion_test.cpp +++ b/src/plugins/cpptools/cppcompletion_test.cpp @@ -328,17 +328,16 @@ void CppToolsPlugin::test_completion() actualCompletions.sort(); expectedCompletions.sort(); - QEXPECT_FAIL("template_as_base: typedef not available in derived", - "We can live with that...", Abort); - QEXPECT_FAIL("template_specialization_with_reference", "test of reverted change", Abort); - QEXPECT_FAIL("specialization_multiple_arguments", "test of reverted change", Abort); - QEXPECT_FAIL("specialization_with_default_value", "test of reverted change", Abort); + QEXPECT_FAIL("template_as_base: explicit typedef from base", "QTCREATORBUG-14218", 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_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_inline_cxx11", "QTCREATORBUG-13757", Abort); - QEXPECT_FAIL("recursive_instantiation_of_template_type", "QTCREATORBUG-14237", Abort); + QEXPECT_FAIL("pointer_indirect_specialization", "QTCREATORBUG-14141", Abort); + QEXPECT_FAIL("pointer_indirect_specialization_typedef", "QTCREATORBUG-14141", Abort); + QEXPECT_FAIL("pointer_indirect_specialization_double_indirection", "QTCREATORBUG-14141", Abort); + QEXPECT_FAIL("pointer_indirect_specialization_double_indirection_with_base", "QTCREATORBUG-14141", Abort); QCOMPARE(actualCompletions, expectedCompletions); } @@ -802,21 +801,6 @@ void CppToolsPlugin::test_completion_data() << QLatin1String("Data") << QLatin1String("dataMember")); - QTest::newRow("explicit_instantiation") << _( - "template\n" - "struct Foo { T bar; };\n" - "\n" - "template class Foo;\n" - "\n" - "void func()\n" - "{\n" - " Foo foo;\n" - " @\n" - "}\n" - ) << _("foo.") << (QStringList() - << QLatin1String("Foo") - << QLatin1String("bar")); - QTest::newRow("use_global_identifier_as_base_class: derived as global and base as global") << _( "struct Global\n" "{\n" @@ -1327,28 +1311,21 @@ void CppToolsPlugin::test_completion_data() << QLatin1String("Template1")); QTest::newRow("template_specialization_with_pointer") << _( - "template struct Temp { T variable; };\n" - "template struct Temp { T *pointer; };\n" - "void func()\n" + "template \n" + "struct Template\n" "{\n" - " Temp templ;\n" - " @\n" - "}" - ) << _("templ.") << (QStringList() - << QLatin1String("Temp") - << QLatin1String("pointer")); - - QTest::newRow("template_specialization_with_reference") << _( - "template struct Temp { T variable; };\n" - "template struct Temp { T reference; };\n" - "void func()\n" + " T variable;\n" + "};\n" + "template \n" + "struct Template\n" "{\n" - " Temp templ;\n" - " @\n" - "}" + " T *pointer;\n" + "};\n" + "Template templ;\n" + "@\n" ) << _("templ.") << (QStringList() - << QLatin1String("Temp") - << QLatin1String("reference")); + << QLatin1String("Template") + << QLatin1String("pointer")); QTest::newRow("typedef_using_templates1") << _( "namespace NS1\n" @@ -1572,29 +1549,6 @@ void CppToolsPlugin::test_completion_data() << QLatin1String("C") << QLatin1String("m")); - QTest::newRow("type_and_using_declaration: type in nested namespace and using in global") << _( - "namespace Ns {\n" - "namespace Nested {\n" - "struct Foo\n" - "{\n" - " void func();\n" - " int m_bar;\n" - "};\n" - "}\n" - "}\n" - "\n" - "using namespace Ns::Nested;\n" - "\n" - "namespace Ns\n" - "{\n" - "void Foo::func()\n" - "{\n" - " @\n" - "}\n" - "}\n" - ) << _("m_") << (QStringList() - << QLatin1String("m_bar")); - QTest::newRow("instantiate_template_with_anonymous_class") << _( "template \n" "struct S\n" @@ -2568,21 +2522,6 @@ void CppToolsPlugin::test_completion_data() ) << _("ar") << (QStringList() << QLatin1String("arg1")); - QTest::newRow("local_typedef_access_in_lambda") << _( - "struct Foo { int bar; };\n" - "\n" - "void func()\n" - "{\n" - " typedef Foo F;\n" - " []() {\n" - " F f;\n" - " @\n" - " };\n" - "}\n" - ) << _("f.") << (QStringList() - << QLatin1String("Foo") - << QLatin1String("bar")); - QTest::newRow("default_arguments_for_class_templates_and_base_class_QTCREATORBUG-12605") << _( "struct Foo { int foo; };\n" "template \n" @@ -2689,78 +2628,6 @@ void CppToolsPlugin::test_completion_data() ) << _("s.") << (QStringList() << QLatin1String("S")); - QTest::newRow("partial_specialization") << _( - "struct b {};\n" - "template struct s { float f; };\n" - "template struct s { int i; };\n" - "\n" - "void f()\n" - "{\n" - " s var;\n" - " @\n" - "}\n" - ) << _("var.") << (QStringList() - << QLatin1String("i") - << QLatin1String("s")); - -// QTest::newRow("partial_specialization_with_pointer") << _( -// "struct b {};\n" -// "struct a : b {};\n" -// "template struct s { float f; };\n" -// "template struct s { int i; };\n" -// "template struct s { char j; };\n" -// "\n" -// "void f()\n" -// "{\n" -// " s var;\n" -// " @\n" -// "}\n" -// ) << _("var.") << (QStringList() -// << QLatin1String("j") -// << QLatin1String("s")); - - QTest::newRow("partial_specialization_templated_argument") << _( - "template struct t {};\n" - "\n" - "template struct s { float f; };\n" - "template struct s> { int i; };\n" - "\n" - "void f()\n" - "{\n" - " s> var;\n" - " @\n" - "}\n" - ) << _("var.") << (QStringList() - << QLatin1String("i") - << QLatin1String("s")); - - QTest::newRow("specialization_multiple_arguments") << _( - "class false_type {};\n" - "class true_type {};\n" - "template class and_type { false_type f; };\n" - "template<> class and_type { true_type t; };\n" - "void func()\n" - "{\n" - " and_type a;\n" - " @;\n" - "}\n" - ) << _("a.") << (QStringList() - << QLatin1String("f") - << QLatin1String("and_type")); - - QTest::newRow("specialization_with_default_value") << _( - "class Foo {};\n" - "template class Temp;\n" - "template<> class Temp { int var; };\n" - "void func()\n" - "{\n" - " Temp<> t;\n" - " @\n" - "}\n" - ) << _("t.") << (QStringList() - << QLatin1String("var") - << QLatin1String("Temp")); - QTest::newRow("auto_declaration_in_if_condition") << _( "struct Foo { int bar; };\n" "void fun() {\n" @@ -2966,28 +2833,6 @@ void CppToolsPlugin::test_completion_data() << QLatin1String("Foo") << QLatin1String("bar")); - QTest::newRow("instantiation_of_indirect_typedef") << _( - "template\n" - "struct Indirect { _Tp t; };\n" - "\n" - "template\n" - "struct Temp\n" - "{\n" - " typedef T MyT;\n" - " typedef Indirect indirect;\n" - "};\n" - "\n" - "struct Foo { int bar; };\n" - "\n" - "void func()\n" - "{\n" - " Temp::indirect i;\n" - " @\n" - "}\n" - ) << _("i.t.") << (QStringList() - << QLatin1String("Foo") - << QLatin1String("bar"));; - QTest::newRow("pointer_indirect_specialization_double_indirection_with_base") << _( "template\n" "struct Traits { };\n" @@ -3024,337 +2869,6 @@ void CppToolsPlugin::test_completion_data() ) << _("t.p->") << (QStringList() << QLatin1String("Foo") << QLatin1String("bar")); - - QTest::newRow("recursive_instantiation_of_template_type") << _( - "template\n" - "struct Temp { typedef _Tp value_type; };\n" - "\n" - "struct Foo { int bar; };\n" - "\n" - "void func()\n" - "{\n" - " Temp >::value_type::value_type *p;\n" - " @\n" - "}\n" - ) << _("p->") << (QStringList() - << QLatin1String("Foo") - << QLatin1String("bar")); - - QTest::newRow("recursive_instantiation_of_template_type_2") << _( - "template\n" - "struct Temp { typedef _Tp value_type; };\n" - "\n" - "struct Foo { int bar; };\n" - "\n" - "void func()\n" - "{\n" - " Temp::value_type>::value_type *p;\n" - " @\n" - "}\n" - ) << _("p->") << (QStringList() - << QLatin1String("Foo") - << QLatin1String("bar")); - - QTest::newRow("template_using_instantiation") << _( - "template\n" - "using T = _Tp;\n" - "\n" - "struct Foo { int bar; };\n" - "\n" - "void func()\n" - "{\n" - " T p;\n" - " @\n" - "}\n" - ) << _("p.") << (QStringList() - << QLatin1String("Foo") - << QLatin1String("bar")); - - QTest::newRow("nested_template_using_instantiation") << _( - "struct Parent {\n" - " template\n" - " using T = _Tp;\n" - "};\n" - "\n" - "struct Foo { int bar; };\n" - "\n" - "void func()\n" - "{\n" - " Parent::T p;\n" - " @;\n" - "}\n" - ) << _("p.") << (QStringList() - << QLatin1String("Foo") - << QLatin1String("bar")); - - QTest::newRow("nested_template_using_instantiation_in_template_class") << _( - "template\n" - "struct Parent {\n" - " template\n" - " using T = _Tp;\n" - "};\n" - "\n" - "struct Foo { int bar; };\n" - "\n" - "void func()\n" - "{\n" - " Parent::T p;\n" - " @;\n" - "}\n" - ) << _("p.") << (QStringList() - << QLatin1String("Foo") - << QLatin1String("bar")); - - QTest::newRow("recursive_nested_template_using_instantiation") << _( - "struct Foo { int bar; };\n" - "\n" - "struct A { typedef Foo value_type; };\n" - "\n" - "template\n" - "struct Traits\n" - "{\n" - " typedef Foo value_type;\n" - "\n" - " template\n" - " using U = T;\n" - "};\n" - "\n" - "template\n" - "struct Temp\n" - "{\n" - " typedef Traits TraitsT;\n" - " typedef typename T::value_type value_type;\n" - " typedef typename TraitsT::template U rebind;\n" - "};\n" - "\n" - "void func()\n" - "{\n" - " typename Temp::rebind>::value_type p;\n" - " @\n" - "}\n" - ) << _("p.") << (QStringList() - << QLatin1String("Foo") - << QLatin1String("bar")); - - QTest::newRow("qualified_name_in_nested_type") << _( - "template\n" - "struct Temp {\n" - " struct Nested {\n" - " typedef typename _Tp::Nested2 N;\n" - " };\n" - "};\n" - "\n" - "struct Foo {\n" - " struct Nested2 {\n" - " int bar;\n" - " };\n" - "};\n" - "\n" - "void func()\n" - "{\n" - " Temp::Nested::N p;\n" - " @;\n" - "}\n" - ) << _("p.") << (QStringList() - << QLatin1String("Nested2") - << QLatin1String("bar")); - - QTest::newRow("simple_decltype_declaration") << _( - "struct Foo { int bar; };\n" - "Foo foo;\n" - "void fun() {\n" - " decltype(foo) s;\n" - " @\n" - "}\n" - ) << _("s.") << (QStringList() - << QLatin1String("Foo") - << QLatin1String("bar")); - - QTest::newRow("typedefed_decltype_declaration") << _( - "struct Foo { int bar; };\n" - "Foo foo;\n" - "typedef decltype(foo) TypedefedFooWithDecltype;\n" - "void fun() {\n" - " TypedefedFooWithDecltype s;\n" - " @\n" - "}\n" - ) << _("s.") << (QStringList() - << QLatin1String("Foo") - << QLatin1String("bar")); - - QTest::newRow("nested_instantiation_typedefed_decltype_declaration") << _( - "template \n" - "struct Temp\n" - "{\n" - " struct Nested\n" - " {\n" - " static T f();\n" - " typedef decltype(f()) type;\n" - " };\n" - "};\n" - "\n" - "struct Foo { int bar; };\n" - "\n" - "void fun()\n" - "{\n" - " Temp::Nested::type s;\n" - " @\n" - "}\n" - ) << _("s.") << (QStringList() - << QLatin1String("Foo") - << QLatin1String("bar")); - - QTest::newRow("typedefed_decltype_of_template_function") << _( - "template\n" - "static T f();\n" - "\n" - "struct Foo { int bar; };\n" - "\n" - "void fun()\n" - "{\n" - " decltype(f()) s;\n" - " @\n" - "}\n" - ) << _("s.") << (QStringList() - << QLatin1String("Foo") - << QLatin1String("bar")); - - QTest::newRow("nested_instantiation_typedefed_decltype_declaration_of_template_function") << _( - "template \n" - "struct Temp\n" - "{\n" - " struct Nested\n" - " {\n" - " template static T* __test(...);\n" - " typedef decltype(__test(0)) type;\n" - " };\n" - "};\n" - "\n" - "struct Foo { int bar; };\n" - "\n" - "void func()\n" - "{\n" - " Temp::Nested::type s;\n" - " @\n" - "}\n" - ) << _("s.") << (QStringList() - << QLatin1String("Foo") - << QLatin1String("bar")); - - QTest::newRow("typedef for templates in namespace") << _( - "namespace N {\n" - "\n" - "struct Data { int x; };\n" - "template struct Foo { T member; };\n" - "typedef Foo Bar;\n" - "\n" - "} // N\n" - "\n" - "\n" - "void f()\n" - "{\n" - " N::Bar o;\n" - " @\n" - "}\n" - ) << _("o.member.") << (QStringList() - << QLatin1String("Data") - << QLatin1String("x")); - - QTest::newRow("std vector") << _( - "namespace std\n" - "{\n" - "template\n" - "struct allocator\n" - "{\n" - " typedef _Tp value_type;\n" - "\n" - " template\n" - " struct rebind\n" - " { typedef allocator<_Tp1> other; };\n" - "};\n" - "\n" - "template\n" - "struct __alloctr_rebind\n" - "{\n" - " typedef typename _Alloc::template rebind<_Tp>::other __type;\n" - "};\n" - "\n" - "template\n" - "struct allocator_traits\n" - "{\n" - " typedef typename _Alloc::value_type value_type;\n" - "\n" - " template\n" - " using rebind_alloc = typename __alloctr_rebind<_Alloc, _Tp>::__type;\n" - "};\n" - "\n" - "template\n" - "struct iterator_traits { };\n" - "\n" - "template\n" - "struct iterator_traits<_Tp*>\n" - "{\n" - " typedef _Tp* pointer;\n" - "};\n" - "} // namespace std\n" - "\n" - "namespace __gnu_cxx\n" - "{\n" - "template\n" - "struct __alloc_traits\n" - "{\n" - " typedef _Alloc allocator_type;\n" - " typedef std::allocator_traits<_Alloc> _Base_type;\n" - " typedef typename _Alloc::value_type value_type;\n" - "\n" - " static value_type *_S_pointer_helper(...);\n" - " typedef decltype(_S_pointer_helper((_Alloc*)0)) __pointer;\n" - " typedef __pointer pointer;\n" - "\n" - " template\n" - " struct rebind\n" - " { typedef typename _Base_type::template rebind_alloc<_Tp> other; };\n" - "};\n" - "\n" - "template\n" - "struct __normal_iterator\n" - "{\n" - " typedef std::iterator_traits<_Iterator> __traits_type;\n" - " typedef typename __traits_type::pointer pointer;\n" - "\n" - " pointer p;\n" - "};\n" - "} // namespace __gnu_cxx\n" - "\n" - "namespace std {\n" - "template\n" - "struct _Vector_Base\n" - "{\n" - " typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template\n" - " rebind<_Tp>::other _Tp_alloc_type;\n" - " typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer\n" - " pointer;\n" - "};\n" - "\n" - "template >\n" - "struct vector : protected _Vector_Base<_Tp, _Alloc>\n" - "{\n" - " typedef _Vector_Base<_Tp, _Alloc> _Base;\n" - " typedef typename _Base::pointer pointer;\n" - " typedef __gnu_cxx::__normal_iterator iterator;\n" - "};\n" - "} // namespace std\n" - "\n" - "struct Foo { int bar; };\n" - "\n" - "void func()\n" - "{\n" - " std::vector::iterator it;\n" - " @;\n" - "}\n" - ) << _("it.p->") << (QStringList() - << QLatin1String("Foo") - << QLatin1String("bar")); } void CppToolsPlugin::test_completion_member_access_operator() diff --git a/src/plugins/cpptools/cppcompletionassist.cpp b/src/plugins/cpptools/cppcompletionassist.cpp index fa7790a915..eec2f2e5fe 100644 --- a/src/plugins/cpptools/cppcompletionassist.cpp +++ b/src/plugins/cpptools/cppcompletionassist.cpp @@ -753,8 +753,8 @@ bool canCompleteClassNameAt2ndOr4thConnectArgument( || eater.eatConnectOpenParenthesisExpressionCommaAmpersandExpressionComma(); } -LookupScope *lookupScopeFromLookupItem(const LookupItem &lookupItem, - const LookupContext &context) +ClassOrNamespace *classOrNamespaceFromLookupItem(const LookupItem &lookupItem, + const LookupContext &context) { const Name *name = 0; @@ -783,7 +783,7 @@ LookupScope *lookupScopeFromLookupItem(const LookupItem &lookupItem, Class *classFromLookupItem(const LookupItem &lookupItem, const LookupContext &context) { - LookupScope *b = lookupScopeFromLookupItem(lookupItem, context); + ClassOrNamespace *b = classOrNamespaceFromLookupItem(lookupItem, context); if (!b) return 0; @@ -796,7 +796,7 @@ Class *classFromLookupItem(const LookupItem &lookupItem, const LookupContext &co const Name *minimalName(Symbol *symbol, Scope *targetScope, const LookupContext &context) { - LookupScope *target = context.lookupType(targetScope); + ClassOrNamespace *target = context.lookupType(targetScope); if (!target) target = context.globalNamespace(); return context.minimalName(symbol, target, context.bindings()->control().data()); @@ -1219,12 +1219,12 @@ bool InternalCppCompletionAssistProcessor::tryObjCCompletion() ty = ty->asPointerType()->elementType().simplified(); if (NamedType *namedTy = ty->asNamedType()) { - LookupScope *binding = lookupContext.lookupType(namedTy->name(), item.scope()); + ClassOrNamespace *binding = lookupContext.lookupType(namedTy->name(), item.scope()); completeObjCMsgSend(binding, false); } } else { if (ObjCClass *clazz = ty->asObjCClassType()) { - LookupScope *binding = lookupContext.lookupType(clazz->name(), item.scope()); + ClassOrNamespace *binding = lookupContext.lookupType(clazz->name(), item.scope()); completeObjCMsgSend(binding, true); } } @@ -1273,7 +1273,7 @@ void InternalCppCompletionAssistProcessor::addCompletionItem(Symbol *symbol, int } } -void InternalCppCompletionAssistProcessor::completeObjCMsgSend(LookupScope *binding, +void InternalCppCompletionAssistProcessor::completeObjCMsgSend(ClassOrNamespace *binding, bool staticClassAccess) { QList memberScopes; @@ -1542,26 +1542,26 @@ bool InternalCppCompletionAssistProcessor::globalCompletion(Scope *currentScope) return !m_completions.isEmpty(); } - QList usingBindings; - LookupScope *currentBinding = 0; + QList usingBindings; + ClassOrNamespace *currentBinding = 0; for (Scope *scope = currentScope; scope; scope = scope->enclosingScope()) { if (Block *block = scope->asBlock()) { - if (LookupScope *binding = context.lookupType(scope)) { + if (ClassOrNamespace *binding = context.lookupType(scope)) { for (unsigned i = 0; i < scope->memberCount(); ++i) { Symbol *member = scope->memberAt(i); if (member->isEnum()) { - if (LookupScope *b = binding->findBlock(block)) + if (ClassOrNamespace *b = binding->findBlock(block)) completeNamespace(b); } if (!member->name()) continue; if (UsingNamespaceDirective *u = member->asUsingNamespaceDirective()) { - if (LookupScope *b = binding->lookupType(u->name())) + if (ClassOrNamespace *b = binding->lookupType(u->name())) usingBindings.append(b); } else if (Class *c = member->asClass()) { if (c->name()->isAnonymousNameId()) { - if (LookupScope *b = binding->findBlock(block)) + if (ClassOrNamespace *b = binding->findBlock(block)) completeClass(b); } } @@ -1588,7 +1588,7 @@ bool InternalCppCompletionAssistProcessor::globalCompletion(Scope *currentScope) } for (; currentBinding; currentBinding = currentBinding->parent()) { - foreach (LookupScope* u, currentBinding->usings()) + foreach (ClassOrNamespace* u, currentBinding->usings()) usingBindings.append(u); const QList symbols = currentBinding->symbols(); @@ -1601,7 +1601,7 @@ bool InternalCppCompletionAssistProcessor::globalCompletion(Scope *currentScope) } } - foreach (LookupScope *b, usingBindings) + foreach (ClassOrNamespace *b, usingBindings) completeNamespace(b); addKeywords(); @@ -1624,7 +1624,7 @@ bool InternalCppCompletionAssistProcessor::completeMember(const QListlanguageFeatures().objCEnabled) replaceDotForArrow = &m_model->m_replaceDotForArrow; - if (LookupScope *binding = + if (ClassOrNamespace *binding = resolveExpression.baseExpression(baseResults, m_model->m_completionOperator, replaceDotForArrow)) { @@ -1648,27 +1648,27 @@ bool InternalCppCompletionAssistProcessor::completeScope(const QList Scope *scope = result.scope(); if (NamedType *namedTy = ty->asNamedType()) { - if (LookupScope *b = context.lookupType(namedTy->name(), scope)) { + if (ClassOrNamespace *b = context.lookupType(namedTy->name(), scope)) { completeClass(b); break; } } else if (Class *classTy = ty->asClassType()) { - if (LookupScope *b = context.lookupType(classTy)) { + if (ClassOrNamespace *b = context.lookupType(classTy)) { completeClass(b); break; } // it can be class defined inside a block if (classTy->enclosingScope()->isBlock()) { - if (LookupScope *b = context.lookupType(classTy->name(), classTy->enclosingScope())) { + if (ClassOrNamespace *b = context.lookupType(classTy->name(), classTy->enclosingScope())) { completeClass(b); break; } } } else if (Namespace *nsTy = ty->asNamespaceType()) { - if (LookupScope *b = context.lookupType(nsTy)) { + if (ClassOrNamespace *b = context.lookupType(nsTy)) { completeNamespace(b); break; } @@ -1676,7 +1676,7 @@ bool InternalCppCompletionAssistProcessor::completeScope(const QList } else if (Template *templ = ty->asTemplateType()) { if (!result.binding()) continue; - if (LookupScope *b = result.binding()->lookupType(templ->name())) { + if (ClassOrNamespace *b = result.binding()->lookupType(templ->name())) { completeClass(b); break; } @@ -1684,16 +1684,16 @@ bool InternalCppCompletionAssistProcessor::completeScope(const QList } else if (Enum *e = ty->asEnumType()) { // it can be class defined inside a block if (e->enclosingScope()->isBlock()) { - if (LookupScope *b = context.lookupType(e)) { + if (ClassOrNamespace *b = context.lookupType(e)) { Block *block = e->enclosingScope()->asBlock(); - if (LookupScope *bb = b->findBlock(block)) { + if (ClassOrNamespace *bb = b->findBlock(block)) { completeNamespace(bb); break; } } } - if (LookupScope *b = context.lookupType(e)) { + if (ClassOrNamespace *b = context.lookupType(e)) { completeNamespace(b); break; } @@ -1704,14 +1704,14 @@ bool InternalCppCompletionAssistProcessor::completeScope(const QList return !m_completions.isEmpty(); } -void InternalCppCompletionAssistProcessor::completeNamespace(LookupScope *b) +void InternalCppCompletionAssistProcessor::completeNamespace(ClassOrNamespace *b) { - QSet bindingsVisited; - QList bindingsToVisit; + QSet bindingsVisited; + QList bindingsToVisit; bindingsToVisit.append(b); while (!bindingsToVisit.isEmpty()) { - LookupScope *binding = bindingsToVisit.takeFirst(); + ClassOrNamespace *binding = bindingsToVisit.takeFirst(); if (!binding || bindingsVisited.contains(binding)) continue; @@ -1744,14 +1744,14 @@ void InternalCppCompletionAssistProcessor::completeNamespace(LookupScope *b) } } -void InternalCppCompletionAssistProcessor::completeClass(LookupScope *b, bool staticLookup) +void InternalCppCompletionAssistProcessor::completeClass(ClassOrNamespace *b, bool staticLookup) { - QSet bindingsVisited; - QList bindingsToVisit; + QSet bindingsVisited; + QList bindingsToVisit; bindingsToVisit.append(b); while (!bindingsToVisit.isEmpty()) { - LookupScope *binding = bindingsToVisit.takeFirst(); + ClassOrNamespace *binding = bindingsToVisit.takeFirst(); if (!binding || bindingsVisited.contains(binding)) continue; @@ -1838,16 +1838,16 @@ bool InternalCppCompletionAssistProcessor::completeQtMethod(const QList signatures; foreach (const LookupItem &lookupItem, results) { - LookupScope *b = lookupScopeFromLookupItem(lookupItem, context); + ClassOrNamespace *b = classOrNamespaceFromLookupItem(lookupItem, context); if (!b) continue; - QListtodo; - QSet processed; + QListtodo; + QSet processed; QList scopes; todo.append(b); while (!todo.isEmpty()) { - LookupScope *binding = todo.takeLast(); + ClassOrNamespace *binding = todo.takeLast(); if (!processed.contains(binding)) { processed.insert(binding); @@ -2063,7 +2063,7 @@ bool InternalCppCompletionAssistProcessor::completeConstructorOrFunction(const Q Scope *scope = result.scope(); if (NamedType *namedTy = ty->asNamedType()) { - if (LookupScope *b = context.lookupType(namedTy->name(), scope)) { + if (ClassOrNamespace *b = context.lookupType(namedTy->name(), scope)) { foreach (const LookupItem &r, b->lookup(functionCallOp)) { Symbol *overload = r.declaration(); FullySpecifiedType overloadTy = overload->type().simplified(); @@ -2145,7 +2145,7 @@ bool InternalCppCompletionAssistProcessor::completeConstructorOrFunction(const Q SubstitutionEnvironment env; env.setContext(context); env.switchScope(sc); - LookupScope *targetCoN = context.lookupType(sc); + ClassOrNamespace *targetCoN = context.lookupType(sc); if (!targetCoN) targetCoN = context.globalNamespace(); UseMinimalNames q(targetCoN); diff --git a/src/plugins/cpptools/cppcompletionassist.h b/src/plugins/cpptools/cppcompletionassist.h index 01fd44e5b8..30f8809081 100644 --- a/src/plugins/cpptools/cppcompletionassist.h +++ b/src/plugins/cpptools/cppcompletionassist.h @@ -53,7 +53,7 @@ namespace CPlusPlus { class LookupItem; -class LookupScope; +class ClassOrNamespace; class Function; class LookupContext; } // namespace CPlusPlus @@ -121,7 +121,7 @@ private: const QString &expression, int endOfExpression); - void completeObjCMsgSend(CPlusPlus::LookupScope *binding, bool staticClassAccess); + void completeObjCMsgSend(CPlusPlus::ClassOrNamespace *binding, bool staticClassAccess); bool completeInclude(const QTextCursor &cursor); void completeInclude(const QString &realPath, const QStringList &suffixes); void completePreprocessor(); @@ -130,8 +130,8 @@ private: bool toolTipOnly); bool completeMember(const QList &results); bool completeScope(const QList &results); - void completeNamespace(CPlusPlus::LookupScope *binding); - void completeClass(CPlusPlus::LookupScope *b, bool staticLookup = true); + void completeNamespace(CPlusPlus::ClassOrNamespace *binding); + void completeClass(CPlusPlus::ClassOrNamespace *b, bool staticLookup = true); void addClassMembersToCompletion(CPlusPlus::Scope *scope, bool staticLookup); enum CompleteQtMethodMode { CompleteQt4Signals, diff --git a/src/plugins/cpptools/cpptoolsreuse.cpp b/src/plugins/cpptools/cpptoolsreuse.cpp index f3a7942954..c70bdb14e5 100644 --- a/src/plugins/cpptools/cpptoolsreuse.cpp +++ b/src/plugins/cpptools/cpptoolsreuse.cpp @@ -108,7 +108,7 @@ bool isOwnershipRAIIType(Symbol *symbol, const LookupContext &context) Declaration *declaration = symbol->asDeclaration(); const NamedType *namedType = declaration->type()->asNamedType(); if (namedType) { - LookupScope *clazz = context.lookupType(namedType->name(), + ClassOrNamespace *clazz = context.lookupType(namedType->name(), declaration->enclosingScope()); if (clazz && !clazz->symbols().isEmpty()) { Overview overview; diff --git a/src/plugins/cpptools/symbolfinder.cpp b/src/plugins/cpptools/symbolfinder.cpp index 3bc72c00b5..cc5006e63a 100644 --- a/src/plugins/cpptools/symbolfinder.cpp +++ b/src/plugins/cpptools/symbolfinder.cpp @@ -151,7 +151,7 @@ Function *SymbolFinder::findMatchingDefinition(Symbol *declaration, QList viableFunctions; - LookupScope *enclosingType = context.lookupType(declaration); + ClassOrNamespace *enclosingType = context.lookupType(declaration); if (!enclosingType) continue; // nothing to do @@ -214,15 +214,13 @@ Function *SymbolFinder::findMatchingDefinition(Symbol *declaration, return 0; } -Class *SymbolFinder::findMatchingClassDeclaration(Symbol *declaration, const Snapshot &snapshot, - const LookupContext *context) +Class *SymbolFinder::findMatchingClassDeclaration(Symbol *declaration, const Snapshot &snapshot) { if (!declaration->identifier()) return 0; QString declFile = QString::fromUtf8(declaration->fileName(), declaration->fileNameLength()); - const bool useLocalContext = !context; foreach (const QString &file, fileIterationOrder(declFile, snapshot)) { Document::Ptr doc = snapshot.document(file); if (!doc) { @@ -234,13 +232,9 @@ Class *SymbolFinder::findMatchingClassDeclaration(Symbol *declaration, const Sna declaration->identifier()->size())) continue; - QScopedPointer localContext; - if (useLocalContext) { - localContext.reset(new LookupContext(doc, snapshot)); - context = localContext.data(); - } + LookupContext context(doc, snapshot); - LookupScope *type = context->lookupType(declaration); + ClassOrNamespace *type = context.lookupType(declaration); if (!type) continue; @@ -289,7 +283,7 @@ void SymbolFinder::findMatchingDeclaration(const LookupContext &context, if (!functionName) return; - LookupScope *binding = 0; + ClassOrNamespace *binding = 0; const QualifiedNameId *qName = functionName->asQualifiedNameId(); if (qName) { if (qName->base()) diff --git a/src/plugins/cpptools/symbolfinder.h b/src/plugins/cpptools/symbolfinder.h index 45236eb1ad..c1d65f7716 100644 --- a/src/plugins/cpptools/symbolfinder.h +++ b/src/plugins/cpptools/symbolfinder.h @@ -61,8 +61,7 @@ public: bool strict = false); CPlusPlus::Class *findMatchingClassDeclaration(CPlusPlus::Symbol *declaration, - const CPlusPlus::Snapshot &snapshot, - const CPlusPlus::LookupContext *context = 0); + const CPlusPlus::Snapshot &snapshot); void findMatchingDeclaration(const CPlusPlus::LookupContext &context, CPlusPlus::Function *functionType, diff --git a/src/tools/cplusplus-mkvisitor/cplusplus-mkvisitor.cpp b/src/tools/cplusplus-mkvisitor/cplusplus-mkvisitor.cpp index 5c2be00058..3b7e4c52d0 100644 --- a/src/tools/cplusplus-mkvisitor/cplusplus-mkvisitor.cpp +++ b/src/tools/cplusplus-mkvisitor/cplusplus-mkvisitor.cpp @@ -65,12 +65,12 @@ class MkVisitor: protected SymbolVisitor { const LookupContext &context; Overview oo; - QList interfaces; - QList nodes; + QList interfaces; + QList nodes; - bool isMiscNode(LookupScope *b) const + bool isMiscNode(ClassOrNamespace *b) const { - foreach (LookupScope *u, b->usings()) { + foreach (ClassOrNamespace *u, b->usings()) { if (oo(u->symbols().first()->name()) == QLatin1String("AST")) return true; } @@ -78,7 +78,7 @@ class MkVisitor: protected SymbolVisitor return false; } - QString getAcceptFunctionName(LookupScope *b, QString *retType) const + QString getAcceptFunctionName(ClassOrNamespace *b, QString *retType) const { Q_ASSERT(b != 0); @@ -131,7 +131,7 @@ public: << " Semantic(TranslationUnit *unit): ASTVisitor(unit) { translationUnit(unit->ast()->asTranslationUnit()); }" << std::endl << std::endl; - foreach (LookupScope *b, interfaces) { + foreach (ClassOrNamespace *b, interfaces) { Q_ASSERT(! b->symbols().isEmpty()); Class *klass = 0; @@ -162,10 +162,10 @@ public: std::cout << " using ASTVisitor::translationUnit;" << std::endl << std::endl; - QHash > implements; - foreach (LookupScope *b, nodes) { - LookupScope *iface = 0; - foreach (LookupScope *u, b->usings()) { + QHash > implements; + foreach (ClassOrNamespace *b, nodes) { + ClassOrNamespace *iface = 0; + foreach (ClassOrNamespace *u, b->usings()) { if (interfaces.contains(u)) { iface = u; break; @@ -175,8 +175,8 @@ public: implements[iface].append(b); } - foreach (LookupScope *iface, interfaces) { - foreach (LookupScope *b, implements.value(iface)) { + foreach (ClassOrNamespace *iface, interfaces) { + foreach (ClassOrNamespace *b, implements.value(iface)) { if (! isMiscNode(b)) continue; @@ -195,9 +195,9 @@ public: std::cout << std::endl; - foreach (LookupScope *iface, interfaces) { + foreach (ClassOrNamespace *iface, interfaces) { std::cout << " // " << qPrintable(oo(iface->symbols().first()->name())) << std::endl; - foreach (LookupScope *b, implements.value(iface)) { + foreach (ClassOrNamespace *b, implements.value(iface)) { Class *klass = 0; foreach (Symbol *s, b->symbols()) if ((klass = s->asClass()) != 0) @@ -212,7 +212,7 @@ public: } std::cout << "private:" << std::endl; - foreach (LookupScope *b, interfaces) { + foreach (ClassOrNamespace *b, interfaces) { Q_ASSERT(! b->symbols().isEmpty()); Class *klass = 0; @@ -245,7 +245,7 @@ public: // implementation - foreach (LookupScope *b, interfaces) { + foreach (ClassOrNamespace *b, interfaces) { Q_ASSERT(! b->symbols().isEmpty()); Class *klass = 0; @@ -280,9 +280,9 @@ public: << std::endl; } - foreach (LookupScope *iface, interfaces) { + foreach (ClassOrNamespace *iface, interfaces) { std::cout << "// " << qPrintable(oo(iface->symbols().first()->name())) << std::endl; - foreach (LookupScope *b, implements.value(iface)) { + foreach (ClassOrNamespace *b, implements.value(iface)) { Class *klass = 0; foreach (Symbol *s, b->symbols()) if ((klass = s->asClass()) != 0) @@ -331,7 +331,7 @@ public: Control *control = context.thisDocument()->control(); const Name *n = control->identifier(name.toLatin1().constData()); - if (LookupScope *bb = context.lookupType(n, klass)) { + if (ClassOrNamespace *bb = context.lookupType(n, klass)) { QString retTy; QString funcName = getAcceptFunctionName(bb, &retTy); Q_ASSERT(! funcName.isEmpty()); @@ -350,7 +350,7 @@ public: continue; } - if (LookupScope *ty = context.lookupType(namedTy->name(), klass)) { + if (ClassOrNamespace *ty = context.lookupType(namedTy->name(), klass)) { QString className = oo(ty->symbols().first()->name()); QString baseClassName = className; if (baseClassName.endsWith(QLatin1String("AST"))) { @@ -386,9 +386,9 @@ public: protected: using SymbolVisitor::visit; - QList baseClasses(LookupScope *b) { - QList usings = b->usings(); - foreach (LookupScope *u, usings) + QList baseClasses(ClassOrNamespace *b) { + QList usings = b->usings(); + foreach (ClassOrNamespace *u, usings) usings += baseClasses(u); return usings; } @@ -398,14 +398,14 @@ protected: if (! className.endsWith(QLatin1String("AST"))) return false; - LookupScope *b = context.lookupType(klass); + ClassOrNamespace *b = context.lookupType(klass); Q_ASSERT(b != 0); const Identifier *accept0 = context.thisDocument()->control()->identifier("accept0"); if (Symbol *s = klass->find(accept0)) { if (Function *meth = s->type()->asFunctionType()) { if (! meth->isPureVirtual()) { - foreach (LookupScope *u, b->usings()) { + foreach (ClassOrNamespace *u, b->usings()) { if (interfaces.contains(u)) { // qDebug() << oo(klass->name()) << "implements" << oo(u->symbols().first()->name()); } else { diff --git a/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp b/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp index 3a39909e3c..683513f12b 100644 --- a/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp +++ b/tests/auto/cplusplus/checksymbols/tst_checksymbols.cpp @@ -115,7 +115,6 @@ public: // Process source const Document::Ptr document = createDocument(filePath, source); - QVERIFY(document); Snapshot snapshot; snapshot.insert(document); @@ -225,8 +224,6 @@ private slots: void test_checksymbols_infiniteLoop_data(); void test_checksymbols_infiniteLoop(); - void test_checksymbols_infiniteLoop_BUG15141(); - void test_parentOfBlock(); void findField(); @@ -1173,25 +1170,6 @@ void tst_CheckSymbols::test_checksymbols_infiniteLoop() TestCase::runCheckSymbols(document1, snapshot); } -void tst_CheckSymbols::test_checksymbols_infiniteLoop_BUG15141() -{ - QByteArray source = - "template \n" - "struct Base\n" - "{\n" - "};\n" - "\n" - "template\n" - "struct Derived :\n" - " Base<\n" - " typename Derived::type>::type,\n" - " typename Derived::type>::type\n" - " >::type\n" - "{};\n"; - - BaseTestCase tc(source); -} - void tst_CheckSymbols::test_parentOfBlock() { const QByteArray source = "void C::f()\n" @@ -1286,8 +1264,13 @@ void tst_CheckSymbols::findField() source[position] = ' '; BaseTestCase tc(source); Use use = tc.findUse(line, column); - + QEXPECT_FAIL("pointer_indirect_specialization", "QTCREATORBUG-14141", Abort); + QEXPECT_FAIL("pointer_indirect_specialization_typedef", "QTCREATORBUG-14141", Abort); + QEXPECT_FAIL("pointer_indirect_specialization_double_indirection", "QTCREATORBUG-14141", Abort); + QEXPECT_FAIL("instantiation_of_pointer_typedef_in_block", "QTCREATORBUG-14141", 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_2", "QTCREATORBUG-14141", Abort); QVERIFY(use.isValid()); QVERIFY(use.kind == Highlighting::FieldUse); } @@ -1364,26 +1347,6 @@ void tst_CheckSymbols::findField_data() "}\n" ); - QTest::newRow("instantiation_of_indirect_typedef") << _( - "template\n" - "struct Indirect { _Tp t; };\n" - "\n" - "template\n" - "struct Temp\n" - "{\n" - " typedef T MyT;\n" - " typedef Indirect indirect;\n" - "};\n" - "\n" - "struct Foo { int bar; };\n" - "\n" - "void func()\n" - "{\n" - " Temp::indirect i;\n" - " i.t.@bar;\n" - "}\n" - ); - QTest::newRow("pointer_indirect_specialization_double_indirection") << _( "template\n" "struct Traits { };\n" @@ -1475,100 +1438,6 @@ void tst_CheckSymbols::findField_data() " p->@bar;\n" "}\n" ); - - QTest::newRow("std vector") << _( - "namespace std\n" - "{\n" - "template\n" - "struct allocator\n" - "{\n" - " typedef _Tp value_type;\n" - "\n" - " template\n" - " struct rebind\n" - " { typedef allocator<_Tp1> other; };\n" - "};\n" - "\n" - "template\n" - "struct __alloctr_rebind\n" - "{\n" - " typedef typename _Alloc::template rebind<_Tp>::other __type;\n" - "};\n" - "\n" - "template\n" - "struct allocator_traits\n" - "{\n" - " typedef typename _Alloc::value_type value_type;\n" - "\n" - " template\n" - " using rebind_alloc = typename __alloctr_rebind<_Alloc, _Tp>::__type;\n" - "};\n" - "\n" - "template\n" - "struct iterator_traits { };\n" - "\n" - "template\n" - "struct iterator_traits<_Tp*>\n" - "{\n" - " typedef _Tp* pointer;\n" - "};\n" - "} // namespace std\n" - "\n" - "namespace __gnu_cxx\n" - "{\n" - "template\n" - "struct __alloc_traits\n" - "{\n" - " typedef _Alloc allocator_type;\n" - " typedef std::allocator_traits<_Alloc> _Base_type;\n" - " typedef typename _Alloc::value_type value_type;\n" - "\n" - " static value_type *_S_pointer_helper(...);\n" - " typedef decltype(_S_pointer_helper((_Alloc*)0)) __pointer;\n" - " typedef __pointer pointer;\n" - "\n" - " template\n" - " struct rebind\n" - " { typedef typename _Base_type::template rebind_alloc<_Tp> other; };\n" - "};\n" - "\n" - "template\n" - "struct __normal_iterator\n" - "{\n" - " typedef std::iterator_traits<_Iterator> __traits_type;\n" - " typedef typename __traits_type::pointer pointer;\n" - "\n" - " pointer p;\n" - "};\n" - "} // namespace __gnu_cxx\n" - "\n" - "namespace std {\n" - "template\n" - "struct _Vector_Base\n" - "{\n" - " typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template\n" - " rebind<_Tp>::other _Tp_alloc_type;\n" - " typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer\n" - " pointer;\n" - "};\n" - "\n" - "template >\n" - "struct vector : protected _Vector_Base<_Tp, _Alloc>\n" - "{\n" - " typedef _Vector_Base<_Tp, _Alloc> _Base;\n" - " typedef typename _Base::pointer pointer;\n" - " typedef __gnu_cxx::__normal_iterator iterator;\n" - "};\n" - "} // namespace std\n" - "\n" - "struct Foo { int bar; };\n" - "\n" - "void func()\n" - "{\n" - " std::vector::iterator it;\n" - " it.p->@bar;\n" - "}\n" - ); } QTEST_APPLESS_MAIN(tst_CheckSymbols) diff --git a/tests/auto/cplusplus/lookup/tst_lookup.cpp b/tests/auto/cplusplus/lookup/tst_lookup.cpp index deab703a8f..8347749f43 100644 --- a/tests/auto/cplusplus/lookup/tst_lookup.cpp +++ b/tests/auto/cplusplus/lookup/tst_lookup.cpp @@ -133,7 +133,7 @@ void tst_Lookup::base_class_defined_1() const LookupContext ctx(doc, snapshot); - LookupScope *klass = ctx.lookupType(derivedClass->baseClassAt(0)->name(), derivedClass->enclosingScope()); + ClassOrNamespace *klass = ctx.lookupType(derivedClass->baseClassAt(0)->name(), derivedClass->enclosingScope()); QVERIFY(klass != 0); QCOMPARE(klass->symbols().size(), 1); @@ -272,7 +272,7 @@ void tst_Lookup::simple_class_1() const LookupContext context(doc, snapshot); // check class resolving: - LookupScope *klass = context.lookupType(impl->name(), impl->enclosingScope()); + ClassOrNamespace *klass = context.lookupType(impl->name(), impl->enclosingScope()); QVERIFY(klass != 0); QCOMPARE(klass->symbols().size(), 2); QVERIFY(klass->symbols().contains(iface)); @@ -336,7 +336,7 @@ void tst_Lookup::class_with_baseclass() const LookupContext context(doc, snapshot); - LookupScope *objClass = context.lookupType(baseZoo->name(), zooImpl->enclosingScope()); + ClassOrNamespace *objClass = context.lookupType(baseZoo->name(), zooImpl->enclosingScope()); QVERIFY(objClass != 0); QVERIFY(objClass->symbols().contains(baseZoo)); diff --git a/tests/auto/cplusplus/semantic/tst_semantic.cpp b/tests/auto/cplusplus/semantic/tst_semantic.cpp index 4717c5fc22..2011f03e00 100644 --- a/tests/auto/cplusplus/semantic/tst_semantic.cpp +++ b/tests/auto/cplusplus/semantic/tst_semantic.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -47,7 +48,6 @@ #include #include #include -#include //TESTED_COMPONENT=src/libs/cplusplus @@ -166,7 +166,6 @@ private slots: void pointer_to_function_1(); void template_instance_1(); - void explicit_instantiation_1(); void expression_under_cursor_1(); @@ -512,37 +511,17 @@ void tst_Semantic::template_instance_1() QVERIFY(decl); FullySpecifiedType templArgs[] = { control->integerType(IntegerType::Int) }; - Clone cloner(control.data()); - Class *clone = cloner.instantiate(templ, templArgs, 1)->asClass(); - QVERIFY(clone); + const Name *templId = control->templateNameId(control->identifier("QList"), false, templArgs, 1); + + FullySpecifiedType genTy = DeprecatedGenTemplateInstance::instantiate(templId, decl, control); Overview oo; oo.showReturnTypes = true; - Declaration *clonedDecl = clone->memberAt(0)->asDeclaration(); - const QString genDecl = oo.prettyType(clonedDecl->type()); + const QString genDecl = oo.prettyType(genTy); QCOMPARE(genDecl, QString::fromLatin1("void (const int &)")); } -void tst_Semantic::explicit_instantiation_1() -{ - QSharedPointer doc = document("template class basic_string;"); - QCOMPARE(doc->errorCount, 0U); - QCOMPARE(doc->globals->memberCount(), 1U); - - ExplicitInstantiation *inst = doc->globals->memberAt(0)->asExplicitInstantiation(); - QVERIFY(inst); - - ForwardClassDeclaration *fwd = inst->memberAt(0)->asForwardClassDeclaration(); - QVERIFY(fwd); - - QVERIFY(inst->name()->match(fwd->name())); - - Overview oo; - const QString name = oo.prettyName(inst->name()); - QCOMPARE(name, QString::fromLatin1("basic_string")); -} - void tst_Semantic::expression_under_cursor_1() { const QString plainText = "void *ptr = foo(10, bar"; -- cgit v1.2.1