Store.cpp revision 18c66fdc3c4008d335885695fe36fb5353c5f672
1c62abc1012feb0b15eff091b02c176649766a347Ted Kremenek//== Store.cpp - Interface for maps from Locations to Values ----*- C++ -*--==// 2c62abc1012feb0b15eff091b02c176649766a347Ted Kremenek// 3c62abc1012feb0b15eff091b02c176649766a347Ted Kremenek// The LLVM Compiler Infrastructure 4c62abc1012feb0b15eff091b02c176649766a347Ted Kremenek// 5c62abc1012feb0b15eff091b02c176649766a347Ted Kremenek// This file is distributed under the University of Illinois Open Source 6c62abc1012feb0b15eff091b02c176649766a347Ted Kremenek// License. See LICENSE.TXT for details. 7c62abc1012feb0b15eff091b02c176649766a347Ted Kremenek// 8c62abc1012feb0b15eff091b02c176649766a347Ted Kremenek//===----------------------------------------------------------------------===// 9c62abc1012feb0b15eff091b02c176649766a347Ted Kremenek// 10c62abc1012feb0b15eff091b02c176649766a347Ted Kremenek// This file defined the types Store and StoreManager. 11c62abc1012feb0b15eff091b02c176649766a347Ted Kremenek// 12c62abc1012feb0b15eff091b02c176649766a347Ted Kremenek//===----------------------------------------------------------------------===// 13c62abc1012feb0b15eff091b02c176649766a347Ted Kremenek 149b663716449b618ba0390b1dbebc54fa8e971124Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" 1518c66fdc3c4008d335885695fe36fb5353c5f672Ted Kremenek#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" 16199c3d6cd16aebbb9c7f0d42af9d922c9628bf70Ken Dyck#include "clang/AST/CharUnits.h" 17c62abc1012feb0b15eff091b02c176649766a347Ted Kremenek 18c62abc1012feb0b15eff091b02c176649766a347Ted Kremenekusing namespace clang; 199ef6537a894c33003359b1f9b9676e9178e028b7Ted Kremenekusing namespace ento; 20c62abc1012feb0b15eff091b02c176649766a347Ted Kremenek 2118c66fdc3c4008d335885695fe36fb5353c5f672Ted KremenekStoreManager::StoreManager(ProgramStateManager &stateMgr) 22c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek : svalBuilder(stateMgr.getSValBuilder()), StateMgr(stateMgr), 23c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek MRMgr(svalBuilder.getRegionManager()), Ctx(stateMgr.getContext()) {} 24c62abc1012feb0b15eff091b02c176649766a347Ted Kremenek 2518c66fdc3c4008d335885695fe36fb5353c5f672Ted KremenekStoreRef StoreManager::enterStackFrame(const ProgramState *state, 2677a4d5687c2cb3199c689892c9d040a94ff270afTed Kremenek const StackFrameContext *frame) { 2777a4d5687c2cb3199c689892c9d040a94ff270afTed Kremenek return StoreRef(state->getStore(), *this); 28ff59efd65bb1f2f8d005079597f814a3c8381f95Jordy Rose} 29ff59efd65bb1f2f8d005079597f814a3c8381f95Jordy Rose 3009270cc1b9cdd4c50012cb7984df8745e05833e5Zhongxing Xuconst MemRegion *StoreManager::MakeElementRegion(const MemRegion *Base, 31652be346f74feba027bcbdeb6a3e3f4755a0e62cZhongxing Xu QualType EleTy, uint64_t index) { 32c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek NonLoc idx = svalBuilder.makeArrayIndex(index); 33c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek return MRMgr.getElementRegion(EleTy, idx, Base, svalBuilder.getContext()); 34411af40d038947b6d2a8ad9549c85c1c4c52d15aTed Kremenek} 35411af40d038947b6d2a8ad9549c85c1c4c52d15aTed Kremenek 3619e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek// FIXME: Merge with the implementation of the same method in MemRegion.cpp 37169077dde4d91270a7495793f1e00b22aa0bc7caTed Kremenekstatic bool IsCompleteType(ASTContext &Ctx, QualType Ty) { 386217b80b7a1379b74cced1c076338262c3c980b3Ted Kremenek if (const RecordType *RT = Ty->getAs<RecordType>()) { 39169077dde4d91270a7495793f1e00b22aa0bc7caTed Kremenek const RecordDecl *D = RT->getDecl(); 40952b017601f9c82b51119c3a1600f1312a833db9Douglas Gregor if (!D->getDefinition()) 41169077dde4d91270a7495793f1e00b22aa0bc7caTed Kremenek return false; 42169077dde4d91270a7495793f1e00b22aa0bc7caTed Kremenek } 431eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 44169077dde4d91270a7495793f1e00b22aa0bc7caTed Kremenek return true; 45169077dde4d91270a7495793f1e00b22aa0bc7caTed Kremenek} 46169077dde4d91270a7495793f1e00b22aa0bc7caTed Kremenek 4777a4d5687c2cb3199c689892c9d040a94ff270afTed KremenekStoreRef StoreManager::BindDefault(Store store, const MemRegion *R, SVal V) { 4877a4d5687c2cb3199c689892c9d040a94ff270afTed Kremenek return StoreRef(store, *this); 4977a4d5687c2cb3199c689892c9d040a94ff270afTed Kremenek} 5077a4d5687c2cb3199c689892c9d040a94ff270afTed Kremenek 51856c6bcaea56e05255e9f3997ddd56b5c18a14f0Zhongxing Xuconst ElementRegion *StoreManager::GetElementZeroRegion(const MemRegion *R, 52856c6bcaea56e05255e9f3997ddd56b5c18a14f0Zhongxing Xu QualType T) { 53c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek NonLoc idx = svalBuilder.makeZeroArrayIndex(); 54856c6bcaea56e05255e9f3997ddd56b5c18a14f0Zhongxing Xu assert(!T.isNull()); 55856c6bcaea56e05255e9f3997ddd56b5c18a14f0Zhongxing Xu return MRMgr.getElementRegion(T, idx, R, Ctx); 56856c6bcaea56e05255e9f3997ddd56b5c18a14f0Zhongxing Xu} 57856c6bcaea56e05255e9f3997ddd56b5c18a14f0Zhongxing Xu 582534528c22260211a073e192c38d0db84c70c327Ted Kremenekconst MemRegion *StoreManager::castRegion(const MemRegion *R, QualType CastToTy) { 591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 609c378f705405d37f49795d5e915989de774fe11fTed Kremenek ASTContext &Ctx = StateMgr.getContext(); 611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 62b9a44250c502cf9f9a2c18ccd50f06158dd7357bTed Kremenek // Handle casts to Objective-C objects. 6319e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek if (CastToTy->isObjCObjectPointerType()) 64479529e679957fbb92b56e116e3c86734429331eZhongxing Xu return R->StripCasts(); 6519e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek 6663b9cfe8f2aaec53710b59e565bb8d5afb558b40Ted Kremenek if (CastToTy->isBlockPointerType()) { 67abd46e13cfd48f2c9bf26d9759edb4366aaa6d5bTed Kremenek // FIXME: We may need different solutions, depending on the symbol 6863b9cfe8f2aaec53710b59e565bb8d5afb558b40Ted Kremenek // involved. Blocks can be casted to/from 'id', as they can be treated 69abd46e13cfd48f2c9bf26d9759edb4366aaa6d5bTed Kremenek // as Objective-C objects. This could possibly be handled by enhancing 701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // our reasoning of downcasts of symbolic objects. 71abd46e13cfd48f2c9bf26d9759edb4366aaa6d5bTed Kremenek if (isa<CodeTextRegion>(R) || isa<SymbolicRegion>(R)) 7209270cc1b9cdd4c50012cb7984df8745e05833e5Zhongxing Xu return R; 7363b9cfe8f2aaec53710b59e565bb8d5afb558b40Ted Kremenek 7463b9cfe8f2aaec53710b59e565bb8d5afb558b40Ted Kremenek // We don't know what to make of it. Return a NULL region, which 7563b9cfe8f2aaec53710b59e565bb8d5afb558b40Ted Kremenek // will be interpretted as UnknownVal. 7609270cc1b9cdd4c50012cb7984df8745e05833e5Zhongxing Xu return NULL; 7763b9cfe8f2aaec53710b59e565bb8d5afb558b40Ted Kremenek } 78411af40d038947b6d2a8ad9549c85c1c4c52d15aTed Kremenek 7948ce7deb86ffb1e028ac9a8e7cddffc32843c26cTed Kremenek // Now assume we are casting from pointer to pointer. Other cases should 8048ce7deb86ffb1e028ac9a8e7cddffc32843c26cTed Kremenek // already be handled. 81b14175a5371a6c71f3b2dbe4e7aa14803ac38c54Argyrios Kyrtzidis QualType PointeeTy = CastToTy->getPointeeType(); 829a108eb88f93c524dfa5fb2c3fea3896b1eb6525Ted Kremenek QualType CanonPointeeTy = Ctx.getCanonicalType(PointeeTy); 839a108eb88f93c524dfa5fb2c3fea3896b1eb6525Ted Kremenek 849a108eb88f93c524dfa5fb2c3fea3896b1eb6525Ted Kremenek // Handle casts to void*. We just pass the region through. 85a4923eb7c4b04d360cb2747641a5e92818edf804Douglas Gregor if (CanonPointeeTy.getLocalUnqualifiedType() == Ctx.VoidTy) 8609270cc1b9cdd4c50012cb7984df8745e05833e5Zhongxing Xu return R; 871eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 889a108eb88f93c524dfa5fb2c3fea3896b1eb6525Ted Kremenek // Handle casts from compatible types. 8919e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek if (R->isBoundable()) 909697934650354bed2e509d8e7e44f21a1fb00f76Ted Kremenek if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(R)) { 91018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu QualType ObjTy = Ctx.getCanonicalType(TR->getValueType()); 929a108eb88f93c524dfa5fb2c3fea3896b1eb6525Ted Kremenek if (CanonPointeeTy == ObjTy) 9309270cc1b9cdd4c50012cb7984df8745e05833e5Zhongxing Xu return R; 9419e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek } 9519e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek 9648ce7deb86ffb1e028ac9a8e7cddffc32843c26cTed Kremenek // Process region cast according to the kind of the region being cast. 97fc8f57c31d8336db0ccb2ce8eb9ebf52228a47c1Ted Kremenek switch (R->getKind()) { 98de0d26310191215a6d1d189dc419f87af18ce6beTed Kremenek case MemRegion::CXXThisRegionKind: 9967d1287035767f4f6c8ca0c2bb755990012a44caTed Kremenek case MemRegion::GenericMemSpaceRegionKind: 10067d1287035767f4f6c8ca0c2bb755990012a44caTed Kremenek case MemRegion::StackLocalsSpaceRegionKind: 10167d1287035767f4f6c8ca0c2bb755990012a44caTed Kremenek case MemRegion::StackArgumentsSpaceRegionKind: 10267d1287035767f4f6c8ca0c2bb755990012a44caTed Kremenek case MemRegion::HeapSpaceRegionKind: 1032b87ae45e129b941d0a4d221c9d4842385a119bdTed Kremenek case MemRegion::UnknownSpaceRegionKind: 104dcee3ce97fc76f20ce8f5a7451071e3dec537073Ted Kremenek case MemRegion::NonStaticGlobalSpaceRegionKind: 105dcee3ce97fc76f20ce8f5a7451071e3dec537073Ted Kremenek case MemRegion::StaticGlobalSpaceRegionKind: { 106fc8f57c31d8336db0ccb2ce8eb9ebf52228a47c1Ted Kremenek assert(0 && "Invalid region cast"); 107fc8f57c31d8336db0ccb2ce8eb9ebf52228a47c1Ted Kremenek break; 1081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump } 1091e4a32acfad6a9f4cf555fdbc5c6c44c558b9fcbTed Kremenek 110eb1c7a04509f5d25c09005a6d46bd8bbb3ca88cbTed Kremenek case MemRegion::FunctionTextRegionKind: 111bf0fe6c5b7bd7bc67b6b3ef0acb22bf4811f2a1bTed Kremenek case MemRegion::BlockTextRegionKind: 1121e4a32acfad6a9f4cf555fdbc5c6c44c558b9fcbTed Kremenek case MemRegion::BlockDataRegionKind: 113fc8f57c31d8336db0ccb2ce8eb9ebf52228a47c1Ted Kremenek case MemRegion::StringRegionKind: 114fc8f57c31d8336db0ccb2ce8eb9ebf52228a47c1Ted Kremenek // FIXME: Need to handle arbitrary downcasts. 11519e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek case MemRegion::SymbolicRegionKind: 11619e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek case MemRegion::AllocaRegionKind: 117fc8f57c31d8336db0ccb2ce8eb9ebf52228a47c1Ted Kremenek case MemRegion::CompoundLiteralRegionKind: 118fc8f57c31d8336db0ccb2ce8eb9ebf52228a47c1Ted Kremenek case MemRegion::FieldRegionKind: 119fc8f57c31d8336db0ccb2ce8eb9ebf52228a47c1Ted Kremenek case MemRegion::ObjCIvarRegionKind: 1201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump case MemRegion::VarRegionKind: 12102fe28c8a6da29d4ad88d0900c133dcf22d24a75Zhongxing Xu case MemRegion::CXXTempObjectRegionKind: 12202fe28c8a6da29d4ad88d0900c133dcf22d24a75Zhongxing Xu case MemRegion::CXXBaseObjectRegionKind: 12309270cc1b9cdd4c50012cb7984df8745e05833e5Zhongxing Xu return MakeElementRegion(R, PointeeTy); 1241eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 12519e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek case MemRegion::ElementRegionKind: { 12619e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // If we are casting from an ElementRegion to another type, the 12719e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // algorithm is as follows: 12819e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // 12919e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // (1) Compute the "raw offset" of the ElementRegion from the 13019e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // base region. This is done by calling 'getAsRawOffset()'. 13119e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // 1321eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // (2a) If we get a 'RegionRawOffset' after calling 13319e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // 'getAsRawOffset()', determine if the absolute offset 1341eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // can be exactly divided into chunks of the size of the 1351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // casted-pointee type. If so, create a new ElementRegion with 13619e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // the pointee-cast type as the new ElementType and the index 13719e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // being the offset divded by the chunk size. If not, create 13819e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // a new ElementRegion at offset 0 off the raw offset region. 13919e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // 14019e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // (2b) If we don't a get a 'RegionRawOffset' after calling 14119e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // 'getAsRawOffset()', it means that we are at offset 0. 1421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // 14319e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // FIXME: Handle symbolic raw offsets. 1441eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14519e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek const ElementRegion *elementR = cast<ElementRegion>(R); 1467caf9b369cba6edaf6eac25121cbc65ee938f14dZhongxing Xu const RegionRawOffset &rawOff = elementR->getAsArrayOffset(); 14719e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek const MemRegion *baseR = rawOff.getRegion(); 1481eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 14919e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // If we cannot compute a raw offset, throw up our hands and return 15019e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // a NULL MemRegion*. 15119e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek if (!baseR) 15209270cc1b9cdd4c50012cb7984df8745e05833e5Zhongxing Xu return NULL; 1531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 1549ff2b13aee0f89d23ef4820218f9b88bb5e5c1c1Ken Dyck CharUnits off = rawOff.getOffset(); 1551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 156199c3d6cd16aebbb9c7f0d42af9d922c9628bf70Ken Dyck if (off.isZero()) { 15719e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // Edge case: we are at 0 bytes off the beginning of baseR. We 15819e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // check to see if type we are casting to is the same as the base 1591eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump // region. If so, just return the base region. 1609697934650354bed2e509d8e7e44f21a1fb00f76Ted Kremenek if (const TypedValueRegion *TR = dyn_cast<TypedValueRegion>(baseR)) { 161018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu QualType ObjTy = Ctx.getCanonicalType(TR->getValueType()); 16219e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek QualType CanonPointeeTy = Ctx.getCanonicalType(PointeeTy); 16319e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek if (CanonPointeeTy == ObjTy) 16409270cc1b9cdd4c50012cb7984df8745e05833e5Zhongxing Xu return baseR; 16519e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek } 1661eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 16719e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // Otherwise, create a new ElementRegion at offset 0. 16809270cc1b9cdd4c50012cb7984df8745e05833e5Zhongxing Xu return MakeElementRegion(baseR, PointeeTy); 169169077dde4d91270a7495793f1e00b22aa0bc7caTed Kremenek } 1701eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17119e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // We have a non-zero offset from the base region. We want to determine 17219e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // if the offset can be evenly divided by sizeof(PointeeTy). If so, 17319e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // we create an ElementRegion whose index is that value. Otherwise, we 17419e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // create two ElementRegions, one that reflects a raw offset and the other 17519e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // that reflects the cast. 1761eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 17719e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // Compute the index for the new ElementRegion. 17819e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek int64_t newIndex = 0; 17919e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek const MemRegion *newSuperR = 0; 180169077dde4d91270a7495793f1e00b22aa0bc7caTed Kremenek 18119e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // We can only compute sizeof(PointeeTy) if it is a complete type. 18219e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek if (IsCompleteType(Ctx, PointeeTy)) { 18319e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // Compute the size in **bytes**. 184199c3d6cd16aebbb9c7f0d42af9d922c9628bf70Ken Dyck CharUnits pointeeTySize = Ctx.getTypeSizeInChars(PointeeTy); 185974d97b251aaf5a735af83367cd3a930f3eb4333Ted Kremenek if (!pointeeTySize.isZero()) { 186974d97b251aaf5a735af83367cd3a930f3eb4333Ted Kremenek // Is the offset a multiple of the size? If so, we can layer the 187974d97b251aaf5a735af83367cd3a930f3eb4333Ted Kremenek // ElementRegion (with elementType == PointeeTy) directly on top of 188974d97b251aaf5a735af83367cd3a930f3eb4333Ted Kremenek // the base region. 189974d97b251aaf5a735af83367cd3a930f3eb4333Ted Kremenek if (off % pointeeTySize == 0) { 190974d97b251aaf5a735af83367cd3a930f3eb4333Ted Kremenek newIndex = off / pointeeTySize; 191974d97b251aaf5a735af83367cd3a930f3eb4333Ted Kremenek newSuperR = baseR; 192974d97b251aaf5a735af83367cd3a930f3eb4333Ted Kremenek } 19319e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek } 19419e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek } 1951eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 19619e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek if (!newSuperR) { 19719e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // Create an intermediate ElementRegion to represent the raw byte. 19819e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek // This will be the super region of the final ElementRegion. 199199c3d6cd16aebbb9c7f0d42af9d922c9628bf70Ken Dyck newSuperR = MakeElementRegion(baseR, Ctx.CharTy, off.getQuantity()); 20019e1f0ba5cec738ce6cebe3fe0e1edc782206494Ted Kremenek } 2011eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20209270cc1b9cdd4c50012cb7984df8745e05833e5Zhongxing Xu return MakeElementRegion(newSuperR, PointeeTy, newIndex); 20348ce7deb86ffb1e028ac9a8e7cddffc32843c26cTed Kremenek } 20448ce7deb86ffb1e028ac9a8e7cddffc32843c26cTed Kremenek } 2051eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump 20609270cc1b9cdd4c50012cb7984df8745e05833e5Zhongxing Xu assert(0 && "unreachable"); 20709270cc1b9cdd4c50012cb7984df8745e05833e5Zhongxing Xu return 0; 20848ce7deb86ffb1e028ac9a8e7cddffc32843c26cTed Kremenek} 2091894dce96476dbe58c0e60d47f8987cbeb3d3869Ted Kremenek 2101894dce96476dbe58c0e60d47f8987cbeb3d3869Ted Kremenek 2111894dce96476dbe58c0e60d47f8987cbeb3d3869Ted Kremenek/// CastRetrievedVal - Used by subclasses of StoreManager to implement 2121894dce96476dbe58c0e60d47f8987cbeb3d3869Ted Kremenek/// implicit casts that arise from loads from regions that are reinterpreted 2131894dce96476dbe58c0e60d47f8987cbeb3d3869Ted Kremenek/// as another region. 2149697934650354bed2e509d8e7e44f21a1fb00f76Ted KremenekSVal StoreManager::CastRetrievedVal(SVal V, const TypedValueRegion *R, 215c50e6df965ff264952d8d5805d151f89c89af302Ted Kremenek QualType castTy, bool performTestOnly) { 216852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek 2171894dce96476dbe58c0e60d47f8987cbeb3d3869Ted Kremenek if (castTy.isNull()) 218652be346f74feba027bcbdeb6a3e3f4755a0e62cZhongxing Xu return V; 219852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek 220c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek ASTContext &Ctx = svalBuilder.getContext(); 2212f4a6b25a7409f6f05e8a5e6864de21a337c8958Zhongxing Xu 222c50e6df965ff264952d8d5805d151f89c89af302Ted Kremenek if (performTestOnly) { 223c50e6df965ff264952d8d5805d151f89c89af302Ted Kremenek // Automatically translate references to pointers. 224018220c343c103b7dfaa117a7a474c7a7fd6d068Zhongxing Xu QualType T = R->getValueType(); 225c50e6df965ff264952d8d5805d151f89c89af302Ted Kremenek if (const ReferenceType *RT = T->getAs<ReferenceType>()) 226c50e6df965ff264952d8d5805d151f89c89af302Ted Kremenek T = Ctx.getPointerType(RT->getPointeeType()); 227c50e6df965ff264952d8d5805d151f89c89af302Ted Kremenek 228c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek assert(svalBuilder.getContext().hasSameUnqualifiedType(castTy, T)); 229c50e6df965ff264952d8d5805d151f89c89af302Ted Kremenek return V; 230c50e6df965ff264952d8d5805d151f89c89af302Ted Kremenek } 231c50e6df965ff264952d8d5805d151f89c89af302Ted Kremenek 232c50e6df965ff264952d8d5805d151f89c89af302Ted Kremenek if (const Loc *L = dyn_cast<Loc>(&V)) 2339f8862aa64300ef97b8fe85034ee93bbc03e3b7bZhanyong Wan return svalBuilder.evalCastFromLoc(*L, castTy); 234c50e6df965ff264952d8d5805d151f89c89af302Ted Kremenek else if (const NonLoc *NL = dyn_cast<NonLoc>(&V)) 2359f8862aa64300ef97b8fe85034ee93bbc03e3b7bZhanyong Wan return svalBuilder.evalCastFromNonLoc(*NL, castTy); 236c50e6df965ff264952d8d5805d151f89c89af302Ted Kremenek 237652be346f74feba027bcbdeb6a3e3f4755a0e62cZhongxing Xu return V; 2381894dce96476dbe58c0e60d47f8987cbeb3d3869Ted Kremenek} 2391894dce96476dbe58c0e60d47f8987cbeb3d3869Ted Kremenek 2409c378f705405d37f49795d5e915989de774fe11fTed KremenekSVal StoreManager::getLValueFieldOrIvar(const Decl *D, SVal Base) { 241c1511e04998e685c9e030323e248363b9633267dZhongxing Xu if (Base.isUnknownOrUndef()) 242c1511e04998e685c9e030323e248363b9633267dZhongxing Xu return Base; 243c1511e04998e685c9e030323e248363b9633267dZhongxing Xu 244c1511e04998e685c9e030323e248363b9633267dZhongxing Xu Loc BaseL = cast<Loc>(Base); 245c1511e04998e685c9e030323e248363b9633267dZhongxing Xu const MemRegion* BaseR = 0; 246c1511e04998e685c9e030323e248363b9633267dZhongxing Xu 247c1511e04998e685c9e030323e248363b9633267dZhongxing Xu switch (BaseL.getSubKind()) { 248c1511e04998e685c9e030323e248363b9633267dZhongxing Xu case loc::MemRegionKind: 249c1511e04998e685c9e030323e248363b9633267dZhongxing Xu BaseR = cast<loc::MemRegionVal>(BaseL).getRegion(); 250c1511e04998e685c9e030323e248363b9633267dZhongxing Xu break; 251c1511e04998e685c9e030323e248363b9633267dZhongxing Xu 252c1511e04998e685c9e030323e248363b9633267dZhongxing Xu case loc::GotoLabelKind: 253c1511e04998e685c9e030323e248363b9633267dZhongxing Xu // These are anormal cases. Flag an undefined value. 254c1511e04998e685c9e030323e248363b9633267dZhongxing Xu return UndefinedVal(); 255c1511e04998e685c9e030323e248363b9633267dZhongxing Xu 256c1511e04998e685c9e030323e248363b9633267dZhongxing Xu case loc::ConcreteIntKind: 257c1511e04998e685c9e030323e248363b9633267dZhongxing Xu // While these seem funny, this can happen through casts. 258c1511e04998e685c9e030323e248363b9633267dZhongxing Xu // FIXME: What we should return is the field offset. For example, 259c1511e04998e685c9e030323e248363b9633267dZhongxing Xu // add the field offset to the integer value. That way funny things 260c1511e04998e685c9e030323e248363b9633267dZhongxing Xu // like this work properly: &(((struct foo *) 0xa)->f) 261c1511e04998e685c9e030323e248363b9633267dZhongxing Xu return Base; 262c1511e04998e685c9e030323e248363b9633267dZhongxing Xu 263c1511e04998e685c9e030323e248363b9633267dZhongxing Xu default: 264c1511e04998e685c9e030323e248363b9633267dZhongxing Xu assert(0 && "Unhandled Base."); 265c1511e04998e685c9e030323e248363b9633267dZhongxing Xu return Base; 266c1511e04998e685c9e030323e248363b9633267dZhongxing Xu } 267c1511e04998e685c9e030323e248363b9633267dZhongxing Xu 268c1511e04998e685c9e030323e248363b9633267dZhongxing Xu // NOTE: We must have this check first because ObjCIvarDecl is a subclass 269c1511e04998e685c9e030323e248363b9633267dZhongxing Xu // of FieldDecl. 270c1511e04998e685c9e030323e248363b9633267dZhongxing Xu if (const ObjCIvarDecl *ID = dyn_cast<ObjCIvarDecl>(D)) 271c1511e04998e685c9e030323e248363b9633267dZhongxing Xu return loc::MemRegionVal(MRMgr.getObjCIvarRegion(ID, BaseR)); 272c1511e04998e685c9e030323e248363b9633267dZhongxing Xu 273c1511e04998e685c9e030323e248363b9633267dZhongxing Xu return loc::MemRegionVal(MRMgr.getFieldRegion(cast<FieldDecl>(D), BaseR)); 274c1511e04998e685c9e030323e248363b9633267dZhongxing Xu} 27552535688b1339e0b3898ac0d670052482851a3abZhongxing Xu 27602282acd7a42d06a3178e3102d34a585bd82dd9fTed KremenekSVal StoreManager::getLValueElement(QualType elementType, NonLoc Offset, 27752535688b1339e0b3898ac0d670052482851a3abZhongxing Xu SVal Base) { 27852535688b1339e0b3898ac0d670052482851a3abZhongxing Xu 27952535688b1339e0b3898ac0d670052482851a3abZhongxing Xu // If the base is an unknown or undefined value, just return it back. 28052535688b1339e0b3898ac0d670052482851a3abZhongxing Xu // FIXME: For absolute pointer addresses, we just return that value back as 28152535688b1339e0b3898ac0d670052482851a3abZhongxing Xu // well, although in reality we should return the offset added to that 28252535688b1339e0b3898ac0d670052482851a3abZhongxing Xu // value. 28352535688b1339e0b3898ac0d670052482851a3abZhongxing Xu if (Base.isUnknownOrUndef() || isa<loc::ConcreteInt>(Base)) 28452535688b1339e0b3898ac0d670052482851a3abZhongxing Xu return Base; 28552535688b1339e0b3898ac0d670052482851a3abZhongxing Xu 28652535688b1339e0b3898ac0d670052482851a3abZhongxing Xu const MemRegion* BaseRegion = cast<loc::MemRegionVal>(Base).getRegion(); 28752535688b1339e0b3898ac0d670052482851a3abZhongxing Xu 28852535688b1339e0b3898ac0d670052482851a3abZhongxing Xu // Pointer of any type can be cast and used as array base. 28952535688b1339e0b3898ac0d670052482851a3abZhongxing Xu const ElementRegion *ElemR = dyn_cast<ElementRegion>(BaseRegion); 29052535688b1339e0b3898ac0d670052482851a3abZhongxing Xu 29152535688b1339e0b3898ac0d670052482851a3abZhongxing Xu // Convert the offset to the appropriate size and signedness. 292c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek Offset = cast<NonLoc>(svalBuilder.convertToArrayIndex(Offset)); 29352535688b1339e0b3898ac0d670052482851a3abZhongxing Xu 29452535688b1339e0b3898ac0d670052482851a3abZhongxing Xu if (!ElemR) { 29552535688b1339e0b3898ac0d670052482851a3abZhongxing Xu // 29652535688b1339e0b3898ac0d670052482851a3abZhongxing Xu // If the base region is not an ElementRegion, create one. 29752535688b1339e0b3898ac0d670052482851a3abZhongxing Xu // This can happen in the following example: 29852535688b1339e0b3898ac0d670052482851a3abZhongxing Xu // 29952535688b1339e0b3898ac0d670052482851a3abZhongxing Xu // char *p = __builtin_alloc(10); 30052535688b1339e0b3898ac0d670052482851a3abZhongxing Xu // p[1] = 8; 30152535688b1339e0b3898ac0d670052482851a3abZhongxing Xu // 30252535688b1339e0b3898ac0d670052482851a3abZhongxing Xu // Observe that 'p' binds to an AllocaRegion. 30352535688b1339e0b3898ac0d670052482851a3abZhongxing Xu // 30452535688b1339e0b3898ac0d670052482851a3abZhongxing Xu return loc::MemRegionVal(MRMgr.getElementRegion(elementType, Offset, 30552535688b1339e0b3898ac0d670052482851a3abZhongxing Xu BaseRegion, Ctx)); 30652535688b1339e0b3898ac0d670052482851a3abZhongxing Xu } 30752535688b1339e0b3898ac0d670052482851a3abZhongxing Xu 30852535688b1339e0b3898ac0d670052482851a3abZhongxing Xu SVal BaseIdx = ElemR->getIndex(); 30952535688b1339e0b3898ac0d670052482851a3abZhongxing Xu 31052535688b1339e0b3898ac0d670052482851a3abZhongxing Xu if (!isa<nonloc::ConcreteInt>(BaseIdx)) 31152535688b1339e0b3898ac0d670052482851a3abZhongxing Xu return UnknownVal(); 31252535688b1339e0b3898ac0d670052482851a3abZhongxing Xu 31352535688b1339e0b3898ac0d670052482851a3abZhongxing Xu const llvm::APSInt& BaseIdxI = cast<nonloc::ConcreteInt>(BaseIdx).getValue(); 314e701117b21356d3c60133315b5bdd50232ec6ccaJordy Rose 315e701117b21356d3c60133315b5bdd50232ec6ccaJordy Rose // Only allow non-integer offsets if the base region has no offset itself. 316e701117b21356d3c60133315b5bdd50232ec6ccaJordy Rose // FIXME: This is a somewhat arbitrary restriction. We should be using 317846eabd187be4bfe992e8bca131166b734d86e0dTed Kremenek // SValBuilder here to add the two offsets without checking their types. 318e701117b21356d3c60133315b5bdd50232ec6ccaJordy Rose if (!isa<nonloc::ConcreteInt>(Offset)) { 319e701117b21356d3c60133315b5bdd50232ec6ccaJordy Rose if (isa<ElementRegion>(BaseRegion->StripCasts())) 320e701117b21356d3c60133315b5bdd50232ec6ccaJordy Rose return UnknownVal(); 321e701117b21356d3c60133315b5bdd50232ec6ccaJordy Rose 322e701117b21356d3c60133315b5bdd50232ec6ccaJordy Rose return loc::MemRegionVal(MRMgr.getElementRegion(elementType, Offset, 323e701117b21356d3c60133315b5bdd50232ec6ccaJordy Rose ElemR->getSuperRegion(), 324e701117b21356d3c60133315b5bdd50232ec6ccaJordy Rose Ctx)); 325e701117b21356d3c60133315b5bdd50232ec6ccaJordy Rose } 326e701117b21356d3c60133315b5bdd50232ec6ccaJordy Rose 32752535688b1339e0b3898ac0d670052482851a3abZhongxing Xu const llvm::APSInt& OffI = cast<nonloc::ConcreteInt>(Offset).getValue(); 32852535688b1339e0b3898ac0d670052482851a3abZhongxing Xu assert(BaseIdxI.isSigned()); 32952535688b1339e0b3898ac0d670052482851a3abZhongxing Xu 33052535688b1339e0b3898ac0d670052482851a3abZhongxing Xu // Compute the new index. 331c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek nonloc::ConcreteInt NewIdx(svalBuilder.getBasicValueFactory().getValue(BaseIdxI + 33202282acd7a42d06a3178e3102d34a585bd82dd9fTed Kremenek OffI)); 33352535688b1339e0b3898ac0d670052482851a3abZhongxing Xu 33452535688b1339e0b3898ac0d670052482851a3abZhongxing Xu // Construct the new ElementRegion. 33552535688b1339e0b3898ac0d670052482851a3abZhongxing Xu const MemRegion *ArrayR = ElemR->getSuperRegion(); 33652535688b1339e0b3898ac0d670052482851a3abZhongxing Xu return loc::MemRegionVal(MRMgr.getElementRegion(elementType, NewIdx, ArrayR, 33752535688b1339e0b3898ac0d670052482851a3abZhongxing Xu Ctx)); 33852535688b1339e0b3898ac0d670052482851a3abZhongxing Xu} 339a4c7a4314ffbe402091695874e93d9b0a79c8099Ted Kremenek 340a4c7a4314ffbe402091695874e93d9b0a79c8099Ted KremenekStoreManager::BindingsHandler::~BindingsHandler() {} 341a4c7a4314ffbe402091695874e93d9b0a79c8099Ted Kremenek 342