]> granicus.if.org Git - clang/commitdiff
Fix crash in StoreManager::NewCastRegion regarding handling casts to void*,
authorTed Kremenek <kremenek@apple.com>
Fri, 10 Jul 2009 21:11:16 +0000 (21:11 +0000)
committerTed Kremenek <kremenek@apple.com>
Fri, 10 Jul 2009 21:11:16 +0000 (21:11 +0000)
void**, void***, etc.  Such casts should just pass the region through.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@75281 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/Store.cpp
test/Analysis/misc-ps.m

index d7633a46ac9dc7b37e2d4b844ab7ba3c26f525a4..ad6bd7e4f664d43a6594631d0d2ff841cb104461 100644 (file)
@@ -45,6 +45,24 @@ static bool IsCompleteType(ASTContext &Ctx, QualType Ty) {
   return true;
 }
 
+static bool isVoidOrHigherOrderVoidPtr(ASTContext &Ctx, QualType Ty) {
+  while (true) {
+    Ty = Ctx.getCanonicalType(Ty);
+    
+    if (Ty->isVoidType())
+      return true;    
+
+    if (const PointerType *PT = Ty->getAsPointerType()) {
+      Ty = PT->getPointeeType();
+      continue;
+    }
+    
+    break;
+  }
+  
+  return false;
+}
+
 StoreManager::CastResult
 StoreManager::NewCastRegion(const GRState *state, const MemRegion* R,
                             QualType CastToTy) {
@@ -64,6 +82,10 @@ StoreManager::NewCastRegion(const GRState *state, const MemRegion* R,
   // already be handled.
   QualType PointeeTy = CastToTy->getAsPointerType()->getPointeeType();
   
+  // Casts to 'void*', 'void**', 'void***', etc., should just pass through.
+  if (isVoidOrHigherOrderVoidPtr(Ctx, PointeeTy))
+    return CastResult(state, R);
+  
   // Process region cast according to the kind of the region being cast.
   switch (R->getKind()) {
     case MemRegion::BEG_TYPED_REGIONS:
@@ -78,9 +100,8 @@ StoreManager::NewCastRegion(const GRState *state, const MemRegion* R,
       
     case MemRegion::CodeTextRegionKind: {
       // CodeTextRegion should be cast to only function pointer type.
-      assert(CastToTy->isFunctionPointerType() || CastToTy->isBlockPointerType()
-             || (CastToTy->isPointerType() &&
-                 CastToTy->getAsPointerType()->getPointeeType()->isVoidType()));
+      assert(CastToTy->isFunctionPointerType() || 
+             CastToTy->isBlockPointerType());
       break;
     }
       
index 5e063d07fda50d60f22b0f20bf5efdd243708373..19d76228054cad1d93507777f1c3042e54699f08 100644 (file)
@@ -324,3 +324,17 @@ void test_rdar_7034511(NSArray *y) {
   if (x == ((void*) 0)) {}
 }
 
+// Handle arbitrary void*^n -> void*^m casts.  This was previously causing
+// a crash in CastRegion.
+void handle_higher_order_voidptr_casts() {
+  void **ptr;
+  typedef void *PVOID;
+  typedef long INT_PTR, *PINT_PTR;
+  typedef INT_PTR (*FARPROC)();
+  FARPROC handle_higher_order_voidptr_casts_aux();
+  PVOID handle_higher_order_voidptr_casts_aux_2(PVOID volatile *x);
+  
+  ptr = (void**) handle_higher_order_voidptr_casts_aux();
+  handle_higher_order_voidptr_casts_aux_2(ptr);
+}
+