Skip to content

Commit 1202efb

Browse files
authored
some --exception-handling related improvements (cppcheck-opensource#4368)
1 parent b04bf73 commit 1202efb

9 files changed

Lines changed: 123 additions & 15 deletions

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -640,7 +640,7 @@ test/testclangimport.o: test/testclangimport.cpp lib/clangimport.h lib/color.h l
640640
test/testclass.o: test/testclass.cpp externals/tinyxml2/tinyxml2.h lib/check.h lib/checkclass.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/sourcelocation.h lib/standards.h lib/suppressions.h lib/symboldatabase.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h
641641
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testclass.o test/testclass.cpp
642642

643-
test/testcmdlineparser.o: test/testcmdlineparser.cpp cli/cmdlineparser.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h test/redirect.h test/testsuite.h
643+
test/testcmdlineparser.o: test/testcmdlineparser.cpp cli/cmdlineparser.h cli/cppcheckexecutor.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/settings.h lib/standards.h lib/suppressions.h lib/timer.h lib/utils.h test/redirect.h test/testsuite.h
644644
$(CXX) ${INCLUDE_FOR_TEST} $(CPPFLAGS) $(CPPFILESDIR) $(CXXFLAGS) $(UNDEF_STRICT_ANSI) -c -o test/testcmdlineparser.o test/testcmdlineparser.cpp
645645

646646
test/testcondition.o: test/testcondition.cpp externals/simplecpp/simplecpp.h externals/tinyxml2/tinyxml2.h lib/check.h lib/checkcondition.h lib/color.h lib/config.h lib/errorlogger.h lib/errortypes.h lib/importproject.h lib/library.h lib/mathlib.h lib/platform.h lib/preprocessor.h lib/settings.h lib/standards.h lib/suppressions.h lib/templatesimplifier.h lib/timer.h lib/token.h lib/tokenize.h lib/tokenlist.h lib/utils.h lib/valueflow.h test/testsuite.h

cli/cmdlineparser.cpp

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -242,11 +242,13 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
242242
mSettings->addEnabled("information");
243243
}
244244

245-
else if (std::strncmp(argv[i], "--clang", 7) == 0) {
245+
else if (std::strcmp(argv[i], "--clang") == 0) {
246246
mSettings->clang = true;
247-
if (std::strncmp(argv[i], "--clang=", 8) == 0) {
248-
mSettings->clangExecutable = argv[i] + 8;
249-
}
247+
}
248+
249+
else if (std::strncmp(argv[i], "--clang=", 8) == 0) {
250+
mSettings->clang = true;
251+
mSettings->clangExecutable = argv[i] + 8;
250252
}
251253

252254
else if (std::strncmp(argv[i], "--config-exclude=",17) ==0) {
@@ -339,14 +341,19 @@ bool CmdLineParser::parseFromArgs(int argc, const char* const argv[])
339341
}
340342

341343
// Exception handling inside cppcheck client
342-
else if (std::strcmp(argv[i], "--exception-handling") == 0)
344+
else if (std::strcmp(argv[i], "--exception-handling") == 0) {
343345
mSettings->exceptionHandling = true;
346+
}
344347

345-
// TODO: only applied with Signal handling i.e. Linux
348+
// Exception handling inside cppcheck client
346349
else if (std::strncmp(argv[i], "--exception-handling=", 21) == 0) {
350+
const std::string exceptionOutfilename = argv[i] + 21;
351+
if (exceptionOutfilename != "stderr" && exceptionOutfilename != "stdout") {
352+
printError("invalid '--exception-handling' argument");
353+
return false;
354+
}
347355
mSettings->exceptionHandling = true;
348-
const std::string exceptionOutfilename = &(argv[i][21]);
349-
CppCheckExecutor::setExceptionOutput((exceptionOutfilename=="stderr") ? stderr : stdout);
356+
CppCheckExecutor::setExceptionOutput((exceptionOutfilename == "stderr") ? stderr : stdout);
350357
}
351358

352359
// Filter errors

cli/cppcheckexecutorseh.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -165,9 +165,8 @@ namespace {
165165
/*
166166
* Any evaluation of the exception needs to be done here!
167167
*/
168-
int filterException(int code, PEXCEPTION_POINTERS ex)
168+
int filterException(FILE *outputFile, int code, PEXCEPTION_POINTERS ex)
169169
{
170-
FILE *outputFile = stdout;
171170
fputs("Internal error: ", outputFile);
172171
switch (ex->ExceptionRecord->ExceptionCode) {
173172
case EXCEPTION_ACCESS_VIOLATION:
@@ -256,11 +255,10 @@ namespace {
256255
*/
257256
int check_wrapper_seh(CppCheckExecutor& executor, int (CppCheckExecutor::*f)(CppCheck&), CppCheck& cppcheck)
258257
{
259-
FILE *outputFile = stdout;
258+
FILE *outputFile = CppCheckExecutor::getExceptionOutput();
260259
__try {
261260
return (&executor->*f)(cppcheck);
262-
} __except (filterException(GetExceptionCode(), GetExceptionInformation())) {
263-
// reporting to stdout may not be helpful within a GUI application...
261+
} __except (filterException(outputFile, GetExceptionCode(), GetExceptionInformation())) {
264262
fputs("Please report this to the cppcheck developers!\n", outputFile);
265263
return -1;
266264
}

cmake/compilerDefinitions.cmake

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,17 @@ if (MSVC AND DISABLE_CRTDBG_MAP_ALLOC)
4040
add_definitions(-DDISABLE_CRTDBG_MAP_ALLOC)
4141
endif()
4242

43+
if (NO_UNIX_SIGNAL_HANDLING)
44+
add_definitions(-DNO_UNIX_SIGNAL_HANDLING)
45+
endif()
46+
47+
if (NO_UNIX_BACKTRACE_SUPPORT)
48+
add_definitions(-DNO_UNIX_BACKTRACE_SUPPORT)
49+
endif()
50+
51+
if (NO_WINDOWS_SEH)
52+
add_definitions(-DNO_WINDOWS_SEH)
53+
endif()
54+
4355
file(TO_CMAKE_PATH ${FILESDIR} _filesdir)
4456
add_definitions(-DFILESDIR="${_filesdir}")

cmake/options.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,11 @@ option(USE_BUNDLED_TINYXML2 "Usage of bundled tinyxml2 library"
4545
option(CPPCHK_GLIBCXX_DEBUG "Usage of _GLIBCXX_DEBUG in Debug build" ON)
4646
option(USE_THREADS "Usage of threads instead of fork() for -j" OFF)
4747
option(USE_BOOST "Usage of Boost" OFF)
48+
4849
option(DISABLE_CRTDBG_MAP_ALLOC "Disable usage of Visual Studio C++ memory leak detection in Debug build" OFF)
50+
option(NO_UNIX_SIGNAL_HANDLING "Disable usage of Unix Signal Handling" OFF)
51+
option(NO_UNIX_BACKTRACE_SUPPORT "Disable usage of Unix Backtrace support" OFF)
52+
option(NO_WINDOWS_SEH "Disable usage of Windows SEH" OFF)
4953

5054
if (CMAKE_VERSION VERSION_EQUAL "3.16" OR CMAKE_VERSION VERSION_GREATER "3.16")
5155
set(CMAKE_DISABLE_PRECOMPILE_HEADERS Off CACHE BOOL "Disable precompiled headers")

cmake/printInfo.cmake

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ message( STATUS )
2828
message( STATUS "USE_MATCHCOMPILER = ${USE_MATCHCOMPILER}" )
2929
message( STATUS "USE_MATCHCOMPILER_OPT = ${USE_MATCHCOMPILER_OPT}" )
3030
message( STATUS )
31+
message( STATUS "DISABLE_CRTDBG_MAP_ALLOC = ${DISABLE_CRTDBG_MAP_ALLOC}")
32+
message( STATUS "NO_UNIX_SIGNAL_HANDLING = ${NO_UNIX_SIGNAL_HANDLING}")
33+
message( STATUS "NO_UNIX_BACKTRACE_SUPPORT = ${NO_UNIX_BACKTRACE_SUPPORT}")
34+
message( STATUS "NO_WINDOWS_SEH = ${NO_WINDOWS_SEH}")
35+
message( STATUS )
3136
if(NOT DEFINED BUILD_SHARED_LIBS)
3237
message( STATUS "BUILD_SHARED_LIBS = OFF" )
3338
else()

lib/config.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ static const std::string emptyString;
131131
#define SUPPRESS_FLOAT_EQUAL_WARNING(...) __VA_ARGS__
132132
#endif
133133

134-
#if defined(_WIN32) && defined(_MSC_VER)
134+
#if !defined(NO_WINDOWS_SEH) && defined(_WIN32) && defined(_MSC_VER)
135135
#define USE_WINDOWS_SEH
136136
#endif
137137

releasenotes.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,5 @@ release notes for cppcheck-2.9
22

33
- restored check for negative allocation (new[]) and negative VLA sizes from cppcheck 1.87 (LCppC backport)
44
- replaced hardcoded check for pipe() buffer size by library configuration option (LCppC backport)
5+
- on Windows the callstack is now being written to the output specific via "--exception-handling"
6+
- make it possible to disable the various exception handling parts via the CMake options "NO_UNIX_SIGNAL_HANDLING", "NO_UNIX_BACKTRACE_SUPPORT" and "NO_WINDOWS_SEH"

test/testcmdlineparser.cpp

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
*/
1818

1919
#include "cmdlineparser.h"
20+
#include "cppcheckexecutor.h"
2021
#include "errortypes.h"
2122
#include "platform.h"
2223
#include "redirect.h"
@@ -131,6 +132,14 @@ class TestCmdlineParser : public TestFixture {
131132
TEST_CASE(errorlistverbose1);
132133
TEST_CASE(errorlistverbose2);
133134
TEST_CASE(ignorepathsnopath);
135+
TEST_CASE(exceptionhandling);
136+
TEST_CASE(exceptionhandling2);
137+
TEST_CASE(exceptionhandling3);
138+
TEST_CASE(exceptionhandlingInvalid);
139+
TEST_CASE(exceptionhandlingInvalid2);
140+
TEST_CASE(clang);
141+
TEST_CASE(clang2);
142+
TEST_CASE(clangInvalid);
134143

135144
// TODO
136145
// Disabling these tests since they use relative paths to the
@@ -965,6 +974,77 @@ class TestCmdlineParser : public TestFixture {
965974
ASSERT_EQUALS(0, parser.getIgnoredPaths().size());
966975
}
967976

977+
void exceptionhandling() {
978+
REDIRECT;
979+
const char * const argv[] = {"cppcheck", "--exception-handling"};
980+
settings.exceptionHandling = false;
981+
CppCheckExecutor::setExceptionOutput(stderr);
982+
ASSERT(defParser.parseFromArgs(2, argv));
983+
ASSERT(settings.exceptionHandling);
984+
ASSERT_EQUALS(stderr, CppCheckExecutor::getExceptionOutput());
985+
}
986+
987+
void exceptionhandling2() {
988+
REDIRECT;
989+
const char * const argv[] = {"cppcheck", "--exception-handling=stderr"};
990+
settings.exceptionHandling = false;
991+
CppCheckExecutor::setExceptionOutput(stdout);
992+
ASSERT(defParser.parseFromArgs(2, argv));
993+
ASSERT(settings.exceptionHandling);
994+
ASSERT_EQUALS(stderr, CppCheckExecutor::getExceptionOutput());
995+
}
996+
997+
void exceptionhandling3() {
998+
REDIRECT;
999+
const char * const argv[] = {"cppcheck", "--exception-handling=stdout"};
1000+
settings.exceptionHandling = false;
1001+
CppCheckExecutor::setExceptionOutput(stderr);
1002+
ASSERT(defParser.parseFromArgs(2, argv));
1003+
ASSERT(settings.exceptionHandling);
1004+
ASSERT_EQUALS(stdout, CppCheckExecutor::getExceptionOutput());
1005+
}
1006+
1007+
void exceptionhandlingInvalid() {
1008+
REDIRECT;
1009+
const char * const argv[] = {"cppcheck", "--exception-handling=exfile"};
1010+
ASSERT_EQUALS(false, defParser.parseFromArgs(2, argv));
1011+
ASSERT_EQUALS("cppcheck: error: invalid '--exception-handling' argument\n", GET_REDIRECT_OUTPUT);
1012+
}
1013+
1014+
void exceptionhandlingInvalid2() {
1015+
REDIRECT;
1016+
const char * const argv[] = {"cppcheck", "--exception-handling-foo"};
1017+
ASSERT_EQUALS(false, defParser.parseFromArgs(2, argv));
1018+
ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--exception-handling-foo\".\n", GET_REDIRECT_OUTPUT);
1019+
}
1020+
1021+
void clang() {
1022+
REDIRECT;
1023+
const char * const argv[] = {"cppcheck", "--clang"};
1024+
settings.clang = false;
1025+
settings.clangExecutable = "exe";
1026+
ASSERT(defParser.parseFromArgs(2, argv));
1027+
ASSERT(settings.clang);
1028+
ASSERT_EQUALS("exe", settings.clangExecutable);
1029+
}
1030+
1031+
void clang2() {
1032+
REDIRECT;
1033+
const char * const argv[] = {"cppcheck", "--clang=clang-14"};
1034+
settings.clang = false;
1035+
settings.clangExecutable = "";
1036+
ASSERT(defParser.parseFromArgs(2, argv));
1037+
ASSERT(settings.clang);
1038+
ASSERT_EQUALS("clang-14", settings.clangExecutable);
1039+
}
1040+
1041+
void clangInvalid() {
1042+
REDIRECT;
1043+
const char * const argv[] = {"cppcheck", "--clang-foo"};
1044+
ASSERT_EQUALS(false, defParser.parseFromArgs(2, argv));
1045+
ASSERT_EQUALS("cppcheck: error: unrecognized command line option: \"--clang-foo\".\n", GET_REDIRECT_OUTPUT);
1046+
}
1047+
9681048
/*
9691049
void ignorepaths1() {
9701050
REDIRECT;

0 commit comments

Comments
 (0)