aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2013-06-10 20:45:12 +0000
committerDimitry Andric <dim@FreeBSD.org>2013-06-10 20:45:12 +0000
commit6a0372513edbc473b538d2f724efac50405d6fef (patch)
tree8f7776b7310bebaf415ac5b69e46e9f928c37144 /lib/StaticAnalyzer/Core/PathDiagnostic.cpp
parent809500fc2c13c8173a16b052304d983864e4a1e1 (diff)
downloadsrc-6a0372513edbc473b538d2f724efac50405d6fef.tar.gz
src-6a0372513edbc473b538d2f724efac50405d6fef.zip
Vendor import of clang tags/RELEASE_33/final r183502 (effectively, 3.3vendor/clang/clang-release_33-r183502
Notes
Notes: svn path=/vendor/clang/dist/; revision=251609 svn path=/vendor/clang/clang-release_33-r183502/; revision=251610; tag=vendor/clang/clang-release_33-r183502
Diffstat (limited to 'lib/StaticAnalyzer/Core/PathDiagnostic.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/PathDiagnostic.cpp89
1 files changed, 68 insertions, 21 deletions
diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
index 7c0fb14a5c82..03513106ecd3 100644
--- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -297,11 +297,16 @@ static Optional<bool> comparePiece(const PathDiagnosticPiece &X,
static Optional<bool> comparePath(const PathPieces &X, const PathPieces &Y) {
if (X.size() != Y.size())
return X.size() < Y.size();
- for (unsigned i = 0, n = X.size(); i != n; ++i) {
- Optional<bool> b = comparePiece(*X[i], *Y[i]);
+
+ PathPieces::const_iterator X_I = X.begin(), X_end = X.end();
+ PathPieces::const_iterator Y_I = Y.begin(), Y_end = Y.end();
+
+ for ( ; X_I != X_end && Y_I != Y_end; ++X_I, ++Y_I) {
+ Optional<bool> b = comparePiece(**X_I, **Y_I);
if (b.hasValue())
return b.getValue();
}
+
return None;
}
@@ -608,31 +613,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);