Skip to content

Commit

Permalink
default to --check-level=exhaustive internally / several related cl…
Browse files Browse the repository at this point in the history
…eanups (#6225)
  • Loading branch information
firewave authored Apr 11, 2024
1 parent 83d4e31 commit 524e979
Show file tree
Hide file tree
Showing 17 changed files with 203 additions and 96 deletions.
23 changes: 17 additions & 6 deletions cli/cmdlineparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,9 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
{
mSettings.exename = Path::getCurrentExecutablePath(argv[0]);

// default to --check-level=normal from CLI for now
mSettings.setCheckLevel(Settings::CheckLevel::normal);

if (argc <= 1) {
printHelp();
return Result::Exit;
Expand Down Expand Up @@ -468,13 +471,21 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a
else if (std::strcmp(argv[i], "--check-config") == 0)
mSettings.checkConfiguration = true;

// Check code exhaustively
else if (std::strcmp(argv[i], "--check-level=exhaustive") == 0)
mSettings.setCheckLevelExhaustive();
// Check level
else if (std::strncmp(argv[i], "--check-level=", 14) == 0) {
Settings::CheckLevel level = Settings::CheckLevel::normal;
const std::string level_s(argv[i] + 14);
if (level_s == "normal")
level = Settings::CheckLevel::normal;
else if (level_s == "exhaustive")
level = Settings::CheckLevel::exhaustive;
else {
mLogger.printError("unknown '--check-level' value '" + level_s + "'.");
return Result::Fail;
}

// Check code with normal analysis
else if (std::strcmp(argv[i], "--check-level=normal") == 0)
mSettings.setCheckLevelNormal();
mSettings.setCheckLevel(level);
}

// Check library definitions
else if (std::strcmp(argv[i], "--check-library") == 0) {
Expand Down
7 changes: 5 additions & 2 deletions gui/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -969,6 +969,9 @@ QPair<bool,Settings> MainWindow::getCppcheckSettings()

result.exename = QCoreApplication::applicationFilePath().toStdString();

// default to --check-level=normal for GUI for now
result.setCheckLevel(Settings::CheckLevel::normal);

const bool std = tryLoadLibrary(&result.library, "std.cfg");
if (!std) {
QMessageBox::critical(this, tr("Error"), tr("Failed to load %1. Your Cppcheck installation is broken. You can use --data-dir=<directory> at the command line to specify where this file is located. Please note that --data-dir is supposed to be used by installation scripts and therefore the GUI does not start when it is used, all that happens is that the setting is configured.\n\nAnalysis is aborted.").arg("std.cfg"));
Expand Down Expand Up @@ -1061,9 +1064,9 @@ QPair<bool,Settings> MainWindow::getCppcheckSettings()
result.maxCtuDepth = mProjectFile->getMaxCtuDepth();
result.maxTemplateRecursion = mProjectFile->getMaxTemplateRecursion();
if (mProjectFile->isCheckLevelExhaustive())
result.setCheckLevelExhaustive();
result.setCheckLevel(Settings::CheckLevel::exhaustive);
else
result.setCheckLevelNormal();
result.setCheckLevel(Settings::CheckLevel::normal);
result.checkHeaders = mProjectFile->getCheckHeaders();
result.checkUnusedTemplates = mProjectFile->getCheckUnusedTemplates();
result.safeChecks.classes = mProjectFile->safeChecks.classes;
Expand Down
7 changes: 5 additions & 2 deletions lib/importproject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1125,6 +1125,9 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings *setti
std::list<SuppressionList::Suppression> suppressions;
Settings temp;

// default to --check-level=normal for import for now
temp.setCheckLevel(Settings::CheckLevel::normal);

guiProject.analyzeAllVsConfigs.clear();

bool checkLevelExhaustive = false;
Expand Down Expand Up @@ -1268,9 +1271,9 @@ bool ImportProject::importCppcheckGuiProject(std::istream &istr, Settings *setti
settings->safeChecks = temp.safeChecks;

if (checkLevelExhaustive)
settings->setCheckLevelExhaustive();
settings->setCheckLevel(Settings::CheckLevel::exhaustive);
else
settings->setCheckLevelNormal();
settings->setCheckLevel(Settings::CheckLevel::normal);

return true;
}
Expand Down
29 changes: 14 additions & 15 deletions lib/settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Settings::Settings()
{
severity.setEnabled(Severity::error, true);
certainty.setEnabled(Certainty::normal, true);
setCheckLevelNormal();
setCheckLevel(Settings::CheckLevel::exhaustive);
executor = defaultExecutor();
}

Expand Down Expand Up @@ -268,21 +268,20 @@ void Settings::loadSummaries()
Summaries::loadReturn(buildDir, summaryReturn);
}


void Settings::setCheckLevelExhaustive()
{
// Checking can take a little while. ~ 10 times slower than normal analysis is OK.
checkLevel = CheckLevel::exhaustive;
performanceValueFlowMaxIfCount = -1;
performanceValueFlowMaxSubFunctionArgs = 256;
}

void Settings::setCheckLevelNormal()
void Settings::setCheckLevel(CheckLevel level)
{
// Checking should finish in reasonable time.
checkLevel = CheckLevel::normal;
performanceValueFlowMaxSubFunctionArgs = 8;
performanceValueFlowMaxIfCount = 100;
if (level == CheckLevel::normal) {
// Checking should finish in reasonable time.
checkLevel = level;
performanceValueFlowMaxSubFunctionArgs = 8;
performanceValueFlowMaxIfCount = 100;
}
else if (level == CheckLevel::exhaustive) {
// Checking can take a little while. ~ 10 times slower than normal analysis is OK.
checkLevel = CheckLevel::exhaustive;
performanceValueFlowMaxIfCount = -1;
performanceValueFlowMaxSubFunctionArgs = 256;
}
}

// TODO: auto generate these tables
Expand Down
15 changes: 7 additions & 8 deletions lib/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -259,10 +259,10 @@ class CPPCHECKLIB WARN_UNUSED Settings {
int performanceValueFlowMaxTime = -1;

/** @brief --performance-valueflow-max-if-count=C */
int performanceValueFlowMaxIfCount;
int performanceValueFlowMaxIfCount = -1;

/** @brief max number of sets of arguments to pass to subfuncions in valueflow */
int performanceValueFlowMaxSubFunctionArgs;
int performanceValueFlowMaxSubFunctionArgs = 256;

/** @brief plist output (--plist-output=&lt;dir&gt;) */
std::string plistOutput;
Expand Down Expand Up @@ -456,14 +456,13 @@ class CPPCHECKLIB WARN_UNUSED Settings {
return jobs == 1;
}

void setCheckLevelExhaustive();
void setCheckLevelNormal();

enum class CheckLevel {
exhaustive,
normal
normal,
exhaustive
};
CheckLevel checkLevel = CheckLevel::normal;
CheckLevel checkLevel = CheckLevel::exhaustive;

void setCheckLevel(CheckLevel level);

using ExecuteCmdFn = std::function<int (std::string,std::vector<std::string>,std::string,std::string&)>;
void setMisraRuleTexts(const ExecuteCmdFn& executeCommand);
Expand Down
4 changes: 2 additions & 2 deletions test/fixture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -445,8 +445,8 @@ void TestFixture::setTemplateFormat(const std::string &templateFormat)
}
}

TestFixture::SettingsBuilder& TestFixture::SettingsBuilder::exhaustive() {
settings.setCheckLevelExhaustive();
TestFixture::SettingsBuilder& TestFixture::SettingsBuilder::checkLevel(Settings::CheckLevel level) {
settings.setCheckLevel(level);
return *this;
}

Expand Down
2 changes: 1 addition & 1 deletion test/fixture.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ class TestFixture : public ErrorLogger {
return *this;
}

SettingsBuilder& exhaustive();
SettingsBuilder& checkLevel(Settings::CheckLevel level);

SettingsBuilder& library(const char lib[]);

Expand Down
38 changes: 38 additions & 0 deletions test/testcmdlineparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,10 @@ class TestCmdlineParser : public TestFixture {
#else
TEST_CASE(executorProcessNotSupported);
#endif
TEST_CASE(checkLevelDefault);
TEST_CASE(checkLevelNormal);
TEST_CASE(checkLevelExhaustive);
TEST_CASE(checkLevelUnknown);

TEST_CASE(ignorepaths1);
TEST_CASE(ignorepaths2);
Expand Down Expand Up @@ -2565,6 +2569,40 @@ class TestCmdlineParser : public TestFixture {
}
#endif

void checkLevelDefault() {
REDIRECT;
const char * const argv[] = {"cppcheck", "file.cpp"};
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(2, argv));
ASSERT_EQUALS_ENUM(Settings::CheckLevel::normal, settings->checkLevel);
ASSERT_EQUALS(100, settings->performanceValueFlowMaxIfCount);
ASSERT_EQUALS(8, settings->performanceValueFlowMaxSubFunctionArgs);
}

void checkLevelNormal() {
REDIRECT;
const char * const argv[] = {"cppcheck", "--check-level=normal", "file.cpp"};
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
ASSERT_EQUALS_ENUM(Settings::CheckLevel::normal, settings->checkLevel);
ASSERT_EQUALS(100, settings->performanceValueFlowMaxIfCount);
ASSERT_EQUALS(8, settings->performanceValueFlowMaxSubFunctionArgs);
}

void checkLevelExhaustive() {
REDIRECT;
const char * const argv[] = {"cppcheck", "--check-level=exhaustive", "file.cpp"};
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv));
ASSERT_EQUALS_ENUM(Settings::CheckLevel::exhaustive, settings->checkLevel);
ASSERT_EQUALS(-1, settings->performanceValueFlowMaxIfCount);
ASSERT_EQUALS(256, settings->performanceValueFlowMaxSubFunctionArgs);
}

void checkLevelUnknown() {
REDIRECT;
const char * const argv[] = {"cppcheck", "--check-level=default", "file.cpp"};
ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv));
ASSERT_EQUALS("cppcheck: error: unknown '--check-level' value 'default'.\n", logger->str());
}

void ignorepaths1() {
REDIRECT;
const char * const argv[] = {"cppcheck", "-isrc", "file.cpp"};
Expand Down
2 changes: 1 addition & 1 deletion test/testcondition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ class TestCondition : public TestFixture {
}

void check_(const char* file, int line, const char code[], const char* filename = "test.cpp", bool inconclusive = false) {
const Settings settings = settingsBuilder(settings0).certainty(Certainty::inconclusive, inconclusive).exhaustive().build();
const Settings settings = settingsBuilder(settings0).certainty(Certainty::inconclusive, inconclusive).build();
check_(file, line, code, settings, filename);
}

Expand Down
12 changes: 12 additions & 0 deletions test/testgarbage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,7 @@ class TestGarbage : public TestFixture {

void garbageCode16() {
checkCode("{ } A() { delete }"); // #6080
ignore_errout(); // we do not care about the output
}

void garbageCode17() {
Expand Down Expand Up @@ -563,6 +564,7 @@ class TestGarbage : public TestFixture {
" case struct Tree : break;\n"
" }\n"
"}"), SYNTAX);
ignore_errout(); // we do not care about the output
}

void garbageCode26() {
Expand Down Expand Up @@ -633,10 +635,12 @@ class TestGarbage : public TestFixture {
void garbageCode37() {
// #5166 segmentation fault (invalid code) in lib/checkother.cpp:329 ( void * f { } void b ( ) { * f } )
checkCode("void * f { } void b ( ) { * f }");
ignore_errout(); // we do not care about the output
}

void garbageCode38() { // Ticket #6666
checkCode("{ f2 { } } void f3 () { delete[] } { }");
ignore_errout(); // we do not care about the output
}

void garbageCode40() { // #6620
Expand Down Expand Up @@ -1222,6 +1226,7 @@ class TestGarbage : public TestFixture {
" for (j = 0; j < 1; j)\n"
" j6;\n"
"}");
ignore_errout(); // we do not care about the output
}

void garbageCode150() { // #7089
Expand Down Expand Up @@ -1441,6 +1446,7 @@ class TestGarbage : public TestFixture {
void garbageCode168() {
// 7246
checkCode("long foo(void) { return *bar; }", false);
ignore_errout(); // we do not care about the output
}

void garbageCode169() {
Expand Down Expand Up @@ -1581,6 +1587,7 @@ class TestGarbage : public TestFixture {
" double e(b);\n"
" if(e <= 0) {}\n"
"}");
ignore_errout(); // we do not care about the output
}

// #8265
Expand All @@ -1607,6 +1614,7 @@ class TestGarbage : public TestFixture {
// #8752
void garbageCode199() {
checkCode("d f(){e n00e0[]n00e0&" "0+f=0}");
ignore_errout(); // we do not care about the output
}

// #8757
Expand All @@ -1623,6 +1631,7 @@ class TestGarbage : public TestFixture {
void garbageCode202() {
ASSERT_THROW_INTERNAL(checkCode("void f() { UNKNOWN_MACRO(return); }"), UNKNOWN_MACRO);
ASSERT_THROW_INTERNAL(checkCode("void f() { UNKNOWN_MACRO(throw); }"), UNKNOWN_MACRO);
ignore_errout();
}

void garbageCode203() { // #8972
Expand Down Expand Up @@ -1735,7 +1744,9 @@ class TestGarbage : public TestFixture {
}
void garbageCode224() {
ASSERT_THROW_INTERNAL(checkCode("void f(){ auto* b = dynamic_cast<const }"), SYNTAX); // don't crash
ASSERT_EQUALS("", errout_str());
ASSERT_THROW_INTERNAL(checkCode("void f(){ auto* b = dynamic_cast x; }"), SYNTAX);
ignore_errout();
}
void garbageCode225() {
ASSERT_THROW_INTERNAL(checkCode("int n() { c * s0, 0 s0 = c(sizeof = ) }"), SYNTAX);
Expand Down Expand Up @@ -1859,6 +1870,7 @@ class TestGarbage : public TestFixture {
"void f() {\n"
" auto fn = []() -> foo* { return new foo(); };\n"
"}");
ignore_errout(); // we do not care about the output
}
};

Expand Down
9 changes: 9 additions & 0 deletions test/testsettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class TestSettings : public TestFixture {
TEST_CASE(loadCppcheckCfgSafety);
TEST_CASE(getNameAndVersion);
TEST_CASE(ruleTexts);
TEST_CASE(checkLevelDefault);
}

void simpleEnableGroup() const {
Expand Down Expand Up @@ -266,6 +267,14 @@ class TestSettings : public TestFixture {
ASSERT_EQUALS("text 1", s.getMisraRuleText("misra-c2012-1.1", "---"));
ASSERT_EQUALS("text 2", s.getMisraRuleText("misra-c2012-1.2", "---"));
}

void checkLevelDefault() const
{
Settings s;
ASSERT_EQUALS_ENUM(s.checkLevel, Settings::CheckLevel::exhaustive);
ASSERT_EQUALS(s.performanceValueFlowMaxIfCount, -1);
ASSERT_EQUALS(s.performanceValueFlowMaxSubFunctionArgs, 256);
}
};

REGISTER_TEST(TestSettings)
Loading

0 comments on commit 524e979

Please sign in to comment.