diff --git a/src/libs/cplusplus/FastPreprocessor.cpp b/src/libs/cplusplus/FastPreprocessor.cpp index c49695fc8cc..3c5b4312cea 100644 --- a/src/libs/cplusplus/FastPreprocessor.cpp +++ b/src/libs/cplusplus/FastPreprocessor.cpp @@ -66,9 +66,10 @@ QByteArray FastPreprocessor::run(Document::Ptr newDoc, const QByteArray &source) return preprocessed; } -void FastPreprocessor::sourceNeeded(unsigned line, const QString &fileName, - IncludeType mode) +void FastPreprocessor::sourceNeeded(unsigned line, const QString &fileName, IncludeType mode, + const QStringList &initialIncludes) { + Q_UNUSED(initialIncludes) Q_ASSERT(_currentDoc); // CHECKME: Is that cleanName needed? QString cleanName = QDir::cleanPath(fileName); diff --git a/src/libs/cplusplus/FastPreprocessor.h b/src/libs/cplusplus/FastPreprocessor.h index df19c4dcdf5..b4a14cfdb42 100644 --- a/src/libs/cplusplus/FastPreprocessor.h +++ b/src/libs/cplusplus/FastPreprocessor.h @@ -57,7 +57,8 @@ public: QByteArray run(Document::Ptr newDoc, const QByteArray &source); // CPlusPlus::Client - virtual void sourceNeeded(unsigned line, const QString &fileName, IncludeType mode); + virtual void sourceNeeded(unsigned line, const QString &fileName, IncludeType mode, + const QStringList &initialIncludes = QStringList()); virtual void macroAdded(const Macro &); diff --git a/src/libs/cplusplus/PreprocessorClient.h b/src/libs/cplusplus/PreprocessorClient.h index a990a393575..3680770dc2f 100644 --- a/src/libs/cplusplus/PreprocessorClient.h +++ b/src/libs/cplusplus/PreprocessorClient.h @@ -32,7 +32,7 @@ #include -#include +#include #include QT_BEGIN_NAMESPACE @@ -100,7 +100,8 @@ public: virtual void startSkippingBlocks(unsigned utf16charsOffset) = 0; virtual void stopSkippingBlocks(unsigned utf16charsOffset) = 0; - virtual void sourceNeeded(unsigned line, const QString &fileName, IncludeType mode) = 0; + virtual void sourceNeeded(unsigned line, const QString &fileName, IncludeType mode, + const QStringList &initialIncludes = QStringList()) = 0; static inline bool isInjectedFile(const QString &fileName) { diff --git a/src/plugins/cpptools/cppmodelmanager_test.cpp b/src/plugins/cpptools/cppmodelmanager_test.cpp index 3ca3e3d49dd..6f7a6f1fa06 100644 --- a/src/plugins/cpptools/cppmodelmanager_test.cpp +++ b/src/plugins/cpptools/cppmodelmanager_test.cpp @@ -37,6 +37,8 @@ #include #include #include + +#include #include #include @@ -873,7 +875,7 @@ void CppToolsPlugin::test_modelmanager_defines_per_project() } } -void CppToolsPlugin::test_modelmanager_defines_per_project_pch() +void CppToolsPlugin::test_modelmanager_precompiled_headers() { ModelManagerTestHelper helper; @@ -922,14 +924,16 @@ void CppToolsPlugin::test_modelmanager_defines_per_project_pch() struct Data { QString firstDeclarationName; + QString firstClassInPchFile; QString fileName; } d[] = { - { _("one"), main1File }, - { _("two"), main2File } + { _("one"), _("ClassInPch1"), main1File }, + { _("two"), _("ClassInPch2"), main2File } }; const int size = sizeof(d) / sizeof(d[0]); for (int i = 0; i < size; ++i) { const QString firstDeclarationName = d[i].firstDeclarationName; + const QByteArray firstClassInPchFile = d[i].firstClassInPchFile.toUtf8(); const QString fileName = d[i].fileName; Core::IEditor *editor = Core::EditorManager::openEditor(fileName); @@ -943,11 +947,22 @@ void CppToolsPlugin::test_modelmanager_defines_per_project_pch() while (sup->lastSemanticInfoDocument().isNull()) QCoreApplication::processEvents(); - sup->snapshotUpdater()->setUsePrecompiledHeaders(true); - sup->snapshotUpdater()->update(mm->workingCopy()); + const QSharedPointer updater = sup->snapshotUpdater(); + updater->setUsePrecompiledHeaders(true); + updater->update(mm->workingCopy()); - Document::Ptr doc = mm->document(fileName); - QCOMPARE(nameOfFirstDeclaration(doc), firstDeclarationName); + // Check if defines from pch are considered + Document::Ptr document = mm->document(fileName); + QCOMPARE(nameOfFirstDeclaration(document), firstDeclarationName); + + // Check if declarations from pch are considered + CPlusPlus::LookupContext context(document, updater->snapshot()); + const CPlusPlus::Identifier *identifier + = document->control()->identifier(firstClassInPchFile.data()); + const QList results = context.lookup(identifier, + document->globalNamespace()); + QVERIFY(!results.isEmpty()); + QVERIFY(results.first().declaration()->type()->asClassType()); } } diff --git a/src/plugins/cpptools/cppsnapshotupdater.cpp b/src/plugins/cpptools/cppsnapshotupdater.cpp index 60c8d3e4146..a6900d3d2c0 100644 --- a/src/plugins/cpptools/cppsnapshotupdater.cpp +++ b/src/plugins/cpptools/cppsnapshotupdater.cpp @@ -177,7 +177,8 @@ void SnapshotUpdater::update(CppModelManager::WorkingCopy workingCopy) } if (!m_editorDefines.isEmpty()) sourceProcessor.run(editorDefinesFileName); - sourceProcessor.run(m_fileInEditor); + sourceProcessor.run(m_fileInEditor, m_usePrecompiledHeaders ? m_precompiledHeaders + : QStringList()); m_snapshot = sourceProcessor.snapshot(); Snapshot newSnapshot = m_snapshot.simplified(document()); diff --git a/src/plugins/cpptools/cppsourceprocessor.cpp b/src/plugins/cpptools/cppsourceprocessor.cpp index 47986331b37..33b2a0896eb 100644 --- a/src/plugins/cpptools/cppsourceprocessor.cpp +++ b/src/plugins/cpptools/cppsourceprocessor.cpp @@ -148,9 +148,10 @@ void CppSourceProcessor::addFrameworkPath(const ProjectPart::HeaderPath &framewo void CppSourceProcessor::setTodo(const QStringList &files) { m_todo = QSet::fromList(files); } -void CppSourceProcessor::run(const QString &fileName) +void CppSourceProcessor::run(const QString &fileName, + const QStringList &initialIncludes) { - sourceNeeded(0, fileName, IncludeGlobal); + sourceNeeded(0, fileName, IncludeGlobal, initialIncludes); } void CppSourceProcessor::removeFromCache(const QString &fileName) @@ -377,7 +378,8 @@ void CppSourceProcessor::stopSkippingBlocks(unsigned utf16charsOffset) m_currentDoc->stopSkippingBlocks(utf16charsOffset); } -void CppSourceProcessor::sourceNeeded(unsigned line, const QString &fileName, IncludeType type) +void CppSourceProcessor::sourceNeeded(unsigned line, const QString &fileName, IncludeType type, + const QStringList &initialIncludes) { if (fileName.isEmpty()) return; @@ -417,6 +419,11 @@ void CppSourceProcessor::sourceNeeded(unsigned line, const QString &fileName, In Document::Ptr document = Document::create(absoluteFileName); document->setRevision(m_revision); document->setEditorRevision(editorRevision); + foreach (const QString &include, initialIncludes) { + m_included.insert(include); + Document::Include inc(include, include, 0, IncludeLocal); + document->addIncludeFile(inc); + } const QFileInfo info(absoluteFileName); if (info.exists()) document->setLastModified(info.lastModified()); diff --git a/src/plugins/cpptools/cppsourceprocessor.h b/src/plugins/cpptools/cppsourceprocessor.h index e10d1438163..e51315c32cc 100644 --- a/src/plugins/cpptools/cppsourceprocessor.h +++ b/src/plugins/cpptools/cppsourceprocessor.h @@ -43,7 +43,7 @@ public: void setHeaderPaths(const ProjectPart::HeaderPaths &headerPaths); void setTodo(const QStringList &files); - void run(const QString &fileName); + void run(const QString &fileName, const QStringList &initialIncludes = QStringList()); void removeFromCache(const QString &fileName); void resetEnvironment(); @@ -80,7 +80,8 @@ private: void markAsIncludeGuard(const QByteArray ¯oName) QTC_OVERRIDE; void startSkippingBlocks(unsigned utf16charsOffset) QTC_OVERRIDE; void stopSkippingBlocks(unsigned utf16charsOffset) QTC_OVERRIDE; - void sourceNeeded(unsigned line, const QString &fileName, IncludeType type) QTC_OVERRIDE; + void sourceNeeded(unsigned line, const QString &fileName, IncludeType type, + const QStringList &initialIncludes) QTC_OVERRIDE; private: CPlusPlus::Snapshot m_snapshot; diff --git a/src/plugins/cpptools/cpptoolsplugin.h b/src/plugins/cpptools/cpptoolsplugin.h index 3d54eb0cdee..771bc542c66 100644 --- a/src/plugins/cpptools/cpptoolsplugin.h +++ b/src/plugins/cpptools/cpptoolsplugin.h @@ -146,8 +146,8 @@ private slots: void test_modelmanager_gc_if_last_cppeditor_closed(); void test_modelmanager_dont_gc_opened_files(); void test_modelmanager_defines_per_project(); - void test_modelmanager_defines_per_project_pch(); void test_modelmanager_defines_per_editor(); + void test_modelmanager_precompiled_headers(); void test_cpplocatorfilters_CppLocatorFilter(); void test_cpplocatorfilters_CppLocatorFilter_data(); diff --git a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp index a7d4287dacf..6b8dad64886 100644 --- a/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp +++ b/tests/auto/cplusplus/preprocessor/tst_preprocessor.cpp @@ -159,8 +159,10 @@ public: virtual void stopSkippingBlocks(unsigned utf16charsOffset) { m_skippedBlocks.last().end = utf16charsOffset; } - virtual void sourceNeeded(unsigned line, const QString &includedFileName, IncludeType mode) + virtual void sourceNeeded(unsigned line, const QString &includedFileName, IncludeType mode, + const QStringList &initialIncludes = QStringList()) { + Q_UNUSED(initialIncludes) #if 1 m_recordedIncludes.append(Include(includedFileName, mode, line)); Q_UNUSED(m_env); diff --git a/tests/cppmodelmanager/testdata_defines/pch1.h b/tests/cppmodelmanager/testdata_defines/pch1.h index a5a8cae412f..b76608a7725 100644 --- a/tests/cppmodelmanager/testdata_defines/pch1.h +++ b/tests/cppmodelmanager/testdata_defines/pch1.h @@ -1 +1,2 @@ #define SUB1 +class ClassInPch1{}; diff --git a/tests/cppmodelmanager/testdata_defines/pch2.h b/tests/cppmodelmanager/testdata_defines/pch2.h index 2b715eaec16..289da5b927a 100644 --- a/tests/cppmodelmanager/testdata_defines/pch2.h +++ b/tests/cppmodelmanager/testdata_defines/pch2.h @@ -1 +1,2 @@ #define SUB2 +class ClassInPch2{};