[cfe-commits] r139703 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h lib/StaticAnalyzer/Core/PathDiagnostic.cpp test/Analysis/plist-output-alternate.m
Anna Zaks
ganna at apple.com
Wed Sep 14 10:48:01 PDT 2011
Author: zaks
Date: Wed Sep 14 12:48:01 2011
New Revision: 139703
URL: http://llvm.org/viewvc/llvm-project?rev=139703&view=rev
Log:
[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.
Modified:
cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
cfe/trunk/test/Analysis/plist-output-alternate.m
Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h?rev=139703&r1=139702&r2=139703&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h Wed Sep 14 12:48:01 2011
@@ -89,32 +89,35 @@
const Stmt *S;
const Decl *D;
const SourceManager *SM;
+ const LocationContext *LC;
public:
PathDiagnosticLocation()
- : K(SingleLocK), S(0), D(0), SM(0) {}
+ : K(SingleLocK), S(0), D(0), SM(0), LC(0) {}
PathDiagnosticLocation(FullSourceLoc L)
- : K(SingleLocK), R(L, L), S(0), D(0), SM(&L.getManager()) {}
+ : K(SingleLocK), R(L, L), S(0), D(0), SM(&L.getManager()), LC(0) {}
- PathDiagnosticLocation(const Stmt *s, const SourceManager &sm)
- : K(StmtK), S(s), D(0), SM(&sm) {}
+ PathDiagnosticLocation(const Stmt *s,
+ const SourceManager &sm,
+ const LocationContext *lc = 0)
+ : K(StmtK), S(s), D(0), SM(&sm), LC(lc) {}
/// Create a location corresponding to the next valid ExplodedNode.
static PathDiagnosticLocation create(const ExplodedNode* N,
const SourceManager &SM);
PathDiagnosticLocation(SourceRange r, const SourceManager &sm)
- : K(RangeK), R(r), S(0), D(0), SM(&sm) {}
+ : K(RangeK), R(r), S(0), D(0), SM(&sm), LC(0) {}
PathDiagnosticLocation(const Decl *d, const SourceManager &sm)
- : K(DeclK), S(0), D(d), SM(&sm) {}
+ : K(DeclK), S(0), D(d), SM(&sm), LC(0) {}
bool operator==(const PathDiagnosticLocation &X) const {
- return K == X.K && R == X.R && S == X.S && D == X.D;
+ return K == X.K && R == X.R && S == X.S && D == X.D && LC == X.LC;
}
bool operator!=(const PathDiagnosticLocation &X) const {
- return K != X.K || R != X.R || S != X.S || D != X.D;;
+ return !(*this == X);
}
PathDiagnosticLocation& operator=(const PathDiagnosticLocation &X) {
Modified: cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp?rev=139703&r1=139702&r2=139703&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/PathDiagnostic.cpp Wed Sep 14 12:48:01 2011
@@ -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 @@
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 @@
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 @@
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 @@
case Stmt::BinaryConditionalOperatorClass:
case Stmt::ConditionalOperatorClass:
case Stmt::ObjCForCollectionStmtClass: {
- SourceLocation L = S->getLocStart();
+ SourceLocation L = getValidSourceLocation(S, LC);
return SourceRange(L, L);
}
}
Modified: cfe/trunk/test/Analysis/plist-output-alternate.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/plist-output-alternate.m?rev=139703&r1=139702&r2=139703&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/plist-output-alternate.m (original)
+++ cfe/trunk/test/Analysis/plist-output-alternate.m Wed Sep 14 12:48:01 2011
@@ -317,6 +317,68 @@
// CHECK: <key>end</key>
// CHECK: <array>
// CHECK: <dict>
+// CHECK: <key>line</key><integer>22</integer>
+// CHECK: <key>col</key><integer>7</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>22</integer>
+// CHECK: <key>col</key><integer>8</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>kind</key><string>event</string>
+// CHECK: <key>location</key>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>22</integer>
+// CHECK: <key>col</key><integer>7</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <key>ranges</key>
+// CHECK: <array>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>22</integer>
+// CHECK: <key>col</key><integer>7</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>22</integer>
+// CHECK: <key>col</key><integer>8</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </array>
+// CHECK: <key>extended_message</key>
+// CHECK: <string>Assuming 'p' is null</string>
+// CHECK: <key>message</key>
+// CHECK: <string>Assuming 'p' is null</string>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>kind</key><string>control</string>
+// CHECK: <key>edges</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>start</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>22</integer>
+// CHECK: <key>col</key><integer>7</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>22</integer>
+// CHECK: <key>col</key><integer>8</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: <key>end</key>
+// CHECK: <array>
+// CHECK: <dict>
// CHECK: <key>line</key><integer>23</integer>
// CHECK: <key>col</key><integer>5</integer>
// CHECK: <key>file</key><integer>0</integer>
@@ -393,6 +455,68 @@
// CHECK: <key>end</key>
// CHECK: <array>
// CHECK: <dict>
+// CHECK: <key>line</key><integer>28</integer>
+// CHECK: <key>col</key><integer>7</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>28</integer>
+// CHECK: <key>col</key><integer>8</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>kind</key><string>event</string>
+// CHECK: <key>location</key>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>28</integer>
+// CHECK: <key>col</key><integer>7</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <key>ranges</key>
+// CHECK: <array>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>28</integer>
+// CHECK: <key>col</key><integer>7</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>28</integer>
+// CHECK: <key>col</key><integer>8</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </array>
+// CHECK: <key>extended_message</key>
+// CHECK: <string>Assuming 'q' is null</string>
+// CHECK: <key>message</key>
+// CHECK: <string>Assuming 'q' is null</string>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>kind</key><string>control</string>
+// CHECK: <key>edges</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>start</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>28</integer>
+// CHECK: <key>col</key><integer>7</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>28</integer>
+// CHECK: <key>col</key><integer>8</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: <key>end</key>
+// CHECK: <array>
+// CHECK: <dict>
// CHECK: <key>line</key><integer>29</integer>
// CHECK: <key>col</key><integer>5</integer>
// CHECK: <key>file</key><integer>0</integer>
@@ -743,6 +867,68 @@
// CHECK: <key>end</key>
// CHECK: <array>
// CHECK: <dict>
+// CHECK: <key>line</key><integer>54</integer>
+// CHECK: <key>col</key><integer>7</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>54</integer>
+// CHECK: <key>col</key><integer>7</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>kind</key><string>event</string>
+// CHECK: <key>location</key>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>54</integer>
+// CHECK: <key>col</key><integer>7</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <key>ranges</key>
+// CHECK: <array>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>54</integer>
+// CHECK: <key>col</key><integer>7</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>54</integer>
+// CHECK: <key>col</key><integer>7</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: </array>
+// CHECK: <key>extended_message</key>
+// CHECK: <string>Assuming 'x' is 0</string>
+// CHECK: <key>message</key>
+// CHECK: <string>Assuming 'x' is 0</string>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>kind</key><string>control</string>
+// CHECK: <key>edges</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>start</key>
+// CHECK: <array>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>54</integer>
+// CHECK: <key>col</key><integer>7</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: <dict>
+// CHECK: <key>line</key><integer>54</integer>
+// CHECK: <key>col</key><integer>7</integer>
+// CHECK: <key>file</key><integer>0</integer>
+// CHECK: </dict>
+// CHECK: </array>
+// CHECK: <key>end</key>
+// CHECK: <array>
+// CHECK: <dict>
// CHECK: <key>line</key><integer>56</integer>
// CHECK: <key>col</key><integer>10</integer>
// CHECK: <key>file</key><integer>0</integer>
@@ -832,4 +1018,3 @@
// CHECK: </array>
// CHECK: </dict>
// CHECK: </plist>
-
More information about the cfe-commits
mailing list