diff options
-rw-r--r-- | lib/Analysis/Store.cpp | 22 | ||||
-rw-r--r-- | test/Analysis/misc-ps.m | 7 |
2 files changed, 27 insertions, 2 deletions
diff --git a/lib/Analysis/Store.cpp b/lib/Analysis/Store.cpp index b939a0df9c..bd46a68d01 100644 --- a/lib/Analysis/Store.cpp +++ b/lib/Analysis/Store.cpp @@ -59,6 +59,23 @@ StoreManager::NewCastRegion(const GRState *state, const MemRegion* R, state = setCastType(state, R, CastToTy); return CastResult(state, R); } + + if (CastToTy->isBlockPointerType()) { + if (isa<CodeTextRegion>(R)) + return CastResult(state, R); + + // FIXME: This may not be the right approach, depending on the symbol + // involved. Blocks can be casted to/from 'id', as they can be treated + // as Objective-C objects. + if (SymbolRef sym = loc::MemRegionVal(R).getAsSymbol()) { + R = MRMgr.getCodeTextRegion(sym, CastToTy); + return CastResult(state, R); + } + + // We don't know what to make of it. Return a NULL region, which + // will be interpretted as UnknownVal. + return CastResult(state, NULL); + } // Now assume we are casting from pointer to pointer. Other cases should // already be handled. @@ -77,8 +94,9 @@ StoreManager::NewCastRegion(const GRState *state, const MemRegion* R, } case MemRegion::CodeTextRegionKind: { - // CodeTextRegion should be cast to only function pointer type, although - // they can in practice be casted to anything, e.g, void*, char*, etc. + // CodeTextRegion should be cast to only a function or block pointer type, + // although they can in practice be casted to anything, e.g, void*, + // char*, etc. // Just pass the region through. break; } diff --git a/test/Analysis/misc-ps.m b/test/Analysis/misc-ps.m index 503352b6f7..862709cc7d 100644 --- a/test/Analysis/misc-ps.m +++ b/test/Analysis/misc-ps.m @@ -430,3 +430,10 @@ unsigned char test_array_index_bitwidth(const unsigned char *p) { return p[i+1]; } +// This case tests that CastRegion handles casts involving BlockPointerTypes. +// It should not crash. +void test_block_cast() { + id test_block_cast_aux(); + (void (^)(void *))test_block_cast_aux(); // expected-warning{{expression result unused}} +} + |