forked from qt-creator/qt-creator
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 <hjk121@nokiamail.com>
Reviewed-by: Erik Verbruggen <erik.verbruggen@theqtcompany.com>
This commit is contained in:
@@ -52,8 +52,6 @@ class CORE_EXPORT TestDataDir
|
|||||||
public:
|
public:
|
||||||
TestDataDir(const QString &directory);
|
TestDataDir(const QString &directory);
|
||||||
QString file(const QString &fileName) const;
|
QString file(const QString &fileName) const;
|
||||||
|
|
||||||
protected:
|
|
||||||
QString directory(const QString &subdir = QString(), bool clean = true) const;
|
QString directory(const QString &subdir = QString(), bool clean = true) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -272,19 +272,33 @@ QString CppSourceProcessor::resolveFile_helper(const QString &fileName, IncludeT
|
|||||||
if (QFileInfo(fileName).isAbsolute())
|
if (QFileInfo(fileName).isAbsolute())
|
||||||
return checkFile(fileName) ? fileName : QString();
|
return checkFile(fileName) ? fileName : QString();
|
||||||
|
|
||||||
if (type == IncludeLocal && m_currentDoc) {
|
auto headerPathsIt = m_headerPaths.begin();
|
||||||
|
auto headerPathsEnd = m_headerPaths.end();
|
||||||
|
if (m_currentDoc) {
|
||||||
|
if (type == IncludeLocal) {
|
||||||
const QFileInfo currentFileInfo(m_currentDoc->fileName());
|
const QFileInfo currentFileInfo(m_currentDoc->fileName());
|
||||||
const QString path = cleanPath(currentFileInfo.absolutePath()) + fileName;
|
const QString path = cleanPath(currentFileInfo.absolutePath()) + fileName;
|
||||||
if (checkFile(path))
|
if (checkFile(path))
|
||||||
return path;
|
return path;
|
||||||
// Fall through! "16.2 Source file inclusion" from the standard states to continue
|
// Fall through! "16.2 Source file inclusion" from the standard states to continue
|
||||||
// searching as if this would be a global include.
|
// 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) {
|
for (; headerPathsIt != headerPathsEnd; ++headerPathsIt) {
|
||||||
if (headerPath.isFrameworkPath())
|
if (headerPathsIt->isFrameworkPath())
|
||||||
continue;
|
continue;
|
||||||
const QString path = headerPath.path + fileName;
|
const QString path = headerPathsIt->path + fileName;
|
||||||
if (m_workingCopy.contains(path) || checkFile(path))
|
if (m_workingCopy.contains(path) || checkFile(path))
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
#include "cpptoolstestcase.h"
|
#include "cpptoolstestcase.h"
|
||||||
#include "editordocumenthandle.h"
|
#include "editordocumenthandle.h"
|
||||||
|
|
||||||
|
#include <coreplugin/testdatadir.h>
|
||||||
#include <texteditor/texteditor.h>
|
#include <texteditor/texteditor.h>
|
||||||
|
|
||||||
#include <cplusplus/CppDocument.h>
|
#include <cplusplus/CppDocument.h>
|
||||||
@@ -203,3 +204,38 @@ void CppToolsPlugin::test_cppsourceprocessor_macroUses()
|
|||||||
QCOMPARE(macroUse.utf16charsEnd(), 35U);
|
QCOMPARE(macroUse.utf16charsEnd(), 35U);
|
||||||
QCOMPARE(macroUse.beginLine(), 2U);
|
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));
|
||||||
|
}
|
||||||
|
|||||||
@@ -133,6 +133,7 @@ private slots:
|
|||||||
void test_cppsourceprocessor_includes_cyclic();
|
void test_cppsourceprocessor_includes_cyclic();
|
||||||
void test_cppsourceprocessor_includes_allDiagnostics();
|
void test_cppsourceprocessor_includes_allDiagnostics();
|
||||||
void test_cppsourceprocessor_macroUses();
|
void test_cppsourceprocessor_macroUses();
|
||||||
|
void test_cppsourceprocessor_includeNext();
|
||||||
|
|
||||||
void test_functionutils_virtualFunctions();
|
void test_functionutils_virtualFunctions();
|
||||||
void test_functionutils_virtualFunctions_data();
|
void test_functionutils_virtualFunctions_data();
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
#define ENABLE_FEATURE_X
|
||||||
|
#include_next "t.h"
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// Copyright
|
||||||
|
|
||||||
|
#include "t.h"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
#ifdef FEATURE_X_ENABLED
|
||||||
|
#define OK_FEATURE_X_ENABLED
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#define SYSTEM_HEADER_INCLUDED
|
||||||
|
|
||||||
|
#ifdef ENABLE_FEATURE_X
|
||||||
|
#define FEATURE_X_ENABLED
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user