]> granicus.if.org Git - clang/commitdiff
Fix regression in GRExprEngine::VisitCast: Do not wrap symbolic function pointers...
authorTed Kremenek <kremenek@apple.com>
Thu, 5 Mar 2009 20:22:13 +0000 (20:22 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 5 Mar 2009 20:22:13 +0000 (20:22 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66187 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/GRExprEngine.cpp
test/Analysis/casts.m [new file with mode: 0644]

index 1d2c70cba2acbd6435450d25d2a7d7cfd65172a8..c2e898abe3b5376a49d9f4bf6db2a00a49a8cb52 100644 (file)
@@ -1757,6 +1757,7 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
     NodeTy* N = *I1;
     const GRState* state = GetState(N);
     SVal V = GetSVal(state, Ex);
+    ASTContext& C = getContext();
 
     // Unknown?
     if (V.isUnknown()) {
@@ -1765,19 +1766,13 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
     }
     
     // Undefined?
-    if (V.isUndef()) {
-      MakeNode(Dst, CastE, N, BindExpr(state, CastE, V));
-      continue;
-    }
+    if (V.isUndef())
+      goto PassThrough;
     
     // For const casts, just propagate the value.
-    ASTContext& C = getContext();
-    
     if (C.getCanonicalType(T).getUnqualifiedType() == 
-        C.getCanonicalType(ExTy).getUnqualifiedType()) {
-      MakeNode(Dst, CastE, N, BindExpr(state, CastE, V));
-      continue;
-    }
+        C.getCanonicalType(ExTy).getUnqualifiedType())
+      goto PassThrough;
       
     // Check for casts from pointers to integers.
     if (T->isIntegerType() && Loc::IsLocType(ExTy)) {
@@ -1791,19 +1786,16 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
         // Just unpackage the lval and return it.
         V = LV->getLoc();
         MakeNode(Dst, CastE, N, BindExpr(state, CastE, V));
+        continue;
       }
       
-      MakeNode(Dst, CastE, N, BindExpr(state, CastE,
-                                       EvalCast(V, CastE->getType())));
-      
-      continue;      
+      goto DispatchCast;
     }
     
     // Just pass through function and block pointers.
     if (ExTy->isBlockPointerType() || ExTy->isFunctionPointerType()) {
       assert(Loc::IsLocType(T));
-      MakeNode(Dst, CastE, N, BindExpr(state, CastE, V));
-      continue;
+      goto PassThrough;
     }
     
     // Check for casts from array type to another type.
@@ -1813,10 +1805,8 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
       
       // Are we casting from an array to a pointer?  If so just pass on
       // the decayed value.
-      if (T->isPointerType()) {
-        MakeNode(Dst, CastE, N, BindExpr(state, CastE, V));
-        continue;
-      }
+      if (T->isPointerType())
+        goto PassThrough;
       
       // Are we casting from an array to an integer?  If so, cast the decayed
       // pointer value to an integer.
@@ -1853,6 +1843,12 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
     // TypedViewRegion subregion.
     if (loc::SymbolVal* SV = dyn_cast<loc::SymbolVal>(&V)) {
       SymbolRef Sym = SV->getSymbol();
+      QualType SymTy = getSymbolManager().getType(Sym);
+
+      // Just pass through symbols that are function or block pointers.
+      if (SymTy->isFunctionPointerType() || SymTy->isBlockPointerType())
+        goto PassThrough;
+
       StoreManager& StoreMgr = getStoreManager();
       const MemRegion* R =
         StoreMgr.getRegionManager().getSymbolicRegion(Sym, getSymbolManager());
@@ -1871,9 +1867,16 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
       continue;
     }
 
-    // All other cases.
-    MakeNode(Dst, CastE, N, BindExpr(state, CastE,
-                                     EvalCast(V, CastE->getType())));
+        // All other cases.
+    DispatchCast: {
+      MakeNode(Dst, CastE, N, BindExpr(state, CastE,
+                                       EvalCast(V, CastE->getType())));
+      continue;
+    }
+    
+    PassThrough: {
+      MakeNode(Dst, CastE, N, BindExpr(state, CastE, V));
+    }
   }
 }
 
diff --git a/test/Analysis/casts.m b/test/Analysis/casts.m
new file mode 100644 (file)
index 0000000..37b8e3d
--- /dev/null
@@ -0,0 +1,16 @@
+// RUN: clang -analyze -checker-cfref -analyzer-store=basic --verify %s &&
+// RUN: clang -analyze -checker-cfref -analyzer-store=region --verify %s
+
+// Test function pointer casts.  Currently we track function addresses using
+// loc::FunctionVal.  Because casts can be arbitrary, do we need to model
+// functions with regions?
+
+typedef void (*MyFuncTest1)(void);
+
+MyFuncTest1 test1_aux(void);
+void test1(void) {
+  void *x;
+  void* (*p)(void);
+  p = ((void*) test1_aux());
+  if (p != ((void*) 0)) x = (*p)();
+}