From: George Karpenkov Date: Fri, 23 Feb 2018 23:26:54 +0000 (+0000) Subject: [analyzer] Consider switch- and goto- labels when constructing the set of executed... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=599d6eacd94ca6c6bcd81448927929a386d042d0;p=clang [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 --- 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}};