Skip to content
Merged
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
371 changes: 195 additions & 176 deletions cli/cmdlineparser.cpp

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion cli/cmdlineparser.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class CmdLineParser {
/**
* Print help text to the console.
*/
void printHelp();
void printHelp() const;

private:
bool isCppcheckPremium() const;
Expand Down
19 changes: 10 additions & 9 deletions cli/cppcheckexecutor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,9 @@ class CmdLineLoggerStd : public CmdLineLogger

// TODO: do not directly write to stdout

#if defined(USE_WINDOWS_SEH) || defined(USE_UNIX_SIGNAL_HANDLING)
/*static*/ FILE* CppCheckExecutor::mExceptionOutput = stdout;
#endif

CppCheckExecutor::~CppCheckExecutor()
{
Expand Down Expand Up @@ -257,11 +259,7 @@ int CppCheckExecutor::check(int argc, const char* const argv[])
cppCheck.settings() = settings;
mSettings = &settings;

int ret;
if (settings.exceptionHandling)
ret = check_wrapper(cppCheck);
else
ret = check_internal(cppCheck);
const int ret = check_wrapper(cppCheck);

mSettings = nullptr;
return ret;
Expand All @@ -270,12 +268,13 @@ int CppCheckExecutor::check(int argc, const char* const argv[])
int CppCheckExecutor::check_wrapper(CppCheck& cppcheck)
{
#ifdef USE_WINDOWS_SEH
return check_wrapper_seh(*this, &CppCheckExecutor::check_internal, cppcheck);
if (cppcheck.settings().exceptionHandling)
return check_wrapper_seh(*this, &CppCheckExecutor::check_internal, cppcheck);
#elif defined(USE_UNIX_SIGNAL_HANDLING)
return check_wrapper_sig(*this, &CppCheckExecutor::check_internal, cppcheck);
#else
return check_internal(cppcheck);
if (cppcheck.settings().exceptionHandling)
return check_wrapper_sig(*this, &CppCheckExecutor::check_internal, cppcheck);
#endif
return check_internal(cppcheck);
}

bool CppCheckExecutor::reportSuppressions(const Settings &settings, bool unusedFunctionCheckEnabled, const std::map<std::string, std::size_t> &files, ErrorLogger& errorLogger) {
Expand Down Expand Up @@ -522,6 +521,7 @@ void CppCheckExecutor::reportErr(const ErrorMessage &msg)
reportErr(msg.toString(mSettings->verbose, mSettings->templateFormat, mSettings->templateLocation));
}

#if defined(USE_WINDOWS_SEH) || defined(USE_UNIX_SIGNAL_HANDLING)
void CppCheckExecutor::setExceptionOutput(FILE* exceptionOutput)
{
mExceptionOutput = exceptionOutput;
Expand All @@ -531,6 +531,7 @@ FILE* CppCheckExecutor::getExceptionOutput()
{
return mExceptionOutput;
}
#endif

bool CppCheckExecutor::tryLoadLibrary(Library& destination, const std::string& basepath, const char* filename)
{
Expand Down
2 changes: 2 additions & 0 deletions cli/cppcheckexecutor.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,12 @@ class CppCheckExecutor : public ErrorLogger {
*/
std::time_t mLatestProgressOutputTime{};

#if defined(USE_WINDOWS_SEH) || defined(USE_UNIX_SIGNAL_HANDLING)
/**
* Output file name for exception handler
*/
static FILE* mExceptionOutput;
#endif

/**
* Error output
Expand Down
4 changes: 3 additions & 1 deletion lib/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,10 @@ class CPPCHECKLIB WARN_UNUSED Settings {
/** @brief Name of the language that is enforced. Empty per default. */
Language enforcedLang{};

#if defined(USE_WINDOWS_SEH) || defined(USE_UNIX_SIGNAL_HANDLING)
/** @brief Is --exception-handling given */
bool exceptionHandling{};
#endif

// argv[0]
std::string exename;
Expand Down Expand Up @@ -276,6 +278,7 @@ class CPPCHECKLIB WARN_UNUSED Settings {
/** @brief --report-progress */
int reportProgress{-1};

#ifdef HAVE_RULES
/** Rule */
struct CPPCHECKLIB Rule {
std::string tokenlist = "normal"; // use normal tokenlist
Expand All @@ -285,7 +288,6 @@ class CPPCHECKLIB WARN_UNUSED Settings {
Severity severity = Severity::style; // default severity
};

#ifdef HAVE_RULES
/**
* @brief Extra rules
*/
Expand Down
109 changes: 109 additions & 0 deletions test/testcmdlineparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -250,11 +250,16 @@ class TestCmdlineParser : public TestFixture {
TEST_CASE(errorlistverbose1);
TEST_CASE(errorlistverbose2);
TEST_CASE(ignorepathsnopath);
#if defined(USE_WINDOWS_SEH) || defined(USE_UNIX_SIGNAL_HANDLING)
TEST_CASE(exceptionhandling);
TEST_CASE(exceptionhandling2);
TEST_CASE(exceptionhandling3);
TEST_CASE(exceptionhandlingInvalid);
TEST_CASE(exceptionhandlingInvalid2);
#else
TEST_CASE(exceptionhandlingNotSupported);
TEST_CASE(exceptionhandlingNotSupported2);
#endif
TEST_CASE(clang);
TEST_CASE(clang2);
TEST_CASE(clangInvalid);
Expand All @@ -270,6 +275,8 @@ class TestCmdlineParser : public TestFixture {
TEST_CASE(loadAverage);
TEST_CASE(loadAverage2);
TEST_CASE(loadAverageInvalid);
#else
TEST_CASE(loadAverageNotSupported);
#endif
TEST_CASE(maxCtuDepth);
TEST_CASE(maxCtuDepthInvalid);
Expand All @@ -292,6 +299,19 @@ class TestCmdlineParser : public TestFixture {
TEST_CASE(projectMissing);
TEST_CASE(projectNoPaths);
TEST_CASE(addon);
#ifdef HAVE_RULES
TEST_CASE(rule);
#else
TEST_CASE(ruleNotSupported);
#endif
#ifdef HAVE_RULES
TEST_CASE(ruleFile);
TEST_CASE(ruleFileEmpty);
TEST_CASE(ruleFileMissing);
TEST_CASE(ruleFileInvalid);
#else
TEST_CASE(ruleFileNotSupported);
#endif

TEST_CASE(ignorepaths1);
TEST_CASE(ignorepaths2);
Expand Down Expand Up @@ -1698,6 +1718,7 @@ class TestCmdlineParser : public TestFixture {
ASSERT_EQUALS("cppcheck: error: argument to '-i' is missing.\n", logger->str());
}

#if defined(USE_WINDOWS_SEH) || defined(USE_UNIX_SIGNAL_HANDLING)
void exceptionhandling() {
REDIRECT;
const char * const argv[] = {"cppcheck", "--exception-handling", "file.cpp"};
Expand Down Expand Up @@ -1744,6 +1765,21 @@ class TestCmdlineParser : public TestFixture {
ASSERT_EQUALS(false, parser->parseFromArgs(2, argv));
ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--exception-handling-foo\".\n", logger->str());
}
#else
void exceptionhandlingNotSupported() {
REDIRECT;
const char * const argv[] = {"cppcheck", "--exception-handling", "file.cpp"};
ASSERT(!parser->parseFromArgs(3, argv));
ASSERT_EQUALS("cppcheck: error: Option --exception-handling is not supported since Cppcheck has not been built with any exception handling enabled.\n", logger->str());
}

void exceptionhandlingNotSupported2() {
REDIRECT;
const char * const argv[] = {"cppcheck", "--exception-handling=stderr", "file.cpp"};
ASSERT(!parser->parseFromArgs(3, argv));
ASSERT_EQUALS("cppcheck: error: Option --exception-handling is not supported since Cppcheck has not been built with any exception handling enabled.\n", logger->str());
}
#endif

void clang() {
REDIRECT;
Expand Down Expand Up @@ -1861,6 +1897,13 @@ class TestCmdlineParser : public TestFixture {
ASSERT(!parser->parseFromArgs(4, argv));
ASSERT_EQUALS("cppcheck: error: argument to '-l' is not valid - not an integer.\n", logger->str());
}
#else
void loadAverageNotSupported() {
REDIRECT;
const char * const argv[] = {"cppcheck", "-l", "12", "file.cpp"};
ASSERT(!parser->parseFromArgs(4, argv));
ASSERT_EQUALS("cppcheck: error: Option -l cannot be used as Cppcheck has not been built with fork threading model.\n", logger->str());
}
#endif

void maxCtuDepth() {
Expand Down Expand Up @@ -2021,6 +2064,72 @@ class TestCmdlineParser : public TestFixture {
ASSERT_EQUALS("", GET_REDIRECT_OUTPUT);
}

#ifdef HAVE_RULES
void rule() {
REDIRECT;
const char * const argv[] = {"cppcheck", "--rule=.+", "file.cpp"};
ASSERT(parser->parseFromArgs(3, argv));
ASSERT_EQUALS(1, settings->rules.size());
auto it = settings->rules.cbegin();
ASSERT_EQUALS(".+", it->pattern);
ASSERT_EQUALS("", logger->str());
}
#else
void ruleNotSupported() {
REDIRECT;
const char * const argv[] = {"cppcheck", "--rule=.+", "file.cpp"};
ASSERT(!parser->parseFromArgs(3, argv));
ASSERT_EQUALS("cppcheck: error: Option --rule cannot be used as Cppcheck has not been built with rules support.\n", logger->str());
}
#endif

#ifdef HAVE_RULES
void ruleFile() {
REDIRECT;
ScopedFile file("rule.xml",
"<rules>\n"
"<rule>\n"
"<pattern>.+</pattern>\n"
"</rule>\n"
"</rules>");
const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"};
ASSERT(parser->parseFromArgs(3, argv));
ASSERT_EQUALS(1, settings->rules.size());
auto it = settings->rules.cbegin();
ASSERT_EQUALS(".+", it->pattern);
ASSERT_EQUALS("", logger->str());
}

void ruleFileEmpty() {
REDIRECT;
const char * const argv[] = {"cppcheck", "--rule-file=", "file.cpp"};
ASSERT(!parser->parseFromArgs(3, argv));
ASSERT_EQUALS("cppcheck: error: unable to load rule-file '' (XML_ERROR_FILE_NOT_FOUND).\n", logger->str());
}

void ruleFileMissing() {
REDIRECT;
const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"};
ASSERT(!parser->parseFromArgs(3, argv));
ASSERT_EQUALS("cppcheck: error: unable to load rule-file 'rule.xml' (XML_ERROR_FILE_NOT_FOUND).\n", logger->str());
}

void ruleFileInvalid() {
REDIRECT;
ScopedFile file("rule.xml", "");
const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"};
ASSERT(!parser->parseFromArgs(3, argv));
ASSERT_EQUALS("cppcheck: error: unable to load rule-file 'rule.xml' (XML_ERROR_EMPTY_DOCUMENT).\n", logger->str());
}
#else
void ruleFileNotSupported() {
REDIRECT;
const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"};
ASSERT(!parser->parseFromArgs(3, argv));
ASSERT_EQUALS("cppcheck: error: Option --rule-file cannot be used as Cppcheck has not been built with rules support.\n", logger->str());
}
#endif

void ignorepaths1() {
REDIRECT;
const char * const argv[] = {"cppcheck", "-isrc", "file.cpp"};
Expand Down