diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index e635a109dc1..3f48f00cbf7 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -415,6 +415,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a bool def = false; bool maxconfigs = false; + bool debug = false; ImportProject::Type projectType = ImportProject::Type::NONE; ImportProject project; @@ -636,7 +637,7 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a // Show --debug output after the first simplifications else if (std::strcmp(argv[i], "--debug") == 0 || std::strcmp(argv[i], "--debug-normal") == 0) - mSettings.debugnormal = true; + debug = true; // Show debug warnings for lookup for configuration files else if (std::strcmp(argv[i], "--debug-lookup") == 0) @@ -1591,10 +1592,18 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a if (mSettings.force) mSettings.maxConfigs = INT_MAX; - else if ((def || mSettings.preprocessOnly) && !maxconfigs) mSettings.maxConfigs = 1U; + if (debug) { + mSettings.debugnormal = true; + mSettings.debugvalueflow = true; + if (mSettings.verbose) { + mSettings.debugast = true; + mSettings.debugsymdb = true; + } + } + if (mSettings.jobs > 1 && mSettings.buildDir.empty()) { // TODO: bail out instead? if (mSettings.checks.isEnabled(Checks::unusedFunction)) diff --git a/lib/token.cpp b/lib/token.cpp index e914b02c77b..315d952fb48 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -1655,7 +1655,7 @@ static void astStringXml(const Token *tok, nonneg int indent, std::ostream &out) } } -void Token::printAst(bool verbose, bool xml, const std::vector &fileNames, std::ostream &out) const +void Token::printAst(bool xml, const std::vector &fileNames, std::ostream &out) const { if (!xml) out << "\n\n##AST" << std::endl; @@ -1672,10 +1672,8 @@ void Token::printAst(bool verbose, bool xml, const std::vector &fil << "\" column=\"" << tok->column() << "\">" << std::endl; astStringXml(tok, 2U, out); out << "" << std::endl; - } else if (verbose) + } else out << "[" << fileNames[tok->fileIndex()] << ":" << tok->linenr() << "]" << std::endl << tok->astStringVerbose() << std::endl; - else - out << tok->astString(" ") << std::endl; if (tok->str() == "(") tok = tok->link(); } diff --git a/lib/token.h b/lib/token.h index 59774747f70..244d560689c 100644 --- a/lib/token.h +++ b/lib/token.h @@ -1544,6 +1544,7 @@ class CPPCHECKLIB Token { mImpl->mValues = nullptr; } + // cppcheck-suppress unusedFunction - used in tests only std::string astString(const char *sep = "") const { std::string ret; if (mImpl->mAstOperand1) @@ -1559,7 +1560,7 @@ class CPPCHECKLIB Token { std::string expressionString() const; - void printAst(bool verbose, bool xml, const std::vector &fileNames, std::ostream &out) const; + void printAst(bool xml, const std::vector &fileNames, std::ostream &out) const; void printValueFlow(const std::vector& files, bool xml, std::ostream &out) const; diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index d91e9e7c3b9..35b0ffc06bc 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -5941,7 +5941,6 @@ bool Tokenizer::simplifyTokenList1(const char FileName[]) } //--------------------------------------------------------------------------- -// TODO: do not depend on --verbose void Tokenizer::printDebugOutput(std::ostream &out) const { if (!list.front()) @@ -5962,14 +5961,14 @@ void Tokenizer::printDebugOutput(std::ostream &out) const if (mSymbolDatabase) { if (xml) mSymbolDatabase->printXml(out); - else if (mSettings.debugsymdb || (mSettings.debugnormal && mSettings.verbose)) + else if (mSettings.debugsymdb) mSymbolDatabase->printOut("Symbol database"); } - if (mSettings.debugast || (mSettings.debugnormal && mSettings.verbose)) - list.front()->printAst(mSettings.verbose, xml, list.getFiles(), out); + if (mSettings.debugast) + list.front()->printAst(xml, list.getFiles(), out); - if (mSettings.debugnormal || mSettings.debugvalueflow) + if (mSettings.debugvalueflow) list.front()->printValueFlow(list.getFiles(), xml, out); if (xml) diff --git a/test/cli/other_test.py b/test/cli/other_test.py index 6a573579c52..8008e2fc862 100644 --- a/test/cli/other_test.py +++ b/test/cli/other_test.py @@ -2701,8 +2701,9 @@ def test_debug_verbose_xml(tmp_path): assert len(ast_elem) == 1 +# TODO: remove interaction with --debug? # TODO: test with --xml -def __test_debug_template(tmp_path, verbose): +def __test_debug_template(tmp_path, verbose=False, debug=False): test_file = tmp_path / 'test.cpp' with open(test_file, "w") as f: f.write( @@ -2722,14 +2723,31 @@ def __test_debug_template(tmp_path, verbose): if verbose: args += ['--verbose'] + if debug: + args += ['--debug'] exitcode, stdout, stderr = cppcheck(args) assert exitcode == 0, stdout - assert stdout.find('##file ') == -1 - assert stdout.find('##Value flow') == -1 - assert stdout.find('### Symbol database ###') == -1 - assert stdout.find('##AST') == -1 - assert stdout.find('### Template Simplifier pass ') != -1 + if debug: + assert stdout.find('##file ') != -1 + else: + assert stdout.find('##file ') == -1 + if debug: + assert stdout.find('##Value flow') != -1 + else: + assert stdout.find('##Value flow') == -1 + if debug and verbose: + assert stdout.find('### Symbol database ###') != -1 + else: + assert stdout.find('### Symbol database ###') == -1 + if debug and verbose: + assert stdout.find('##AST') != -1 + else: + assert stdout.find('##AST') == -1 + if debug: + assert stdout.count('### Template Simplifier pass ') == 2 + else: + assert stdout.count('### Template Simplifier pass ') == 1 assert stderr.splitlines() == [ '{}:4:13: error: Null pointer dereference: (int*)nullptr [nullPointer]'.format(test_file) ] @@ -2737,12 +2755,22 @@ def __test_debug_template(tmp_path, verbose): def test_debug_template(tmp_path): - __test_debug_template(tmp_path, False) + __test_debug_template(tmp_path, verbose=False) def test_debug_template_verbose_nodiff(tmp_path): # make sure --verbose does not change the output - assert __test_debug_template(tmp_path, False) == __test_debug_template(tmp_path, True) + assert __test_debug_template(tmp_path, verbose=False) == __test_debug_template(tmp_path, verbose=True) + + +def test_debug_template_debug(tmp_path): + __test_debug_template(tmp_path, debug=True) + + +@pytest.mark.xfail(strict=True) # TODO: remove dependency on --verbose +def test_debug_template_debug_verbose_nodiff(tmp_path): + # make sure --verbose does not change the output + assert __test_debug_template(tmp_path, debug=True, verbose=False) == __test_debug_template(tmp_path, debug=True, verbose=True) def test_file_ignore_2(tmp_path): # #13570 @@ -3467,7 +3495,6 @@ def test_debug_ast(tmp_path): __test_debug_ast(tmp_path, False) -@pytest.mark.xfail(strict=True) # TODO: remove dependency on --verbose def test_debug_ast_verbose_nodiff(tmp_path): # make sure --verbose does not change the output assert __test_debug_ast(tmp_path, False) == __test_debug_ast(tmp_path, True) diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index a647c460834..67d71f2f2f2 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -462,6 +462,10 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(debugSymdb); TEST_CASE(debugAst); TEST_CASE(debugValueflow); + TEST_CASE(debugNormal); + TEST_CASE(debugNormalVerbose); + TEST_CASE(debug); + TEST_CASE(debugVerbose); TEST_CASE(ignorepaths1); TEST_CASE(ignorepaths2); @@ -3179,6 +3183,50 @@ class TestCmdlineParser : public TestFixture { ASSERT_EQUALS(true, settings->debugvalueflow); } + void debugNormal() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--debug-normal", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); + ASSERT_EQUALS(true, settings->debugnormal); + ASSERT_EQUALS(false, settings->debugSimplified); + ASSERT_EQUALS(true, settings->debugvalueflow); + ASSERT_EQUALS(false, settings->debugast); + ASSERT_EQUALS(false, settings->debugsymdb); + } + + void debugNormalVerbose() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--debug-normal", "--verbose", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); + ASSERT_EQUALS(true, settings->debugnormal); + ASSERT_EQUALS(false, settings->debugSimplified); + ASSERT_EQUALS(true, settings->debugvalueflow); + ASSERT_EQUALS(true, settings->debugast); + ASSERT_EQUALS(true, settings->debugsymdb); + } + + void debug() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--debug", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); + ASSERT_EQUALS(true, settings->debugnormal); + ASSERT_EQUALS(false, settings->debugSimplified); + ASSERT_EQUALS(true, settings->debugvalueflow); + ASSERT_EQUALS(false, settings->debugast); + ASSERT_EQUALS(false, settings->debugsymdb); + } + + void debugVerbose() { + REDIRECT; + const char * const argv[] = {"cppcheck", "--debug", "--verbose", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parseFromArgs(argv)); + ASSERT_EQUALS(true, settings->debugnormal); + ASSERT_EQUALS(false, settings->debugSimplified); + ASSERT_EQUALS(true, settings->debugvalueflow); + ASSERT_EQUALS(true, settings->debugast); + ASSERT_EQUALS(true, settings->debugsymdb); + } + void ignorepaths1() { REDIRECT; const char * const argv[] = {"cppcheck", "-isrc", "file.cpp"};