diff --git a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h index 4643c67b7002..c84f6c3768c0 100644 --- a/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ b/clang/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -297,6 +297,13 @@ public: /// option, which accepts the values "true" and "false". bool shouldAvoidSuppressingNullArgumentPaths(); + /// Returns whether irrelevant parts of a bug report path should be pruned + /// out of the final output. + /// + /// This is controlled by the 'prune-paths' config option, which accepts the + /// values "true" and "false". + bool shouldPrunePaths(); + // Returns the size of the functions (in basic blocks), which should be // considered to be small enough to always inline. // diff --git a/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp b/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp index 193e3b875d48..e2dedb4ac89d 100644 --- a/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp +++ b/clang/lib/StaticAnalyzer/Core/AnalyzerOptions.cpp @@ -186,3 +186,7 @@ unsigned AnalyzerOptions::getMaxTimesInlineLarge() { bool AnalyzerOptions::shouldSynthesizeBodies() { return getBooleanOption("faux-bodies", true); } + +bool AnalyzerOptions::shouldPrunePaths() { + return getBooleanOption("prune-paths", true); +} diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp index 38069a56ac7a..473472872b18 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -2123,7 +2123,8 @@ bool GRBugReporter::generatePathDiagnostic(PathDiagnostic& PD, // Remove messages that are basically the same. removeRedundantMsgs(PD.getMutablePieces()); - if (R->shouldPrunePath()) { + if (R->shouldPrunePath() && + getEngine().getAnalysisManager().options.shouldPrunePaths()) { bool hasSomethingInteresting = RemoveUnneededCalls(PD.getMutablePieces(), R); assert(hasSomethingInteresting); diff --git a/clang/test/Analysis/diagnostics/no-prune-paths.c b/clang/test/Analysis/diagnostics/no-prune-paths.c new file mode 100644 index 000000000000..fab5cf82059b --- /dev/null +++ b/clang/test/Analysis/diagnostics/no-prune-paths.c @@ -0,0 +1,21 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-output=text -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-output=text -analyzer-config prune-paths=false -DNPRUNE=1 -verify %s + +// "prune-paths" is a debug option only; this is just a simple test to see that +// it's being honored. + +void helper() { + extern void foo(); + foo(); +} + +void test() { + helper(); +#if NPRUNE + // expected-note@-2 {{Calling 'helper'}} + // expected-note@-3 {{Returning from 'helper'}} +#endif + + *(volatile int *)0 = 1; // expected-warning {{Dereference of null pointer}} + // expected-note@-1 {{Dereference of null pointer}} +}