[cfe-commits] r128612 - in /cfe/trunk: lib/StaticAnalyzer/Core/ExprEngine.cpp test/Analysis/misc-ps-region-store.cpp

Ted Kremenek kremenek at apple.com
Wed Mar 30 21:46:53 PDT 2011


Author: kremenek
Date: Wed Mar 30 23:46:53 2011
New Revision: 128612

URL: http://llvm.org/viewvc/llvm-project?rev=128612&view=rev
Log:
Static analyzer: fix bug in handling of dynamic_cast<>.  The sink node wouldn't always be the final node, thus causing the state to continue propagating.  Instead,
recover some path-sensitivity by conjuring a symbol.

Modified:
    cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
    cfe/trunk/test/Analysis/misc-ps-region-store.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp?rev=128612&r1=128611&r2=128612&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngine.cpp Wed Mar 30 23:46:53 2011
@@ -2124,106 +2124,95 @@
 
   if (const ExplicitCastExpr *ExCast=dyn_cast_or_null<ExplicitCastExpr>(CastE))
     T = ExCast->getTypeAsWritten();
- 
-#if 0
-  // If we are evaluating the cast in an lvalue context, we implicitly want
-  // the cast to evaluate to a location.
-  if (asLValue) {
-    ASTContext &Ctx = getContext();
-    T = Ctx.getPointerType(Ctx.getCanonicalType(T));
-    ExTy = Ctx.getPointerType(Ctx.getCanonicalType(ExTy));
-  }
-#endif
 
-  switch (CastE->getCastKind()) {
-  case CK_ToVoid:
-    for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I)
-      Dst.Add(*I);
-    return;
-
-  case CK_LValueToRValue:
-  case CK_NoOp:
-  case CK_FunctionToPointerDecay:
-    for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
-      // Copy the SVal of Ex to CastE.
-      ExplodedNode *N = *I;
-      const GRState *state = GetState(N);
-      SVal V = state->getSVal(Ex);
-      state = state->BindExpr(CastE, V);
-      MakeNode(Dst, CastE, N, state);
-    }
-    return;
+  for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
+    Pred = *I;
 
-  case CK_GetObjCProperty:
-  case CK_Dependent:
-  case CK_ArrayToPointerDecay:
-  case CK_BitCast:
-  case CK_LValueBitCast:
-  case CK_IntegralCast:
-  case CK_NullToPointer:
-  case CK_IntegralToPointer:
-  case CK_PointerToIntegral:
-  case CK_PointerToBoolean:
-  case CK_IntegralToBoolean:
-  case CK_IntegralToFloating:
-  case CK_FloatingToIntegral:
-  case CK_FloatingToBoolean:
-  case CK_FloatingCast:
-  case CK_FloatingRealToComplex:
-  case CK_FloatingComplexToReal:
-  case CK_FloatingComplexToBoolean:
-  case CK_FloatingComplexCast:
-  case CK_FloatingComplexToIntegralComplex:
-  case CK_IntegralRealToComplex:
-  case CK_IntegralComplexToReal:
-  case CK_IntegralComplexToBoolean:
-  case CK_IntegralComplexCast:
-  case CK_IntegralComplexToFloatingComplex:
-  case CK_AnyPointerToObjCPointerCast:
-  case CK_AnyPointerToBlockPointerCast:
-  
-  case CK_ObjCObjectLValueCast: {
-    // Delegate to SValBuilder to process.
-    for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
-      ExplodedNode* N = *I;
-      const GRState* state = GetState(N);
-      SVal V = state->getSVal(Ex);
-      V = svalBuilder.evalCast(V, T, ExTy);
-      state = state->BindExpr(CastE, V);
-      MakeNode(Dst, CastE, N, state);
-    }
-    return;
-  }
+    switch (CastE->getCastKind()) {
+      case CK_ToVoid:
+        Dst.Add(Pred);
+        continue;
+      case CK_LValueToRValue:
+      case CK_NoOp:
+      case CK_FunctionToPointerDecay: {
+        // Copy the SVal of Ex to CastE.
+        const GRState *state = GetState(Pred);
+        SVal V = state->getSVal(Ex);
+        state = state->BindExpr(CastE, V);
+        MakeNode(Dst, CastE, Pred, state);
+        continue;
+      }
+      case CK_GetObjCProperty:
+      case CK_Dependent:
+      case CK_ArrayToPointerDecay:
+      case CK_BitCast:
+      case CK_LValueBitCast:
+      case CK_IntegralCast:
+      case CK_NullToPointer:
+      case CK_IntegralToPointer:
+      case CK_PointerToIntegral:
+      case CK_PointerToBoolean:
+      case CK_IntegralToBoolean:
+      case CK_IntegralToFloating:
+      case CK_FloatingToIntegral:
+      case CK_FloatingToBoolean:
+      case CK_FloatingCast:
+      case CK_FloatingRealToComplex:
+      case CK_FloatingComplexToReal:
+      case CK_FloatingComplexToBoolean:
+      case CK_FloatingComplexCast:
+      case CK_FloatingComplexToIntegralComplex:
+      case CK_IntegralRealToComplex:
+      case CK_IntegralComplexToReal:
+      case CK_IntegralComplexToBoolean:
+      case CK_IntegralComplexCast:
+      case CK_IntegralComplexToFloatingComplex:
+      case CK_AnyPointerToObjCPointerCast:
+      case CK_AnyPointerToBlockPointerCast:  
+      case CK_ObjCObjectLValueCast: {
+        // Delegate to SValBuilder to process.
+        const GRState* state = GetState(Pred);
+        SVal V = state->getSVal(Ex);
+        V = svalBuilder.evalCast(V, T, ExTy);
+        state = state->BindExpr(CastE, V);
+        MakeNode(Dst, CastE, Pred, state);
+        continue;
+      }
+      case CK_DerivedToBase:
+      case CK_UncheckedDerivedToBase: {
+        // For DerivedToBase cast, delegate to the store manager.
+        const GRState *state = GetState(Pred);
+        SVal val = state->getSVal(Ex);
+        val = getStoreManager().evalDerivedToBase(val, T);
+        state = state->BindExpr(CastE, val);
+        MakeNode(Dst, CastE, Pred, state);
+        continue;
+      }
+      // Various C++ casts that are not handled yet.
+      case CK_Dynamic:  
+      case CK_ToUnion:
+      case CK_BaseToDerived:
+      case CK_NullToMemberPointer:
+      case CK_BaseToDerivedMemberPointer:
+      case CK_DerivedToBaseMemberPointer:
+      case CK_UserDefinedConversion:
+      case CK_ConstructorConversion:
+      case CK_VectorSplat:
+      case CK_MemberPointerToBoolean: {
+        // Recover some path-sensitivty by conjuring a new value.
+        QualType resultType = CastE->getType();
+        if (CastE->isLValue())
+          resultType = getContext().getPointerType(resultType);
+
+        SVal result =
+          svalBuilder.getConjuredSymbolVal(NULL, CastE, resultType,
+                                           Builder->getCurrentBlockCount());
 
-  case CK_DerivedToBase:
-  case CK_UncheckedDerivedToBase:
-    // For DerivedToBase cast, delegate to the store manager.
-    for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
-      ExplodedNode *node = *I;
-      const GRState *state = GetState(node);
-      SVal val = state->getSVal(Ex);
-      val = getStoreManager().evalDerivedToBase(val, T);
-      state = state->BindExpr(CastE, val);
-      MakeNode(Dst, CastE, node, state);
+        const GRState *state = GetState(Pred)->BindExpr(CastE, result);
+        MakeNode(Dst, CastE, Pred, state);
+        continue;
+      }
     }
-    return;
-
-  // Various C++ casts that are not handled yet.
-  case CK_Dynamic:  
-  case CK_ToUnion:
-  case CK_BaseToDerived:
-  case CK_NullToMemberPointer:
-  case CK_BaseToDerivedMemberPointer:
-  case CK_DerivedToBaseMemberPointer:
-  case CK_UserDefinedConversion:
-  case CK_ConstructorConversion:
-  case CK_VectorSplat:
-  case CK_MemberPointerToBoolean: {
-    SaveAndRestore<bool> OldSink(Builder->BuildSinks);
-    Builder->BuildSinks = true;
-    MakeNode(Dst, CastE, Pred, GetState(Pred));
-    return;
-  }
   }
 }
 

Modified: cfe/trunk/test/Analysis/misc-ps-region-store.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/misc-ps-region-store.cpp?rev=128612&r1=128611&r2=128612&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/misc-ps-region-store.cpp (original)
+++ cfe/trunk/test/Analysis/misc-ps-region-store.cpp Wed Mar 30 23:46:53 2011
@@ -264,3 +264,17 @@
   }
 }
 
+// Test basic support for dynamic_cast<>.
+struct Rdar9212495_C { virtual void bar() const; };
+class Rdar9212495_B : public Rdar9212495_C {};
+class Rdar9212495_A : public Rdar9212495_B {};
+const Rdar9212495_A& rdar9212495(const Rdar9212495_C* ptr) {
+  const Rdar9212495_A& val = dynamic_cast<const Rdar9212495_A&>(*ptr);
+  
+  if (&val == 0) {
+    val.bar(); // FIXME: This should eventually be a null dereference.
+  }
+  
+  return val;
+}
+





More information about the cfe-commits mailing list