diff options
-rw-r--r-- | include/clang/Analysis/FlowSensitive/DataflowSolver.h | 24 | ||||
-rw-r--r-- | include/clang/Analysis/Support/BlkExprDeclBitVector.h | 8 | ||||
-rw-r--r-- | lib/Analysis/LiveVariables.cpp | 4 | ||||
-rw-r--r-- | test/Analysis/rdar-6540084.m | 36 |
4 files changed, 46 insertions, 26 deletions
diff --git a/include/clang/Analysis/FlowSensitive/DataflowSolver.h b/include/clang/Analysis/FlowSensitive/DataflowSolver.h index 0ed4c8667f..3861259336 100644 --- a/include/clang/Analysis/FlowSensitive/DataflowSolver.h +++ b/include/clang/Analysis/FlowSensitive/DataflowSolver.h @@ -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); diff --git a/include/clang/Analysis/Support/BlkExprDeclBitVector.h b/include/clang/Analysis/Support/BlkExprDeclBitVector.h index 5bd42332ba..a592be8154 100644 --- a/include/clang/Analysis/Support/BlkExprDeclBitVector.h +++ b/include/clang/Analysis/Support/BlkExprDeclBitVector.h @@ -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; diff --git a/lib/Analysis/LiveVariables.cpp b/lib/Analysis/LiveVariables.cpp index 4c86d44e4d..23f6f461aa 100644 --- a/lib/Analysis/LiveVariables.cpp +++ b/lib/Analysis/LiveVariables.cpp @@ -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 index 0000000000..e1347d92eb --- /dev/null +++ b/test/Analysis/rdar-6540084.m @@ -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 |