Store.cpp revision bf0fe6c5b7bd7bc67b6b3ef0acb22bf4811f2a1b
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//== Store.cpp - Interface for maps from Locations to Values ----*- C++ -*--==//
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                     The LLVM Compiler Infrastructure
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)//  This file defined the types Store and StoreManager.
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/Analysis/PathSensitive/Store.h"
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "clang/Analysis/PathSensitive/GRState.h"
167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace clang;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)StoreManager::StoreManager(GRStateManager &stateMgr)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  : ValMgr(stateMgr.getValueManager()), StateMgr(stateMgr),
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MRMgr(ValMgr.getRegionManager()) {}
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const MemRegion *StoreManager::MakeElementRegion(const MemRegion *Base,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              QualType EleTy, uint64_t index) {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SVal idx = ValMgr.makeArrayIndex(index);
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return MRMgr.getElementRegion(EleTy, idx, Base, ValMgr.getContext());
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FIXME: Merge with the implementation of the same method in MemRegion.cpp
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static bool IsCompleteType(ASTContext &Ctx, QualType Ty) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (const RecordType *RT = Ty->getAs<RecordType>()) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const RecordDecl *D = RT->getDecl();
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!D->getDefinition(Ctx))
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const MemRegion *StoreManager::CastRegion(const MemRegion *R, QualType CastToTy) {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASTContext& Ctx = StateMgr.getContext();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Handle casts to Objective-C objects.
457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (CastToTy->isObjCObjectPointerType())
467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return R->StripCasts();
477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (CastToTy->isBlockPointerType()) {
497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // FIXME: We may need different solutions, depending on the symbol
50f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // involved.  Blocks can be casted to/from 'id', as they can be treated
517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // as Objective-C objects.  This could possibly be handled by enhancing
52f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // our reasoning of downcasts of symbolic objects.
53f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (isa<CodeTextRegion>(R) || isa<SymbolicRegion>(R))
547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return R;
557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // We don't know what to make of it.  Return a NULL region, which
577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // will be interpretted as UnknownVal.
587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    return NULL;
597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
61f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Now assume we are casting from pointer to pointer. Other cases should
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // already be handled.
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  QualType PointeeTy = CastToTy->getAs<PointerType>()->getPointeeType();
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  QualType CanonPointeeTy = Ctx.getCanonicalType(PointeeTy);
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Handle casts to void*.  We just pass the region through.
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (CanonPointeeTy.getLocalUnqualifiedType() == Ctx.VoidTy)
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return R;
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Handle casts from compatible types.
71f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (R->isBoundable())
72f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (const TypedRegion *TR = dyn_cast<TypedRegion>(R)) {
73f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      QualType ObjTy = Ctx.getCanonicalType(TR->getValueType(Ctx));
74f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (CanonPointeeTy == ObjTy)
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        return R;
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Process region cast according to the kind of the region being cast.
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  switch (R->getKind()) {
80f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case MemRegion::BEG_TYPED_REGIONS:
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case MemRegion::MemSpaceRegionKind:
827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    case MemRegion::BEG_DECL_REGIONS:
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MemRegion::END_DECL_REGIONS:
84f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    case MemRegion::END_TYPED_REGIONS: {
85f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      assert(0 && "Invalid region cast");
86f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      break;
87f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MemRegion::FunctionTextRegionKind:
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MemRegion::BlockTextRegionKind:
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MemRegion::BlockDataRegionKind: {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // CodeTextRegion should be cast to only a function or block pointer type,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // although they can in practice be casted to anything, e.g, void*, char*,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // etc.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Just return the region.
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return R;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MemRegion::StringRegionKind:
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MemRegion::ObjCObjectRegionKind:
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // FIXME: Need to handle arbitrary downcasts.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MemRegion::SymbolicRegionKind:
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MemRegion::AllocaRegionKind:
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MemRegion::CompoundLiteralRegionKind:
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MemRegion::FieldRegionKind:
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MemRegion::ObjCIvarRegionKind:
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MemRegion::VarRegionKind:
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return MakeElementRegion(R, PointeeTy);
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case MemRegion::ElementRegionKind: {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If we are casting from an ElementRegion to another type, the
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // algorithm is as follows:
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // (1) Compute the "raw offset" of the ElementRegion from the
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //     base region.  This is done by calling 'getAsRawOffset()'.
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // (2a) If we get a 'RegionRawOffset' after calling
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //      'getAsRawOffset()', determine if the absolute offset
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //      can be exactly divided into chunks of the size of the
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //      casted-pointee type.  If so, create a new ElementRegion with
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //      the pointee-cast type as the new ElementType and the index
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //      being the offset divded by the chunk size.  If not, create
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //      a new ElementRegion at offset 0 off the raw offset region.
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // (2b) If we don't a get a 'RegionRawOffset' after calling
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //      'getAsRawOffset()', it means that we are at offset 0.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // FIXME: Handle symbolic raw offsets.
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const ElementRegion *elementR = cast<ElementRegion>(R);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const RegionRawOffset &rawOff = elementR->getAsRawOffset();
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const MemRegion *baseR = rawOff.getRegion();
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // If we cannot compute a raw offset, throw up our hands and return
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // a NULL MemRegion*.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!baseR)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return NULL;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int64_t off = rawOff.getByteOffset();
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (off == 0) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Edge case: we are at 0 bytes off the beginning of baseR.  We
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // check to see if type we are casting to is the same as the base
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // region.  If so, just return the base region.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (const TypedRegion *TR = dyn_cast<TypedRegion>(baseR)) {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          QualType ObjTy = Ctx.getCanonicalType(TR->getValueType(Ctx));
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          QualType CanonPointeeTy = Ctx.getCanonicalType(PointeeTy);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (CanonPointeeTy == ObjTy)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return baseR;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Otherwise, create a new ElementRegion at offset 0.
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return MakeElementRegion(baseR, PointeeTy);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We have a non-zero offset from the base region.  We want to determine
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // if the offset can be evenly divided by sizeof(PointeeTy).  If so,
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // we create an ElementRegion whose index is that value.  Otherwise, we
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // create two ElementRegions, one that reflects a raw offset and the other
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // that reflects the cast.
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Compute the index for the new ElementRegion.
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      int64_t newIndex = 0;
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const MemRegion *newSuperR = 0;
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We can only compute sizeof(PointeeTy) if it is a complete type.
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (IsCompleteType(Ctx, PointeeTy)) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Compute the size in **bytes**.
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int64_t pointeeTySize = (int64_t) (Ctx.getTypeSize(PointeeTy) / 8);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Is the offset a multiple of the size?  If so, we can layer the
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // ElementRegion (with elementType == PointeeTy) directly on top of
173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        // the base region.
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (off % pointeeTySize == 0) {
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          newIndex = off / pointeeTySize;
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          newSuperR = baseR;
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (!newSuperR) {
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // Create an intermediate ElementRegion to represent the raw byte.
1825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // This will be the super region of the final ElementRegion.
1835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        newSuperR = MakeElementRegion(baseR, Ctx.CharTy, off);
1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return MakeElementRegion(newSuperR, PointeeTy, newIndex);
187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  assert(0 && "unreachable");
1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return 0;
1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/// CastRetrievedVal - Used by subclasses of StoreManager to implement
1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci///  implicit casts that arise from loads from regions that are reinterpreted
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///  as another region.
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SVal  StoreManager::CastRetrievedVal(SVal V, const TypedRegion *R,
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     QualType castTy) {
200  if (castTy.isNull())
201    return V;
202
203  assert(ValMgr.getContext().hasSameUnqualifiedType(castTy,
204                                         R->getValueType(ValMgr.getContext())));
205  return V;
206}
207
208