some `missingInclude`/`missingIncludeSystem` fixes and tests (#4027)

* do not emit `missingInclude` and `missingIncludeSystem` errors when not enabled / fixed and improved TestPreprocessor::inline_suppression_for_missing_include()

* testpreprocessor.cpp: added missing tests for `missingInclude` and `missingIncludeSystem`

* cppcheckexecutor.cpp: `missingIncludeSystem` was not emitted in normal analysis if `missingInclude` existed

* dmake

* added `run-dmake` as `testrunner` dependency
This commit is contained in:
Oliver Stöneberg 2022-07-09 23:21:11 +02:00 committed by GitHub
parent 4587178cfa
commit c36320747f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 117 additions and 13 deletions

View File

@ -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 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 $(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 $(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 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

View File

@ -1018,10 +1018,17 @@ int CppCheckExecutor::check_internal(CppCheck& cppcheck)
"files are found. Please check your project's include directories and add all of them " "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 " "as include directories for Cppcheck. To see what files Cppcheck cannot find use "
"--check-config.", "--check-config.",
Preprocessor::missingIncludeFlag ? "missingInclude" : "missingIncludeSystem", "",
Certainty::normal); Certainty::normal);
if (Preprocessor::missingIncludeFlag) {
msg.id = "missingInclude";
reportInfo(msg); reportInfo(msg);
} }
if (Preprocessor::missingSystemIncludeFlag) {
msg.id = "missingIncludeSystem";
reportInfo(msg);
}
}
} }
if (settings.xml) { if (settings.xml) {

View File

@ -840,6 +840,9 @@ void Preprocessor::error(const std::string &filename, unsigned int linenr, const
// Report that include is missing // Report that include is missing
void Preprocessor::missingInclude(const std::string &filename, unsigned int linenr, const std::string &header, HeaderTypes headerType) 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); const std::string fname = Path::fromNativeSeparators(filename);
Suppressions::ErrorMessage errorMessage; Suppressions::ErrorMessage errorMessage;
errorMessage.errorId = "missingInclude"; errorMessage.errorId = "missingInclude";
@ -855,6 +858,7 @@ void Preprocessor::missingInclude(const std::string &filename, unsigned int line
missingSystemIncludeFlag = true; missingSystemIncludeFlag = true;
else else
missingIncludeFlag = true; missingIncludeFlag = true;
if (mErrorLogger && mSettings.checkConfiguration) { if (mErrorLogger && mSettings.checkConfiguration) {
std::list<ErrorMessage::FileLocation> locationList; std::list<ErrorMessage::FileLocation> locationList;

View File

@ -33,6 +33,7 @@ if (BUILD_TESTS)
add_dependencies(testrunner copy_cfg) add_dependencies(testrunner copy_cfg)
add_dependencies(testrunner copy_addons) add_dependencies(testrunner copy_addons)
add_dependencies(testrunner run-dmake)
if (LIBXML2_XMLLINT_EXECUTABLE) if (LIBXML2_XMLLINT_EXECUTABLE)
# TODO: run the CMake implementation of the tests # TODO: run the CMake implementation of the tests

View File

@ -25,6 +25,7 @@
#include "preprocessor.h" #include "preprocessor.h"
#include "settings.h" #include "settings.h"
#include "testsuite.h" #include "testsuite.h"
#include "testutils.h"
#include <atomic> #include <atomic>
#include <cstring> #include <cstring>
@ -200,8 +201,9 @@ private:
TEST_CASE(invalid_define_1); // #2605 - hang for: '#define =' TEST_CASE(invalid_define_1); // #2605 - hang for: '#define ='
TEST_CASE(invalid_define_2); // #4036 - hang for: '#define () {(int f(x) }' 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);
TEST_CASE(inline_suppression_for_missing_include_check_config);
// Using -D to predefine symbols // Using -D to predefine symbols
TEST_CASE(predefine1); TEST_CASE(predefine1);
@ -254,6 +256,9 @@ private:
TEST_CASE(testDirectiveIncludeTypes); TEST_CASE(testDirectiveIncludeTypes);
TEST_CASE(testDirectiveIncludeLocations); TEST_CASE(testDirectiveIncludeLocations);
TEST_CASE(testDirectiveIncludeComments); TEST_CASE(testDirectiveIncludeComments);
TEST_CASE(testMissingInclude);
TEST_CASE(testMissingIncludeCheckConfig);
} }
void preprocess(const char* code, std::map<std::string, std::string>& actual, const char filename[] = "file.c") { void preprocess(const char* code, std::map<std::string, std::string>& actual, const char filename[] = "file.c") {
@ -1931,25 +1936,55 @@ private:
preprocess("#define () {(int f(x) }\n", actual); // don't hang 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::missingIncludeFlag = false;
Preprocessor::missingSystemIncludeFlag = false;
Settings settings; Settings settings;
settings.checkConfiguration = checkConfig;
settings.inlineSuppressions = true; 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); Preprocessor preprocessor(settings, this);
std::istringstream src("// cppcheck-suppress missingInclude\n" const std::string code("// cppcheck-suppress missingInclude\n"
"#include \"missing.h\"\n" "#include \"missing.h\"\n"
"int x;"); "// cppcheck-suppress missingIncludeSystem\n"
std::string processedFile; "#include <missing2.h>\n");
std::list<std::string> cfg;
std::list<std::string> paths;
// Don't report that the include is missing // Don't report that the include is missing
errout.str(""); errout.str("");
preprocessor.preprocess(src, processedFile, cfg, "test.c", paths); preprocessor.getcode(code, "", "test.c");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
ASSERT_EQUALS(false, Preprocessor::missingIncludeFlag); 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() { void predefine1() {
@ -2395,6 +2430,63 @@ private:
preprocessor.dump(ostr); preprocessor.dump(ostr);
ASSERT_EQUALS(dumpdata, ostr.str()); 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 <header.h>\n"
"#include <missing2.h>\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 <header.h>\n"
"#include <missing2.h>\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: <missing2.h> 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) REGISTER_TEST(TestPreprocessor)