blob: 4341abdc7250cf5f1e2a64170540f518bbb518d3 [file] [log] [blame]
Ted Kremenekc62abc12009-04-21 21:51:34 +00001//== 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
17using namespace clang;
18
Ted Kremenekf7a0cf42009-07-29 21:43:22 +000019StoreManager::StoreManager(GRStateManager &stateMgr)
20 : ValMgr(stateMgr.getValueManager()), StateMgr(stateMgr),
Ted Kremenekc62abc12009-04-21 21:51:34 +000021 MRMgr(ValMgr.getRegionManager()) {}
22
23StoreManager::CastResult
Ted Kremenek411af402009-07-06 22:23:45 +000024StoreManager::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 Kremenek169077d2009-07-06 23:47:19 +000036static bool IsCompleteType(ASTContext &Ctx, QualType Ty) {
Ted Kremenek35366a62009-07-17 17:50:17 +000037 if (const RecordType *RT = Ty->getAsRecordType()) {
Ted Kremenek169077d2009-07-06 23:47:19 +000038 const RecordDecl *D = RT->getDecl();
39 if (!D->getDefinition(Ctx))
40 return false;
41 }
42
43 return true;
44}
45
Ted Kremenek411af402009-07-06 22:23:45 +000046StoreManager::CastResult
Ted Kremenekf7a0cf42009-07-29 21:43:22 +000047StoreManager::CastRegion(const GRState *state, const MemRegion* R,
48 QualType CastToTy) {
Ted Kremenek48ce7de2009-07-06 20:21:51 +000049
50 ASTContext& Ctx = StateMgr.getContext();
51
52 // We need to know the real type of CastToTy.
53 QualType ToTy = Ctx.getCanonicalType(CastToTy);
Ted Kremenek411af402009-07-06 22:23:45 +000054
Ted Kremenekb9a44252009-07-06 22:39:40 +000055 // Handle casts to Objective-C objects.
Steve Narofff4954562009-07-16 15:41:00 +000056 if (CastToTy->isObjCObjectPointerType()) {
Ted Kremenekfc8f57c2009-07-06 22:56:37 +000057 state = setCastType(state, R, CastToTy);
Ted Kremenek145918c2009-07-06 21:01:16 +000058 return CastResult(state, R);
59 }
Ted Kremenek63b9cfe2009-07-18 06:27:51 +000060
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 Kremenek411af402009-07-06 22:23:45 +000077
Ted Kremenek48ce7de2009-07-06 20:21:51 +000078 // Now assume we are casting from pointer to pointer. Other cases should
79 // already be handled.
Ted Kremenek35366a62009-07-17 17:50:17 +000080 QualType PointeeTy = CastToTy->getAsPointerType()->getPointeeType();
Ted Kremenek169077d2009-07-06 23:47:19 +000081
Ted Kremenek48ce7de2009-07-06 20:21:51 +000082 // Process region cast according to the kind of the region being cast.
Ted Kremenekfc8f57c2009-07-06 22:56:37 +000083 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 Kremenekf7a0cf42009-07-29 21:43:22 +000088 case MemRegion::END_TYPED_REGIONS: {
Ted Kremenekfc8f57c2009-07-06 22:56:37 +000089 assert(0 && "Invalid region cast");
90 break;
Ted Kremenek48ce7de2009-07-06 20:21:51 +000091 }
Ted Kremenekfc8f57c2009-07-06 22:56:37 +000092
93 case MemRegion::CodeTextRegionKind: {
Ted Kremenek63b9cfe2009-07-18 06:27:51 +000094 // 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 Kremenek8d344ae2009-07-10 21:24:45 +000097 // Just pass the region through.
Ted Kremenekfc8f57c2009-07-06 22:56:37 +000098 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 Kremenekdb5f2662009-07-06 22:59:23 +0000118 // 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 Kremenekfc8f57c2009-07-06 22:56:37 +0000122
Zhongxing Xudb4f5312009-07-07 01:36:53 +0000123 // If the pointee or object type is incomplete, do not compute their
124 // sizes, and return the original region.
Ted Kremenekfc8f57c2009-07-06 22:56:37 +0000125 QualType ObjTy = cast<TypedRegion>(R)->getValueType(Ctx);
Ted Kremenek169077d2009-07-06 23:47:19 +0000126
127 if (!IsCompleteType(Ctx, PointeeTy) || !IsCompleteType(Ctx, ObjTy)) {
128 state = setCastType(state, R, ToTy);
129 break;
130 }
131
Ted Kremenekfc8f57c2009-07-06 22:56:37 +0000132 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 Kremenek48ce7de2009-07-06 20:21:51 +0000140 state = setCastType(state, R, ToTy);
Ted Kremenekfc8f57c2009-07-06 22:56:37 +0000141 break;
Ted Kremenek48ce7de2009-07-06 20:21:51 +0000142 }
143 }
144
Ted Kremenekfc8f57c2009-07-06 22:56:37 +0000145 return CastResult(state, R);
Ted Kremenek48ce7de2009-07-06 20:21:51 +0000146}