[cfe-commits] r97591 - in /cfe/trunk/lib: Analysis/CFG.cpp Analysis/UninitializedValues.cpp Checker/BasicStore.cpp

Ted Kremenek kremenek at apple.com
Tue Mar 2 13:43:55 PST 2010


Author: kremenek
Date: Tue Mar  2 15:43:54 2010
New Revision: 97591

URL: http://llvm.org/viewvc/llvm-project?rev=97591&view=rev
Log:
[CFG]

After discussion with Zhongxing, don't force the initializer of DeclStmts to be
block-level expressions.

This led to some interesting fallout:

[UninitializedValues]

Always visit the initializer of DeclStmts (do not assume they are block-level expressions).

[BasicStore]

With initializers of DeclStmts no longer block-level expressions, this causes self-referencing initializers (e.g. 'int x = x') to no longer cause the initialized variable to be live before the DeclStmt.  While this is correct, it caused BasicStore::RemoveDeadBindings() to prune off the values of these variables from the initial store (where they are set to uninitialized).  The fix is to back-port some (and only some) of the lazy-binding logic from RegionStore to
BasicStore.  Now the default values of local variables are determined lazily as opposed
to explicitly initialized.

Modified:
    cfe/trunk/lib/Analysis/CFG.cpp
    cfe/trunk/lib/Analysis/UninitializedValues.cpp
    cfe/trunk/lib/Checker/BasicStore.cpp

Modified: cfe/trunk/lib/Analysis/CFG.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFG.cpp?rev=97591&r1=97590&r2=97591&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CFG.cpp (original)
+++ cfe/trunk/lib/Analysis/CFG.cpp Tue Mar  2 15:43:54 2010
@@ -38,13 +38,21 @@
   
 class AddStmtChoice {
 public:
-  enum Kind { NotAlwaysAdd = 0, AlwaysAdd, AlwaysAddAsLValue };
+  enum Kind { NotAlwaysAdd = 0,
+              AlwaysAdd = 1,
+              AsLValueNotAlwaysAdd = 2,
+              AlwaysAddAsLValue = 3 };
+
 public:
-  AddStmtChoice(Kind kind) : k(kind) {}  
-  bool alwaysAdd() const { return k != NotAlwaysAdd; }
-  bool asLValue() const { return k == AlwaysAddAsLValue; }
+  AddStmtChoice(Kind k)
+    : AsLValue(k >= AlwaysAddAsLValue), AlwaysAddStmt((unsigned)k & 0x1) {}
+
+  bool alwaysAdd() const { return (bool) AlwaysAddStmt; };
+  bool asLValue() const { return (bool) AsLValue; };
+
 private:
-  Kind k;
+  unsigned AsLValue : 1;
+  unsigned AlwaysAddStmt : 1;
 };
 
 /// CFGBuilder - This class implements CFG construction from an AST.
@@ -771,18 +779,10 @@
   Expr *Init = VD->getInit();
 
   if (Init) {
-    // Optimization: Don't create separate block-level statements for literals.
-    switch (Init->getStmtClass()) {
-      case Stmt::IntegerLiteralClass:
-      case Stmt::CharacterLiteralClass:
-      case Stmt::StringLiteralClass:
-        break;
-      default:
-        Block = addStmt(Init,
-                        VD->getType()->isReferenceType()
-                        ? AddStmtChoice::AlwaysAddAsLValue
-                        : AddStmtChoice::AlwaysAdd);
-    }
+    AddStmtChoice::Kind k =
+      VD->getType()->isReferenceType() ? AddStmtChoice::AsLValueNotAlwaysAdd
+                                       : AddStmtChoice::NotAlwaysAdd;
+    Visit(Init, AddStmtChoice(k));
   }
 
   // If the type of VD is a VLA, then we must process its size expressions.

Modified: cfe/trunk/lib/Analysis/UninitializedValues.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/UninitializedValues.cpp?rev=97591&r1=97590&r2=97591&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/UninitializedValues.cpp (original)
+++ cfe/trunk/lib/Analysis/UninitializedValues.cpp Tue Mar  2 15:43:54 2010
@@ -134,8 +134,12 @@
   for (DeclStmt::decl_iterator I=S->decl_begin(), E=S->decl_end(); I!=E; ++I) {
     VarDecl *VD = dyn_cast<VarDecl>(*I);
     if (VD && VD->isBlockVarDecl()) {
-      if (Stmt* I = VD->getInit())
-        V(VD,AD) = AD.FullUninitTaint ? V(cast<Expr>(I),AD) : Initialized;
+      if (Stmt* I = VD->getInit()) {
+        // Visit the subexpression to check for uses of uninitialized values,
+        // even if we don't propagate that value.
+        bool isSubExprUninit = Visit(I);
+        V(VD,AD) = AD.FullUninitTaint ? isSubExprUninit : Initialized;
+      }
       else {
         // Special case for declarations of array types.  For things like:
         //

Modified: cfe/trunk/lib/Checker/BasicStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Checker/BasicStore.cpp?rev=97591&r1=97590&r2=97591&view=diff
==============================================================================
--- cfe/trunk/lib/Checker/BasicStore.cpp (original)
+++ cfe/trunk/lib/Checker/BasicStore.cpp Tue Mar  2 15:43:54 2010
@@ -95,6 +95,8 @@
              const char *sep);
 
 private:
+  SVal LazyRetrieve(Store store, const TypedRegion *R);
+
   ASTContext& getContext() { return StateMgr.getContext(); }
 };
 
@@ -126,6 +128,25 @@
   }
 }
 
+SVal BasicStoreManager::LazyRetrieve(Store store, const TypedRegion *R) {
+  const VarRegion *VR = dyn_cast<VarRegion>(R);
+  if (!VR)
+    return UnknownVal();
+
+  const VarDecl *VD = VR->getDecl();
+  QualType T = VD->getType();
+
+  // Only handle simple types that we can symbolicate.
+  if (!SymbolManager::canSymbolicate(T) || !T->isScalarType())
+    return UnknownVal();
+
+  // Globals and parameters start with symbolic values.
+  // Local variables initially are undefined.
+  if (VR->hasGlobalsOrParametersStorage())
+    return ValMgr.getRegionValueSymbolVal(R);
+  return UndefinedVal();
+}
+
 SVal BasicStoreManager::Retrieve(Store store, Loc loc, QualType T) {
   if (isa<UnknownVal>(loc))
     return UnknownVal();
@@ -142,11 +163,13 @@
 
       BindingsTy B = GetBindings(store);
       BindingsTy::data_type *Val = B.lookup(R);
+      const TypedRegion *TR = cast<TypedRegion>(R);
 
-      if (!Val)
-        break;
+      if (Val)
+        return CastRetrievedVal(*Val, TR, T);
 
-      return CastRetrievedVal(*Val, cast<TypedRegion>(R), T);
+      SVal V = LazyRetrieve(store, TR);
+      return V.isUnknownOrUndef() ? V : CastRetrievedVal(V, TR, T);
     }
 
     case loc::ConcreteIntKind:
@@ -353,8 +376,8 @@
           // SelfRegion?  (i.e., it implements MD->getClassInterface()).
           const VarRegion *VR = MRMgr.getVarRegion(PD, InitLoc);
           const MemRegion *SelfRegion =
-            ValMgr.getRegionValueSymbolVal(VR).getAsRegion();          
-          assert(SelfRegion);          
+            ValMgr.getRegionValueSymbolVal(VR).getAsRegion();
+          assert(SelfRegion);
           St = Bind(St, ValMgr.makeLoc(VR), loc::MemRegionVal(SelfRegion));
           // Scan the method for ivar references.  While this requires an
           // entire AST scan, the cost should not be high in practice.
@@ -362,21 +385,8 @@
         }
       }
     }
-    else if (VarDecl* VD = dyn_cast<VarDecl>(ND)) {
-      // Only handle simple types that we can symbolicate.
-      if (!SymbolManager::canSymbolicate(VD->getType()))
-        continue;
-
-      // Initialize globals and parameters to symbolic values.
-      // Initialize local variables to undefined.
-      const VarRegion *R = ValMgr.getRegionManager().getVarRegion(VD, InitLoc);
-      SVal X = UndefinedVal();
-      if (R->hasGlobalsOrParametersStorage())
-        X = ValMgr.getRegionValueSymbolVal(R);
-
-      St = Bind(St, ValMgr.makeLoc(R), X);
-    }
   }
+
   return St;
 }
 





More information about the cfe-commits mailing list