diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index 75f64fea5da9db750abf37ff1de1652a31e7c13e..c7e1d3fc5da50ab54e12e6f32dd07dc9e73b4f0a 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -120,6 +120,9 @@ public: void run(QString &fileName); void operator()(QString &fileName); +public: // attributes + Snapshot snapshot; + protected: CPlusPlus::Document::Ptr switchDocument(CPlusPlus::Document::Ptr doc); @@ -141,7 +144,6 @@ protected: private: QPointer<CppModelManager> m_modelManager; - Snapshot m_snapshot; Environment env; Preprocessor m_proc; QStringList m_includePaths; @@ -157,9 +159,9 @@ private: } // namespace CppTools CppPreprocessor::CppPreprocessor(QPointer<CppModelManager> modelManager) - : m_modelManager(modelManager), - m_snapshot(modelManager->snapshot()), - m_proc(this, env) + : snapshot(modelManager->snapshot()), + m_modelManager(modelManager), + m_proc(this, env) { } void CppPreprocessor::setWorkingCopy(const QMap<QString, QByteArray> &workingCopy) @@ -337,8 +339,13 @@ void CppPreprocessor::mergeEnvironment(Document::Ptr doc, QSet<QString> *process processed->insert(fn); - foreach (QString includedFile, doc->includedFiles()) { - mergeEnvironment(m_snapshot.value(includedFile), processed); + foreach (Document::Include incl, doc->includes()) { + QString includedFile = incl.fileName(); + + if (Document::Ptr includedDoc = snapshot.value(includedFile)) + mergeEnvironment(includedDoc, processed); + else + run(includedFile); } foreach (const Macro macro, doc->definedMacros()) { @@ -384,7 +391,7 @@ void CppPreprocessor::sourceNeeded(QString &fileName, IncludeType type, } if (! contents.isEmpty()) { - Document::Ptr cachedDoc = m_snapshot.value(fileName); + Document::Ptr cachedDoc = snapshot.value(fileName); if (cachedDoc && m_currentDoc) { mergeEnvironment(cachedDoc); } else { @@ -393,8 +400,8 @@ void CppPreprocessor::sourceNeeded(QString &fileName, IncludeType type, const QByteArray previousFile = env.currentFile; const unsigned previousLine = env.currentLine; - env.currentFile = QByteArray(m_currentDoc->translationUnit()->fileName(), - m_currentDoc->translationUnit()->fileNameLength()); + TranslationUnit *unit = m_currentDoc->translationUnit(); + env.currentFile = QByteArray(unit->fileName(), unit->fileNameLength()); QByteArray preprocessedCode; m_proc(contents, &preprocessedCode); @@ -775,7 +782,12 @@ void CppModelManager::parse(QFutureInterface<void> &future, CppPreprocessor *preproc, QStringList files) { - QTC_ASSERT(!files.isEmpty(), return); + if (files.isEmpty()) + return; + + foreach (QString file, files) { + preproc->snapshot.remove(file); + } // Change the priority of the background parser thread to idle. QThread::currentThread()->setPriority(QThread::IdlePriority); diff --git a/src/shared/cplusplus/AST.h b/src/shared/cplusplus/AST.h index f5e3ac42fc57463e533e6a4aa54d57792cc895b8..d29342b30a69ee629ecadc08da930376e65bd83d 100644 --- a/src/shared/cplusplus/AST.h +++ b/src/shared/cplusplus/AST.h @@ -60,6 +60,20 @@ CPLUSPLUS_BEGIN_HEADER CPLUSPLUS_BEGIN_NAMESPACE +template <typename _Tp> +class List: public Managed +{ + List(const List &other); + void operator =(const List &other); + +public: + List() + { } + + _Tp value; + List *next; +}; + class CPLUSPLUS_EXPORT AST: public Managed { AST(const AST &other); @@ -351,6 +365,9 @@ public: DeclaratorListAST *declarators; unsigned semicolon_token; +public: + List<Declaration *> *symbols; + public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; @@ -422,6 +439,9 @@ public: NameAST *name; BaseSpecifierAST *next; +public: // annotations + BaseClass *symbol; + public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; @@ -516,7 +536,7 @@ public: unsigned rbrace_token; public: // annotations - Class *class_symbol; + Class *symbol; public: virtual unsigned firstToken() const; @@ -691,6 +711,9 @@ public: SpecifierAST *cv_qualifier_seq; ExceptionSpecificationAST *exception_specification; +public: // annotations + Function *symbol; + public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; @@ -918,6 +941,9 @@ public: CtorInitializerAST *ctor_initializer; StatementAST *function_body; +public: // annotations + Function *symbol; + public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; @@ -1060,6 +1086,9 @@ protected: class CPLUSPLUS_EXPORT NameAST: public ExpressionAST { +public: // annotations + Name *name; + public: virtual NameAST *clone(MemoryPool *pool) const = 0; }; @@ -1188,6 +1217,9 @@ public: SpecifierAST *attributes; DeclarationAST *linkage_body; +public: // annotations + Namespace *symbol; + public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; @@ -1312,6 +1344,9 @@ public: unsigned equal_token; ExpressionAST *expression; +public: // annotations + Argument *symbol; + public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; @@ -1849,6 +1884,9 @@ public: unsigned equal_token; ExpressionAST *type_id; +public: // annotations + Argument *symbol; + public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; @@ -1871,6 +1909,9 @@ public: unsigned equal_token; ExpressionAST *type_id; +public: + Argument *symbol; + public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; @@ -1905,6 +1946,9 @@ public: NameAST *name; unsigned semicolon_token; +public: // annotations + UsingDeclaration *symbol; + public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; @@ -1923,6 +1967,9 @@ public: NameAST *name; unsigned semicolon_token; +public: + UsingNamespaceDirective *symbol; + public: virtual unsigned firstToken() const; virtual unsigned lastToken() const; diff --git a/src/shared/cplusplus/CheckDeclaration.cpp b/src/shared/cplusplus/CheckDeclaration.cpp index 610d57626f43849816ee078788eb0c0dcc58d2f2..179dd069879c76ab6e63a6a3bc547d08d20a7435 100644 --- a/src/shared/cplusplus/CheckDeclaration.cpp +++ b/src/shared/cplusplus/CheckDeclaration.cpp @@ -136,6 +136,7 @@ bool CheckDeclaration::visit(SimpleDeclarationAST *ast) } } + List<Declaration *> **decl_it = &ast->symbols; for (DeclaratorListAST *it = ast->declarators; it; it = it->next) { Name *name = 0; FullySpecifiedType declTy = semantic()->check(it->declarator, qualTy, @@ -179,6 +180,10 @@ bool CheckDeclaration::visit(SimpleDeclarationAST *ast) else if (ty.isTypedef()) symbol->setStorage(Symbol::Typedef); + *decl_it = new (translationUnit()->memoryPool()) List<Declaration *>(); + (*decl_it)->value = symbol; + decl_it = &(*decl_it)->next; + _scope->enterSymbol(symbol); } return false; @@ -234,6 +239,7 @@ bool CheckDeclaration::visit(FunctionDefinitionAST *ast) checkFunctionArguments(fun); + ast->symbol = fun; _scope->enterSymbol(fun); if (ast->ctor_initializer) { @@ -286,6 +292,7 @@ bool CheckDeclaration::visit(NamespaceAST *ast) Identifier *id = identifier(ast->identifier_token); Name *namespaceName = control()->nameId(id); Namespace *ns = control()->newNamespace(ast->firstToken(), namespaceName); + ast->symbol = ns; _scope->enterSymbol(ns); semantic()->check(ast->linkage_body, ns->members()); // ### we'll do the merge later. @@ -310,6 +317,7 @@ bool CheckDeclaration::visit(ParameterDeclarationAST *ast) _scope, &argName); FullySpecifiedType exprTy = semantic()->check(ast->expression, _scope); Argument *arg = control()->newArgument(ast->firstToken(), argName); + ast->symbol = arg; if (ast->expression) arg->setInitializer(true); arg->setType(argTy); @@ -319,15 +327,6 @@ bool CheckDeclaration::visit(ParameterDeclarationAST *ast) bool CheckDeclaration::visit(TemplateDeclarationAST *ast) { -/* - Template *templ = control()->newTemplate(ast->firstToken()); - - for (DeclarationAST *param = ast->template_parameters; param; - param = param->next) { - semantic()->check(param, templ->members()); - } -*/ - Scope *previousScope = switchScope(new Scope(_scope->owner())); for (DeclarationAST *param = ast->template_parameters; param; param = param->next) { @@ -343,6 +342,7 @@ bool CheckDeclaration::visit(TypenameTypeParameterAST *ast) { Name *name = semantic()->check(ast->name, _scope); Argument *arg = control()->newArgument(ast->firstToken(), name); // ### new template type + ast->symbol = arg; _scope->enterSymbol(arg); return false; } @@ -351,6 +351,7 @@ bool CheckDeclaration::visit(TemplateTypeParameterAST *ast) { Name *name = semantic()->check(ast->name, _scope); Argument *arg = control()->newArgument(ast->firstToken(), name); // ### new template type + ast->symbol = arg; _scope->enterSymbol(arg); return false; } @@ -359,6 +360,7 @@ bool CheckDeclaration::visit(UsingAST *ast) { Name *name = semantic()->check(ast->name, _scope); UsingDeclaration *u = control()->newUsingDeclaration(ast->firstToken(), name); + ast->symbol = u; _scope->enterSymbol(u); return false; } @@ -367,6 +369,7 @@ bool CheckDeclaration::visit(UsingDirectiveAST *ast) { Name *name = semantic()->check(ast->name, _scope); UsingNamespaceDirective *u = control()->newUsingNamespaceDirective(ast->firstToken(), name); + ast->symbol = u; _scope->enterSymbol(u); return false; } diff --git a/src/shared/cplusplus/CheckDeclarator.cpp b/src/shared/cplusplus/CheckDeclarator.cpp index 13120fec589265f83e4989b174a00f10c72e9779..beb2ed0bca769f0f556ec2a6076a4a2d73926cf3 100644 --- a/src/shared/cplusplus/CheckDeclarator.cpp +++ b/src/shared/cplusplus/CheckDeclarator.cpp @@ -158,6 +158,7 @@ bool CheckDeclarator::visit(NestedDeclaratorAST *ast) bool CheckDeclarator::visit(FunctionDeclaratorAST *ast) { Function *fun = control()->newFunction(ast->firstToken()); + ast->symbol = fun; fun->setReturnType(_fullySpecifiedType); if (ast->parameters) { diff --git a/src/shared/cplusplus/CheckName.cpp b/src/shared/cplusplus/CheckName.cpp index 09b90f3cb804f4c777eaa4b29ee96a16e52a7d8d..dfd8158464052704ce5f9ce60ebddc07a8aa1eca 100644 --- a/src/shared/cplusplus/CheckName.cpp +++ b/src/shared/cplusplus/CheckName.cpp @@ -121,6 +121,8 @@ bool CheckName::visit(QualifiedNameAST *ast) names.push_back(semantic()->check(ast->unqualified_name, _scope)); _name = control()->qualifiedNameId(&names[0], names.size(), ast->global_scope_token != 0); + + ast->name = _name; return false; } @@ -302,6 +304,7 @@ bool CheckName::visit(OperatorFunctionIdAST *ast) } // switch _name = control()->operatorNameId(kind); + ast->name = _name; return false; } @@ -317,6 +320,7 @@ bool CheckName::visit(SimpleNameAST *ast) { Identifier *id = identifier(ast->identifier_token); _name = control()->nameId(id); + ast->name = _name; return false; } @@ -324,6 +328,7 @@ bool CheckName::visit(DestructorNameAST *ast) { Identifier *id = identifier(ast->identifier_token); _name = control()->destructorNameId(id); + ast->name = _name; return false; } @@ -342,6 +347,7 @@ bool CheckName::visit(TemplateIdAST *ast) else _name = control()->templateNameId(id, &templateArguments[0], templateArguments.size()); + ast->name = _name; return false; } diff --git a/src/shared/cplusplus/CheckSpecifier.cpp b/src/shared/cplusplus/CheckSpecifier.cpp index cb929b868caac1c68d314fc79ed7fa951983bf31..20a3662e7b8c8b770de4fe8d0fcef3f54a6356f6 100644 --- a/src/shared/cplusplus/CheckSpecifier.cpp +++ b/src/shared/cplusplus/CheckSpecifier.cpp @@ -300,7 +300,7 @@ bool CheckSpecifier::visit(ClassSpecifierAST *ast) { Name *className = semantic()->check(ast->name, _scope); Class *klass = control()->newClass(ast->firstToken(), className); - ast->class_symbol = klass; + ast->symbol = klass; unsigned classKey = tokenKind(ast->classkey_token); if (classKey == T_CLASS) klass->setClassKey(Class::ClassKey); @@ -315,6 +315,7 @@ bool CheckSpecifier::visit(ClassSpecifierAST *ast) for (BaseSpecifierAST *base = ast->base_clause; base; base = base->next) { Name *baseClassName = semantic()->check(base->name, _scope); BaseClass *baseClass = control()->newBaseClass(ast->firstToken(), baseClassName); + base->symbol = baseClass; if (base->token_virtual) baseClass->setVirtual(true); if (base->token_access_specifier) { diff --git a/src/shared/cplusplus/Control.cpp b/src/shared/cplusplus/Control.cpp index e44d84a1aee801bf7daf22bf3348ae8bcb876af3..4d708f4340c5553206984ba155ea2222bd53c500 100644 --- a/src/shared/cplusplus/Control.cpp +++ b/src/shared/cplusplus/Control.cpp @@ -51,7 +51,6 @@ // THE SOFTWARE. #include "Control.h" -#include "MemoryPool.h" #include "Literals.h" #include "LiteralTable.h" #include "TranslationUnit.h" diff --git a/tests/auto/cplusplus/lookup/tst_lookup.cpp b/tests/auto/cplusplus/lookup/tst_lookup.cpp index ecf3ae71fefe6164e1eab56cfc6d72b8fdc39481..f3e6a570d5a81ac02eadfc4091a55e605abaf633 100644 --- a/tests/auto/cplusplus/lookup/tst_lookup.cpp +++ b/tests/auto/cplusplus/lookup/tst_lookup.cpp @@ -12,6 +12,17 @@ CPLUSPLUS_USE_NAMESPACE +template <template <typename, typename> class _Map, typename _T1, typename _T2> +_Map<_T2, _T1> invert(const _Map<_T1, _T2> &m) +{ + _Map<_T2, _T1> i; + typename _Map<_T1, _T2>::const_iterator it = m.constBegin(); + for (; it != m.constEnd(); ++it) { + i.insertMulti(it.value(), it.key()); + } + return i; +} + class ClassSymbols: protected ASTVisitor, public QMap<ClassSpecifierAST *, Class *> { @@ -20,13 +31,16 @@ public: : ASTVisitor(control) { } + QMap<ClassSpecifierAST *, Class *> asMap() const + { return *this; } + void operator()(AST *ast) { accept(ast); } protected: virtual bool visit(ClassSpecifierAST *ast) { - Class *classSymbol = ast->class_symbol; + Class *classSymbol = ast->symbol; Q_ASSERT(classSymbol != 0); insert(ast, classSymbol); @@ -62,7 +76,7 @@ void tst_Lookup::base_class_defined_1() Snapshot snapshot; snapshot.insert(doc->fileName(), doc); - Document::Ptr emptyDoc = Document::create("empty"); + Document::Ptr emptyDoc = Document::create("<empty>"); Class *baseClass = doc->globalSymbolAt(0)->asClass(); QVERIFY(baseClass); @@ -88,6 +102,12 @@ void tst_Lookup::base_class_defined_1() classSymbols(ast); QCOMPARE(classSymbols.size(), 2); + + const QMap<Class *, ClassSpecifierAST *> classToAST = + invert(classSymbols.asMap()); + + QVERIFY(classToAST.value(baseClass) != 0); + QVERIFY(classToAST.value(derivedClass) != 0); } QTEST_APPLESS_MAIN(tst_Lookup)