[cfe-commits] r42041 - in /cfe/trunk: Analysis/UnintializedValues.cpp include/clang/Analysis/UninitializedValues.h

Ted Kremenek kremenek at apple.com
Mon Sep 17 11:31:23 PDT 2007


Author: kremenek
Date: Mon Sep 17 13:31:23 2007
New Revision: 42041

URL: http://llvm.org/viewvc/llvm-project?rev=42041&view=rev
Log:
Split tracking of unitialized values for Decls and CFGBlock-level expressions.

Modified:
    cfe/trunk/Analysis/UnintializedValues.cpp
    cfe/trunk/include/clang/Analysis/UninitializedValues.h

Modified: cfe/trunk/Analysis/UnintializedValues.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/UnintializedValues.cpp?rev=42041&r1=42040&r2=42041&view=diff

==============================================================================
--- cfe/trunk/Analysis/UnintializedValues.cpp (original)
+++ cfe/trunk/Analysis/UnintializedValues.cpp Mon Sep 17 13:31:23 2007
@@ -33,12 +33,12 @@
   
   void VisitVarDecl(VarDecl* D) {
     if (AD.VMap.find(D) == AD.VMap.end())
-      AD.VMap[D] = AD.Counter++;
+      AD.VMap[D] = AD.NumDecls++;
   }
   
   void BlockStmt_VisitExpr(Expr* E) {
     if (AD.EMap.find(E) == AD.EMap.end())
-      AD.EMap[E] = AD.Counter++;
+      AD.EMap[E] = AD.NumBlockExprs++;
   }        
 };
   
@@ -47,7 +47,9 @@
 void UninitializedValues::InitializeValues(const CFG& cfg) {
   RegisterDeclsAndExprs R(cfg,this->getAnalysisData());
   R.VisitAllDecls();    
-  getBlockDataMap()[ &cfg.getEntry() ].resize( getAnalysisData().Counter );
+  UninitializedValues::ValTy& V = getBlockDataMap()[&cfg.getEntry()];
+  V.DeclBV.resize(getAnalysisData().NumDecls);
+  V.ExprBV.resize(getAnalysisData().NumBlockExprs);
 }
 
 //===--------------------------------------------------------------------===//
@@ -55,44 +57,140 @@
 //===--------------------------------------------------------------------===//      
 
 namespace {
+
 class TransferFuncs : public CFGStmtVisitor<TransferFuncs,bool> {
   UninitializedValues::ValTy V;
   UninitializedValues::AnalysisDataTy& AD;
 public:
   TransferFuncs(UninitializedValues::AnalysisDataTy& ad) : AD(ad) {
-    V.resize(AD.Counter);
+    V.DeclBV.resize(AD.NumDecls);
+    V.ExprBV.resize(AD.NumBlockExprs);
   }
   
   UninitializedValues::ValTy& getVal() { return V; }
   
-//  bool VisitDeclRefExpr(DeclRefExpr* DR);
-//  bool VisitBinaryOperator(BinaryOperator* B);
-//  bool VisitUnaryOperator(UnaryOperator* U);    
+  bool VisitDeclRefExpr(DeclRefExpr* DR);
+  bool VisitBinaryOperator(BinaryOperator* B);
+  bool VisitUnaryOperator(UnaryOperator* U);
+  bool VisitStmt(Stmt* S);
+  bool VisitCallExpr(CallExpr* C);
+  bool BlockStmt_VisitExpr(Expr* E);
+  
+  static inline bool Initialized() { return true; }
+  static inline bool Unintialized() { return false; }
 };
+
+
+bool TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) {
+  if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) {
+    assert ( AD.VMap.find(VD) != AD.VMap.end() && "Unknown VarDecl.");
+    return V.DeclBV[ AD.VMap[VD] ];    
+  }
+  else
+    return Initialized();
+}
+
+bool TransferFuncs::VisitBinaryOperator(BinaryOperator* B) {
+  if (CFG::hasImplicitControlFlow(B)) {
+    assert ( AD.EMap.find(B) != AD.EMap.end() && "Unknown block-level expr.");
+    return V.ExprBV[ AD.EMap[B] ];
+  }
+
+  return VisitStmt(B);
+}
+
+bool TransferFuncs::VisitCallExpr(CallExpr* C) {
+  VisitStmt(C);
+  return Initialized();
+}
+
+bool TransferFuncs::VisitUnaryOperator(UnaryOperator* U) {
+  switch (U->getOpcode()) {
+    case UnaryOperator::AddrOf: {
+      // Blast through parentheses and find the decl (if any).  Treat it
+      // as initialized from this point forward.
+      for (Stmt* S = U->getSubExpr() ;; )
+        if (ParenExpr* P = dyn_cast<ParenExpr>(S))
+          S = P->getSubExpr();
+        else if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S)) {
+          if (VarDecl* VD = dyn_cast<VarDecl>(DR->getDecl())) {
+            assert ( AD.VMap.find(VD) != AD.VMap.end() && "Unknown VarDecl.");
+            V.DeclBV[ AD.VMap[VD] ] = Initialized();
+          }
+          break;
+        }
+        else {
+          // Evaluate the transfer function for subexpressions, even
+          // if we cannot reason more deeply about the &-expression.
+          return Visit(U->getSubExpr());
+        }
+
+      return Initialized();
+    }
+
+    default:
+      return Visit(U->getSubExpr());
+  }      
+}
+
+bool TransferFuncs::VisitStmt(Stmt* S) {
+  bool x = Initialized();
+
+  // We don't stop at the first subexpression that is Uninitialized because
+  // evaluating some subexpressions may result in propogating "Uninitialized"
+  // or "Initialized" to variables referenced in the other subexpressions.
+  for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I)
+    if (Visit(*I) == Unintialized())
+      x = Unintialized();
+  
+  return x;
+}
+
+bool TransferFuncs::BlockStmt_VisitExpr(Expr* E) {
+  assert ( AD.EMap.find(E) != AD.EMap.end() );
+  return V.ExprBV[ AD.EMap[E] ] = Visit(E);
+}
+  
 } // end anonymous namespace
 
 //===--------------------------------------------------------------------===//
 // Merge operator.
+//
+//  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 (for Decls) 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.
+//
+//  For tracked CFGBlock-level expressions (such as the result of
+//  short-circuit), we do the opposite merge: if a value is EVER uninitialized
+//  in a predecessor we treat it as uninitalized at the confluence point.
+//  The reason we do this is because dataflow values for tracked Exprs are
+//  not as control-dependent as dataflow values for tracked Decls.
 //===--------------------------------------------------------------------===//      
 
 namespace {
 struct Merge {
   void operator()(UninitializedValues::ValTy& Dst,
                   UninitializedValues::ValTy& Src) {
-    assert (Dst.size() == Src.size() && "Bitvector sizes do not match.");
-    Src |= Dst;
+    assert (Dst.DeclBV.size() == Src.DeclBV.size() 
+            && "Bitvector sizes do not match.");
+            
+    Dst.DeclBV |= Src.DeclBV;
+    
+    assert (Dst.ExprBV.size() == Src.ExprBV.size()
+            && "Bitvector sizes do not match.");
+
+    Dst.ExprBV &= Src.ExprBV;
   }
 };
 } // end anonymous namespace
 
 //===--------------------------------------------------------------------===//
-// Observer to flag warnings for uses of uninitialized variables.
-//===--------------------------------------------------------------------===//      
-
-
-
-
-//===--------------------------------------------------------------------===//
 // External interface (driver logic).
 //===--------------------------------------------------------------------===//      
 

Modified: cfe/trunk/include/clang/Analysis/UninitializedValues.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/UninitializedValues.h?rev=42041&r1=42040&r2=42041&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/UninitializedValues.h (original)
+++ cfe/trunk/include/clang/Analysis/UninitializedValues.h Mon Sep 17 13:31:23 2007
@@ -28,27 +28,33 @@
 ///   Unitialized Values analysis.
 class UninitializedValues_ValueTypes {
 public:
-  class ValTy {
-    llvm::BitVector BV;
-  public:
-    // Accessors to internal bitvector.    
-    unsigned size() const { return BV.size(); }
-    void resize(unsigned i) { BV.resize(i); }
-    llvm::BitVector::reference operator[](unsigned i) { return BV[i]; }
-    void operator|=(const ValTy& RHS) { BV |= RHS.BV; }
-    
+  struct ValTy {
+    llvm::BitVector DeclBV;
+    llvm::BitVector ExprBV;
+
     // Used by the solver.
-    void resetValues() { BV.reset(); }
-    bool equal(ValTy& RHS) const { return BV == RHS.BV; }
-    void copyValues(ValTy& RHS) { BV = RHS.BV; }    
+    void resetValues() {
+      DeclBV.reset();
+      ExprBV.reset();
+    }
+    
+    bool equal(ValTy& RHS) const { 
+      return DeclBV == RHS.DeclBV && ExprBV == RHS.ExprBV; 
+    }
+    
+    void copyValues(ValTy& RHS) {
+      DeclBV = RHS.DeclBV;
+      ExprBV = RHS.ExprBV;
+    }    
   };
   
   struct AnalysisDataTy {
     llvm::DenseMap<const VarDecl*, unsigned > VMap;
     llvm::DenseMap<const Expr*, unsigned > EMap;
-    unsigned Counter;
+    unsigned NumDecls;
+    unsigned NumBlockExprs;
     
-    AnalysisDataTy() : Counter(0) {}
+    AnalysisDataTy() : NumDecls(0), NumBlockExprs(0) {}
   };
 };
 





More information about the cfe-commits mailing list