|
25 | 25 | #include "preprocessor.h" |
26 | 26 | #include "settings.h" |
27 | 27 | #include "testsuite.h" |
| 28 | +#include "testutils.h" |
28 | 29 |
|
29 | 30 | #include <atomic> |
30 | 31 | #include <cstring> |
@@ -200,8 +201,9 @@ class TestPreprocessor : public TestFixture { |
200 | 201 | TEST_CASE(invalid_define_1); // #2605 - hang for: '#define =' |
201 | 202 | TEST_CASE(invalid_define_2); // #4036 - hang for: '#define () {(int f(x) }' |
202 | 203 |
|
203 | | - // inline suppression, missingInclude |
| 204 | + // inline suppression, missingInclude/missingIncludeSystem |
204 | 205 | TEST_CASE(inline_suppression_for_missing_include); |
| 206 | + TEST_CASE(inline_suppression_for_missing_include_check_config); |
205 | 207 |
|
206 | 208 | // Using -D to predefine symbols |
207 | 209 | TEST_CASE(predefine1); |
@@ -254,6 +256,9 @@ class TestPreprocessor : public TestFixture { |
254 | 256 | TEST_CASE(testDirectiveIncludeTypes); |
255 | 257 | TEST_CASE(testDirectiveIncludeLocations); |
256 | 258 | TEST_CASE(testDirectiveIncludeComments); |
| 259 | + |
| 260 | + TEST_CASE(testMissingInclude); |
| 261 | + TEST_CASE(testMissingIncludeCheckConfig); |
257 | 262 | } |
258 | 263 |
|
259 | 264 | void preprocess(const char* code, std::map<std::string, std::string>& actual, const char filename[] = "file.c") { |
@@ -1931,25 +1936,55 @@ class TestPreprocessor : public TestFixture { |
1931 | 1936 | preprocess("#define () {(int f(x) }\n", actual); // don't hang |
1932 | 1937 | } |
1933 | 1938 |
|
1934 | | - void inline_suppression_for_missing_include() { |
| 1939 | + void inline_suppression_for_missing_include_internal(bool checkConfig) { |
1935 | 1940 | Preprocessor::missingIncludeFlag = false; |
| 1941 | + Preprocessor::missingSystemIncludeFlag = false; |
1936 | 1942 | Settings settings; |
| 1943 | + settings.checkConfiguration = checkConfig; |
1937 | 1944 | settings.inlineSuppressions = true; |
1938 | | - settings.severity.fill(); |
| 1945 | + settings.severity.clear(); |
| 1946 | + // --check-config needs to report this regardless of the emanled checks |
| 1947 | + if (!checkConfig) |
| 1948 | + settings.checks.enable(Checks::missingInclude); |
1939 | 1949 | Preprocessor preprocessor(settings, this); |
1940 | 1950 |
|
1941 | | - std::istringstream src("// cppcheck-suppress missingInclude\n" |
| 1951 | + const std::string code("// cppcheck-suppress missingInclude\n" |
1942 | 1952 | "#include \"missing.h\"\n" |
1943 | | - "int x;"); |
1944 | | - std::string processedFile; |
1945 | | - std::list<std::string> cfg; |
1946 | | - std::list<std::string> paths; |
1947 | | - |
| 1953 | + "// cppcheck-suppress missingIncludeSystem\n" |
| 1954 | + "#include <missing2.h>\n"); |
1948 | 1955 | // Don't report that the include is missing |
1949 | 1956 | errout.str(""); |
1950 | | - preprocessor.preprocess(src, processedFile, cfg, "test.c", paths); |
| 1957 | + preprocessor.getcode(code, "", "test.c"); |
1951 | 1958 | ASSERT_EQUALS("", errout.str()); |
1952 | 1959 | ASSERT_EQUALS(false, Preprocessor::missingIncludeFlag); |
| 1960 | + ASSERT_EQUALS(false, Preprocessor::missingSystemIncludeFlag); |
| 1961 | + |
| 1962 | + auto suppressions = settings.nomsg.getSuppressions(); |
| 1963 | + ASSERT_EQUALS(2, suppressions.size()); |
| 1964 | + |
| 1965 | + auto suppr = suppressions.front(); |
| 1966 | + suppressions.pop_front(); |
| 1967 | + ASSERT_EQUALS("missingInclude", suppr.errorId); |
| 1968 | + ASSERT_EQUALS("test.c", suppr.fileName); |
| 1969 | + ASSERT_EQUALS(2, suppr.lineNumber); |
| 1970 | + ASSERT_EQUALS(true, suppr.checked); |
| 1971 | + ASSERT_EQUALS(true, suppr.matched); |
| 1972 | + |
| 1973 | + suppr = suppressions.front(); |
| 1974 | + suppressions.pop_front(); |
| 1975 | + ASSERT_EQUALS("missingIncludeSystem", suppr.errorId); |
| 1976 | + ASSERT_EQUALS("test.c", suppr.fileName); |
| 1977 | + ASSERT_EQUALS(4, suppr.lineNumber); |
| 1978 | + ASSERT_EQUALS(true, suppr.checked); |
| 1979 | + ASSERT_EQUALS(true, suppr.matched); |
| 1980 | + } |
| 1981 | + |
| 1982 | + void inline_suppression_for_missing_include() { |
| 1983 | + inline_suppression_for_missing_include_internal(false); |
| 1984 | + } |
| 1985 | + |
| 1986 | + void inline_suppression_for_missing_include_check_config() { |
| 1987 | + inline_suppression_for_missing_include_internal(true); |
1953 | 1988 | } |
1954 | 1989 |
|
1955 | 1990 | void predefine1() { |
@@ -2395,6 +2430,63 @@ class TestPreprocessor : public TestFixture { |
2395 | 2430 | preprocessor.dump(ostr); |
2396 | 2431 | ASSERT_EQUALS(dumpdata, ostr.str()); |
2397 | 2432 | } |
| 2433 | + |
| 2434 | + void testMissingInclude() { |
| 2435 | + Preprocessor::missingIncludeFlag = false; |
| 2436 | + Preprocessor::missingSystemIncludeFlag = false; |
| 2437 | + |
| 2438 | + Settings settings; |
| 2439 | + settings.severity.clear(); |
| 2440 | + settings.checks.enable(Checks::missingInclude); |
| 2441 | + Preprocessor preprocessor(settings, this); |
| 2442 | + |
| 2443 | + ScopedFile header("header.h", ""); |
| 2444 | + ScopedFile header2("header2.h", ""); |
| 2445 | + |
| 2446 | + std::string code("#include \"missing.h\"\n" |
| 2447 | + "#include <header.h>\n" |
| 2448 | + "#include <missing2.h>\n" |
| 2449 | + "#include \"header2.h\""); |
| 2450 | + errout.str(""); |
| 2451 | + preprocessor.getcode(code, "", "test.c"); |
| 2452 | + ASSERT_EQUALS(true, Preprocessor::missingIncludeFlag); |
| 2453 | + ASSERT_EQUALS(true, Preprocessor::missingSystemIncludeFlag); |
| 2454 | + |
| 2455 | + // the expected messages are emited outside of the Preprocessor |
| 2456 | + ASSERT_EQUALS("", errout.str()); |
| 2457 | + |
| 2458 | + Preprocessor::missingIncludeFlag = false; |
| 2459 | + Preprocessor::missingSystemIncludeFlag = false; |
| 2460 | + } |
| 2461 | + |
| 2462 | + void testMissingIncludeCheckConfig() { |
| 2463 | + Preprocessor::missingIncludeFlag = false; |
| 2464 | + Preprocessor::missingSystemIncludeFlag = false; |
| 2465 | + |
| 2466 | + Settings settings; |
| 2467 | + settings.checkConfiguration = true; |
| 2468 | + settings.severity.clear(); |
| 2469 | + // needs to be reported regardless of enabled checks |
| 2470 | + Preprocessor preprocessor(settings, this); |
| 2471 | + |
| 2472 | + ScopedFile header("header.h", ""); |
| 2473 | + ScopedFile header2("header2.h", ""); |
| 2474 | + |
| 2475 | + std::string code("#include \"missing.h\"\n" |
| 2476 | + "#include <header.h>\n" |
| 2477 | + "#include <missing2.h>\n" |
| 2478 | + "#include \"header2.h\""); |
| 2479 | + errout.str(""); |
| 2480 | + preprocessor.getcode(code, "", "test.c"); |
| 2481 | + ASSERT_EQUALS(true, Preprocessor::missingIncludeFlag); |
| 2482 | + ASSERT_EQUALS(true, Preprocessor::missingSystemIncludeFlag); |
| 2483 | + |
| 2484 | + ASSERT_EQUALS("[test.c:1]: (information) Include file: \"missing.h\" not found.\n" |
| 2485 | + "[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()); |
| 2486 | + |
| 2487 | + Preprocessor::missingIncludeFlag = false; |
| 2488 | + Preprocessor::missingSystemIncludeFlag = false; |
| 2489 | + } |
2398 | 2490 | }; |
2399 | 2491 |
|
2400 | 2492 | REGISTER_TEST(TestPreprocessor) |
0 commit comments