]> granicus.if.org Git - clang/commitdiff
Fix horrible non-termination bug in LiveVariables. The issue was that
authorTed Kremenek <kremenek@apple.com>
Fri, 30 Jan 2009 21:35:30 +0000 (21:35 +0000)
committerTed Kremenek <kremenek@apple.com>
Fri, 30 Jan 2009 21:35:30 +0000 (21:35 +0000)
the liveness state of block-level expressions could oscillate because
of two issues:
- The initial value before a merge was not always set to "Top"
- The set of live block-level expressions is a union, not an intersection

This fixes <rdar://problem/650084>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@63421 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Analysis/FlowSensitive/DataflowSolver.h
include/clang/Analysis/Support/BlkExprDeclBitVector.h
lib/Analysis/LiveVariables.cpp
test/Analysis/rdar-6540084.m [new file with mode: 0644]

index 0ed4c8667f16ffdb5e6fe5e1832bd97367f5ea7a..38612593368b60c74184dc25e16875d643b66135 100644 (file)
@@ -200,28 +200,9 @@ private:
     }
   }  
   
-  void ResetValues(CFG& cfg, ValTy& V, const CFGBlock* B,
-                   dataflow::forward_analysis_tag){
-    
-    if (B == &cfg.getEntry())
-      TF.SetTopValue(V);
-    else
-      V.resetValues(D.getAnalysisData());
-  }
-  
-  void ResetValues(CFG& cfg, ValTy& V, const CFGBlock* B,
-                   dataflow::backward_analysis_tag){
-    
-    if (B == &cfg.getExit())
-      TF.SetTopValue(V);
-    else
-      V.resetValues(D.getAnalysisData());
-  }
-
   void ProcessMerge(CFG& cfg, const CFGBlock* B) {
-
-    ValTy& V = TF.getVal();    
-    ResetValues(cfg, V, B, AnalysisDirTag());
+    ValTy& V = TF.getVal();  
+    TF.SetTopValue(V);
 
     // Merge dataflow values from all predecessors of this block.
     MergeOperatorTy Merge;
@@ -287,7 +268,6 @@ private:
     
   /// UpdateEdgeValue - Update the value associated with a given edge.
   void UpdateEdgeValue(BlockEdge E, ValTy& V, const CFGBlock* TargetBlock) {
-  
     EdgeDataMapTy& M = D.getEdgeDataMap();
     typename EdgeDataMapTy::iterator I = M.find(E);
       
index 5bd42332ba32dc98a7a13f0d1143db37cb068e66..a592be815419e8ab0b1e393e83acb973000800cf 100644 (file)
@@ -216,8 +216,7 @@ struct StmtDeclBitVector_Types {
     }
     
   public:
-    
-    
+
     void resetBlkExprValues(AnalysisDataTy& AD) {
       BlkExprBV.resize(AD.getNumBlkExprs());
       BlkExprBV.reset();
@@ -233,6 +232,11 @@ struct StmtDeclBitVector_Types {
       resetBlkExprValues(AD);
     }
     
+    void setValues(AnalysisDataTy& AD) {
+      setDeclValues(AD);
+      setBlkExprValues(AD);
+    }
+    
     bool operator==(const ValTy& RHS) const { 
       return ParentRef(*this) == ParentRef(RHS) 
           && BlkExprBV == RHS.BlkExprBV;
index 4c86d44e4db6d5d6215e36a539a21dd6a622ff82..23f6f461aa13ef3a712028ce52d0a31cb46d3101 100644 (file)
@@ -130,7 +130,7 @@ public:
   void VisitTerminator(CFGBlock* B); 
   
   void SetTopValue(LiveVariables::ValTy& V) {
-    V = AD.AlwaysLive;    
+    V = AD.AlwaysLive;
   }
   
 };
@@ -300,7 +300,7 @@ struct Merge {
     
   void operator()(ValTy& Dst, const ValTy& Src) {
     Dst.OrDeclBits(Src);
-    Dst.AndBlkExprBits(Src);
+    Dst.OrBlkExprBits(Src);
   }
 };
   
diff --git a/test/Analysis/rdar-6540084.m b/test/Analysis/rdar-6540084.m
new file mode 100644 (file)
index 0000000..e1347d9
--- /dev/null
@@ -0,0 +1,36 @@
+// RUN: clang -analyze -warn-dead-stores -verify %s
+//
+// This test exercises the live variables analysis (LiveVariables.cpp).
+// The case originally identified a non-termination bug.
+//
+typedef signed char BOOL;
+typedef unsigned int NSUInteger;
+typedef struct _NSZone NSZone;
+@protocol NSObject  - (BOOL)isEqual:(id)object; @end
+@interface NSObject <NSObject> {} @end
+extern id NSAllocateObject(Class aClass, NSUInteger extraBytes, NSZone *zone);
+@class NSArray;
+@class NSMutableArray, NSIndexSet, NSView, NSPredicate, NSString, NSViewAnimation, NSTimer;
+@interface FooBazController : NSObject {}
+@end
+typedef struct {} TazVersion;
+@class TazNode;
+@interface TazGuttenberg : NSObject {} typedef NSUInteger BugsBunnyType; @end
+@interface FooBaz : NSObject {}
+@property (nonatomic) BugsBunnyType matchType;
+@property (nonatomic, retain) NSArray *papyrus; @end
+@implementation FooBazController
+- (NSArray *)excitingStuff:(FooBaz *)options {
+  BugsBunnyType matchType = options.matchType;
+  NSPredicate *isSearchablePredicate = [NSPredicate predicateWithFormat:@"isSearchable == YES"]; // expected-warning{{return type defaults to 'id'}}
+  for (TazGuttenberg *Guttenberg in options.papyrus) {
+    NSArray *GuttenbergNodes = [Guttenberg nodes]; // expected-warning{{return type defaults to 'id'}}
+    NSArray *searchableNodes = [GuttenbergNodes filteredArrayUsingPredicate:isSearchablePredicate]; // expected-warning{{return type defaults to 'id'}}
+    for (TazNode *node in searchableNodes) {
+      switch (matchType) {
+        default: break;
+      }
+    }
+  }
+}
+@end