diff options
4 files changed, 77 insertions, 6 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp index 6e8b05b820a..5d32ef36327 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -3547,6 +3547,16 @@ static void populateExecutedLinesWithFunctionSignature( ExecutedLines->operator[](FID.getHashValue()).insert(Line); } +static void populateExecutedLinesWithStmt( + const Stmt *S, SourceManager &SM, + std::unique_ptr<FilesToLineNumsMap> &ExecutedLines) { + SourceLocation Loc = S->getSourceRange().getBegin(); + SourceLocation ExpansionLoc = SM.getExpansionLoc(Loc); + FileID FID = SM.getFileID(ExpansionLoc); + unsigned LineNo = SM.getExpansionLineNumber(ExpansionLoc); + ExecutedLines->operator[](FID.getHashValue()).insert(LineNo); +} + /// \return all executed lines including function signatures on the path /// starting from \p N. static std::unique_ptr<FilesToLineNumsMap> @@ -3567,13 +3577,21 @@ findExecutedLines(SourceManager &SM, const ExplodedNode *N) { populateExecutedLinesWithFunctionSignature(D, SM, ExecutedLines); } else if (const Stmt *S = PathDiagnosticLocation::getStmt(N)) { + populateExecutedLinesWithStmt(S, SM, ExecutedLines); + + // Show extra context for some parent kinds. + const Stmt *P = N->getParentMap().getParent(S); + + // The path exploration can die before the node with the associated + // return statement is generated, but we do want to show the whole + // return. + if (auto *RS = dyn_cast_or_null<ReturnStmt>(P)) { + populateExecutedLinesWithStmt(RS, SM, ExecutedLines); + P = N->getParentMap().getParent(RS); + } - // Otherwise: show lines associated with the processed statement. - SourceLocation Loc = S->getSourceRange().getBegin(); - SourceLocation ExpansionLoc = SM.getExpansionLoc(Loc); - FileID FID = SM.getFileID(ExpansionLoc); - unsigned LineNo = SM.getExpansionLineNumber(ExpansionLoc); - ExecutedLines->operator[](FID.getHashValue()).insert(LineNo); + if (P && (isa<SwitchCase>(P) || isa<LabelStmt>(P))) + populateExecutedLinesWithStmt(P, SM, ExecutedLines); } N = N->getFirstPred(); diff --git a/clang/test/Analysis/html_diagnostics/relevant_lines/goto.c b/clang/test/Analysis/html_diagnostics/relevant_lines/goto.c new file mode 100644 index 00000000000..fc90f1334f0 --- /dev/null +++ b/clang/test/Analysis/html_diagnostics/relevant_lines/goto.c @@ -0,0 +1,13 @@ +int goto_test(int input) { + int *p = 0; + if (input) + goto mylabel; + return 0; +mylabel: + return *p; +} + +// RUN: rm -rf %t.output +// RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core -analyzer-output html -o %t.output %s +// RUN: cat %t.output/* | FileCheck %s --match-full-lines +// CHECK: var relevant_lines = {"1": {"1": 1, "2": 1, "3": 1, "4": 1, "6": 1, "7": 1}}; diff --git a/clang/test/Analysis/html_diagnostics/relevant_lines/switch.c b/clang/test/Analysis/html_diagnostics/relevant_lines/switch.c new file mode 100644 index 00000000000..e9032cdece9 --- /dev/null +++ b/clang/test/Analysis/html_diagnostics/relevant_lines/switch.c @@ -0,0 +1,20 @@ +enum E { + A, B, C +}; + +int f(enum E input) { + int *x = 0; + switch (input) { + case A: + return 1; + case B: + return 0; + case C: + return *x; + } +} + +// RUN: rm -rf %t.output +// RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core -analyzer-output html -o %t.output %s +// RUN: cat %t.output/* | FileCheck %s --match-full-lines +// CHECK: var relevant_lines = {"1": {"5": 1, "6": 1, "7": 1, "12": 1, "13": 1}}; diff --git a/clang/test/Analysis/html_diagnostics/relevant_lines/switch_default.c b/clang/test/Analysis/html_diagnostics/relevant_lines/switch_default.c new file mode 100644 index 00000000000..b14e3f9fa8f --- /dev/null +++ b/clang/test/Analysis/html_diagnostics/relevant_lines/switch_default.c @@ -0,0 +1,20 @@ +enum E { + A, B, C +}; + +int f(enum E input) { + int *x = 0; + switch (input) { + case A: + return 1; + case B: + return 0; + default: + return *x; + } +} + +// RUN: rm -rf %t.output +// RUN: %clang_analyze_cc1 -analyze -analyzer-checker=core -analyzer-output html -o %t.output %s +// RUN: cat %t.output/* | FileCheck %s --match-full-lines +// CHECK: var relevant_lines = {"1": {"5": 1, "6": 1, "7": 1, "12": 1, "13": 1}}; |

