diff options
Diffstat (limited to 'src/libs/cplusplus')
-rw-r--r-- | src/libs/cplusplus/CppRewriter.cpp | 2 | ||||
-rw-r--r-- | src/libs/cplusplus/CppRewriter.h | 4 | ||||
-rw-r--r-- | src/libs/cplusplus/DeprecatedGenTemplateInstance.cpp | 430 | ||||
-rw-r--r-- | src/libs/cplusplus/DeprecatedGenTemplateInstance.h (renamed from src/libs/cplusplus/TypeResolver.h) | 45 | ||||
-rw-r--r-- | src/libs/cplusplus/FindUsages.cpp | 2 | ||||
-rw-r--r-- | src/libs/cplusplus/LookupContext.cpp | 1363 | ||||
-rw-r--r-- | src/libs/cplusplus/LookupContext.h | 209 | ||||
-rw-r--r-- | src/libs/cplusplus/LookupItem.cpp | 4 | ||||
-rw-r--r-- | src/libs/cplusplus/LookupItem.h | 8 | ||||
-rw-r--r-- | src/libs/cplusplus/ResolveExpression.cpp | 415 | ||||
-rw-r--r-- | src/libs/cplusplus/ResolveExpression.h | 15 | ||||
-rw-r--r-- | src/libs/cplusplus/TypeOfExpression.cpp | 8 | ||||
-rw-r--r-- | src/libs/cplusplus/TypeOfExpression.h | 14 | ||||
-rw-r--r-- | src/libs/cplusplus/TypeResolver.cpp | 262 | ||||
-rw-r--r-- | src/libs/cplusplus/cplusplus-lib.pri | 4 | ||||
-rw-r--r-- | src/libs/cplusplus/cplusplus.qbs | 2 |
16 files changed, 1614 insertions, 1173 deletions
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 <cplusplus/Control.h> +#include <cplusplus/Scope.h> +#include <cplusplus/Names.h> +#include <cplusplus/Symbols.h> +#include <cplusplus/CoreTypes.h> +#include <cplusplus/Literals.h> + +#include <QVarLengthArray> +#include <QDebug> + +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<Symbol *, FullySpecifiedType> _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<FullySpecifiedType, 8> 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<FullySpecifiedType, 8> 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<const Identifier *, FullySpecifiedType> 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> 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> 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/TypeResolver.h b/src/libs/cplusplus/DeprecatedGenTemplateInstance.h index bf25e468c6..9e488478c6 100644 --- a/src/libs/cplusplus/TypeResolver.h +++ b/src/libs/cplusplus/DeprecatedGenTemplateInstance.h @@ -28,41 +28,36 @@ ** ****************************************************************************/ -#ifndef TYPERESOLVER_H -#define TYPERESOLVER_H +#ifndef CPLUSPLUS_DEPRECATEDGENTEMPLATEINSTANCE_H +#define CPLUSPLUS_DEPRECATEDGENTEMPLATEINSTANCE_H -#include "LookupContext.h" +#include <cplusplus/TypeVisitor.h> +#include <cplusplus/NameVisitor.h> +#include <cplusplus/FullySpecifiedType.h> + +#include <QList> +#include <QPair> +#include <QSharedPointer> namespace CPlusPlus { -class TypeResolver +class CPLUSPLUS_EXPORT DeprecatedGenTemplateInstance { public: - TypeResolver(CreateBindings &factory) : _factory(factory) {} - void resolve(FullySpecifiedType *type, Scope **scope, LookupScope *binding); - static QList<LookupItem> resolveDeclInitializer( - CreateBindings &factory, const Declaration *decl, - const QSet<const Declaration *> &declarationsBeingResolved, - const Identifier *id = 0); - -private: - NamedType *getNamedType(FullySpecifiedType& type) const; - - QList<LookupItem> getNamedTypeItems(const Name *name, Scope *scope, - LookupScope *binding) const; + typedef QList< QPair<const Identifier *, FullySpecifiedType> > Substitution; - static QList<LookupItem> typedefsFromScopeUpToFunctionScope(const Name *name, Scope *scope); - - static bool isTypedefWithName(const Declaration *declaration, const Name *name); +public: + static FullySpecifiedType instantiate(const Name *className, Symbol *candidate, QSharedPointer<Control> control); - bool findTypedef(const QList<LookupItem>& namedTypeItems, FullySpecifiedType *type, - Scope **scope, QSet<Symbol *>& visited); +private: + DeprecatedGenTemplateInstance(QSharedPointer<Control> control, const Substitution &substitution); + FullySpecifiedType gen(Symbol *symbol); - CreateBindings &_factory; - // binding has to be remembered in case of resolving typedefs for templates - LookupScope *_binding; +private: + QSharedPointer<Control> _control; + const Substitution _substitution; }; } // namespace CPlusPlus -#endif // TYPERESOLVER_H +#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 <cplusplus/CoreTypes.h> #include <cplusplus/Symbols.h> @@ -41,18 +41,15 @@ #include <cplusplus/Names.h> #include <cplusplus/Scope.h> #include <cplusplus/Control.h> -#include <cplusplus/cppassert.h> #include <QStack> #include <QHash> #include <QVarLengthArray> #include <QDebug> -static const bool debug = ! qgetenv("QTC_LOOKUPCONTEXT_DEBUG").isEmpty(); - -namespace CPlusPlus { +using namespace CPlusPlus; -typedef QSet<Internal::LookupScopePrivate *> ProcessedSet; +static const bool debug = ! qgetenv("QTC_LOOKUPCONTEXT_DEBUG").isEmpty(); static void addNames(const Name *name, QList<const Name *> *names, bool addAllNames = false) { @@ -92,6 +89,24 @@ static void path_helper(Symbol *symbol, QList<const Name *> *names) } } +static bool isNestedInstantiationEnclosingTemplate( + ClassOrNamespace *nestedClassOrNamespaceInstantiation, + ClassOrNamespace *enclosingTemplateClassInstantiation) +{ + QList<ClassOrNamespace *> 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<const Name *> &path, const QList<cons return true; } +} + +namespace CPlusPlus { namespace Internal { bool operator==(const FullyQualifiedName &left, const FullyQualifiedName &right) @@ -142,6 +160,7 @@ uint qHash(const FullyQualifiedName &fullyQualifiedName) return h; } } +} ///////////////////////////////////////////////////////////////////// // LookupContext @@ -163,7 +182,7 @@ LookupContext::LookupContext(Document::Ptr thisDocument, LookupContext::LookupContext(Document::Ptr expressionDocument, Document::Ptr thisDocument, const Snapshot &snapshot, - CreateBindings::Ptr bindings) + QSharedPointer<CreateBindings> 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<const Name *> names = LookupContext::fullyQualifiedName(symbol); @@ -241,7 +260,7 @@ const Name *LookupContext::minimalName(Symbol *symbol, LookupScope *target, Cont } QList<LookupItem> LookupContext::lookupByUsing(const Name *name, - LookupScope *bindingScope) const + ClassOrNamespace *bindingScope) const { QList<LookupItem> candidates; // if it is a nameId there can be a using declaration for it @@ -275,7 +294,7 @@ QList<LookupItem> 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<const Declaration *> typedefsBeingResolved) const +ClassOrNamespace *LookupContext::lookupType(const Name *name, Scope *scope, + ClassOrNamespace *enclosingBinding, + QSet<const Declaration *> 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<LookupItem> 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<LookupItem> 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<LookupItem> 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<LookupItem> 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<LookupItem> 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<LookupItem> 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<LookupItem> 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<LookupItem> 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<LookupItem> 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<LookupItem> LookupContext::lookup(const Name *name, Scope *scope) const return candidates; } -LookupScope *LookupContext::lookupParent(Symbol *symbol) const +ClassOrNamespace *LookupContext::lookupParent(Symbol *symbol) const { QList<const Name *> 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<const Name *, LookupScopePrivate *, Name::Compare> Table; - typedef std::map<const Name *, Declaration *, Name::Compare> TypedefTable; - typedef std::map<const TemplateNameId *, - LookupScopePrivate *, - TemplateNameId::Compare> TemplateNameIdTable; - typedef QHash<const AnonymousNameId *, LookupScopePrivate *> Anonymouses; - - LookupScopePrivate *allocateChild(const Name *name); - - void flush(); - - LookupScope *globalNamespace() const; - - Symbol *lookupInScope(const QList<const Name *> &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<LookupItem> lookup_helper(const Name *name, bool searchInEnclosingScope); - - void lookup_helper(const Name *name, LookupScopePrivate *binding, - QList<LookupItem> *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<Symbol *> _symbols; - QList<LookupScope *> _usings; - Table _nestedScopes; - TypedefTable _typedefs; - QHash<Block *, LookupScope *> _blocks; - QList<Enum *> _enums; - QList<Symbol *> _todo; - QSharedPointer<Control> _control; - TemplateNameIdTable _specializations; - QMap<const TemplateNameId *, LookupScopePrivate *> _instantiations; - Anonymouses _anonymouses; - QSet<const AnonymousNameId *> _declaredOrTypedefedAnonymouses; - - QHash<Internal::FullyQualifiedName, Symbol *> *_scopeLookupCache; - - // it's an instantiation. - LookupScopePrivate *_instantiationOrigin; - - AlreadyConsideredClassContainer<Class> _alreadyConsideredClasses; - AlreadyConsideredClassContainer<TemplateNameId> _alreadyConsideredTemplates; - QSet<const Declaration *> _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 *> ClassOrNamespace::usings() const { - if (Internal::LookupScopePrivate *i = d->_instantiationOrigin) - return i->q; - return 0; + const_cast<ClassOrNamespace *>(this)->flush(); + return _usings; } -LookupScope *LookupScope::parent() const +QList<Enum *> ClassOrNamespace::unscopedEnums() const { - if (Internal::LookupScopePrivate *p = d->_parent) - return p->q; - return 0; + const_cast<ClassOrNamespace *>(this)->flush(); + return _enums; } -QList<LookupScope *> LookupScope::usings() const +QList<Symbol *> ClassOrNamespace::symbols() const { - const_cast<LookupScope *>(this)->d->flush(); - return d->_usings; + const_cast<ClassOrNamespace *>(this)->flush(); + return _symbols; } -QList<Enum *> LookupScope::unscopedEnums() const +ClassOrNamespace *ClassOrNamespace::globalNamespace() const { - const_cast<LookupScope *>(this)->d->flush(); - return d->_enums; -} - -QList<Symbol *> LookupScope::symbols() const -{ - const_cast<LookupScope *>(this)->d->flush(); - return d->_symbols; -} - -QList<LookupItem> LookupScope::find(const Name *name) -{ - return d->lookup_helper(name, false); -} - -QList<LookupItem> 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<ClassOrNamespace *>(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<LookupItem> LookupScopePrivate::lookup_helper(const Name *name, bool searchInEnclosingScope) +QList<LookupItem> ClassOrNamespace::find(const Name *name) +{ + return lookup_helper(name, false); +} + +QList<LookupItem> ClassOrNamespace::lookup(const Name *name) +{ + return lookup_helper(name, true); +} + +QList<LookupItem> ClassOrNamespace::lookup_helper(const Name *name, bool searchInEnclosingScope) { QList<LookupItem> 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<const Name *> fullName; addNames(name, &fullName); @@ -735,10 +631,10 @@ QList<LookupItem> 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<ClassOrNamespace *> 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<LookupItem> LookupScopePrivate::lookup_helper(const Name *name, bool searc return result; } - ProcessedSet processed; - ProcessedSet processedOwnParents; - LookupScopePrivate *binding = this; + QSet<ClassOrNamespace *> processed; + QSet<ClassOrNamespace *> 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<LookupItem> LookupScopePrivate::lookup_helper(const Name *name, bool searc return result; } -void LookupScopePrivate::lookup_helper( - const Name *name, LookupScopePrivate *binding, QList<LookupItem> *result, - ProcessedSet *processed) +void ClassOrNamespace::lookup_helper(const Name *name, ClassOrNamespace *binding, + QList<LookupItem> *result, + QSet<ClassOrNamespace *> *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<LookupItem> *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("<null>")); + << (binding ? oo(binding->_name) : QString::fromLatin1("<null>")); } 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<ClassOrNamespace *> 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<Block *, LookupScope *>::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<Block *, ClassOrNamespace *>::const_iterator citBlock = _blocks.constFind(block); + if (citBlock != _blocks.constEnd()) { + ClassOrNamespace *nestedBlock = citBlock.value(); + QSet<ClassOrNamespace *> 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<ClassOrNamespace *> 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<ClassOrNamespace *> *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<ClassOrNamespace *> processed; + return findBlock_helper(block, &processed, true); } -Symbol *Internal::LookupScopePrivate::lookupInScope(const QList<const Name *> &fullName) +Symbol *ClassOrNamespace::lookupInScope(const QList<const Name *> &fullName) { if (!_scopeLookupCache) { _scopeLookupCache = new QHash<Internal::FullyQualifiedName, Symbol *>; - 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<const Name *> &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<ClassOrNamespace *> *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<ClassOrNamespace *> 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 AnonymousNameId *, ClassOrNamespace *>::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<LookupScopePrivate *>(this)->flush(); + const_cast<ClassOrNamespace *>(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 TemplateNameId *, ClassOrNamespace *>::const_iterator citInstantiation + = reference->_instantiations.constFind(templId); if (citInstantiation != reference->_instantiations.constEnd()) return citInstantiation.value(); TemplateNameId *nonConstTemplId = const_cast<TemplateNameId *>(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<const Name *> 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<LookupScope *> knownUsings = reference->_usings.toSet(); + QSet<ClassOrNamespace *> 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<const Name*, unsigned> 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 T> 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 T> class A : public B<T> {}; - if (baseTemplId->identifier() != templId->identifier()) { - if (LookupScopePrivate *nested = nestedType(baseName, origin)) - baseBinding = nested->q; + QHash<const Name*, unsigned> 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 T> 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 T> class A : public B<T>::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 T> class A : public B<T> {}; + if (baseTemplId->identifier() != templId->identifier()) + baseBinding = nestedType(baseName, origin); + } else if (const QualifiedNameId *qBaseName = baseName->asQualifiedNameId()) { + // Qualified names in general. + // Ex.: template <class T> class A : public B<T>::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<Some>::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<Symbol *> &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<Symbol *> 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<Control>(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<const Name *> path = LookupContext::path(symbol); return lookupType(path, enclosingBinding); } -LookupScope *CreateBindings::lookupType(const QList<const Name *> &path, - LookupScope *enclosingBinding) +ClassOrNamespace *CreateBindings::lookupType(const QList<const Name *> &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<const Name *> &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 <cplusplus/Control.h> #include <cplusplus/Name.h> -#include <QEnableSharedFromThis> #include <QSet> #include <QMap> @@ -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<LookupScope *> usings() const; + ClassOrNamespace *parent() const; + QList<ClassOrNamespace *> usings() const; QList<Enum *> unscopedEnums() const; QList<Symbol *> symbols() const; + ClassOrNamespace *globalNamespace() const; + QList<LookupItem> lookup(const Name *name); QList<LookupItem> 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<const Name *> &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<const Name *, ClassOrNamespace *, Name::Compare> Table; + typedef std::map<const TemplateNameId *, ClassOrNamespace *, TemplateNameId::Compare> TemplateNameIdTable; + typedef QHash<const AnonymousNameId *, ClassOrNamespace *> 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<LookupItem> lookup_helper(const Name *name, bool searchInEnclosingScope); + + void lookup_helper(const Name *name, ClassOrNamespace *binding, + QList<LookupItem> *result, + QSet<ClassOrNamespace *> *processed, + const TemplateNameId *templateId); + + ClassOrNamespace *lookupType_helper(const Name *name, QSet<ClassOrNamespace *> *processed, + bool searchInEnclosingScope, ClassOrNamespace *origin); + + ClassOrNamespace *findBlock_helper(Block *block, QSet<ClassOrNamespace *> *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<Symbol *> _symbols; + QList<ClassOrNamespace *> _usings; + Table _classOrNamespaces; + QHash<Block *, ClassOrNamespace *> _blocks; + QList<Enum *> _enums; + QList<Symbol *> _todo; + QSharedPointer<Control> _control; + TemplateNameIdTable _specializations; + QMap<const TemplateNameId *, ClassOrNamespace *> _instantiations; + Anonymouses _anonymouses; + QSet<const AnonymousNameId *> _declaredOrTypedefedAnonymouses; + + QHash<Internal::FullyQualifiedName, Symbol *> *_scopeLookupCache; + + // it's an instantiation. + const TemplateNameId *_templateId; + ClassOrNamespace *_instantiationOrigin; + + AlreadyConsideredClassContainer<Class> _alreadyConsideredClasses; + AlreadyConsideredClassContainer<TemplateNameId> _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<Symbol *> &symbols) const; + bool containsTemplateType(Declaration *declaration) const; + bool containsTemplateType(Function *function) const; + NamedType *findNamedType(Type *memberType) const; + + QSet<ClassOrNamespace *> _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<CreateBindings> +class CPLUSPLUS_EXPORT CreateBindings: protected SymbolVisitor { Q_DISABLE_COPY(CreateBindings) public: - typedef QSharedPointer<CreateBindings> 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<const Name *> &path, LookupScope *enclosingBinding = 0); + ClassOrNamespace *lookupType(Symbol *symbol, ClassOrNamespace *enclosingBinding = 0); + ClassOrNamespace *lookupType(const QList<const Name *> &path, + ClassOrNamespace *enclosingBinding = 0); /// Returns the Control that must be used to create temporary symbols. /// \internal QSharedPointer<Control> 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<LookupItem> *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> _control; - QList<Document::Ptr> _expressionDocuments; QSet<Namespace *> _processed; - QList<LookupScope *> _entities; - LookupScope *_globalNamespace; - LookupScope *_currentLookupScope; + QList<ClassOrNamespace *> _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<CreateBindings> bindings = QSharedPointer<CreateBindings>()); 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<LookupItem> 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<const Declaration *> typedefsBeingResolved = QSet<const Declaration *>()) 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<CreateBindings> bindings() const { return _bindings; } static QList<const Name *> fullyQualifiedName(Symbol *symbol); static QList<const Name *> 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<LookupItem> lookupByUsing(const Name *name, LookupScope *bindingScope) const; + QList<LookupItem> 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<CreateBindings> _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 <cplusplus/Control.h> #include <cplusplus/AST.h> @@ -75,6 +75,131 @@ static QList<T> removeDuplicates(const QList<T> &results) return uniqueList; } +class TypedefsResolver +{ +public: + TypedefsResolver(const LookupContext &context) : _context(context) {} + void resolve(FullySpecifiedType *type, Scope **scope, ClassOrNamespace *binding) + { + QSet<Symbol *> 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<LookupItem> 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<LookupItem> getNamedTypeItems(const Name *name, Scope *scope, + ClassOrNamespace *binding) const + { + QList<LookupItem> 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<LookupItem> typedefsFromScopeUpToFunctionScope(const Name *name, Scope *scope) + { + QList<LookupItem> 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<LookupItem>& namedTypeItems, FullySpecifiedType *type, + Scope **scope, QSet<Symbol *>& 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<LookupItem> &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<LookupItem> 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<const Declaration* >(_autoDeclarationsBeingResolved) << decl); + + Document::Ptr exprDoc = + documentForExpression(exprTyper.preprocessedExpression(initializer)); + exprDoc->check(); + + DeduceAutoCheck deduceAuto(ast->name->identifier(), exprDoc->translationUnit()); + if (deduceAuto._block) + continue; + + const QList<LookupItem> &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<LookupItem> ResolveExpression::getMembers(LookupScope *binding, const Name *memberName) const +QList<LookupItem> 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<LookupItem> &baseResults, - int accessOp, - bool *replacedDotOperator) const +ClassOrNamespace *ResolveExpression::baseExpression(const QList<LookupItem> &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<LookupItem> &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<LookupItem> &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<LookupItem> &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<LookupItem> 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<LookupItem> resolve(ExpressionAST *ast, Scope *scope, bool ref = false); QList<LookupItem> reference(ExpressionAST *ast, Scope *scope); - LookupScope *baseExpression(const QList<LookupItem> &baseResults, + ClassOrNamespace *baseExpression(const QList<LookupItem> &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<LookupItem> expression(ExpressionAST *ast); QList<LookupItem> switchResults(const QList<LookupItem> &symbols); + FullySpecifiedType instantiate(const Name *className, Symbol *candidate) const; - QList<LookupItem> getMembers(LookupScope *binding, const Name *memberName) const; + QList<LookupItem> 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<Symbol *> &symbols); void addResults(const QList<LookupItem> &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<CreateBindings> bindings, const QSet<const Declaration *> &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<CreateBindings>(new CreateBindings(thisDocument, snapshot)); m_environment.clear(); m_autoDeclarationsBeingResolved = autoDeclarationsBeingResolved; @@ -105,7 +105,7 @@ QList<LookupItem> 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<LookupItem> 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<CreateBindings> bindings = QSharedPointer<CreateBindings>(), const QSet<const Declaration *> &autoDeclarationsBeingResolved = QSet<const Declaration *>()); @@ -135,6 +135,7 @@ public: } private: + void processEnvironment(Document::Ptr doc, Environment *env, QSet<QString> *processed) const; @@ -142,13 +143,20 @@ private: private: Document::Ptr m_thisDocument; Snapshot m_snapshot; - CreateBindings::Ptr m_bindings; + QSharedPointer<CreateBindings> m_bindings; ExpressionAST *m_ast; Scope *m_scope; LookupContext m_lookupContext; mutable QSharedPointer<Environment> m_environment; - QSet<const Declaration *> 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<Document::Ptr> m_documents; + + QSet<const Declaration *> 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 <QDebug> - -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<Symbol *> 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<LookupItem> 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<LookupItem> TypeResolver::getNamedTypeItems(const Name *name, Scope *scope, - LookupScope *binding) const -{ - QList<LookupItem> 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<LookupItem> TypeResolver::typedefsFromScopeUpToFunctionScope(const Name *name, Scope *scope) -{ - QList<LookupItem> 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<LookupItem> TypeResolver::resolveDeclInitializer( - CreateBindings &factory, const Declaration *decl, - const QSet<const Declaration* > &declarationsBeingResolved, - const Identifier *id) -{ - const StringLiteral *initializationString = decl->getInitializer(); - if (initializationString == 0) - return QList<LookupItem>(); - - const QByteArray &initializer = - QByteArray::fromRawData(initializationString->chars(), - initializationString->size()).trimmed(); - - // Skip lambda-function initializers - if (initializer.length() > 0 && initializer[0] == '[') - return QList<LookupItem>(); - - 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<LookupItem>(); - } - - 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<LookupItem> &namedTypeItems, FullySpecifiedType *type, - Scope **scope, QSet<Symbol *> &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<LookupItem> resolved = - resolveDeclInitializer(_factory, decl, QSet<const Declaration* >() << 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/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", |