1218887Sdim//== Store.cpp - Interface for maps from Locations to Values ----*- C++ -*--==// 2218887Sdim// 3218887Sdim// The LLVM Compiler Infrastructure 4218887Sdim// 5218887Sdim// This file is distributed under the University of Illinois Open Source 6218887Sdim// License. See LICENSE.TXT for details. 7218887Sdim// 8218887Sdim//===----------------------------------------------------------------------===// 9218887Sdim// 10218887Sdim// This file defined the types Store and StoreManager. 11218887Sdim// 12218887Sdim//===----------------------------------------------------------------------===// 13218887Sdim 14218887Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" 15249423Sdim#include "clang/AST/CXXInheritance.h" 16249423Sdim#include "clang/AST/CharUnits.h" 17249423Sdim#include "clang/AST/DeclObjC.h" 18239462Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h" 19226633Sdim#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 20218887Sdim 21218887Sdimusing namespace clang; 22218887Sdimusing namespace ento; 23218887Sdim 24226633SdimStoreManager::StoreManager(ProgramStateManager &stateMgr) 25218887Sdim : svalBuilder(stateMgr.getSValBuilder()), StateMgr(stateMgr), 26218887Sdim MRMgr(svalBuilder.getRegionManager()), Ctx(stateMgr.getContext()) {} 27218887Sdim 28239462SdimStoreRef StoreManager::enterStackFrame(Store OldStore, 29239462Sdim const CallEvent &Call, 30239462Sdim const StackFrameContext *LCtx) { 31239462Sdim StoreRef Store = StoreRef(OldStore, *this); 32239462Sdim 33239462Sdim SmallVector<CallEvent::FrameBindingTy, 16> InitialBindings; 34239462Sdim Call.getInitialStackFrameContents(LCtx, InitialBindings); 35239462Sdim 36239462Sdim for (CallEvent::BindingsTy::iterator I = InitialBindings.begin(), 37239462Sdim E = InitialBindings.end(); 38239462Sdim I != E; ++I) { 39239462Sdim Store = Bind(Store.getStore(), I->first, I->second); 40239462Sdim } 41239462Sdim 42239462Sdim return Store; 43218887Sdim} 44218887Sdim 45218887Sdimconst MemRegion *StoreManager::MakeElementRegion(const MemRegion *Base, 46218887Sdim QualType EleTy, uint64_t index) { 47218887Sdim NonLoc idx = svalBuilder.makeArrayIndex(index); 48218887Sdim return MRMgr.getElementRegion(EleTy, idx, Base, svalBuilder.getContext()); 49218887Sdim} 50218887Sdim 51218887Sdim// FIXME: Merge with the implementation of the same method in MemRegion.cpp 52218887Sdimstatic bool IsCompleteType(ASTContext &Ctx, QualType Ty) { 53218887Sdim if (const RecordType *RT = Ty->getAs<RecordType>()) { 54218887Sdim const RecordDecl *D = RT->getDecl(); 55218887Sdim if (!D->getDefinition()) 56218887Sdim return false; 57218887Sdim } 58218887Sdim 59218887Sdim return true; 60218887Sdim} 61218887Sdim 62218887SdimStoreRef StoreManager::BindDefault(Store store, const MemRegion *R, SVal V) { 63218887Sdim return StoreRef(store, *this); 64218887Sdim} 65218887Sdim 66218887Sdimconst ElementRegion *StoreManager::GetElementZeroRegion(const MemRegion *R, 67218887Sdim QualType T) { 68218887Sdim NonLoc idx = svalBuilder.makeZeroArrayIndex(); 69218887Sdim assert(!T.isNull()); 70218887Sdim return MRMgr.getElementRegion(T, idx, R, Ctx); 71218887Sdim} 72218887Sdim 73218887Sdimconst MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy) { 74218887Sdim 75226633Sdim ASTContext &Ctx = StateMgr.getContext(); 76218887Sdim 77218887Sdim // Handle casts to Objective-C objects. 78218887Sdim if (CastToTy->isObjCObjectPointerType()) 79218887Sdim return R->StripCasts(); 80218887Sdim 81218887Sdim if (CastToTy->isBlockPointerType()) { 82218887Sdim // FIXME: We may need different solutions, depending on the symbol 83218887Sdim // involved. Blocks can be casted to/from 'id', as they can be treated 84218887Sdim // as Objective-C objects. This could possibly be handled by enhancing 85218887Sdim // our reasoning of downcasts of symbolic objects. 86218887Sdim if (isa<CodeTextRegion>(R) || isa<SymbolicRegion>(R)) 87218887Sdim return R; 88218887Sdim 89218887Sdim // We don't know what to make of it. Return a NULL region, which 90218887Sdim // will be interpretted as UnknownVal. 91218887Sdim return NULL; 92218887Sdim } 93218887Sdim 94218887Sdim // Now assume we are casting from pointer to pointer. Other cases should 95218887Sdim // already be handled. 96218887Sdim QualType PointeeTy = CastToTy->getPointeeType(); 97218887Sdim QualType CanonPointeeTy = Ctx.getCanonicalType(PointeeTy); 98218887Sdim 99218887Sdim // Handle casts to void*. We just pass the region through. 100218887Sdim if (CanonPointeeTy.getLocalUnqualifiedType() == Ctx.VoidTy) 101218887Sdim return R; 102218887Sdim 103218887Sdim // Handle casts from compatible types. 104218887Sdim if (R->isBoundable()) 105226633Sdim if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { 106218887Sdim QualType ObjTy = Ctx.getCanonicalType(TR->getValueType()); 107218887Sdim if (CanonPointeeTy == ObjTy) 108218887Sdim return R; 109218887Sdim } 110218887Sdim 111218887Sdim // Process region cast according to the kind of the region being cast. 112218887Sdim switch (R->getKind()) { 113218887Sdim case MemRegion::CXXThisRegionKind: 114218887Sdim case MemRegion::GenericMemSpaceRegionKind: 115218887Sdim case MemRegion::StackLocalsSpaceRegionKind: 116218887Sdim case MemRegion::StackArgumentsSpaceRegionKind: 117218887Sdim case MemRegion::HeapSpaceRegionKind: 118218887Sdim case MemRegion::UnknownSpaceRegionKind: 119234353Sdim case MemRegion::StaticGlobalSpaceRegionKind: 120234353Sdim case MemRegion::GlobalInternalSpaceRegionKind: 121234353Sdim case MemRegion::GlobalSystemSpaceRegionKind: 122234353Sdim case MemRegion::GlobalImmutableSpaceRegionKind: { 123226633Sdim llvm_unreachable("Invalid region cast"); 124218887Sdim } 125218887Sdim 126218887Sdim case MemRegion::FunctionTextRegionKind: 127218887Sdim case MemRegion::BlockTextRegionKind: 128218887Sdim case MemRegion::BlockDataRegionKind: 129218887Sdim case MemRegion::StringRegionKind: 130218887Sdim // FIXME: Need to handle arbitrary downcasts. 131218887Sdim case MemRegion::SymbolicRegionKind: 132218887Sdim case MemRegion::AllocaRegionKind: 133218887Sdim case MemRegion::CompoundLiteralRegionKind: 134218887Sdim case MemRegion::FieldRegionKind: 135218887Sdim case MemRegion::ObjCIvarRegionKind: 136234353Sdim case MemRegion::ObjCStringRegionKind: 137218887Sdim case MemRegion::VarRegionKind: 138218887Sdim case MemRegion::CXXTempObjectRegionKind: 139218887Sdim case MemRegion::CXXBaseObjectRegionKind: 140218887Sdim return MakeElementRegion(R, PointeeTy); 141218887Sdim 142218887Sdim case MemRegion::ElementRegionKind: { 143218887Sdim // If we are casting from an ElementRegion to another type, the 144218887Sdim // algorithm is as follows: 145218887Sdim // 146218887Sdim // (1) Compute the "raw offset" of the ElementRegion from the 147218887Sdim // base region. This is done by calling 'getAsRawOffset()'. 148218887Sdim // 149218887Sdim // (2a) If we get a 'RegionRawOffset' after calling 150218887Sdim // 'getAsRawOffset()', determine if the absolute offset 151218887Sdim // can be exactly divided into chunks of the size of the 152218887Sdim // casted-pointee type. If so, create a new ElementRegion with 153218887Sdim // the pointee-cast type as the new ElementType and the index 154218887Sdim // being the offset divded by the chunk size. If not, create 155218887Sdim // a new ElementRegion at offset 0 off the raw offset region. 156218887Sdim // 157218887Sdim // (2b) If we don't a get a 'RegionRawOffset' after calling 158218887Sdim // 'getAsRawOffset()', it means that we are at offset 0. 159218887Sdim // 160218887Sdim // FIXME: Handle symbolic raw offsets. 161218887Sdim 162218887Sdim const ElementRegion *elementR = cast<ElementRegion>(R); 163218887Sdim const RegionRawOffset &rawOff = elementR->getAsArrayOffset(); 164218887Sdim const MemRegion *baseR = rawOff.getRegion(); 165218887Sdim 166218887Sdim // If we cannot compute a raw offset, throw up our hands and return 167218887Sdim // a NULL MemRegion*. 168218887Sdim if (!baseR) 169218887Sdim return NULL; 170218887Sdim 171218887Sdim CharUnits off = rawOff.getOffset(); 172218887Sdim 173218887Sdim if (off.isZero()) { 174218887Sdim // Edge case: we are at 0 bytes off the beginning of baseR. We 175218887Sdim // check to see if type we are casting to is the same as the base 176218887Sdim // region. If so, just return the base region. 177226633Sdim if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(baseR)) { 178218887Sdim QualType ObjTy = Ctx.getCanonicalType(TR->getValueType()); 179218887Sdim QualType CanonPointeeTy = Ctx.getCanonicalType(PointeeTy); 180218887Sdim if (CanonPointeeTy == ObjTy) 181218887Sdim return baseR; 182218887Sdim } 183218887Sdim 184218887Sdim // Otherwise, create a new ElementRegion at offset 0. 185218887Sdim return MakeElementRegion(baseR, PointeeTy); 186218887Sdim } 187218887Sdim 188218887Sdim // We have a non-zero offset from the base region. We want to determine 189218887Sdim // if the offset can be evenly divided by sizeof(PointeeTy). If so, 190218887Sdim // we create an ElementRegion whose index is that value. Otherwise, we 191218887Sdim // create two ElementRegions, one that reflects a raw offset and the other 192218887Sdim // that reflects the cast. 193218887Sdim 194218887Sdim // Compute the index for the new ElementRegion. 195218887Sdim int64_t newIndex = 0; 196218887Sdim const MemRegion *newSuperR = 0; 197218887Sdim 198218887Sdim // We can only compute sizeof(PointeeTy) if it is a complete type. 199218887Sdim if (IsCompleteType(Ctx, PointeeTy)) { 200218887Sdim // Compute the size in **bytes**. 201218887Sdim CharUnits pointeeTySize = Ctx.getTypeSizeInChars(PointeeTy); 202218887Sdim if (!pointeeTySize.isZero()) { 203218887Sdim // Is the offset a multiple of the size? If so, we can layer the 204218887Sdim // ElementRegion (with elementType == PointeeTy) directly on top of 205218887Sdim // the base region. 206218887Sdim if (off % pointeeTySize == 0) { 207218887Sdim newIndex = off / pointeeTySize; 208218887Sdim newSuperR = baseR; 209218887Sdim } 210218887Sdim } 211218887Sdim } 212218887Sdim 213218887Sdim if (!newSuperR) { 214218887Sdim // Create an intermediate ElementRegion to represent the raw byte. 215218887Sdim // This will be the super region of the final ElementRegion. 216218887Sdim newSuperR = MakeElementRegion(baseR, Ctx.CharTy, off.getQuantity()); 217218887Sdim } 218218887Sdim 219218887Sdim return MakeElementRegion(newSuperR, PointeeTy, newIndex); 220218887Sdim } 221218887Sdim } 222218887Sdim 223226633Sdim llvm_unreachable("unreachable"); 224218887Sdim} 225218887Sdim 226249423Sdimstatic bool regionMatchesCXXRecordType(SVal V, QualType Ty) { 227249423Sdim const MemRegion *MR = V.getAsRegion(); 228249423Sdim if (!MR) 229249423Sdim return true; 230249423Sdim 231249423Sdim const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(MR); 232249423Sdim if (!TVR) 233249423Sdim return true; 234249423Sdim 235249423Sdim const CXXRecordDecl *RD = TVR->getValueType()->getAsCXXRecordDecl(); 236249423Sdim if (!RD) 237249423Sdim return true; 238249423Sdim 239249423Sdim const CXXRecordDecl *Expected = Ty->getPointeeCXXRecordDecl(); 240249423Sdim if (!Expected) 241249423Sdim Expected = Ty->getAsCXXRecordDecl(); 242249423Sdim 243249423Sdim return Expected->getCanonicalDecl() == RD->getCanonicalDecl(); 244249423Sdim} 245249423Sdim 246239462SdimSVal StoreManager::evalDerivedToBase(SVal Derived, const CastExpr *Cast) { 247249423Sdim // Sanity check to avoid doing the wrong thing in the face of 248249423Sdim // reinterpret_cast. 249249423Sdim if (!regionMatchesCXXRecordType(Derived, Cast->getSubExpr()->getType())) 250249423Sdim return UnknownVal(); 251249423Sdim 252239462Sdim // Walk through the cast path to create nested CXXBaseRegions. 253239462Sdim SVal Result = Derived; 254239462Sdim for (CastExpr::path_const_iterator I = Cast->path_begin(), 255239462Sdim E = Cast->path_end(); 256239462Sdim I != E; ++I) { 257249423Sdim Result = evalDerivedToBase(Result, (*I)->getType(), (*I)->isVirtual()); 258239462Sdim } 259239462Sdim return Result; 260239462Sdim} 261218887Sdim 262243830SdimSVal StoreManager::evalDerivedToBase(SVal Derived, const CXXBasePath &Path) { 263243830Sdim // Walk through the path to create nested CXXBaseRegions. 264243830Sdim SVal Result = Derived; 265243830Sdim for (CXXBasePath::const_iterator I = Path.begin(), E = Path.end(); 266243830Sdim I != E; ++I) { 267249423Sdim Result = evalDerivedToBase(Result, I->Base->getType(), 268249423Sdim I->Base->isVirtual()); 269243830Sdim } 270243830Sdim return Result; 271243830Sdim} 272239462Sdim 273249423SdimSVal StoreManager::evalDerivedToBase(SVal Derived, QualType BaseType, 274249423Sdim bool IsVirtual) { 275249423Sdim Optional<loc::MemRegionVal> DerivedRegVal = 276249423Sdim Derived.getAs<loc::MemRegionVal>(); 277243830Sdim if (!DerivedRegVal) 278243830Sdim return Derived; 279243830Sdim 280243830Sdim const CXXRecordDecl *BaseDecl = BaseType->getPointeeCXXRecordDecl(); 281243830Sdim if (!BaseDecl) 282243830Sdim BaseDecl = BaseType->getAsCXXRecordDecl(); 283243830Sdim assert(BaseDecl && "not a C++ object?"); 284243830Sdim 285243830Sdim const MemRegion *BaseReg = 286249423Sdim MRMgr.getCXXBaseObjectRegion(BaseDecl, DerivedRegVal->getRegion(), 287249423Sdim IsVirtual); 288243830Sdim 289243830Sdim return loc::MemRegionVal(BaseReg); 290243830Sdim} 291243830Sdim 292251662Sdim/// Returns the static type of the given region, if it represents a C++ class 293251662Sdim/// object. 294251662Sdim/// 295251662Sdim/// This handles both fully-typed regions, where the dynamic type is known, and 296251662Sdim/// symbolic regions, where the dynamic type is merely bounded (and even then, 297251662Sdim/// only ostensibly!), but does not take advantage of any dynamic type info. 298251662Sdimstatic const CXXRecordDecl *getCXXRecordType(const MemRegion *MR) { 299251662Sdim if (const TypedValueRegion *TVR = dyn_cast<TypedValueRegion>(MR)) 300251662Sdim return TVR->getValueType()->getAsCXXRecordDecl(); 301251662Sdim if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR)) 302251662Sdim return SR->getSymbol()->getType()->getPointeeCXXRecordDecl(); 303251662Sdim return 0; 304251662Sdim} 305251662Sdim 306251662SdimSVal StoreManager::evalDynamicCast(SVal Base, QualType TargetType, 307243830Sdim bool &Failed) { 308243830Sdim Failed = false; 309243830Sdim 310251662Sdim const MemRegion *MR = Base.getAsRegion(); 311251662Sdim if (!MR) 312243830Sdim return UnknownVal(); 313243830Sdim 314243830Sdim // Assume the derived class is a pointer or a reference to a CXX record. 315251662Sdim TargetType = TargetType->getPointeeType(); 316251662Sdim assert(!TargetType.isNull()); 317251662Sdim const CXXRecordDecl *TargetClass = TargetType->getAsCXXRecordDecl(); 318251662Sdim if (!TargetClass && !TargetType->isVoidType()) 319243830Sdim return UnknownVal(); 320243830Sdim 321243830Sdim // Drill down the CXXBaseObject chains, which represent upcasts (casts from 322243830Sdim // derived to base). 323251662Sdim while (const CXXRecordDecl *MRClass = getCXXRecordType(MR)) { 324243830Sdim // If found the derived class, the cast succeeds. 325251662Sdim if (MRClass == TargetClass) 326251662Sdim return loc::MemRegionVal(MR); 327243830Sdim 328263508Sdim // We skip over incomplete types. They must be the result of an earlier 329263508Sdim // reinterpret_cast, as one can only dynamic_cast between types in the same 330263508Sdim // class hierarchy. 331263508Sdim if (!TargetType->isVoidType() && MRClass->hasDefinition()) { 332243830Sdim // Static upcasts are marked as DerivedToBase casts by Sema, so this will 333243830Sdim // only happen when multiple or virtual inheritance is involved. 334243830Sdim CXXBasePaths Paths(/*FindAmbiguities=*/false, /*RecordPaths=*/true, 335243830Sdim /*DetectVirtual=*/false); 336251662Sdim if (MRClass->isDerivedFrom(TargetClass, Paths)) 337251662Sdim return evalDerivedToBase(loc::MemRegionVal(MR), Paths.front()); 338243830Sdim } 339243830Sdim 340251662Sdim if (const CXXBaseObjectRegion *BaseR = dyn_cast<CXXBaseObjectRegion>(MR)) { 341243830Sdim // Drill down the chain to get the derived classes. 342251662Sdim MR = BaseR->getSuperRegion(); 343251662Sdim continue; 344251662Sdim } 345243830Sdim 346251662Sdim // If this is a cast to void*, return the region. 347251662Sdim if (TargetType->isVoidType()) 348251662Sdim return loc::MemRegionVal(MR); 349243830Sdim 350251662Sdim // Strange use of reinterpret_cast can give us paths we don't reason 351251662Sdim // about well, by putting in ElementRegions where we'd expect 352251662Sdim // CXXBaseObjectRegions. If it's a valid reinterpret_cast (i.e. if the 353251662Sdim // derived class has a zero offset from the base class), then it's safe 354251662Sdim // to strip the cast; if it's invalid, -Wreinterpret-base-class should 355251662Sdim // catch it. In the interest of performance, the analyzer will silently 356251662Sdim // do the wrong thing in the invalid case (because offsets for subregions 357251662Sdim // will be wrong). 358251662Sdim const MemRegion *Uncasted = MR->StripCasts(/*IncludeBaseCasts=*/false); 359251662Sdim if (Uncasted == MR) { 360251662Sdim // We reached the bottom of the hierarchy and did not find the derived 361251662Sdim // class. We we must be casting the base to derived, so the cast should 362251662Sdim // fail. 363251662Sdim break; 364243830Sdim } 365251662Sdim 366251662Sdim MR = Uncasted; 367243830Sdim } 368251662Sdim 369251662Sdim // We failed if the region we ended up with has perfect type info. 370251662Sdim Failed = isa<TypedValueRegion>(MR); 371243830Sdim return UnknownVal(); 372243830Sdim} 373243830Sdim 374243830Sdim 375218887Sdim/// CastRetrievedVal - Used by subclasses of StoreManager to implement 376218887Sdim/// implicit casts that arise from loads from regions that are reinterpreted 377218887Sdim/// as another region. 378226633SdimSVal StoreManager::CastRetrievedVal(SVal V, const TypedValueRegion *R, 379218887Sdim QualType castTy, bool performTestOnly) { 380218887Sdim 381234353Sdim if (castTy.isNull() || V.isUnknownOrUndef()) 382218887Sdim return V; 383218887Sdim 384218887Sdim ASTContext &Ctx = svalBuilder.getContext(); 385218887Sdim 386218887Sdim if (performTestOnly) { 387218887Sdim // Automatically translate references to pointers. 388218887Sdim QualType T = R->getValueType(); 389218887Sdim if (const ReferenceType *RT = T->getAs<ReferenceType>()) 390218887Sdim T = Ctx.getPointerType(RT->getPointeeType()); 391218887Sdim 392218887Sdim assert(svalBuilder.getContext().hasSameUnqualifiedType(castTy, T)); 393218887Sdim return V; 394218887Sdim } 395218887Sdim 396234353Sdim return svalBuilder.dispatchCast(V, castTy); 397218887Sdim} 398218887Sdim 399226633SdimSVal StoreManager::getLValueFieldOrIvar(const Decl *D, SVal Base) { 400218887Sdim if (Base.isUnknownOrUndef()) 401218887Sdim return Base; 402218887Sdim 403249423Sdim Loc BaseL = Base.castAs<Loc>(); 404218887Sdim const MemRegion* BaseR = 0; 405218887Sdim 406218887Sdim switch (BaseL.getSubKind()) { 407218887Sdim case loc::MemRegionKind: 408249423Sdim BaseR = BaseL.castAs<loc::MemRegionVal>().getRegion(); 409218887Sdim break; 410218887Sdim 411218887Sdim case loc::GotoLabelKind: 412218887Sdim // These are anormal cases. Flag an undefined value. 413218887Sdim return UndefinedVal(); 414218887Sdim 415218887Sdim case loc::ConcreteIntKind: 416218887Sdim // While these seem funny, this can happen through casts. 417218887Sdim // FIXME: What we should return is the field offset. For example, 418218887Sdim // add the field offset to the integer value. That way funny things 419218887Sdim // like this work properly: &(((struct foo *) 0xa)->f) 420218887Sdim return Base; 421218887Sdim 422218887Sdim default: 423226633Sdim llvm_unreachable("Unhandled Base."); 424218887Sdim } 425218887Sdim 426218887Sdim // NOTE: We must have this check first because ObjCIvarDecl is a subclass 427218887Sdim // of FieldDecl. 428218887Sdim if (const ObjCIvarDecl *ID = dyn_cast<ObjCIvarDecl>(D)) 429218887Sdim return loc::MemRegionVal(MRMgr.getObjCIvarRegion(ID, BaseR)); 430218887Sdim 431218887Sdim return loc::MemRegionVal(MRMgr.getFieldRegion(cast<FieldDecl>(D), BaseR)); 432218887Sdim} 433218887Sdim 434234353SdimSVal StoreManager::getLValueIvar(const ObjCIvarDecl *decl, SVal base) { 435234353Sdim return getLValueFieldOrIvar(decl, base); 436234353Sdim} 437234353Sdim 438218887SdimSVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset, 439218887Sdim SVal Base) { 440218887Sdim 441218887Sdim // If the base is an unknown or undefined value, just return it back. 442218887Sdim // FIXME: For absolute pointer addresses, we just return that value back as 443218887Sdim // well, although in reality we should return the offset added to that 444218887Sdim // value. 445249423Sdim if (Base.isUnknownOrUndef() || Base.getAs<loc::ConcreteInt>()) 446218887Sdim return Base; 447218887Sdim 448249423Sdim const MemRegion* BaseRegion = Base.castAs<loc::MemRegionVal>().getRegion(); 449218887Sdim 450218887Sdim // Pointer of any type can be cast and used as array base. 451218887Sdim const ElementRegion *ElemR = dyn_cast<ElementRegion>(BaseRegion); 452218887Sdim 453218887Sdim // Convert the offset to the appropriate size and signedness. 454249423Sdim Offset = svalBuilder.convertToArrayIndex(Offset).castAs<NonLoc>(); 455218887Sdim 456218887Sdim if (!ElemR) { 457218887Sdim // 458218887Sdim // If the base region is not an ElementRegion, create one. 459218887Sdim // This can happen in the following example: 460218887Sdim // 461218887Sdim // char *p = __builtin_alloc(10); 462218887Sdim // p[1] = 8; 463218887Sdim // 464218887Sdim // Observe that 'p' binds to an AllocaRegion. 465218887Sdim // 466218887Sdim return loc::MemRegionVal(MRMgr.getElementRegion(elementType, Offset, 467218887Sdim BaseRegion, Ctx)); 468218887Sdim } 469218887Sdim 470218887Sdim SVal BaseIdx = ElemR->getIndex(); 471218887Sdim 472249423Sdim if (!BaseIdx.getAs<nonloc::ConcreteInt>()) 473218887Sdim return UnknownVal(); 474218887Sdim 475249423Sdim const llvm::APSInt &BaseIdxI = 476249423Sdim BaseIdx.castAs<nonloc::ConcreteInt>().getValue(); 477218887Sdim 478218887Sdim // Only allow non-integer offsets if the base region has no offset itself. 479218887Sdim // FIXME: This is a somewhat arbitrary restriction. We should be using 480218887Sdim // SValBuilder here to add the two offsets without checking their types. 481249423Sdim if (!Offset.getAs<nonloc::ConcreteInt>()) { 482218887Sdim if (isa<ElementRegion>(BaseRegion->StripCasts())) 483218887Sdim return UnknownVal(); 484218887Sdim 485218887Sdim return loc::MemRegionVal(MRMgr.getElementRegion(elementType, Offset, 486218887Sdim ElemR->getSuperRegion(), 487218887Sdim Ctx)); 488218887Sdim } 489218887Sdim 490249423Sdim const llvm::APSInt& OffI = Offset.castAs<nonloc::ConcreteInt>().getValue(); 491218887Sdim assert(BaseIdxI.isSigned()); 492218887Sdim 493218887Sdim // Compute the new index. 494218887Sdim nonloc::ConcreteInt NewIdx(svalBuilder.getBasicValueFactory().getValue(BaseIdxI + 495218887Sdim OffI)); 496218887Sdim 497218887Sdim // Construct the new ElementRegion. 498218887Sdim const MemRegion *ArrayR = ElemR->getSuperRegion(); 499218887Sdim return loc::MemRegionVal(MRMgr.getElementRegion(elementType, NewIdx, ArrayR, 500218887Sdim Ctx)); 501218887Sdim} 502226633Sdim 503226633SdimStoreManager::BindingsHandler::~BindingsHandler() {} 504226633Sdim 505234353Sdimbool StoreManager::FindUniqueBinding::HandleBinding(StoreManager& SMgr, 506234353Sdim Store store, 507234353Sdim const MemRegion* R, 508234353Sdim SVal val) { 509234353Sdim SymbolRef SymV = val.getAsLocSymbol(); 510234353Sdim if (!SymV || SymV != Sym) 511234353Sdim return true; 512234353Sdim 513234353Sdim if (Binding) { 514234353Sdim First = false; 515234353Sdim return false; 516234353Sdim } 517234353Sdim else 518234353Sdim Binding = R; 519234353Sdim 520234353Sdim return true; 521234353Sdim} 522