]> granicus.if.org Git - clang/commitdiff
Fix bug in terminator processing for uninitialized-values: simply ignore the terminat...
authorTed Kremenek <kremenek@apple.com>
Tue, 15 Apr 2008 18:35:30 +0000 (18:35 +0000)
committerTed Kremenek <kremenek@apple.com>
Tue, 15 Apr 2008 18:35:30 +0000 (18:35 +0000)
LiveVariables analysis now does a flow-insensitive analysis to determine what variables have their address taken; these variables are now always treated as being live.

The DataflowSolver now uses "SetTopValue()" when getting the initial value for the entry/exit block.

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

include/clang/Analysis/Analyses/LiveVariables.h
include/clang/Analysis/FlowSensitive/DataflowSolver.h
lib/Analysis/LiveVariables.cpp
lib/Analysis/UninitializedValues.cpp

index f172df62e8169bc882e8c2d3a801385892153807..6571c73ab7230c1022c9d49665dd77701dea880f 100644 (file)
@@ -28,6 +28,8 @@ struct LiveVariables_ValueTypes {
 
   struct ObserverTy;
 
+  // We keep dataflow state for declarations and block-level expressions;
+  typedef ExprDeclBitVector_Types::ValTy ValTy;
 
   // We need to keep track of both declarations and CFGBlock-level expressions,
   // (so that we don't explore such expressions twice).  We also want
@@ -36,12 +38,10 @@ struct LiveVariables_ValueTypes {
   
   struct AnalysisDataTy : public ExprDeclBitVector_Types::AnalysisDataTy {
     ObserverTy* Observer;
+    ValTy AlwaysLive;
     
     AnalysisDataTy() : Observer(NULL) {}
   };
-
-    // We only keep actual dataflow state for declarations.
-  typedef ExprDeclBitVector_Types::ValTy ValTy;
   
   //===-----------------------------------------------------===//
   // ObserverTy - Observer for uninitialized values queries.
@@ -61,6 +61,8 @@ struct LiveVariables_ValueTypes {
 
 class LiveVariables : public DataflowValues<LiveVariables_ValueTypes,
                                             dataflow::backward_analysis_tag> {
+                                              
+                                              
 public:
   typedef LiveVariables_ValueTypes::ObserverTy ObserverTy;
     
index 7a19c19119ccaa4a6f6072af042752cfbbcebd30..9cf77cf1445b19049c1d728457fe57d26411ffd3 100644 (file)
@@ -204,11 +204,31 @@ private:
   void EnqueueFirstBlock(const CFG& cfg, dataflow::backward_analysis_tag) {
     WorkList.enqueue(&cfg.getExit());
   }  
+  
+  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());
+
     // Merge dataflow values from all predecessors of this block.
-    ValTy& V = TF.getVal();
-    V.resetValues(D.getAnalysisData());
     MergeOperatorTy Merge;
     
     EdgeDataMapTy& M = D.getEdgeDataMap();
index 4cef30cab8214d445e105d6b78bd91ff5de9f78d..7896bfcfb0a647236fae0ed3d45f06746a6fef9d 100644 (file)
@@ -19,6 +19,7 @@
 #include "clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h"
 #include "clang/Analysis/FlowSensitive/DataflowSolver.h"
 #include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/Compiler.h"
 
 #include <string.h>
 
 using namespace clang;
 
+//===----------------------------------------------------------------------===//
+// Useful constants.
+//===----------------------------------------------------------------------===//      
+
+static const bool Alive = true;
+static const bool Dead = false; 
+
 //===----------------------------------------------------------------------===//
 // Dataflow initialization logic.
 //===----------------------------------------------------------------------===//      
@@ -35,9 +43,49 @@ class VISIBILITY_HIDDEN RegisterDecls
   : public CFGRecStmtDeclVisitor<RegisterDecls> {
     
   LiveVariables::AnalysisDataTy& AD;
+  
+  typedef llvm::SmallVector<VarDecl*, 20> AlwaysLiveTy;
+  AlwaysLiveTy AlwaysLive;
+
+    
 public:
-  RegisterDecls(LiveVariables::AnalysisDataTy& ad) : AD(ad) {}  
-  void VisitVarDecl(VarDecl* VD) { AD.Register(VD); }
+  RegisterDecls(LiveVariables::AnalysisDataTy& ad) : AD(ad) {}
+
+  ~RegisterDecls() {
+
+    AD.AlwaysLive.resetValues(AD);
+    
+    for (AlwaysLiveTy::iterator I = AlwaysLive.begin(), E = AlwaysLive.end();
+         I != E; ++ I)       
+      AD.AlwaysLive(*I, AD) = Alive;      
+  }
+
+  void VisitVarDecl(VarDecl* VD) {
+    // Register the VarDecl for tracking.
+    AD.Register(VD);
+    
+    // Does the variable have global storage?  If so, it is always live.
+    if (VD->hasGlobalStorage())
+      AlwaysLive.push_back(VD);    
+  }
+  
+  void VisitUnaryOperator(UnaryOperator* U) {
+    // Check for '&'.  Any VarDecl whose value has its address-taken we
+    // treat as always being live (flow-insensitive).
+
+    Expr* E = U->getSubExpr()->IgnoreParenCasts();
+    
+    if (U->getOpcode() == UnaryOperator::AddrOf)
+      if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(E))
+        if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) {
+          AD.Register(VD);
+          AlwaysLive.push_back(VD);
+          return;
+        }
+      
+    Visit(E);
+  }
+    
   CFG& getCFG() { return AD.getCFG(); }
 };
 } // end anonymous namespace
@@ -55,9 +103,6 @@ LiveVariables::LiveVariables(CFG& cfg) {
 //===----------------------------------------------------------------------===//      
 
 namespace {
-  
-static const bool Alive = true;
-static const bool Dead = false;  
 
 class VISIBILITY_HIDDEN TransferFuncs : public CFGRecStmtVisitor<TransferFuncs>{
   LiveVariables::AnalysisDataTy& AD;
@@ -75,6 +120,11 @@ public:
   void VisitUnaryOperator(UnaryOperator* U);
   void Visit(Stmt *S);  
   void VisitTerminator(Stmt* S); 
+  
+  void SetTopValue(LiveVariables::ValTy& V) {
+    V = AD.AlwaysLive;    
+  }
+  
 };
       
 void TransferFuncs::Visit(Stmt *S) {
@@ -151,7 +201,11 @@ void TransferFuncs::VisitAssign(BinaryOperator* B) {
 
   // Assigning to a variable?
   if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(LHS->IgnoreParens())) {
-    LiveState(DR->getDecl(), AD) = Dead;
+    
+    // Update liveness inforamtion.
+    unsigned bit = AD.getIdx(DR->getDecl());
+    LiveState.getDeclBit(bit) = Dead | AD.AlwaysLive.getDeclBit(bit);
+    
     if (AD.Observer) { AD.Observer->ObserverKill(DR); }
     
     // Handle things like +=, etc., which also generate "uses"
@@ -170,7 +224,10 @@ void TransferFuncs::VisitDeclStmt(DeclStmt* DS) {
   // possibly be live before they are declared.
   for (ScopedDecl* D = DS->getDecl(); D != NULL; D = D->getNextDeclarator())
     if (VarDecl* VD = dyn_cast<VarDecl>(D)) {
-      LiveState(D, AD) = Dead;
+      
+      // Update liveness information.
+      unsigned bit = AD.getIdx(VD);
+      LiveState.getDeclBit(bit) = Dead | AD.AlwaysLive.getDeclBit(bit);
       
       if (Expr* Init = VD->getInit())
         Visit(Init);
index d5c697aa1c8d4849e75ef04ee30c73cba7952138..2116e505d5172d9751916b7c7634b2cf1df0852e 100644 (file)
@@ -58,13 +58,15 @@ class VISIBILITY_HIDDEN TransferFuncs
   UninitializedValues::ValTy V;
   UninitializedValues::AnalysisDataTy& AD;
 public:
-  TransferFuncs(UninitializedValues::AnalysisDataTy& ad) : AD(ad) {
-    V.resetValues(AD);
-  }
+  TransferFuncs(UninitializedValues::AnalysisDataTy& ad) : AD(ad) {}
   
   UninitializedValues::ValTy& getVal() { return V; }
   CFG& getCFG() { return AD.getCFG(); }
   
+  void SetTopValue(UninitializedValues::ValTy& X) {
+    X.resetValues(AD);
+  }
+    
   bool VisitDeclRefExpr(DeclRefExpr* DR);
   bool VisitBinaryOperator(BinaryOperator* B);
   bool VisitUnaryOperator(UnaryOperator* U);
@@ -76,7 +78,7 @@ public:
   bool Visit(Stmt *S);
   bool BlockStmt_VisitExpr(Expr* E);
     
-  void VisitTerminator(Stmt* T) { Visit(T); }
+  void VisitTerminator(Stmt* T) { }
   
   BlockVarDecl* FindBlockVarDecl(Stmt* S);
 };
@@ -216,12 +218,9 @@ bool TransferFuncs::BlockStmt_VisitExpr(Expr* E) {
 //  In our transfer functions we take the approach that any
 //  combination of unintialized values, e.g. Unitialized + ___ = Unitialized.
 //
-//  Merges take the opposite approach.
-//
-//  In the merge of dataflow values we prefer unsoundness, and
-//  prefer false negatives to false positives.  At merges, if a value for a
-//  tracked Decl is EVER initialized in any of the predecessors we treat it as
-//  initialized at the confluence point.
+//  Merges take the same approach, preferring soundness.  At a confluence point,
+//  if any predecessor has a variable marked uninitialized, the value is
+//  uninitialized at the confluence point.
 //===----------------------------------------------------------------------===//      
 
 namespace {