aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
diff options
context:
space:
mode:
authorAnna Zaks <ganna@apple.com>2013-04-23 23:57:43 +0000
committerAnna Zaks <ganna@apple.com>2013-04-23 23:57:43 +0000
commit0f8579274a010f360a371b53101859d9d6052314 (patch)
tree944fb500a65d22c06503588fdade01e412ecfa51 /lib/StaticAnalyzer/Core/PathDiagnostic.cpp
parent70054261e009085bff6623eec6cc013430183bec (diff)
[analyzer] Refactor BugReport::getLocation and PathDiagnosticLocation::createEndOfPath for greater code reuse
The 2 functions were computing the same location using different logic (each one had edge case bugs that the other one did not). Refactor them to rely on the same logic. The location of the warning reported in text/command line output format will now match that of the plist file. There is one change in the plist output as well. When reporting an error on a BinaryOperator, we use the location of the operator instead of the beginning of the BinaryOperator expression. This matches our output on command line and looks better in most cases. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@180165 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/PathDiagnostic.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/PathDiagnostic.cpp80
1 files changed, 61 insertions, 19 deletions
diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
index 7c0fb14a5c..a30d871d8f 100644
--- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -608,31 +608,73 @@ PathDiagnosticLocation
return PathDiagnosticLocation(S, SMng, P.getLocationContext());
}
+const Stmt *PathDiagnosticLocation::getStmt(const ExplodedNode *N) {
+ ProgramPoint P = N->getLocation();
+ if (Optional<StmtPoint> SP = P.getAs<StmtPoint>())
+ return SP->getStmt();
+ if (Optional<BlockEdge> BE = P.getAs<BlockEdge>())
+ return BE->getSrc()->getTerminator();
+ if (Optional<CallEnter> CE = P.getAs<CallEnter>())
+ return CE->getCallExpr();
+ if (Optional<CallExitEnd> CEE = P.getAs<CallExitEnd>())
+ return CEE->getCalleeContext()->getCallSite();
+ if (Optional<PostInitializer> PIPP = P.getAs<PostInitializer>())
+ return PIPP->getInitializer()->getInit();
+
+ return 0;
+}
+
+const Stmt *PathDiagnosticLocation::getNextStmt(const ExplodedNode *N) {
+ for (N = N->getFirstSucc(); N; N = N->getFirstSucc()) {
+ if (const Stmt *S = getStmt(N)) {
+ // Check if the statement is '?' or '&&'/'||'. These are "merges",
+ // not actual statement points.
+ switch (S->getStmtClass()) {
+ case Stmt::ChooseExprClass:
+ case Stmt::BinaryConditionalOperatorClass:
+ case Stmt::ConditionalOperatorClass:
+ continue;
+ case Stmt::BinaryOperatorClass: {
+ BinaryOperatorKind Op = cast<BinaryOperator>(S)->getOpcode();
+ if (Op == BO_LAnd || Op == BO_LOr)
+ continue;
+ break;
+ }
+ default:
+ break;
+ }
+ // We found the statement, so return it.
+ return S;
+ }
+ }
+
+ return 0;
+}
+
PathDiagnosticLocation
- PathDiagnosticLocation::createEndOfPath(const ExplodedNode* N,
+ PathDiagnosticLocation::createEndOfPath(const ExplodedNode *N,
const SourceManager &SM) {
assert(N && "Cannot create a location with a null node.");
+ const Stmt *S = getStmt(N);
- const ExplodedNode *NI = N;
- const Stmt *S = 0;
-
- while (NI) {
- ProgramPoint P = NI->getLocation();
- if (Optional<StmtPoint> PS = P.getAs<StmtPoint>()) {
- S = PS->getStmt();
- if (P.getAs<PostStmtPurgeDeadSymbols>())
- return PathDiagnosticLocation::createEnd(S, SM,
- NI->getLocationContext());
- break;
- } else if (Optional<BlockEdge> BE = P.getAs<BlockEdge>()) {
- S = BE->getSrc()->getTerminator();
- break;
- }
- NI = NI->succ_empty() ? 0 : *(NI->succ_begin());
- }
+ if (!S)
+ S = getNextStmt(N);
if (S) {
- const LocationContext *LC = NI->getLocationContext();
+ ProgramPoint P = N->getLocation();
+ const LocationContext *LC = N->getLocationContext();
+
+ // For member expressions, return the location of the '.' or '->'.
+ if (const MemberExpr *ME = dyn_cast<MemberExpr>(S))
+ return PathDiagnosticLocation::createMemberLoc(ME, SM);
+
+ // For binary operators, return the location of the operator.
+ if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S))
+ return PathDiagnosticLocation::createOperatorLoc(B, SM);
+
+ if (P.getAs<PostStmtPurgeDeadSymbols>())
+ return PathDiagnosticLocation::createEnd(S, SM, LC);
+
if (S->getLocStart().isValid())
return PathDiagnosticLocation(S, SM, LC);
return PathDiagnosticLocation(getValidSourceLocation(S, LC), SM);