Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -681,7 +681,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/testrunner.o: test/testrunner.cpp externals/simplecpp/simplecpp.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/preprocessor.h lib/suppressions.h test/options.h test/testsuite.h
Expand Down
11 changes: 9 additions & 2 deletions cli/cppcheckexecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1009,9 +1009,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);
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions lib/preprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -839,6 +839,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";
Expand All @@ -854,6 +857,7 @@ void Preprocessor::missingInclude(const std::string &filename, unsigned int line
missingSystemIncludeFlag = true;
else
missingIncludeFlag = true;

if (mErrorLogger && mSettings.checkConfiguration) {

std::list<ErrorMessage::FileLocation> locationList;
Expand Down
1 change: 1 addition & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ if (BUILD_TESTS)

add_dependencies(testrunner copy_cfg)
add_dependencies(testrunner copy_addons)
add_dependencies(testrunner run-dmake)

if (LIBXML2_XMLLINT_EXECUTABLE)
# TODO: get rid of the copy
Expand Down
112 changes: 102 additions & 10 deletions test/testpreprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "preprocessor.h"
#include "settings.h"
#include "testsuite.h"
#include "testutils.h"

#include <atomic>
#include <cstring>
Expand Down Expand Up @@ -200,8 +201,9 @@ class TestPreprocessor : public TestFixture {
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);
Expand Down Expand Up @@ -254,6 +256,9 @@ class TestPreprocessor : public TestFixture {
TEST_CASE(testDirectiveIncludeTypes);
TEST_CASE(testDirectiveIncludeLocations);
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") {
Expand Down Expand Up @@ -1931,25 +1936,55 @@ class TestPreprocessor : public TestFixture {
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<std::string> cfg;
std::list<std::string> paths;

"// cppcheck-suppress missingIncludeSystem\n"
"#include <missing2.h>\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() {
Expand Down Expand Up @@ -2395,6 +2430,63 @@ class TestPreprocessor : public TestFixture {
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 <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)