[cfe-commits] r128761 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp lib/StaticAnalyzer/Core/ExprEngine.cpp test/Analysis/idempotent-operations.cpp

Ted Kremenek kremenek at apple.com
Fri Apr 1 19:56:23 PDT 2011


Author: kremenek
Date: Fri Apr  1 21:56:23 2011
New Revision: 128761

URL: http://llvm.org/viewvc/llvm-project?rev=128761&view=rev
Log:
Teach IdempotentOperationsChecker about paths aborted because ExprEngine didn't know how to handle a specific Expr type.

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
    cfe/trunk/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/test/Analysis/idempotent-operations.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h?rev=128761&r1=128760&r2=128761&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h Fri Apr  1 21:56:23 2011
@@ -48,6 +48,10 @@
 public:
   typedef std::vector<std::pair<BlockEdge, const ExplodedNode*> >
             BlocksExhausted;
+  
+  typedef std::vector<std::pair<const CFGBlock*, const ExplodedNode*> >
+            BlocksAborted;
+
 private:
 
   SubEngine& SubEng;
@@ -68,6 +72,10 @@
   /// The locations where we stopped doing work because we visited a location
   ///  too many times.
   BlocksExhausted blocksExhausted;
+  
+  /// The locations where we stopped because the engine aborted analysis,
+  /// usually because it could not reason about something.
+  BlocksAborted blocksAborted;
 
   void generateNode(const ProgramPoint& Loc, const GRState* State,
                     ExplodedNode* Pred);
@@ -122,17 +130,32 @@
                                        ExplodedNodeSet &Dst);
 
   // Functions for external checking of whether we have unfinished work
-  bool wasBlockAborted() const { return !blocksExhausted.empty(); }
-  bool hasWorkRemaining() const { return wasBlockAborted() || WList->hasWork(); }
-
+  bool wasBlockAborted() const { return !blocksAborted.empty(); }
+  bool wasBlocksExhausted() const { return !blocksExhausted.empty(); }
+  bool hasWorkRemaining() const { return wasBlocksExhausted() || 
+                                         WList->hasWork() || 
+                                         wasBlockAborted(); }
+
+  /// Inform the CoreEngine that a basic block was aborted because
+  /// it could not be completely analyzed.
+  void addAbortedBlock(const ExplodedNode *node, const CFGBlock *block) {
+    blocksAborted.push_back(std::make_pair(block, node));
+  }
+  
   WorkList *getWorkList() const { return WList; }
 
-  BlocksExhausted::const_iterator blocks_aborted_begin() const {
+  BlocksExhausted::const_iterator blocks_exhausted_begin() const {
     return blocksExhausted.begin();
   }
-  BlocksExhausted::const_iterator blocks_aborted_end() const {
+  BlocksExhausted::const_iterator blocks_exhausted_end() const {
     return blocksExhausted.end();
   }
+  BlocksAborted::const_iterator blocks_aborted_begin() const {
+    return blocksAborted.begin();
+  }
+  BlocksAborted::const_iterator blocks_aborted_end() const {
+    return blocksAborted.end();
+  }
 };
 
 class StmtNodeBuilder {

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h?rev=128761&r1=128760&r2=128761&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h Fri Apr  1 21:56:23 2011
@@ -213,11 +213,9 @@
   const SymbolManager& getSymbolManager() const { return SymMgr; }
 
   // Functions for external checking of whether we have unfinished work
-  bool wasBlockAborted() const { return Engine.wasBlockAborted(); }
+  bool wasBlocksExhausted() const { return Engine.wasBlocksExhausted(); }
   bool hasEmptyWorkList() const { return !Engine.getWorkList()->hasWork(); }
-  bool hasWorkRemaining() const {
-    return wasBlockAborted() || Engine.getWorkList()->hasWork();
-  }
+  bool hasWorkRemaining() const { return Engine.hasWorkRemaining(); }
 
   const CoreEngine &getCoreEngine() const { return Engine; }
 

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp?rev=128761&r1=128760&r2=128761&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/AnalyzerStatsChecker.cpp Fri Apr  1 21:56:23 2011
@@ -88,8 +88,8 @@
   }
   
   output << " -> Total CFGBlocks: " << total << " | Unreachable CFGBlocks: "
-      << unreachable << " | Aborted Block: "
-      << (Eng.wasBlockAborted() ? "yes" : "no")
+      << unreachable << " | Exhausted Block: "
+      << (Eng.wasBlocksExhausted() ? "yes" : "no")
       << " | Empty WorkList: "
       << (Eng.hasEmptyWorkList() ? "yes" : "no");
 
@@ -97,10 +97,10 @@
       D->getLocation());
 
   // Emit warning for each block we bailed out on
-  typedef CoreEngine::BlocksExhausted::const_iterator AbortedIterator;
+  typedef CoreEngine::BlocksExhausted::const_iterator ExhaustedIterator;
   const CoreEngine &CE = Eng.getCoreEngine();
-  for (AbortedIterator I = CE.blocks_aborted_begin(),
-      E = CE.blocks_aborted_end(); I != E; ++I) {
+  for (ExhaustedIterator I = CE.blocks_exhausted_begin(),
+      E = CE.blocks_exhausted_end(); I != E; ++I) {
     const BlockEdge &BE =  I->first;
     const CFGBlock *Exit = BE.getDst();
     const CFGElement &CE = Exit->front();

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp?rev=128761&r1=128760&r2=128761&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp Fri Apr  1 21:56:23 2011
@@ -534,9 +534,9 @@
   CFGReverseBlockReachabilityAnalysis *CRA = AC->getCFGReachablityAnalysis();
   
   // Test for reachability from any aborted blocks to this block
-  typedef CoreEngine::BlocksExhausted::const_iterator AbortedIterator;
-  for (AbortedIterator I = CE.blocks_aborted_begin(),
-      E = CE.blocks_aborted_end(); I != E; ++I) {
+  typedef CoreEngine::BlocksExhausted::const_iterator ExhaustedIterator;
+  for (ExhaustedIterator I = CE.blocks_exhausted_begin(),
+      E = CE.blocks_exhausted_end(); I != E; ++I) {
     const BlockEdge &BE =  I->first;
 
     // The destination block on the BlockEdge is the first block that was not
@@ -550,6 +550,15 @@
     if (destBlock == CB || CRA->isReachable(destBlock, CB))
       return false;
   }
+
+  // Test for reachability from blocks we just gave up on.
+  typedef CoreEngine::BlocksAborted::const_iterator AbortedIterator;
+  for (AbortedIterator I = CE.blocks_aborted_begin(),
+       E = CE.blocks_aborted_end(); I != E; ++I) {
+    const CFGBlock *destBlock = I->first;
+    if (destBlock == CB || CRA->isReachable(destBlock, CB))
+      return false;
+  }
   
   // For the items still on the worklist, see if they are in blocks that
   // can eventually reach 'CB'.

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=128761&r1=128760&r2=128761&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Fri Apr  1 21:56:23 2011
@@ -444,7 +444,8 @@
     {
       SaveAndRestore<bool> OldSink(Builder->BuildSinks);
       Builder->BuildSinks = true;
-      MakeNode(Dst, S, Pred, GetState(Pred));
+      const ExplodedNode *node = MakeNode(Dst, S, Pred, GetState(Pred));
+      Engine.addAbortedBlock(node, Builder->getBlock());
       break;
     }
       

Modified: cfe/trunk/test/Analysis/idempotent-operations.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/idempotent-operations.cpp?rev=128761&r1=128760&r2=128761&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/idempotent-operations.cpp (original)
+++ cfe/trunk/test/Analysis/idempotent-operations.cpp Fri Apr  1 21:56:23 2011
@@ -13,3 +13,22 @@
    test(five * a); // expected-warning {{The right operand to '*' is always 0}}
    b = 4;
 }
+
+// Test not flagging idempotent operations because we aborted the analysis
+// of a path because of an unsupported construct.
+struct RDar9219143_Foo {
+  ~RDar9219143_Foo();
+  operator bool() const;
+};
+
+RDar9219143_Foo foo();
+unsigned RDar9219143_bar();
+void RDar9219143_test() {
+  unsigned i, e;
+  for (i = 0, e = RDar9219143_bar(); i != e; ++i)
+    if (foo())
+      break;  
+  if (i == e) // no-warning
+    return;
+}
+





More information about the cfe-commits mailing list