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

Ted Kremenek kremenek at apple.com
Thu Sep 27 17:09:39 PDT 2007


Author: kremenek
Date: Thu Sep 27 19:09:38 2007
New Revision: 42421

URL: http://llvm.org/viewvc/llvm-project?rev=42421&view=rev
Log:
Fixed several bugs in the propagation of "uninitialized value"
taintness across expressions.

Made "smart-culling" of taint propagation (for error reporting)
correctly handle conditional expressions and a few other edge cases.

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

Modified: cfe/trunk/Analysis/UninitializedValues.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/UninitializedValues.cpp?rev=42421&r1=42420&r2=42421&view=diff

==============================================================================
--- cfe/trunk/Analysis/UninitializedValues.cpp (original)
+++ cfe/trunk/Analysis/UninitializedValues.cpp Thu Sep 27 19:09:38 2007
@@ -53,11 +53,8 @@
 class TransferFuncs : public CFGStmtVisitor<TransferFuncs,bool> {
   UninitializedValues::ValTy V;
   UninitializedValues::AnalysisDataTy& AD;
-  bool InitWithAssigns;
 public:
-  TransferFuncs(UninitializedValues::AnalysisDataTy& ad, 
-                bool init_with_assigns=true) : 
-    AD(ad), InitWithAssigns(init_with_assigns) {
+  TransferFuncs(UninitializedValues::AnalysisDataTy& ad) : AD(ad) {
     V.resetValues(AD);
   }
   
@@ -68,8 +65,11 @@
   bool VisitUnaryOperator(UnaryOperator* U);
   bool VisitStmt(Stmt* S);
   bool VisitCallExpr(CallExpr* C);
-  bool BlockStmt_VisitExpr(Expr* E);
   bool VisitDeclStmt(DeclStmt* D);
+  bool VisitConditionalOperator(ConditionalOperator* C);
+  
+  bool Visit(Stmt *S);
+  bool BlockStmt_VisitExpr(Expr* E);
   
   BlockVarDecl* FindBlockVarDecl(Stmt* S);
 };
@@ -81,64 +81,47 @@
 bool TransferFuncs::VisitDeclRefExpr(DeclRefExpr* DR) {
   if (BlockVarDecl* VD = dyn_cast<BlockVarDecl>(DR->getDecl())) {
     if (AD.Observer) AD.Observer->ObserveDeclRefExpr(V,AD,DR,VD);
-      
-    return V(VD,AD);
+     
+    // Pseudo-hack to prevent cascade of warnings.  If an accessed variable
+    // is uninitialized, then we are already going to flag a warning for
+    // this variable, which a "source" of uninitialized values.
+    // We can otherwise do a full "taint" of uninitialized values.  The
+    // client has both options by toggling AD.FullUninitTaint.
+
+    return AD.FullUninitTaint ? V(VD,AD) : Initialized;
   }
   else return Initialized;
 }
 
 BlockVarDecl* TransferFuncs::FindBlockVarDecl(Stmt *S) {
-  for (;;) {
+  for (;;)
     if (ParenExpr* P = dyn_cast<ParenExpr>(S)) {
-      S = P->getSubExpr();
-      continue;
+      S = P->getSubExpr(); continue;
     }
-    else if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S))
+    else if (DeclRefExpr* DR = dyn_cast<DeclRefExpr>(S)) {
       if (BlockVarDecl* VD = dyn_cast<BlockVarDecl>(DR->getDecl()))
         return VD;
-
-    return NULL;
-  }          
+    }
+    else return NULL;
 }
 
 bool TransferFuncs::VisitBinaryOperator(BinaryOperator* B) {
-
-  if (CFG::hasImplicitControlFlow(B))
-    return V(B,AD);
-  
   if (B->isAssignmentOp())
-    // Get the Decl for the LHS (if any).
     if (BlockVarDecl* VD = FindBlockVarDecl(B->getLHS()))
-      if(InitWithAssigns) {
-        // Pseudo-hack to prevent cascade of warnings.  If the RHS uses
-        // an uninitialized value, then we are already going to flag a warning
-        // for the RHS, or for the root "source" of the unintialized values.  
-        // Thus, propogating uninitialized doesn't make sense, since we are
-        // just adding extra messages that don't
-        // contribute to diagnosing the bug.  In InitWithAssigns mode
-        // we unconditionally set the assigned variable to Initialized to
-        // prevent Uninitialized propagation.
-        return V(VD,AD) = Initialized;
-      }
-      else return V(VD,AD) = Visit(B->getRHS());
+      return V(VD,AD) = AD.FullUninitTaint ? Visit(B->getRHS()) : Initialized;
   
   return VisitStmt(B);
 }
 
 bool TransferFuncs::VisitDeclStmt(DeclStmt* S) {
-  bool x = Initialized;
-  
   for (ScopedDecl* D = S->getDecl(); D != NULL; D = D->getNextDeclarator())
     if (BlockVarDecl* VD = dyn_cast<BlockVarDecl>(D)) {
-      if (Stmt* I = VD->getInit())
-        x = InitWithAssigns ? Initialized : V(cast<Expr>(I),AD);
-      else
-        x = Uninitialized;
-      
-      V(VD,AD) = x;
+      if (Stmt* I = VD->getInit()) 
+        V(VD,AD) = AD.FullUninitTaint ? V(cast<Expr>(I),AD) : Initialized;
+      else V(VD,AD) = Uninitialized;
     }
       
-  return x;
+  return Uninitialized; // Value is never consumed.
 }
 
 bool TransferFuncs::VisitCallExpr(CallExpr* C) {
@@ -147,17 +130,16 @@
 }
 
 bool TransferFuncs::VisitUnaryOperator(UnaryOperator* U) {
-  switch (U->getOpcode()) {
-    case UnaryOperator::AddrOf:
-      // For "&x", treat "x" as now being initialized.
-      if (BlockVarDecl* VD = FindBlockVarDecl(U->getSubExpr()))
-        V(VD,AD) = Initialized;
-      else 
-        return Visit(U->getSubExpr());
-
-    default:
-      return Visit(U->getSubExpr());
-  }      
+  if (U->getOpcode() == UnaryOperator::AddrOf)
+    if (BlockVarDecl* VD = FindBlockVarDecl(U->getSubExpr()))
+      return V(VD,AD) = Initialized;
+
+  return Visit(U->getSubExpr());
+}
+  
+bool TransferFuncs::VisitConditionalOperator(ConditionalOperator* C) {
+  Visit(C->getCond());
+  return Visit(C->getLHS()) & Visit(C->getRHS());  // Yes: we want &, not &&.
 }
 
 bool TransferFuncs::VisitStmt(Stmt* S) {
@@ -167,14 +149,20 @@
   // 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) == Uninitialized) x = Uninitialized;
+    if (*I && Visit(*I) == Uninitialized) x = Uninitialized;
   
   return x;
 }
+  
+bool TransferFuncs::Visit(Stmt *S) {
+  if (AD.isTracked(static_cast<Expr*>(S))) return V(static_cast<Expr*>(S),AD);
+  else return static_cast<CFGStmtVisitor<TransferFuncs,bool>*>(this)->Visit(S);
+}
 
 bool TransferFuncs::BlockStmt_VisitExpr(Expr* E) {
   assert (AD.isTracked(E));
-  return V(E,AD) = Visit(E);
+  return V(E,AD) = 
+    static_cast<CFGStmtVisitor<TransferFuncs,bool>*>(this)->Visit(E);
 }
   
 } // end anonymous namespace
@@ -228,10 +216,12 @@
 } // end anonymous namespace
 
 namespace clang {
-void CheckUninitializedValues(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags) {
+void CheckUninitializedValues(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags,
+                              bool FullUninitTaint) {
   
   // Compute the unitialized values information.
   UninitializedValues U;
+  U.getAnalysisData().FullUninitTaint = FullUninitTaint;
   Solver S(U);
   S.runOnCFG(cfg);
   

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

==============================================================================
--- cfe/trunk/include/clang/Analysis/LocalCheckers.h (original)
+++ cfe/trunk/include/clang/Analysis/LocalCheckers.h Thu Sep 27 19:09:38 2007
@@ -22,7 +22,8 @@
 class ASTContext;
 
 void CheckDeadStores(CFG& cfg, ASTContext &Ctx, Diagnostic &Diags);  
-void CheckUninitializedValues(CFG& cfg, ASTContext& Ctx, Diagnostic& Diags);
+void CheckUninitializedValues(CFG& cfg, ASTContext& Ctx, Diagnostic& Diags,
+                              bool FullUninitTaint=false);
 
 
 } // end namespace clang

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

==============================================================================
--- cfe/trunk/include/clang/Analysis/UninitializedValues.h (original)
+++ cfe/trunk/include/clang/Analysis/UninitializedValues.h Thu Sep 27 19:09:38 2007
@@ -34,10 +34,11 @@
   struct ObserverTy;
   
   struct AnalysisDataTy : public ExprDeclBitVector_Types::AnalysisDataTy {    
-    AnalysisDataTy() : Observer(NULL) {}
+    AnalysisDataTy() : Observer(NULL), FullUninitTaint(true) {}
     virtual ~AnalysisDataTy() {};
     
     ObserverTy* Observer;
+    bool FullUninitTaint;
   };
   
   typedef ExprDeclBitVector_Types::ValTy ValTy;





More information about the cfe-commits mailing list