[cfe-commits] r42046 - in /cfe/trunk: Analysis/UnintializedValues.cpp include/clang/Analysis/LocalCheckers.h include/clang/Analysis/UninitializedValues.h include/clang/Basic/DiagnosticKinds.def

Ted Kremenek kremenek at apple.com
Mon Sep 17 12:59:27 PDT 2007


Author: kremenek
Date: Mon Sep 17 14:59:27 2007
New Revision: 42046

URL: http://llvm.org/viewvc/llvm-project?rev=42046&view=rev
Log:
More progress on UnitializedValues checker.  We now have preliminary support
for reporting errors and running the checker.

Modified:
    cfe/trunk/Analysis/UnintializedValues.cpp
    cfe/trunk/include/clang/Analysis/LocalCheckers.h
    cfe/trunk/include/clang/Analysis/UninitializedValues.h
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def

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

==============================================================================
--- cfe/trunk/Analysis/UnintializedValues.cpp (original)
+++ cfe/trunk/Analysis/UnintializedValues.cpp Mon Sep 17 14:59:27 2007
@@ -14,13 +14,18 @@
 #include "clang/Analysis/UninitializedValues.h"
 #include "clang/Analysis/CFGVarDeclVisitor.h"
 #include "clang/Analysis/CFGStmtVisitor.h"
+#include "clang/Analysis/LocalCheckers.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/AST/ASTContext.h"
 #include "DataflowSolver.h"
 
+#include "llvm/ADT/SmallPtrSet.h"
+
 using namespace clang;
 
-//===--------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
 // Dataflow initialization logic.
-//===--------------------------------------------------------------------===//      
+//===----------------------------------------------------------------------===//      
 
 namespace {
 
@@ -52,9 +57,9 @@
   V.ExprBV.resize(getAnalysisData().NumBlockExprs);
 }
 
-//===--------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
 // Transfer functions.
-//===--------------------------------------------------------------------===//      
+//===----------------------------------------------------------------------===//      
 
 namespace {
 
@@ -75,15 +80,19 @@
   bool VisitStmt(Stmt* S);
   bool VisitCallExpr(CallExpr* C);
   bool BlockStmt_VisitExpr(Expr* E);
+  bool VisitDeclStmt(DeclStmt* D);
   
   static inline bool Initialized() { return true; }
-  static inline bool Unintialized() { return false; }
+  static inline bool Uninitialized() { 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.");
+    if (AD.Observer)
+      AD.Observer->ObserveDeclRefExpr(V,AD,DR,VD);
+      
     return V.DeclBV[ AD.VMap[VD] ];    
   }
   else
@@ -95,10 +104,38 @@
     assert ( AD.EMap.find(B) != AD.EMap.end() && "Unknown block-level expr.");
     return V.ExprBV[ AD.EMap[B] ];
   }
-
+  
+  if (B->isAssignmentOp()) {
+    // Get the Decl for the LHS, if any
+    for (Stmt* S  = B->getLHS() ;; ) {
+      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.");
+          return V.DeclBV[ AD.VMap[VD] ] = Visit(B->getRHS());
+        }
+  
+      break;
+    }
+  }
+  
   return VisitStmt(B);
 }
 
+bool TransferFuncs::VisitDeclStmt(DeclStmt* S) {
+  bool x = Initialized();
+  
+  for (ScopedDecl* D = S->getDecl(); D != NULL; D = D->getNextDeclarator())
+    if (VarDecl* VD = dyn_cast<VarDecl>(D))
+      if (Stmt* I = VD->getInit()) {
+        assert ( AD.VMap.find(VD) != AD.VMap.end() && "Unknown VarDecl.");
+        x = V.DeclBV[ AD.VMap[VD] ] = Visit(I);
+      }
+      
+  return x;
+}
+
 bool TransferFuncs::VisitCallExpr(CallExpr* C) {
   VisitStmt(C);
   return Initialized();
@@ -140,8 +177,8 @@
   // 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();
+    if (Visit(*I) == Uninitialized())
+      x = Uninitialized();
   
   return x;
 }
@@ -153,7 +190,7 @@
   
 } // end anonymous namespace
 
-//===--------------------------------------------------------------------===//
+//===----------------------------------------------------------------------===//
 // Merge operator.
 //
 //  In our transfer functions we take the approach that any
@@ -171,7 +208,7 @@
 //  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 {
@@ -190,24 +227,50 @@
 };
 } // end anonymous namespace
 
-//===--------------------------------------------------------------------===//
-// External interface (driver logic).
-//===--------------------------------------------------------------------===//      
+//===----------------------------------------------------------------------===//
+// Unitialized values checker.   Scan an AST and flag variable uses
+//===----------------------------------------------------------------------===//      
 
-void UninitializedValues::CheckUninitializedValues(const CFG& cfg) {
+UninitializedValues_ValueTypes::ObserverTy::~ObserverTy() {}
 
-  typedef DataflowSolver<UninitializedValues,TransferFuncs,Merge> Solver;
+namespace {
 
-  UninitializedValues U;
+class UninitializedValuesChecker : public UninitializedValues::ObserverTy {
+  ASTContext &Ctx;
+  Diagnostic &Diags;
+  llvm::SmallPtrSet<VarDecl*,10> AlreadyWarned;
   
-  { // Compute the unitialized values information.
-    Solver S(U);
-    S.runOnCFG(cfg);
+public:
+  UninitializedValuesChecker(ASTContext &ctx, Diagnostic &diags)
+    : Ctx(ctx), Diags(diags) {}
+    
+  virtual void ObserveDeclRefExpr(UninitializedValues::ValTy& V,
+                                  UninitializedValues::AnalysisDataTy& AD,
+                                  DeclRefExpr* DR, VarDecl* VD) {
+
+    assert ( AD.VMap.find(VD) != AD.VMap.end() && "Unknown VarDecl.");
+    if (V.DeclBV[ AD.VMap[VD] ] == TransferFuncs::Uninitialized())
+      if (AlreadyWarned.insert(VD))
+        Diags.Report(DR->getSourceRange().Begin(), diag::warn_uninit_val);
   }
+};
+
+} // end anonymous namespace
+
 
-//  WarnObserver O;
+void CheckUninitializedValues(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags) {
+
+  typedef DataflowSolver<UninitializedValues,TransferFuncs,Merge> Solver;
+  
+  // Compute the unitialized values information.
+  UninitializedValues U;
   Solver S(U);
-    
-  for (CFG::const_iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I)
+  S.runOnCFG(cfg);
+  
+  // Scan for DeclRefExprs that use uninitialized values.
+  UninitializedValuesChecker Observer(Ctx,Diags);
+  U.getAnalysisData().Observer = &Observer;
+
+  for (CFG::iterator I=cfg.begin(), E=cfg.end(); I!=E; ++I)
     S.runOnBlock(&*I);
 }

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

==============================================================================
--- cfe/trunk/include/clang/Analysis/LocalCheckers.h (original)
+++ cfe/trunk/include/clang/Analysis/LocalCheckers.h Mon Sep 17 14:59:27 2007
@@ -25,6 +25,10 @@
                      ASTContext &Ctx, Diagnostic &Diags);
 void CheckDeadStores(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags);  
 
+  
+void CheckUninitializedValues(CFG& cfg, ASTContext& Ctx, Diagnostic& Diags);
+
+
 } // end namespace clang
 
 #endif

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

==============================================================================
--- cfe/trunk/include/clang/Analysis/UninitializedValues.h (original)
+++ cfe/trunk/include/clang/Analysis/UninitializedValues.h Mon Sep 17 14:59:27 2007
@@ -22,12 +22,18 @@
 
   class VarDecl;
   class Expr;
+  class DeclRefExpr;
 
 /// UninitializedValues_ValueTypes - Utility class to wrap type declarations
 ///   for dataflow values and dataflow analysis state for the
 ///   Unitialized Values analysis.
 class UninitializedValues_ValueTypes {
 public:
+
+  //===--------------------------------------------------------------------===//
+  // ValTy - Dataflow value.
+  //===--------------------------------------------------------------------===//
+  
   struct ValTy {
     llvm::BitVector DeclBV;
     llvm::BitVector ExprBV;
@@ -48,36 +54,45 @@
     }    
   };
   
+  //===--------------------------------------------------------------------===//
+  // AnalysisDataTy - Whole-function meta data used by the transfer function
+  //  logic.
+  //===--------------------------------------------------------------------===//
+  
+  struct ObserverTy;
+  
   struct AnalysisDataTy {
     llvm::DenseMap<const VarDecl*, unsigned > VMap;
     llvm::DenseMap<const Expr*, unsigned > EMap;
     unsigned NumDecls;
     unsigned NumBlockExprs;
+    ObserverTy* Observer;
     
-    AnalysisDataTy() : NumDecls(0), NumBlockExprs(0) {}
+    AnalysisDataTy() : NumDecls(0), NumBlockExprs(0), Observer(NULL) {}
   };
+  
+  //===--------------------------------------------------------------------===//
+  // ObserverTy - Observer for querying DeclRefExprs that use an uninitalized
+  //   value.
+  //===--------------------------------------------------------------------===//
+  
+  struct ObserverTy {
+    virtual ~ObserverTy();
+    virtual void ObserveDeclRefExpr(ValTy& Val, AnalysisDataTy& AD, 
+                                    DeclRefExpr* DR, VarDecl* VD) = 0;
+  };  
 };
 
 /// UninitializedValues - Objects of this class encapsulate dataflow analysis
 ///  information regarding what variable declarations in a function are
 ///  potentially unintialized.
 class UninitializedValues : 
-  public DataflowValues<UninitializedValues_ValueTypes> {
-  
-  //===--------------------------------------------------------------------===//
-  // Public interface.
-  //===--------------------------------------------------------------------===//      
-    
-  static void CheckUninitializedValues(const CFG& cfg);
+  public DataflowValues<UninitializedValues_ValueTypes> {  
+public:
+  typedef UninitializedValues_ValueTypes::ObserverTy ObserverTy;
 
-  //===--------------------------------------------------------------------===//
-  // Internal logic.
-  //===--------------------------------------------------------------------===//      
-  
-private:
   UninitializedValues() {}
   
-public:
   /// IntializeValues - Create initial dataflow values and meta data for
   ///  a given CFG.  This is intended to be called by the dataflow solver.
   void InitializeValues(const CFG& cfg);

Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=42046&r1=42045&r2=42046&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Mon Sep 17 14:59:27 2007
@@ -753,6 +753,9 @@
 // CHECK: stores to variables that are no longer live (dead stores)
 DIAG(warn_dead_store, WARNING, "value stored to variable is never used")
 
+// CHECK: use of uninitialized values
+DIAG(warn_uninit_val, WARNING, "use of potentially uninitialized variable")
+
 // CFString checking
 DIAG(err_cfstring_literal_not_string_constant, ERROR,
   "CFString literal is not a string constant")





More information about the cfe-commits mailing list