From e3977de08eb5577222f01a9013185b036dee4564 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 5 Dec 2014 11:56:06 +0100 Subject: [PATCH] C++: Finish gcc's include_next support This implements the actual include_next logic and thus completes commit b934cc1 C++: pass #include_next down to CppPreprocessor::tryIncludeFile commmit 140b502 C++: Highlight argument to gcc's #include_next extension Based on https://gcc.gnu.org/onlinedocs/cpp/Wrapper-Headers.html Task-number: QTCREATORBUG-10225 Change-Id: I7eef7f5ea64a114f6d092304d32b72c55c2ce134 Reviewed-by: hjk Reviewed-by: Erik Verbruggen --- src/plugins/coreplugin/testdatadir.h | 2 -- src/plugins/cpptools/cppsourceprocessor.cpp | 34 ++++++++++++------ .../cpptools/cppsourceprocessor_test.cpp | 36 +++++++++++++++++++ src/plugins/cpptools/cpptoolsplugin.h | 1 + .../include_next-data/customIncludePath/t.h | 2 ++ .../data/include_next-data/main.cpp | 13 +++++++ .../include_next-data/systemIncludePath/t.h | 5 +++ 7 files changed, 81 insertions(+), 12 deletions(-) create mode 100644 tests/auto/cplusplus/preprocessor/data/include_next-data/customIncludePath/t.h create mode 100644 tests/auto/cplusplus/preprocessor/data/include_next-data/main.cpp create mode 100644 tests/auto/cplusplus/preprocessor/data/include_next-data/systemIncludePath/t.h diff --git a/src/plugins/coreplugin/testdatadir.h b/src/plugins/coreplugin/testdatadir.h index 3ace53be1ff..232b128ad05 100644 --- a/src/plugins/coreplugin/testdatadir.h +++ b/src/plugins/coreplugin/testdatadir.h @@ -52,8 +52,6 @@ class CORE_EXPORT TestDataDir public: TestDataDir(const QString &directory); QString file(const QString &fileName) const; - -protected: QString directory(const QString &subdir = QString(), bool clean = true) const; private: diff --git a/src/plugins/cpptools/cppsourceprocessor.cpp b/src/plugins/cpptools/cppsourceprocessor.cpp index cd56dae3c91..a8ad8d254a1 100644 --- a/src/plugins/cpptools/cppsourceprocessor.cpp +++ b/src/plugins/cpptools/cppsourceprocessor.cpp @@ -272,19 +272,33 @@ QString CppSourceProcessor::resolveFile_helper(const QString &fileName, IncludeT if (QFileInfo(fileName).isAbsolute()) return checkFile(fileName) ? fileName : QString(); - if (type == IncludeLocal && m_currentDoc) { - const QFileInfo currentFileInfo(m_currentDoc->fileName()); - const QString path = cleanPath(currentFileInfo.absolutePath()) + fileName; - if (checkFile(path)) - return path; - // Fall through! "16.2 Source file inclusion" from the standard states to continue - // searching as if this would be a global include. + auto headerPathsIt = m_headerPaths.begin(); + auto headerPathsEnd = m_headerPaths.end(); + if (m_currentDoc) { + if (type == IncludeLocal) { + const QFileInfo currentFileInfo(m_currentDoc->fileName()); + const QString path = cleanPath(currentFileInfo.absolutePath()) + fileName; + if (checkFile(path)) + return path; + // Fall through! "16.2 Source file inclusion" from the standard states to continue + // searching as if this would be a global include. + + } else if (type == IncludeNext) { + const QFileInfo currentFileInfo(m_currentDoc->fileName()); + const QString currentDirPath = cleanPath(currentFileInfo.dir().path()); + for (; headerPathsIt != headerPathsEnd; ++headerPathsIt) { + if (headerPathsIt->path == currentDirPath) { + ++headerPathsIt; + break; + } + } + } } - foreach (const ProjectPart::HeaderPath &headerPath, m_headerPaths) { - if (headerPath.isFrameworkPath()) + for (; headerPathsIt != headerPathsEnd; ++headerPathsIt) { + if (headerPathsIt->isFrameworkPath()) continue; - const QString path = headerPath.path + fileName; + const QString path = headerPathsIt->path + fileName; if (m_workingCopy.contains(path) || checkFile(path)) return path; } diff --git a/src/plugins/cpptools/cppsourceprocessor_test.cpp b/src/plugins/cpptools/cppsourceprocessor_test.cpp index 70a98bed2c2..624f730d68d 100644 --- a/src/plugins/cpptools/cppsourceprocessor_test.cpp +++ b/src/plugins/cpptools/cppsourceprocessor_test.cpp @@ -37,6 +37,7 @@ #include "cpptoolstestcase.h" #include "editordocumenthandle.h" +#include #include #include @@ -203,3 +204,38 @@ void CppToolsPlugin::test_cppsourceprocessor_macroUses() QCOMPARE(macroUse.utf16charsEnd(), 35U); QCOMPARE(macroUse.beginLine(), 2U); } + +static bool isMacroDefinedInDocument(const QByteArray ¯oName, const Document::Ptr &document) +{ + foreach (const Macro ¯o, document->definedMacros()) { + if (macro.name() == macroName) + return true; + } + + return false; +} + +static inline QString _(const QByteArray &ba) { return QString::fromLatin1(ba, ba.size()); } + +void CppToolsPlugin::test_cppsourceprocessor_includeNext() +{ + const Core::Tests::TestDataDir data( + _(SRCDIR "/../../../tests/auto/cplusplus/preprocessor/data/include_next-data/")); + const QString mainFilePath = data.file(QLatin1String("main.cpp")); + const QString customHeaderPath = data.directory(QLatin1String("customIncludePath")); + const QString systemHeaderPath = data.directory(QLatin1String("systemIncludePath")); + + CppSourceProcessor::DocumentCallback documentCallback = [](const CPlusPlus::Document::Ptr &){}; + CppSourceProcessor sourceProcessor(Snapshot(), documentCallback); + ProjectPart::HeaderPaths headerPaths = ProjectPart::HeaderPaths() + << ProjectPart::HeaderPath(customHeaderPath, ProjectPart::HeaderPath::IncludePath) + << ProjectPart::HeaderPath(systemHeaderPath, ProjectPart::HeaderPath::IncludePath); + sourceProcessor.setHeaderPaths(headerPaths); + + sourceProcessor.run(mainFilePath); + const Snapshot snapshot = sourceProcessor.snapshot(); + QVERIFY(!snapshot.isEmpty()); + const Document::Ptr mainDocument = snapshot.document(mainFilePath); + QVERIFY(mainDocument); + QVERIFY(isMacroDefinedInDocument("OK_FEATURE_X_ENABLED", mainDocument)); +} diff --git a/src/plugins/cpptools/cpptoolsplugin.h b/src/plugins/cpptools/cpptoolsplugin.h index a4200cc4de2..a3dec6b4774 100644 --- a/src/plugins/cpptools/cpptoolsplugin.h +++ b/src/plugins/cpptools/cpptoolsplugin.h @@ -133,6 +133,7 @@ private slots: void test_cppsourceprocessor_includes_cyclic(); void test_cppsourceprocessor_includes_allDiagnostics(); void test_cppsourceprocessor_macroUses(); + void test_cppsourceprocessor_includeNext(); void test_functionutils_virtualFunctions(); void test_functionutils_virtualFunctions_data(); diff --git a/tests/auto/cplusplus/preprocessor/data/include_next-data/customIncludePath/t.h b/tests/auto/cplusplus/preprocessor/data/include_next-data/customIncludePath/t.h new file mode 100644 index 00000000000..0bf1c95e9ad --- /dev/null +++ b/tests/auto/cplusplus/preprocessor/data/include_next-data/customIncludePath/t.h @@ -0,0 +1,2 @@ +#define ENABLE_FEATURE_X +#include_next "t.h" diff --git a/tests/auto/cplusplus/preprocessor/data/include_next-data/main.cpp b/tests/auto/cplusplus/preprocessor/data/include_next-data/main.cpp new file mode 100644 index 00000000000..e4f77f73ab9 --- /dev/null +++ b/tests/auto/cplusplus/preprocessor/data/include_next-data/main.cpp @@ -0,0 +1,13 @@ +// Copyright + +#include "t.h" + +int main() +{ +#ifdef FEATURE_X_ENABLED +#define OK_FEATURE_X_ENABLED + return 0; +#endif + return 1; +} + diff --git a/tests/auto/cplusplus/preprocessor/data/include_next-data/systemIncludePath/t.h b/tests/auto/cplusplus/preprocessor/data/include_next-data/systemIncludePath/t.h new file mode 100644 index 00000000000..12120d56406 --- /dev/null +++ b/tests/auto/cplusplus/preprocessor/data/include_next-data/systemIncludePath/t.h @@ -0,0 +1,5 @@ +#define SYSTEM_HEADER_INCLUDED + +#ifdef ENABLE_FEATURE_X +#define FEATURE_X_ENABLED +#endif