| Ted Kremenek | 9e24049 | 2008-10-04 05:50:14 +0000 | [diff] [blame] | 1 | //== MemRegion.cpp - Abstract memory regions for static analysis --*- 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 defines MemRegion and its subclasses.  MemRegion defines a | 
|  | 11 | //  partially-typed abstraction of memory useful for path-sensitive dataflow | 
|  | 12 | //  analyses. | 
|  | 13 | // | 
|  | 14 | //===----------------------------------------------------------------------===// | 
|  | 15 |  | 
|  | 16 | #include "llvm/Support/raw_ostream.h" | 
|  | 17 | #include "clang/Analysis/PathSensitive/MemRegion.h" | 
|  | 18 |  | 
|  | 19 | using namespace clang; | 
|  | 20 |  | 
|  | 21 |  | 
|  | 22 | MemRegion::~MemRegion() {} | 
|  | 23 |  | 
|  | 24 | void MemSpaceRegion::Profile(llvm::FoldingSetNodeID& ID) const { | 
|  | 25 | ID.AddInteger((unsigned)getKind()); | 
|  | 26 | } | 
|  | 27 |  | 
| Zhongxing Xu | e9f4e54 | 2008-10-25 14:13:41 +0000 | [diff] [blame] | 28 | void StringRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, | 
|  | 29 | const StringLiteral* Str, | 
|  | 30 | const MemRegion* superRegion) { | 
|  | 31 | ID.AddInteger((unsigned) StringRegionKind); | 
|  | 32 | ID.AddPointer(Str); | 
|  | 33 | ID.AddPointer(superRegion); | 
|  | 34 | } | 
|  | 35 |  | 
| Ted Kremenek | 9e24049 | 2008-10-04 05:50:14 +0000 | [diff] [blame] | 36 | void AnonTypedRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, QualType T, | 
|  | 37 | const MemRegion* superRegion) { | 
|  | 38 | ID.AddInteger((unsigned) AnonTypedRegionKind); | 
|  | 39 | ID.Add(T); | 
|  | 40 | ID.AddPointer(superRegion); | 
|  | 41 | } | 
|  | 42 |  | 
| Zhongxing Xu | 1789275 | 2008-10-08 02:50:44 +0000 | [diff] [blame] | 43 | void AnonPointeeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, | 
|  | 44 | const VarDecl* VD, QualType T, | 
|  | 45 | const MemRegion* superRegion) { | 
|  | 46 | ID.AddInteger((unsigned) AnonPointeeRegionKind); | 
|  | 47 | ID.Add(T); | 
|  | 48 | ID.AddPointer(VD); | 
|  | 49 | ID.AddPointer(superRegion); | 
|  | 50 | } | 
|  | 51 |  | 
| Ted Kremenek | 9e24049 | 2008-10-04 05:50:14 +0000 | [diff] [blame] | 52 | void AnonTypedRegion::Profile(llvm::FoldingSetNodeID& ID) const { | 
|  | 53 | AnonTypedRegion::ProfileRegion(ID, T, superRegion); | 
|  | 54 | } | 
|  | 55 |  | 
|  | 56 | void DeclRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl* D, | 
|  | 57 | const MemRegion* superRegion, Kind k) { | 
|  | 58 | ID.AddInteger((unsigned) k); | 
|  | 59 | ID.AddPointer(D); | 
|  | 60 | ID.AddPointer(superRegion); | 
|  | 61 | } | 
|  | 62 |  | 
|  | 63 | void DeclRegion::Profile(llvm::FoldingSetNodeID& ID) const { | 
|  | 64 | DeclRegion::ProfileRegion(ID, D, superRegion, getKind()); | 
|  | 65 | } | 
|  | 66 |  | 
| Ted Kremenek | 993f1c7 | 2008-10-17 20:28:54 +0000 | [diff] [blame] | 67 | void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolID sym) { | 
|  | 68 | ID.AddInteger((unsigned) MemRegion::SymbolicRegionKind); | 
|  | 69 | ID.AddInteger(sym.getNumber()); | 
|  | 70 | } | 
|  | 71 |  | 
|  | 72 | void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const { | 
|  | 73 | SymbolicRegion::ProfileRegion(ID, sym); | 
|  | 74 | } | 
|  | 75 |  | 
| Zhongxing Xu | 511191c | 2008-10-21 05:27:10 +0000 | [diff] [blame] | 76 | void ElementRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SVal Idx, | 
|  | 77 | const MemRegion* superRegion) { | 
|  | 78 | ID.AddInteger(MemRegion::ElementRegionKind); | 
|  | 79 | ID.AddPointer(superRegion); | 
|  | 80 | Idx.Profile(ID); | 
|  | 81 | } | 
|  | 82 |  | 
|  | 83 | void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const { | 
|  | 84 | ElementRegion::ProfileRegion(ID, Index, superRegion); | 
|  | 85 | } | 
| Zhongxing Xu | 27b5706 | 2008-10-27 13:17:02 +0000 | [diff] [blame^] | 86 |  | 
|  | 87 | QualType ElementRegion::getType(ASTContext& C) const { | 
|  | 88 | QualType T = cast<TypedRegion>(superRegion)->getType(C); | 
|  | 89 | ArrayType* AT = cast<ArrayType>(T.getTypePtr()); | 
|  | 90 | return AT->getElementType(); | 
|  | 91 | } | 
|  | 92 |  | 
| Ted Kremenek | 9e24049 | 2008-10-04 05:50:14 +0000 | [diff] [blame] | 93 | //===----------------------------------------------------------------------===// | 
|  | 94 | // Region pretty-printing. | 
|  | 95 | //===----------------------------------------------------------------------===// | 
|  | 96 |  | 
|  | 97 | std::string MemRegion::getString() const { | 
|  | 98 | std::string s; | 
|  | 99 | llvm::raw_string_ostream os(s); | 
|  | 100 | print(os); | 
|  | 101 | return os.str(); | 
|  | 102 | } | 
|  | 103 |  | 
|  | 104 | void MemRegion::print(llvm::raw_ostream& os) const { | 
|  | 105 | os << "<Unknown Region>"; | 
|  | 106 | } | 
|  | 107 |  | 
|  | 108 | void VarRegion::print(llvm::raw_ostream& os) const { | 
|  | 109 | os << cast<VarDecl>(D)->getName(); | 
|  | 110 | } | 
|  | 111 |  | 
| Ted Kremenek | 993f1c7 | 2008-10-17 20:28:54 +0000 | [diff] [blame] | 112 | void SymbolicRegion::print(llvm::raw_ostream& os) const { | 
|  | 113 | os << "$" << sym.getNumber(); | 
|  | 114 | } | 
|  | 115 |  | 
| Ted Kremenek | 4bd1eef | 2008-10-17 21:05:44 +0000 | [diff] [blame] | 116 | void FieldRegion::print(llvm::raw_ostream& os) const { | 
|  | 117 | superRegion->print(os); | 
|  | 118 | os << "->" << getDecl()->getName(); | 
|  | 119 | } | 
|  | 120 |  | 
| Zhongxing Xu | b21ff77 | 2008-10-24 06:30:07 +0000 | [diff] [blame] | 121 | void ElementRegion::print(llvm::raw_ostream& os) const { | 
|  | 122 | superRegion->print(os); | 
|  | 123 | os << '['; Index.print(os); os << ']'; | 
|  | 124 | } | 
|  | 125 |  | 
| Ted Kremenek | 9e24049 | 2008-10-04 05:50:14 +0000 | [diff] [blame] | 126 | //===----------------------------------------------------------------------===// | 
|  | 127 | // MemRegionManager methods. | 
|  | 128 | //===----------------------------------------------------------------------===// | 
|  | 129 |  | 
|  | 130 | MemSpaceRegion* MemRegionManager::LazyAllocate(MemSpaceRegion*& region) { | 
|  | 131 |  | 
|  | 132 | if (!region) { | 
|  | 133 | region = (MemSpaceRegion*) A.Allocate<MemSpaceRegion>(); | 
|  | 134 | new (region) MemSpaceRegion(); | 
|  | 135 | } | 
|  | 136 |  | 
|  | 137 | return region; | 
|  | 138 | } | 
|  | 139 |  | 
|  | 140 | MemSpaceRegion* MemRegionManager::getStackRegion() { | 
|  | 141 | return LazyAllocate(stack); | 
|  | 142 | } | 
|  | 143 |  | 
|  | 144 | MemSpaceRegion* MemRegionManager::getGlobalsRegion() { | 
|  | 145 | return LazyAllocate(globals); | 
|  | 146 | } | 
|  | 147 |  | 
|  | 148 | MemSpaceRegion* MemRegionManager::getHeapRegion() { | 
|  | 149 | return LazyAllocate(heap); | 
|  | 150 | } | 
|  | 151 |  | 
| Zhongxing Xu | 1789275 | 2008-10-08 02:50:44 +0000 | [diff] [blame] | 152 | MemSpaceRegion* MemRegionManager::getUnknownRegion() { | 
|  | 153 | return LazyAllocate(unknown); | 
|  | 154 | } | 
|  | 155 |  | 
| Zhongxing Xu | e9f4e54 | 2008-10-25 14:13:41 +0000 | [diff] [blame] | 156 | StringRegion* MemRegionManager::getStringRegion(const StringLiteral* Str) { | 
|  | 157 | llvm::FoldingSetNodeID ID; | 
|  | 158 | MemSpaceRegion* GlobalsR = getGlobalsRegion(); | 
|  | 159 |  | 
|  | 160 | StringRegion::ProfileRegion(ID, Str, GlobalsR); | 
|  | 161 |  | 
|  | 162 | void* InsertPos; | 
|  | 163 | MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos); | 
|  | 164 | StringRegion* R = cast_or_null<StringRegion>(data); | 
|  | 165 |  | 
|  | 166 | if (!R) { | 
|  | 167 | R = (StringRegion*) A.Allocate<StringRegion>(); | 
|  | 168 | new (R) StringRegion(Str, GlobalsR); | 
|  | 169 | Regions.InsertNode(R, InsertPos); | 
|  | 170 | } | 
|  | 171 |  | 
|  | 172 | return R; | 
|  | 173 | } | 
|  | 174 |  | 
| Ted Kremenek | 9e24049 | 2008-10-04 05:50:14 +0000 | [diff] [blame] | 175 | VarRegion* MemRegionManager::getVarRegion(const VarDecl* d, | 
| Ted Kremenek | 993f1c7 | 2008-10-17 20:28:54 +0000 | [diff] [blame] | 176 | const MemRegion* superRegion) { | 
| Ted Kremenek | 9e24049 | 2008-10-04 05:50:14 +0000 | [diff] [blame] | 177 | llvm::FoldingSetNodeID ID; | 
|  | 178 | DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::VarRegionKind); | 
|  | 179 |  | 
|  | 180 | void* InsertPos; | 
|  | 181 | MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos); | 
|  | 182 | VarRegion* R = cast_or_null<VarRegion>(data); | 
|  | 183 |  | 
|  | 184 | if (!R) { | 
|  | 185 | R = (VarRegion*) A.Allocate<VarRegion>(); | 
|  | 186 | new (R) VarRegion(d, superRegion); | 
|  | 187 | Regions.InsertNode(R, InsertPos); | 
|  | 188 | } | 
|  | 189 |  | 
|  | 190 | return R; | 
|  | 191 | } | 
|  | 192 |  | 
| Zhongxing Xu | 511191c | 2008-10-21 05:27:10 +0000 | [diff] [blame] | 193 | ElementRegion* MemRegionManager::getElementRegion(SVal Idx, | 
|  | 194 | const MemRegion* superRegion){ | 
|  | 195 | llvm::FoldingSetNodeID ID; | 
|  | 196 | ElementRegion::ProfileRegion(ID, Idx, superRegion); | 
|  | 197 |  | 
|  | 198 | void* InsertPos; | 
|  | 199 | MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos); | 
|  | 200 | ElementRegion* R = cast_or_null<ElementRegion>(data); | 
|  | 201 |  | 
|  | 202 | if (!R) { | 
|  | 203 | R = (ElementRegion*) A.Allocate<ElementRegion>(); | 
|  | 204 | new (R) ElementRegion(Idx, superRegion); | 
|  | 205 | Regions.InsertNode(R, InsertPos); | 
|  | 206 | } | 
|  | 207 |  | 
|  | 208 | return R; | 
|  | 209 | } | 
|  | 210 |  | 
| Ted Kremenek | 993f1c7 | 2008-10-17 20:28:54 +0000 | [diff] [blame] | 211 | /// getSymbolicRegion - Retrieve or create a "symbolic" memory region. | 
|  | 212 | SymbolicRegion* MemRegionManager::getSymbolicRegion(const SymbolID sym) { | 
|  | 213 |  | 
|  | 214 | llvm::FoldingSetNodeID ID; | 
|  | 215 | SymbolicRegion::ProfileRegion(ID, sym); | 
|  | 216 |  | 
|  | 217 | void* InsertPos; | 
|  | 218 | MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos); | 
|  | 219 | SymbolicRegion* R = cast_or_null<SymbolicRegion>(data); | 
|  | 220 |  | 
|  | 221 | if (!R) { | 
|  | 222 | R = (SymbolicRegion*) A.Allocate<SymbolicRegion>(); | 
|  | 223 | new (R) SymbolicRegion(sym); | 
|  | 224 | Regions.InsertNode(R, InsertPos); | 
|  | 225 | } | 
|  | 226 |  | 
|  | 227 | return R; | 
|  | 228 | } | 
|  | 229 |  | 
| Ted Kremenek | 9e24049 | 2008-10-04 05:50:14 +0000 | [diff] [blame] | 230 | FieldRegion* MemRegionManager::getFieldRegion(const FieldDecl* d, | 
| Ted Kremenek | 993f1c7 | 2008-10-17 20:28:54 +0000 | [diff] [blame] | 231 | const MemRegion* superRegion) { | 
| Ted Kremenek | 9e24049 | 2008-10-04 05:50:14 +0000 | [diff] [blame] | 232 | llvm::FoldingSetNodeID ID; | 
|  | 233 | DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::FieldRegionKind); | 
|  | 234 |  | 
|  | 235 | void* InsertPos; | 
|  | 236 | MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos); | 
|  | 237 | FieldRegion* R = cast_or_null<FieldRegion>(data); | 
|  | 238 |  | 
|  | 239 | if (!R) { | 
|  | 240 | R = (FieldRegion*) A.Allocate<FieldRegion>(); | 
|  | 241 | new (R) FieldRegion(d, superRegion); | 
|  | 242 | Regions.InsertNode(R, InsertPos); | 
|  | 243 | } | 
|  | 244 |  | 
|  | 245 | return R; | 
|  | 246 | } | 
|  | 247 |  | 
| Ted Kremenek | 993f1c7 | 2008-10-17 20:28:54 +0000 | [diff] [blame] | 248 | ObjCIvarRegion* | 
|  | 249 | MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl* d, | 
|  | 250 | const MemRegion* superRegion) { | 
| Ted Kremenek | 9e24049 | 2008-10-04 05:50:14 +0000 | [diff] [blame] | 251 | llvm::FoldingSetNodeID ID; | 
|  | 252 | DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::ObjCIvarRegionKind); | 
|  | 253 |  | 
|  | 254 | void* InsertPos; | 
|  | 255 | MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos); | 
|  | 256 | ObjCIvarRegion* R = cast_or_null<ObjCIvarRegion>(data); | 
|  | 257 |  | 
|  | 258 | if (!R) { | 
| Zhongxing Xu | 722c288 | 2008-10-06 03:03:33 +0000 | [diff] [blame] | 259 | R = (ObjCIvarRegion*) A.Allocate<ObjCIvarRegion>(); | 
|  | 260 | new (R) ObjCIvarRegion(d, superRegion); | 
| Ted Kremenek | 9e24049 | 2008-10-04 05:50:14 +0000 | [diff] [blame] | 261 | Regions.InsertNode(R, InsertPos); | 
|  | 262 | } | 
|  | 263 |  | 
|  | 264 | return R; | 
|  | 265 | } | 
|  | 266 |  | 
| Ted Kremenek | a7f1b9e | 2008-10-24 20:30:08 +0000 | [diff] [blame] | 267 | ObjCObjectRegion* | 
|  | 268 | MemRegionManager::getObjCObjectRegion(const ObjCInterfaceDecl* d, | 
|  | 269 | const MemRegion* superRegion) { | 
|  | 270 | llvm::FoldingSetNodeID ID; | 
|  | 271 | DeclRegion::ProfileRegion(ID, d, superRegion, | 
|  | 272 | MemRegion::ObjCObjectRegionKind); | 
|  | 273 |  | 
|  | 274 | void* InsertPos; | 
|  | 275 | MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos); | 
|  | 276 | ObjCObjectRegion* R = cast_or_null<ObjCObjectRegion>(data); | 
|  | 277 |  | 
|  | 278 | if (!R) { | 
|  | 279 | R = (ObjCObjectRegion*) A.Allocate<ObjCObjectRegion>(); | 
|  | 280 | new (R) ObjCObjectRegion(d, superRegion); | 
|  | 281 | Regions.InsertNode(R, InsertPos); | 
|  | 282 | } | 
|  | 283 |  | 
|  | 284 | return R; | 
|  | 285 | } | 
|  | 286 |  | 
|  | 287 |  | 
| Zhongxing Xu | 1789275 | 2008-10-08 02:50:44 +0000 | [diff] [blame] | 288 | AnonPointeeRegion* MemRegionManager::getAnonPointeeRegion(const VarDecl* d) { | 
|  | 289 | llvm::FoldingSetNodeID ID; | 
|  | 290 | QualType T = d->getType(); | 
|  | 291 | QualType PointeeType = cast<PointerType>(T.getTypePtr())->getPointeeType(); | 
|  | 292 | MemRegion* superRegion = getUnknownRegion(); | 
|  | 293 |  | 
|  | 294 | AnonPointeeRegion::ProfileRegion(ID, d, PointeeType, superRegion); | 
|  | 295 |  | 
|  | 296 | void* InsertPos; | 
|  | 297 | MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos); | 
|  | 298 | AnonPointeeRegion* R = cast_or_null<AnonPointeeRegion>(data); | 
|  | 299 |  | 
|  | 300 | if (!R) { | 
|  | 301 | R = (AnonPointeeRegion*) A.Allocate<AnonPointeeRegion>(); | 
|  | 302 | new (R) AnonPointeeRegion(d, PointeeType, superRegion); | 
|  | 303 | Regions.InsertNode(R, InsertPos); | 
|  | 304 | } | 
|  | 305 |  | 
|  | 306 | return R; | 
|  | 307 | } | 
|  | 308 |  | 
| Ted Kremenek | 9e24049 | 2008-10-04 05:50:14 +0000 | [diff] [blame] | 309 | bool MemRegionManager::hasStackStorage(const MemRegion* R) { | 
| Ted Kremenek | 993f1c7 | 2008-10-17 20:28:54 +0000 | [diff] [blame] | 310 | const SubRegion* SR = dyn_cast<SubRegion>(R); | 
|  | 311 |  | 
|  | 312 | // Only subregions can have stack storage. | 
|  | 313 | if (!SR) | 
|  | 314 | return false; | 
|  | 315 |  | 
| Ted Kremenek | 9e24049 | 2008-10-04 05:50:14 +0000 | [diff] [blame] | 316 | MemSpaceRegion* S = getStackRegion(); | 
|  | 317 |  | 
| Ted Kremenek | 993f1c7 | 2008-10-17 20:28:54 +0000 | [diff] [blame] | 318 | while (SR) { | 
|  | 319 | R = SR->getSuperRegion(); | 
|  | 320 | if (R == S) | 
|  | 321 | return true; | 
|  | 322 |  | 
|  | 323 | SR = dyn_cast<SubRegion>(R); | 
| Ted Kremenek | 9e24049 | 2008-10-04 05:50:14 +0000 | [diff] [blame] | 324 | } | 
|  | 325 |  | 
|  | 326 | return false; | 
|  | 327 | } |