diff --git a/.github/workflows/selfcheck.yml b/.github/workflows/selfcheck.yml index dcdf8bfbdd3..2061322d005 100644 --- a/.github/workflows/selfcheck.yml +++ b/.github/workflows/selfcheck.yml @@ -121,7 +121,7 @@ jobs: - name: Self check (unusedFunction / no test / no gui) run: | - supprs="--suppress=unusedFunction:lib/errorlogger.h:197 --suppress=unusedFunction:lib/importproject.cpp:1666 --suppress=unusedFunction:lib/importproject.cpp:1690" + supprs="--suppress=unusedFunction:lib/errorlogger.h:197 --suppress=unusedFunction:lib/importproject.cpp:1671 --suppress=unusedFunction:lib/importproject.cpp:1695" ./cppcheck -q --template=selfcheck --error-exitcode=1 --library=cppcheck-lib -D__CPPCHECK__ -D__GNUC__ --enable=unusedFunction,information --exception-handling -rp=. --project=cmake.output.notest_nogui/compile_commands.json --suppressions-list=.selfcheck_unused_suppressions --inline-suppr $supprs env: DISABLE_VALUEFLOW: 1 diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index da078e5eb20..b8707ab151c 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -825,6 +825,7 @@ unsigned int CppCheck::check(const FileSettings &fs) else tempSettings.userDefines += fs.cppcheckDefines(); tempSettings.includePaths = fs.includePaths; + tempSettings.userIncludes.insert(tempSettings.userIncludes.end(), fs.forcedIncludes.cbegin(), fs.forcedIncludes.cend()); tempSettings.userUndefs.insert(fs.undefs.cbegin(), fs.undefs.cend()); if (fs.standard.find("++") != std::string::npos) tempSettings.standards.setCPP(fs.standard); diff --git a/lib/filesettings.h b/lib/filesettings.h index 183e38708fd..0b4f15dd7e1 100644 --- a/lib/filesettings.h +++ b/lib/filesettings.h @@ -148,6 +148,7 @@ struct CPPCHECKLIB FileSettings { } std::set undefs; std::list includePaths; + std::list forcedIncludes; // only used by clang mode std::list systemIncludePaths; std::string standard; diff --git a/lib/importproject.cpp b/lib/importproject.cpp index 0bcda5a43bf..2d63fa8bbb7 100644 --- a/lib/importproject.cpp +++ b/lib/importproject.cpp @@ -149,6 +149,11 @@ void ImportProject::parseArgs(FileSettings &fs, const std::vector & continue; } + if (!(optArg = getOptArg({ "-include", "/FI", "-FI" }, i)).empty()) { + fs.forcedIncludes.push_back(std::move(optArg)); + continue; + } + if (!(optArg = getOptArg({ "-D", "/D" }, i)).empty()) { defs += optArg + ";"; continue; diff --git a/test/testimportproject.cpp b/test/testimportproject.cpp index 88ca2fe75b7..c9889445c3c 100644 --- a/test/testimportproject.cpp +++ b/test/testimportproject.cpp @@ -73,6 +73,7 @@ class TestImportProject : public TestFixture { TEST_CASE(importCompileCommands13); // #13333: duplicate file entries TEST_CASE(importCompileCommands14); // #14156 TEST_CASE(importCompileCommands15); // #14306 + TEST_CASE(importCompileCommandsForcedInclude); // -include / /FI force-include TEST_CASE(importCompileCommandsArgumentsSection); // Handle arguments section TEST_CASE(importCompileCommandsNoCommandSection); // gracefully handles malformed json TEST_CASE(importCompileCommandsDirectoryMissing); // 'directory' field missing @@ -436,6 +437,24 @@ class TestImportProject : public TestFixture { ASSERT_EQUALS("C:/Users/abcd/efg/hijk/path/123/", fs.includePaths.front()); } + void importCompileCommandsForcedInclude() const { // -include / /FI force-include + REDIRECT; + constexpr char json[] = + R"([{ + "file": "/x/a.c", + "directory": "/x", + "command": "cc -include prefix.h /FIplatform.h -c a.c" + }])"; + std::istringstream istr(json); + TestImporter importer; + ASSERT_EQUALS(true, importer.importCompileCommands(istr)); + ASSERT_EQUALS(1, importer.fileSettings.size()); + const FileSettings &fs = importer.fileSettings.front(); + ASSERT_EQUALS(2, fs.forcedIncludes.size()); + ASSERT_EQUALS("prefix.h", fs.forcedIncludes.front()); // gcc/clang -include + ASSERT_EQUALS("platform.h", fs.forcedIncludes.back()); // MSVC/clang-cl /FI + } + void importCompileCommandsArgumentsSection() const { REDIRECT; constexpr char json[] = "[ { \"directory\": \"/tmp/\","