[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