diff --git a/Makefile b/Makefile index 1d8603454..b514e5306 100644 --- a/Makefile +++ b/Makefile @@ -695,7 +695,7 @@ test/testplatform.o: test/testplatform.cpp externals/tinyxml2/tinyxml2.h lib/col test/testpostfixoperator.o: test/testpostfixoperator.cpp lib/check.h lib/checkpostfixoperator.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testpostfixoperator.o test/testpostfixoperator.cpp -test/testpreprocessor.o: test/testpreprocessor.cpp externals/simplecpp/simplecpp.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h test/testsuite.h +test/testpreprocessor.o: test/testpreprocessor.cpp externals/simplecpp/simplecpp.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h test/testutils.h $(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testpreprocessor.o test/testpreprocessor.cpp test/testprocessexecutor.o: test/testprocessexecutor.cpp cli/executor.h cli/processexecutor.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h test/testutils.h diff --git a/cli/cppcheckexecutor.cpp b/cli/cppcheckexecutor.cpp index 14d40bbb5..084f1cb18 100644 --- a/cli/cppcheckexecutor.cpp +++ b/cli/cppcheckexecutor.cpp @@ -1018,9 +1018,16 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck) "files are found. Please check your project's include directories and add all of them " "as include directories for Cppcheck. To see what files Cppcheck cannot find use " "--check-config.", - Preprocessor::missingIncludeFlag ? "missingInclude" : "missingIncludeSystem", + "", Certainty::normal); - reportInfo(msg); + if (Preprocessor::missingIncludeFlag) { + msg.id = "missingInclude"; + reportInfo(msg); + } + if (Preprocessor::missingSystemIncludeFlag) { + msg.id = "missingIncludeSystem"; + reportInfo(msg); + } } } diff --git a/lib/preprocessor.cpp b/lib/preprocessor.cpp index 148932380..c6bdb9dca 100644 --- a/lib/preprocessor.cpp +++ b/lib/preprocessor.cpp @@ -840,6 +840,9 @@ void Preprocessor::error(const std::string &filename, unsigned int linenr, const // Report that include is missing void Preprocessor::missingInclude(const std::string &filename, unsigned int linenr, const std::string &header, HeaderTypes headerType) { + if (!mSettings.checks.isEnabled(Checks::missingInclude) && !mSettings.checkConfiguration) + return; + const std::string fname = Path::fromNativeSeparators(filename); Suppressions::ErrorMessage errorMessage; errorMessage.errorId = "missingInclude"; @@ -855,6 +858,7 @@ void Preprocessor::missingInclude(const std::string &filename, unsigned int line missingSystemIncludeFlag = true; else missingIncludeFlag = true; + if (mErrorLogger && mSettings.checkConfiguration) { std::list locationList; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 962874bfe..0b5f776a9 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -33,6 +33,7 @@ if (BUILD_TESTS) add_dependencies(testrunner copy_cfg) add_dependencies(testrunner copy_addons) + add_dependencies(testrunner run-dmake) if (LIBXML2_XMLLINT_EXECUTABLE) # TODO: run the CMake implementation of the tests diff --git a/test/testpreprocessor.cpp b/test/testpreprocessor.cpp index a24530426..43c5c3bd1 100644 --- a/test/testpreprocessor.cpp +++ b/test/testpreprocessor.cpp @@ -25,6 +25,7 @@ #include "preprocessor.h" #include "settings.h" #include "testsuite.h" +#include "testutils.h" #include #include @@ -200,8 +201,9 @@ private: TEST_CASE(invalid_define_1); // #2605 - hang for: '#define =' TEST_CASE(invalid_define_2); // #4036 - hang for: '#define () {(int f(x) }' - // inline suppression, missingInclude + // inline suppression, missingInclude/missingIncludeSystem TEST_CASE(inline_suppression_for_missing_include); + TEST_CASE(inline_suppression_for_missing_include_check_config); // Using -D to predefine symbols TEST_CASE(predefine1); @@ -254,6 +256,9 @@ private: TEST_CASE(testDirectiveIncludeTypes); TEST_CASE(testDirectiveIncludeLocations); TEST_CASE(testDirectiveIncludeComments); + + TEST_CASE(testMissingInclude); + TEST_CASE(testMissingIncludeCheckConfig); } void preprocess(const char* code, std::map& actual, const char filename[] = "file.c") { @@ -1931,25 +1936,55 @@ private: preprocess("#define () {(int f(x) }\n", actual); // don't hang } - void inline_suppression_for_missing_include() { + void inline_suppression_for_missing_include_internal(bool checkConfig) { Preprocessor::missingIncludeFlag = false; + Preprocessor::missingSystemIncludeFlag = false; Settings settings; + settings.checkConfiguration = checkConfig; settings.inlineSuppressions = true; - settings.severity.fill(); + settings.severity.clear(); + // --check-config needs to report this regardless of the emanled checks + if (!checkConfig) + settings.checks.enable(Checks::missingInclude); Preprocessor preprocessor(settings, this); - std::istringstream src("// cppcheck-suppress missingInclude\n" + const std::string code("// cppcheck-suppress missingInclude\n" "#include \"missing.h\"\n" - "int x;"); - std::string processedFile; - std::list cfg; - std::list paths; - + "// cppcheck-suppress missingIncludeSystem\n" + "#include \n"); // Don't report that the include is missing errout.str(""); - preprocessor.preprocess(src, processedFile, cfg, "test.c", paths); + preprocessor.getcode(code, "", "test.c"); ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS(false, Preprocessor::missingIncludeFlag); + ASSERT_EQUALS(false, Preprocessor::missingSystemIncludeFlag); + + auto suppressions = settings.nomsg.getSuppressions(); + ASSERT_EQUALS(2, suppressions.size()); + + auto suppr = suppressions.front(); + suppressions.pop_front(); + ASSERT_EQUALS("missingInclude", suppr.errorId); + ASSERT_EQUALS("test.c", suppr.fileName); + ASSERT_EQUALS(2, suppr.lineNumber); + ASSERT_EQUALS(true, suppr.checked); + ASSERT_EQUALS(true, suppr.matched); + + suppr = suppressions.front(); + suppressions.pop_front(); + ASSERT_EQUALS("missingIncludeSystem", suppr.errorId); + ASSERT_EQUALS("test.c", suppr.fileName); + ASSERT_EQUALS(4, suppr.lineNumber); + ASSERT_EQUALS(true, suppr.checked); + ASSERT_EQUALS(true, suppr.matched); + } + + void inline_suppression_for_missing_include() { + inline_suppression_for_missing_include_internal(false); + } + + void inline_suppression_for_missing_include_check_config() { + inline_suppression_for_missing_include_internal(true); } void predefine1() { @@ -2395,6 +2430,63 @@ private: preprocessor.dump(ostr); ASSERT_EQUALS(dumpdata, ostr.str()); } + + void testMissingInclude() { + Preprocessor::missingIncludeFlag = false; + Preprocessor::missingSystemIncludeFlag = false; + + Settings settings; + settings.severity.clear(); + settings.checks.enable(Checks::missingInclude); + Preprocessor preprocessor(settings, this); + + ScopedFile header("header.h", ""); + ScopedFile header2("header2.h", ""); + + std::string code("#include \"missing.h\"\n" + "#include \n" + "#include \n" + "#include \"header2.h\""); + errout.str(""); + preprocessor.getcode(code, "", "test.c"); + ASSERT_EQUALS(true, Preprocessor::missingIncludeFlag); + ASSERT_EQUALS(true, Preprocessor::missingSystemIncludeFlag); + + // the expected messages are emited outside of the Preprocessor + ASSERT_EQUALS("", errout.str()); + + Preprocessor::missingIncludeFlag = false; + Preprocessor::missingSystemIncludeFlag = false; + } + + void testMissingIncludeCheckConfig() { + Preprocessor::missingIncludeFlag = false; + Preprocessor::missingSystemIncludeFlag = false; + + Settings settings; + settings.checkConfiguration = true; + settings.severity.clear(); + // needs to be reported regardless of enabled checks + Preprocessor preprocessor(settings, this); + + ScopedFile header("header.h", ""); + ScopedFile header2("header2.h", ""); + + std::string code("#include \"missing.h\"\n" + "#include \n" + "#include \n" + "#include \"header2.h\""); + errout.str(""); + preprocessor.getcode(code, "", "test.c"); + ASSERT_EQUALS(true, Preprocessor::missingIncludeFlag); + ASSERT_EQUALS(true, Preprocessor::missingSystemIncludeFlag); + + ASSERT_EQUALS("[test.c:1]: (information) Include file: \"missing.h\" not found.\n" + "[test.c:3]: (information) Include file: not found. Please note: Cppcheck does not need standard library headers to get proper results.\n", errout.str()); + + Preprocessor::missingIncludeFlag = false; + Preprocessor::missingSystemIncludeFlag = false; + } }; REGISTER_TEST(TestPreprocessor)