Skip to content
Draft
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
8 changes: 0 additions & 8 deletions lib/cppcheck.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1124,15 +1124,7 @@ unsigned int CppCheck::checkInternal(const FileWithDetails& file, const std::str
codeWithoutCfg = preprocessor.getcode(currentConfig, files, true);
});

if (startsWith(codeWithoutCfg,"#file"))
codeWithoutCfg.insert(0U, "//");
std::string::size_type pos = 0;
while ((pos = codeWithoutCfg.find("\n#file",pos)) != std::string::npos)
codeWithoutCfg.insert(pos+1U, "//");
pos = 0;
while ((pos = codeWithoutCfg.find("\n#endfile",pos)) != std::string::npos)
codeWithoutCfg.insert(pos+1U, "//");
pos = 0;
while ((pos = codeWithoutCfg.find(Preprocessor::macroChar,pos)) != std::string::npos)
codeWithoutCfg[pos] = ' ';
mErrorLogger.reportOut(codeWithoutCfg, Color::Reset);
Expand Down
37 changes: 37 additions & 0 deletions test/cli/other_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4022,6 +4022,43 @@ def test_no_valid_configuration(tmp_path):
]


# The implementation for "A::a" is missing - so don't check if "A::b" is used or not
def test_unused_private_function_incomplete_impl(tmpdir):
test_inc = os.path.join(tmpdir, 'test.h')
with open(test_inc, 'wt') as f:
f.write(
"""
class A
{
public:
A();
void a();
private:
void b();
};
""")

test_file = os.path.join(tmpdir, 'test.cpp')
with open(test_file, 'wt') as f:
f.write(
"""
#include "test.h"

A::A() { }
void A::b() { }
""")

args = [
'-q',
'--template=simple',
test_file
]

ret, stdout, stderr = cppcheck(args)
assert stdout == ''
assert stderr.splitlines() == []
assert ret == 0, stdout

def test_no_valid_configuration_check_config(tmp_path):
test_file = tmp_path / 'test.c'
with open(test_file, "w") as f:
Expand Down
81 changes: 42 additions & 39 deletions test/testpreprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ class TestPreprocessor : public TestFixture {
cfgs = preprocessor.getConfigs();
for (const std::string & config : cfgs) {
try {
const bool writeLocations = (strstr(code, "#file") != nullptr) || (strstr(code, "#include") != nullptr);
const bool writeLocations = (strstr(code, "#include") != nullptr);
cfgcode[config] = preprocessor.getcode(config, files, writeLocations);
} catch (const simplecpp::Output &) {
cfgcode[config] = "";
Expand Down Expand Up @@ -374,7 +374,7 @@ class TestPreprocessor : public TestFixture {
simplecpp::OutputList outputList;
// TODO: this adds an empty filename
simplecpp::TokenList tokens(code,files,"",&outputList);
Preprocessor preprocessor(tokens, settings, *this, Standards::Language::C); // TODO: do we need to consider #file?
Preprocessor preprocessor(tokens, settings, *this, Standards::Language::C);
ASSERT(preprocessor.loadFiles(files));
ASSERT(!preprocessor.reportOutput(outputList, true));
preprocessor.removeComments();
Expand All @@ -390,7 +390,7 @@ class TestPreprocessor : public TestFixture {
std::vector<std::string> files;
// TODO: this adds an empty filename
simplecpp::TokenList tokens(code,files,"");
Preprocessor preprocessor(tokens, settingsDefault, *this, Standards::Language::C); // TODO: do we need to consider #file?
Preprocessor preprocessor(tokens, settingsDefault, *this, Standards::Language::C);
ASSERT(preprocessor.loadFiles(files));
preprocessor.removeComments();
return preprocessor.calculateHash("");
Expand Down Expand Up @@ -455,16 +455,19 @@ class TestPreprocessor : public TestFixture {
void error4() {
// In included file
{
ScopedFile header("ab.h", "#error hello world!\n");
const auto settings = dinit(Settings, $.userDefines = "TEST");
const char code[] = "#file \"ab.h\"\n#error hello world!\n#endfile";
const char code[] = "#include \"ab.h\"";
(void)getcodeforcfg(settings, *this, code, "TEST", "test.c");
ASSERT_EQUALS("[ab.h:1:2]: (error) #error hello world! [preprocessorErrorDirective]\n", errout_str());
}

// After including a file
{
ScopedFile header("ab.h", "");
const auto settings = dinit(Settings, $.userDefines = "TEST");
const char code[] = "#file \"ab.h\"\n\n#endfile\n#error aaa";
const char code[] = "#include \"ab.h\"\n"
"#error aaa";
(void)getcodeforcfg(settings, *this, code, "TEST", "test.c");
ASSERT_EQUALS("[test.c:2:2]: (error) #error aaa [preprocessorErrorDirective]\n", errout_str());
}
Expand Down Expand Up @@ -567,35 +570,35 @@ class TestPreprocessor : public TestFixture {
}

void includeguard1() {
ScopedFile header("abc.h",
"#ifndef abcH\n"
"#define abcH\n"
"#endif\n");
// Handling include guards..
const char filedata[] = "#file \"abc.h\"\n"
"#ifndef abcH\n"
"#define abcH\n"
"#endif\n"
"#endfile\n"
const char filedata[] = "#include \"abc.h\"\n"
"#ifdef ABC\n"
"#endif";
ASSERT_EQUALS("\nABC\n", getConfigsStr(filedata));
}

void includeguard2() {
ScopedFile header("abc.h",
"foo\n"
"#ifdef ABC\n"
"\n"
"#endif\n");
// Handling include guards..
const char filedata[] = "#file \"abc.h\"\n"
"foo\n"
"#ifdef ABC\n"
"\n"
"#endif\n"
"#endfile\n";
const char filedata[] = "#include \"abc.h\"\n";
ASSERT_EQUALS("\nABC\n", getConfigsStr(filedata));
}


void ifdefwithfile() {
ScopedFile header("abc.h", "class A{};/*\n\n\n\n\n\n\n*/\n");

// Handling include guards..
const char filedata[] = "#ifdef ABC\n"
"#file \"abc.h\"\n"
"class A{};/*\n\n\n\n\n\n\n*/\n"
"#endfile\n"
"#include \"abc.h\"\n"
"#endif\n"
"int main() {}\n";

Expand Down Expand Up @@ -1559,10 +1562,10 @@ class TestPreprocessor : public TestFixture {
}

{
const char filedata[] = "#file \"abc.h\"\n"
"#define a\n"
"\"\n"
"#endfile\n";
ScopedFile header("abc.h",
"#define a\n"
"\"\n");
const char filedata[] = "#include \"abc.h\"";

// expand macros..
const std::string actual(expandMacros(filedata, *this));
Expand All @@ -1572,9 +1575,9 @@ class TestPreprocessor : public TestFixture {
}

{
const char filedata[] = "#file \"abc.h\"\n"
"#define a\n"
"#endfile\n"
ScopedFile header("abc.h",
"#define a\n");
const char filedata[] = "#include \"abc.h\"\n"
"\"\n";

// expand macros..
Expand Down Expand Up @@ -2237,14 +2240,14 @@ class TestPreprocessor : public TestFixture {
}

void getConfigs7e() {
ScopedFile header("test.h",
"#ifndef test_h\n"
"#define test_h\n"
"#ifdef ABC\n"
"#endif\n"
"#endif\n");
const char filedata[] = "#ifdef ABC\n"
"#file \"test.h\"\n"
"#ifndef test_h\n"
"#define test_h\n"
"#ifdef ABC\n"
"#endif\n"
"#endif\n"
"#endfile\n"
"#include \"test.h\"\n"
"#endif\n";
ASSERT_EQUALS("\nABC\n", getConfigsStr(filedata));
}
Expand All @@ -2266,12 +2269,12 @@ class TestPreprocessor : public TestFixture {
}

void getConfigs11() { // #9832 - include guards
const char filedata[] = "#file \"test.h\"\n"
"#if !defined(test_h)\n"
"#define test_h\n"
"123\n"
"#endif\n"
"#endfile\n";
ScopedFile header("test.h",
"#if !defined(test_h)\n"
"#define test_h\n"
"123\n"
"#endif\n");
const char filedata[] = "#include \"test.h\"\n";
ASSERT_EQUALS("\n", getConfigsStr(filedata));
}

Expand Down
4 changes: 2 additions & 2 deletions test/testtokenize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8584,9 +8584,9 @@ class TestTokenizer : public TestFixture {
"#define macro2 val\n"
"#file \"inc2.h\"\n"
"#define macro3 val\n"
"#endfile\n"
"#endfile\n" // TODO
"#define macro4 val\n"
"#endfile\n"
"#endfile\n" // TODO
"#define macro5 val\n";
const char dumpdata[] = " <directivelist>\n"
" <directive file=\"test.c\" linenr=\"1\" str=\"#define macro1 val\">\n"
Expand Down
21 changes: 1 addition & 20 deletions test/testunusedprivfunc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ class TestUnusedPrivateFunction : public TestFixture {

TEST_CASE(classInClass);
TEST_CASE(sameFunctionNames);
TEST_CASE(incompleteImplementation);

TEST_CASE(derivedClass); // skip warning for derived classes. It might be a virtual function.

Expand Down Expand Up @@ -482,24 +481,6 @@ class TestUnusedPrivateFunction : public TestFixture {
ASSERT_EQUALS("", errout_str());
}

void incompleteImplementation() {
// The implementation for "A::a" is missing - so don't check if
// "A::b" is used or not
check("#file \"test.h\"\n"
"class A\n"
"{\n"
"public:\n"
" A();\n"
" void a();\n"
"private:\n"
" void b();\n"
"};\n"
"#endfile\n"
"A::A() { }\n"
"void A::b() { }");
ASSERT_EQUALS("", errout_str());
}

void derivedClass() {
// skip warning in derived classes in case the base class is invisible
check("class derived : public base\n"
Expand Down Expand Up @@ -791,7 +772,7 @@ class TestUnusedPrivateFunction : public TestFixture {
"private:\n"
" void Init();\n"
"};\n"
"#endfile\n"
"#endfile\n" // TODO
"void Fred::Init()\n"
"{\n"
"}");
Expand Down