From 599d6eacd94ca6c6bcd81448927929a386d042d0 Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Fri, 23 Feb 2018 23:26:54 +0000 Subject: [PATCH] [analyzer] Consider switch- and goto- labels when constructing the set of executed lines When viewing the report in the collapsed mode the label signifying where did the execution go is often necessary for properly understanding the context. Differential Revision: https://reviews.llvm.org/D43145 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@325975 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/BugReporter.cpp | 30 +++++++++++++++---- .../html_diagnostics/relevant_lines/goto.c | 13 ++++++++ .../html_diagnostics/relevant_lines/switch.c | 20 +++++++++++++ .../relevant_lines/switch_default.c | 20 +++++++++++++ 4 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 test/Analysis/html_diagnostics/relevant_lines/goto.c create mode 100644 test/Analysis/html_diagnostics/relevant_lines/switch.c create mode 100644 test/Analysis/html_diagnostics/relevant_lines/switch_default.c diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index 6e8b05b820..5d32ef3632 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/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 &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 @@ -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(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(P) || isa(P))) + populateExecutedLinesWithStmt(P, SM, ExecutedLines); } N = N->getFirstPred(); diff --git a/test/Analysis/html_diagnostics/relevant_lines/goto.c b/test/Analysis/html_diagnostics/relevant_lines/goto.c new file mode 100644 index 0000000000..fc90f1334f --- /dev/null +++ b/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/test/Analysis/html_diagnostics/relevant_lines/switch.c b/test/Analysis/html_diagnostics/relevant_lines/switch.c new file mode 100644 index 0000000000..e9032cdece --- /dev/null +++ b/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/test/Analysis/html_diagnostics/relevant_lines/switch_default.c b/test/Analysis/html_diagnostics/relevant_lines/switch_default.c new file mode 100644 index 0000000000..b14e3f9fa8 --- /dev/null +++ b/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}}; -- 2.40.0