Ted Kremenek | c62abc1 | 2009-04-21 21:51:34 +0000 | [diff] [blame] | 1 | //== Store.cpp - Interface for maps from Locations to Values ----*- C++ -*--==// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This file defined the types Store and StoreManager. |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | |
| 14 | #include "clang/Analysis/PathSensitive/Store.h" |
| 15 | #include "clang/Analysis/PathSensitive/GRState.h" |
| 16 | |
| 17 | using namespace clang; |
| 18 | |
Ted Kremenek | f7a0cf4 | 2009-07-29 21:43:22 +0000 | [diff] [blame^] | 19 | StoreManager::StoreManager(GRStateManager &stateMgr) |
| 20 | : ValMgr(stateMgr.getValueManager()), StateMgr(stateMgr), |
Ted Kremenek | c62abc1 | 2009-04-21 21:51:34 +0000 | [diff] [blame] | 21 | MRMgr(ValMgr.getRegionManager()) {} |
| 22 | |
| 23 | StoreManager::CastResult |
Ted Kremenek | 411af40 | 2009-07-06 22:23:45 +0000 | [diff] [blame] | 24 | StoreManager::MakeElementRegion(const GRState *state, const MemRegion *region, |
| 25 | QualType pointeeTy, QualType castToTy) { |
| 26 | |
| 27 | // Record the cast type of the region. |
| 28 | state = setCastType(state, region, castToTy); |
| 29 | |
| 30 | // Create a new ElementRegion at offset 0. |
| 31 | SVal idx = ValMgr.makeZeroArrayIndex(); |
| 32 | return CastResult(state, MRMgr.getElementRegion(pointeeTy, idx, region, |
| 33 | ValMgr.getContext())); |
| 34 | } |
| 35 | |
Ted Kremenek | 169077d | 2009-07-06 23:47:19 +0000 | [diff] [blame] | 36 | static bool IsCompleteType(ASTContext &Ctx, QualType Ty) { |
Ted Kremenek | 35366a6 | 2009-07-17 17:50:17 +0000 | [diff] [blame] | 37 | if (const RecordType *RT = Ty->getAsRecordType()) { |
Ted Kremenek | 169077d | 2009-07-06 23:47:19 +0000 | [diff] [blame] | 38 | const RecordDecl *D = RT->getDecl(); |
| 39 | if (!D->getDefinition(Ctx)) |
| 40 | return false; |
| 41 | } |
| 42 | |
| 43 | return true; |
| 44 | } |
| 45 | |
Ted Kremenek | 411af40 | 2009-07-06 22:23:45 +0000 | [diff] [blame] | 46 | StoreManager::CastResult |
Ted Kremenek | f7a0cf4 | 2009-07-29 21:43:22 +0000 | [diff] [blame^] | 47 | StoreManager::CastRegion(const GRState *state, const MemRegion* R, |
| 48 | QualType CastToTy) { |
Ted Kremenek | 48ce7de | 2009-07-06 20:21:51 +0000 | [diff] [blame] | 49 | |
| 50 | ASTContext& Ctx = StateMgr.getContext(); |
| 51 | |
| 52 | // We need to know the real type of CastToTy. |
| 53 | QualType ToTy = Ctx.getCanonicalType(CastToTy); |
Ted Kremenek | 411af40 | 2009-07-06 22:23:45 +0000 | [diff] [blame] | 54 | |
Ted Kremenek | b9a4425 | 2009-07-06 22:39:40 +0000 | [diff] [blame] | 55 | // Handle casts to Objective-C objects. |
Steve Naroff | f495456 | 2009-07-16 15:41:00 +0000 | [diff] [blame] | 56 | if (CastToTy->isObjCObjectPointerType()) { |
Ted Kremenek | fc8f57c | 2009-07-06 22:56:37 +0000 | [diff] [blame] | 57 | state = setCastType(state, R, CastToTy); |
Ted Kremenek | 145918c | 2009-07-06 21:01:16 +0000 | [diff] [blame] | 58 | return CastResult(state, R); |
| 59 | } |
Ted Kremenek | 63b9cfe | 2009-07-18 06:27:51 +0000 | [diff] [blame] | 60 | |
| 61 | if (CastToTy->isBlockPointerType()) { |
| 62 | if (isa<CodeTextRegion>(R)) |
| 63 | return CastResult(state, R); |
| 64 | |
| 65 | // FIXME: This may not be the right approach, depending on the symbol |
| 66 | // involved. Blocks can be casted to/from 'id', as they can be treated |
| 67 | // as Objective-C objects. |
| 68 | if (SymbolRef sym = loc::MemRegionVal(R).getAsSymbol()) { |
| 69 | R = MRMgr.getCodeTextRegion(sym, CastToTy); |
| 70 | return CastResult(state, R); |
| 71 | } |
| 72 | |
| 73 | // We don't know what to make of it. Return a NULL region, which |
| 74 | // will be interpretted as UnknownVal. |
| 75 | return CastResult(state, NULL); |
| 76 | } |
Ted Kremenek | 411af40 | 2009-07-06 22:23:45 +0000 | [diff] [blame] | 77 | |
Ted Kremenek | 48ce7de | 2009-07-06 20:21:51 +0000 | [diff] [blame] | 78 | // Now assume we are casting from pointer to pointer. Other cases should |
| 79 | // already be handled. |
Ted Kremenek | 35366a6 | 2009-07-17 17:50:17 +0000 | [diff] [blame] | 80 | QualType PointeeTy = CastToTy->getAsPointerType()->getPointeeType(); |
Ted Kremenek | 169077d | 2009-07-06 23:47:19 +0000 | [diff] [blame] | 81 | |
Ted Kremenek | 48ce7de | 2009-07-06 20:21:51 +0000 | [diff] [blame] | 82 | // Process region cast according to the kind of the region being cast. |
Ted Kremenek | fc8f57c | 2009-07-06 22:56:37 +0000 | [diff] [blame] | 83 | switch (R->getKind()) { |
| 84 | case MemRegion::BEG_TYPED_REGIONS: |
| 85 | case MemRegion::MemSpaceRegionKind: |
| 86 | case MemRegion::BEG_DECL_REGIONS: |
| 87 | case MemRegion::END_DECL_REGIONS: |
Ted Kremenek | f7a0cf4 | 2009-07-29 21:43:22 +0000 | [diff] [blame^] | 88 | case MemRegion::END_TYPED_REGIONS: { |
Ted Kremenek | fc8f57c | 2009-07-06 22:56:37 +0000 | [diff] [blame] | 89 | assert(0 && "Invalid region cast"); |
| 90 | break; |
Ted Kremenek | 48ce7de | 2009-07-06 20:21:51 +0000 | [diff] [blame] | 91 | } |
Ted Kremenek | fc8f57c | 2009-07-06 22:56:37 +0000 | [diff] [blame] | 92 | |
| 93 | case MemRegion::CodeTextRegionKind: { |
Ted Kremenek | 63b9cfe | 2009-07-18 06:27:51 +0000 | [diff] [blame] | 94 | // CodeTextRegion should be cast to only a function or block pointer type, |
| 95 | // although they can in practice be casted to anything, e.g, void*, |
| 96 | // char*, etc. |
Ted Kremenek | 8d344ae | 2009-07-10 21:24:45 +0000 | [diff] [blame] | 97 | // Just pass the region through. |
Ted Kremenek | fc8f57c | 2009-07-06 22:56:37 +0000 | [diff] [blame] | 98 | break; |
| 99 | } |
| 100 | |
| 101 | case MemRegion::StringRegionKind: |
| 102 | // Handle casts of string literals. |
| 103 | return MakeElementRegion(state, R, PointeeTy, CastToTy); |
| 104 | |
| 105 | case MemRegion::ObjCObjectRegionKind: |
| 106 | case MemRegion::SymbolicRegionKind: |
| 107 | // FIXME: Need to handle arbitrary downcasts. |
| 108 | case MemRegion::AllocaRegionKind: { |
| 109 | state = setCastType(state, R, CastToTy); |
| 110 | break; |
| 111 | } |
| 112 | |
| 113 | case MemRegion::CompoundLiteralRegionKind: |
| 114 | case MemRegion::ElementRegionKind: |
| 115 | case MemRegion::FieldRegionKind: |
| 116 | case MemRegion::ObjCIvarRegionKind: |
| 117 | case MemRegion::VarRegionKind: { |
Ted Kremenek | db5f266 | 2009-07-06 22:59:23 +0000 | [diff] [blame] | 118 | // VarRegion, ElementRegion, and FieldRegion has an inherent type. |
| 119 | // Normally they should not be cast. We only layer an ElementRegion when |
| 120 | // the cast-to pointee type is of smaller size. In other cases, we return |
| 121 | // the original VarRegion. |
Ted Kremenek | fc8f57c | 2009-07-06 22:56:37 +0000 | [diff] [blame] | 122 | |
Zhongxing Xu | db4f531 | 2009-07-07 01:36:53 +0000 | [diff] [blame] | 123 | // If the pointee or object type is incomplete, do not compute their |
| 124 | // sizes, and return the original region. |
Ted Kremenek | fc8f57c | 2009-07-06 22:56:37 +0000 | [diff] [blame] | 125 | QualType ObjTy = cast<TypedRegion>(R)->getValueType(Ctx); |
Ted Kremenek | 169077d | 2009-07-06 23:47:19 +0000 | [diff] [blame] | 126 | |
| 127 | if (!IsCompleteType(Ctx, PointeeTy) || !IsCompleteType(Ctx, ObjTy)) { |
| 128 | state = setCastType(state, R, ToTy); |
| 129 | break; |
| 130 | } |
| 131 | |
Ted Kremenek | fc8f57c | 2009-07-06 22:56:37 +0000 | [diff] [blame] | 132 | uint64_t PointeeTySize = Ctx.getTypeSize(PointeeTy); |
| 133 | uint64_t ObjTySize = Ctx.getTypeSize(ObjTy); |
| 134 | |
| 135 | if ((PointeeTySize > 0 && PointeeTySize < ObjTySize) || |
| 136 | (ObjTy->isAggregateType() && PointeeTy->isScalarType()) || |
| 137 | ObjTySize == 0 /* R has 'void*' type. */) |
| 138 | return MakeElementRegion(state, R, PointeeTy, ToTy); |
| 139 | |
Ted Kremenek | 48ce7de | 2009-07-06 20:21:51 +0000 | [diff] [blame] | 140 | state = setCastType(state, R, ToTy); |
Ted Kremenek | fc8f57c | 2009-07-06 22:56:37 +0000 | [diff] [blame] | 141 | break; |
Ted Kremenek | 48ce7de | 2009-07-06 20:21:51 +0000 | [diff] [blame] | 142 | } |
| 143 | } |
| 144 | |
Ted Kremenek | fc8f57c | 2009-07-06 22:56:37 +0000 | [diff] [blame] | 145 | return CastResult(state, R); |
Ted Kremenek | 48ce7de | 2009-07-06 20:21:51 +0000 | [diff] [blame] | 146 | } |