aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
diff options
context:
space:
mode:
authorAnna Zaks <ganna@apple.com>2011-09-14 17:48:01 +0000
committerAnna Zaks <ganna@apple.com>2011-09-14 17:48:01 +0000
commit4d353eb8af7324c0ee3736c736668f6c9b162ee0 (patch)
tree6dfc7fb26baac31742c93cb4d27f8f4b73ad7f29 /lib/StaticAnalyzer/Core/PathDiagnostic.cpp
parentab9b154c93475fa55e6115774f64661737d113f9 (diff)
[analyzer] After CFG has been linearized, we can have a situation where an ExpoledNode has an invalid SourceLocation (which has no correspondence in the source code). This commit is the first step to solve this problem.
- It adds LocationContext to the PathDiagnosticLocation object and uses it to lookup the enclosing statement with a valid location. - So far, the LocationContext is only available when the object is constructed from the ExplodedNode. - Already found some subtle bugs(in plist-output-alternate.m) where the intermediate diagnostic steps were not previously shown. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139703 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/PathDiagnostic.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/PathDiagnostic.cpp34
1 files changed, 29 insertions, 5 deletions
diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
index 28a6d403f5..ac9b15e743 100644
--- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -16,6 +16,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
+#include "clang/AST/ParentMap.h"
#include "clang/AST/StmtCXX.h"
#include "llvm/ADT/SmallString.h"
@@ -137,14 +138,14 @@ PathDiagnosticLocation PathDiagnosticLocation::create(const ExplodedNode* N,
while (NI) {
ProgramPoint P = NI->getLocation();
-
+ const LocationContext *LC = P.getLocationContext();
if (const StmtPoint *PS = dyn_cast<StmtPoint>(&P)) {
- return PathDiagnosticLocation(PS->getStmt(), SM);
+ return PathDiagnosticLocation(PS->getStmt(), SM, LC);
}
else if (const BlockEdge *BE = dyn_cast<BlockEdge>(&P)) {
const Stmt *Term = BE->getSrc()->getTerminator();
assert(Term);
- return PathDiagnosticLocation(Term, SM);
+ return PathDiagnosticLocation(Term, SM, LC);
}
NI = NI->succ_empty() ? 0 : *(NI->succ_begin());
}
@@ -153,6 +154,28 @@ PathDiagnosticLocation PathDiagnosticLocation::create(const ExplodedNode* N,
return PathDiagnosticLocation(D.getBodyRBrace(), SM);
}
+static SourceLocation getValidSourceLocation(const Stmt* S,
+ const LocationContext *LC) {
+ SourceLocation L = S->getLocStart();
+
+ // S might be a temporary statement that does not have a location in the
+ // source code, so find an enclosing statement and use it's location.
+ if (!L.isValid() && LC) {
+ assert(LC);
+ ParentMap & PM = LC->getParentMap();
+
+ const Stmt *PS = S;
+ while (!L.isValid()) {
+ PS = PM.getParent(PS);
+ L = PS->getLocStart();
+ }
+ }
+
+ // TODO: either change the name or uncomment the assert.
+ //assert(L.isValid());
+ return L;
+}
+
FullSourceLoc PathDiagnosticLocation::asLocation() const {
assert(isValid());
// Note that we want a 'switch' here so that the compiler can warn us in
@@ -162,7 +185,8 @@ FullSourceLoc PathDiagnosticLocation::asLocation() const {
case RangeK:
break;
case StmtK:
- return FullSourceLoc(S->getLocStart(), const_cast<SourceManager&>(*SM));
+ return FullSourceLoc(getValidSourceLocation(S, LC),
+ const_cast<SourceManager&>(*SM));
case DeclK:
return FullSourceLoc(D->getLocation(), const_cast<SourceManager&>(*SM));
}
@@ -205,7 +229,7 @@ PathDiagnosticRange PathDiagnosticLocation::asRange() const {
case Stmt::BinaryConditionalOperatorClass:
case Stmt::ConditionalOperatorClass:
case Stmt::ObjCForCollectionStmtClass: {
- SourceLocation L = S->getLocStart();
+ SourceLocation L = getValidSourceLocation(S, LC);
return SourceRange(L, L);
}
}