Skip to content
Open
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 @@ -1136,15 +1136,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
111 changes: 111 additions & 0 deletions test/cli/other_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4240,6 +4240,117 @@ 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',
'--enable=style',
'--suppress=functionStatic', # we do not care about this - this was converted from TestUnusedPrivateFunction
test_file
]

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


def test_unused_private_function_multi_file(tmpdir): # ticket #2567
test_inc = os.path.join(tmpdir, 'test.h')
with open(test_inc, 'wt') as f:
f.write(
"""
struct Fred
{
Fred()
{
Init();
}
private:
void Init();
};
""")

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

void Fred::Init()
{
}
""")

args = [
'-q',
'--template=simple',
'--enable=style',
'--suppress=functionStatic', # we do not care about this - this was converted from TestUnusedPrivateFunction
test_file
]

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


def test_missing_doublequote_include(tmpdir):
test_inc = os.path.join(tmpdir, 'abc.h')
with open(test_inc, 'wt') as f:
f.write(
'''
#define a
"
''')

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

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

ret, stdout, stderr = cppcheck(args)
assert stdout == ''
assert stderr.splitlines() == [
f"{test_inc}:3:1: error: No pair for character (\"). Can't process file. File is either invalid or unicode, which is currently not supported. [syntaxError]"
]
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
91 changes: 41 additions & 50 deletions test/testpreprocessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,14 @@ class TestPreprocessor : public TestFixture {
TestPreprocessor() : TestFixture("TestPreprocessor") {}

private:
#define expandMacros(...) expandMacros_(__FILE__, __LINE__, __VA_ARGS__)
template<size_t size>
std::string expandMacros(const char (&code)[size], ErrorLogger &errorLogger) const {
std::string expandMacros_(const char* file, int line, const char (&code)[size], ErrorLogger &errorLogger) const {
simplecpp::OutputList outputList;
std::vector<std::string> files;
simplecpp::TokenList tokens1 = simplecpp::TokenList(code, files, "file.cpp", &outputList);
Preprocessor p(tokens1, settingsDefault, errorLogger, Path::identify(tokens1.getFiles()[0], false));
ASSERT(p.loadFiles(files));
ASSERT_LOC(p.loadFiles(files), file, line);
simplecpp::TokenList tokens2 = p.preprocess("", files, outputList);
(void)p.reportOutput(outputList, true);
return tokens2.stringify();
Expand Down Expand Up @@ -140,7 +141,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 @@ -392,7 +393,7 @@ class TestPreprocessor : public TestFixture {
std::vector<std::string> files;
simplecpp::OutputList outputList;
simplecpp::TokenList tokens(code,files,"test.c",&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 @@ -407,7 +408,7 @@ class TestPreprocessor : public TestFixture {
std::size_t getHash(const char (&code)[size]) {
std::vector<std::string> files;
simplecpp::TokenList tokens(code,files,"test.c");
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 @@ -472,16 +473,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 @@ -584,35 +588,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=ABC\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=ABC\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 @@ -1576,22 +1580,9 @@ class TestPreprocessor : public TestFixture {
}

{
const char filedata[] = "#file \"abc.h\"\n"
"#define a\n"
"\"\n"
"#endfile\n";

// expand macros..
const std::string actual(expandMacros(filedata, *this));

ASSERT_EQUALS("", actual);
ASSERT_EQUALS("[abc.h:2:1]: (error) No pair for character (\"). Can't process file. File is either invalid or unicode, which is currently not supported. [syntaxError]\n", errout_str());
}

{
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 @@ -2286,14 +2277,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=ABC\n", getConfigsStr(filedata));
}
Expand All @@ -2315,12 +2306,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
35 changes: 16 additions & 19 deletions test/testtokenize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8821,14 +8821,11 @@ class TestTokenizer : public TestFixture {
}

void testDirectiveIncludeLocations() {
ScopedFile inc1("inc1.h", "#define macro2 val\n#include \"inc2.h\"\n#define macro4 val\n");
ScopedFile inc2("inc2.h", "#define macro3 val\n");
// TODO: preprocess?
const char filedata[] = "#define macro1 val\n"
"#file \"inc1.h\"\n"
"#define macro2 val\n"
"#file \"inc2.h\"\n"
"#define macro3 val\n"
"#endfile\n"
"#define macro4 val\n"
"#endfile\n"
"#include \"inc1.h\"\n"
"#define macro5 val\n";
const char dumpdata[] = " <directivelist>\n"
" <directive file=\"test.c\" linenr=\"1\" str=\"#define macro1 val\">\n"
Expand All @@ -8839,8 +8836,14 @@ class TestTokenizer : public TestFixture {
" </directive>\n"
" <directive file=\"test.c\" linenr=\"2\" str=\"#include &quot;inc1.h&quot;\">\n"
" <token column=\"1\" str=\"#\"/>\n"
" <token column=\"2\" str=\"file\"/>\n"
" <token column=\"7\" str=\"&quot;inc1.h&quot;\"/>\n"
" <token column=\"2\" str=\"include\"/>\n"
" <token column=\"10\" str=\"&quot;inc1.h&quot;\"/>\n"
" </directive>\n"
" <directive file=\"test.c\" linenr=\"3\" str=\"#define macro5 val\">\n"
" <token column=\"1\" str=\"#\"/>\n"
" <token column=\"2\" str=\"define\"/>\n"
" <token column=\"9\" str=\"macro5\"/>\n"
" <token column=\"16\" str=\"val\"/>\n"
" </directive>\n"
" <directive file=\"inc1.h\" linenr=\"1\" str=\"#define macro2 val\">\n"
" <token column=\"1\" str=\"#\"/>\n"
Expand All @@ -8850,25 +8853,19 @@ class TestTokenizer : public TestFixture {
" </directive>\n"
" <directive file=\"inc1.h\" linenr=\"2\" str=\"#include &quot;inc2.h&quot;\">\n"
" <token column=\"1\" str=\"#\"/>\n"
" <token column=\"2\" str=\"file\"/>\n"
" <token column=\"7\" str=\"&quot;inc2.h&quot;\"/>\n"
" </directive>\n"
" <directive file=\"inc2.h\" linenr=\"1\" str=\"#define macro3 val\">\n"
" <token column=\"1\" str=\"#\"/>\n"
" <token column=\"2\" str=\"define\"/>\n"
" <token column=\"9\" str=\"macro3\"/>\n"
" <token column=\"16\" str=\"val\"/>\n"
" <token column=\"2\" str=\"include\"/>\n"
" <token column=\"10\" str=\"&quot;inc2.h&quot;\"/>\n"
" </directive>\n"
" <directive file=\"inc1.h\" linenr=\"3\" str=\"#define macro4 val\">\n"
" <token column=\"1\" str=\"#\"/>\n"
" <token column=\"2\" str=\"define\"/>\n"
" <token column=\"9\" str=\"macro4\"/>\n"
" <token column=\"16\" str=\"val\"/>\n"
" </directive>\n"
" <directive file=\"test.c\" linenr=\"3\" str=\"#define macro5 val\">\n"
" <directive file=\"inc2.h\" linenr=\"1\" str=\"#define macro3 val\">\n"
" <token column=\"1\" str=\"#\"/>\n"
" <token column=\"2\" str=\"define\"/>\n"
" <token column=\"9\" str=\"macro5\"/>\n"
" <token column=\"9\" str=\"macro3\"/>\n"
" <token column=\"16\" str=\"val\"/>\n"
" </directive>\n"
" </directivelist>\n"
Expand Down
Loading
Loading