1 //== MemRegion.h - 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 #ifndef LLVM_CLANG_GR_MEMREGION_H
17 #define LLVM_CLANG_GR_MEMREGION_H
18
19 #include "clang/AST/CharUnits.h"
20 #include "clang/AST/Decl.h"
21 #include "clang/AST/ExprObjC.h"
22 #include "clang/Basic/LLVM.h"
23 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
24 #include "llvm/Support/ErrorHandling.h"
25 #include "llvm/ADT/FoldingSet.h"
26 #include <string>
27
28 namespace llvm {
29 class BumpPtrAllocator;
30 }
31
32 namespace clang {
33
34 class LocationContext;
35 class StackFrameContext;
36
37 namespace ento {
38
39 class MemRegionManager;
40 class MemSpaceRegion;
41 class SValBuilder;
42 class VarRegion;
43 class CodeTextRegion;
44
45 /// Represent a region's offset within the top level base region.
46 class RegionOffset {
47 /// The base region.
48 const MemRegion *R;
49
50 /// The bit offset within the base region. It shouldn't be negative.
51 int64_t Offset;
52
53 public:
RegionOffset(const MemRegion * r)54 RegionOffset(const MemRegion *r) : R(r), Offset(0) {}
RegionOffset(const MemRegion * r,int64_t off)55 RegionOffset(const MemRegion *r, int64_t off) : R(r), Offset(off) {}
56
getRegion()57 const MemRegion *getRegion() const { return R; }
getOffset()58 int64_t getOffset() const { return Offset; }
59 };
60
61 //===----------------------------------------------------------------------===//
62 // Base region classes.
63 //===----------------------------------------------------------------------===//
64
65 /// MemRegion - The root abstract class for all memory regions.
66 class MemRegion : public llvm::FoldingSetNode {
67 friend class MemRegionManager;
68 public:
69 enum Kind {
70 // Memory spaces.
71 GenericMemSpaceRegionKind,
72 StackLocalsSpaceRegionKind,
73 StackArgumentsSpaceRegionKind,
74 HeapSpaceRegionKind,
75 UnknownSpaceRegionKind,
76 StaticGlobalSpaceRegionKind,
77 GlobalInternalSpaceRegionKind,
78 GlobalSystemSpaceRegionKind,
79 GlobalImmutableSpaceRegionKind,
80 BEG_NON_STATIC_GLOBAL_MEMSPACES = GlobalInternalSpaceRegionKind,
81 END_NON_STATIC_GLOBAL_MEMSPACES = GlobalImmutableSpaceRegionKind,
82 BEG_GLOBAL_MEMSPACES = StaticGlobalSpaceRegionKind,
83 END_GLOBAL_MEMSPACES = GlobalImmutableSpaceRegionKind,
84 BEG_MEMSPACES = GenericMemSpaceRegionKind,
85 END_MEMSPACES = GlobalImmutableSpaceRegionKind,
86 // Untyped regions.
87 SymbolicRegionKind,
88 AllocaRegionKind,
89 BlockDataRegionKind,
90 // Typed regions.
91 BEG_TYPED_REGIONS,
92 FunctionTextRegionKind = BEG_TYPED_REGIONS,
93 BlockTextRegionKind,
94 BEG_TYPED_VALUE_REGIONS,
95 CompoundLiteralRegionKind = BEG_TYPED_VALUE_REGIONS,
96 CXXThisRegionKind,
97 StringRegionKind,
98 ObjCStringRegionKind,
99 ElementRegionKind,
100 // Decl Regions.
101 BEG_DECL_REGIONS,
102 VarRegionKind = BEG_DECL_REGIONS,
103 FieldRegionKind,
104 ObjCIvarRegionKind,
105 END_DECL_REGIONS = ObjCIvarRegionKind,
106 CXXTempObjectRegionKind,
107 CXXBaseObjectRegionKind,
108 END_TYPED_VALUE_REGIONS = CXXBaseObjectRegionKind,
109 END_TYPED_REGIONS = CXXBaseObjectRegionKind
110 };
111
112 private:
113 const Kind kind;
114
115 protected:
MemRegion(Kind k)116 MemRegion(Kind k) : kind(k) {}
117 virtual ~MemRegion();
118
119 public:
120 ASTContext &getContext() const;
121
122 virtual void Profile(llvm::FoldingSetNodeID& ID) const = 0;
123
124 virtual MemRegionManager* getMemRegionManager() const = 0;
125
126 const MemSpaceRegion *getMemorySpace() const;
127
128 const MemRegion *getBaseRegion() const;
129
130 const MemRegion *StripCasts() const;
131
132 bool hasGlobalsOrParametersStorage() const;
133
134 bool hasStackStorage() const;
135
136 bool hasStackNonParametersStorage() const;
137
138 bool hasStackParametersStorage() const;
139
140 /// Compute the offset within the top level memory object.
141 RegionOffset getAsOffset() const;
142
143 /// \brief Get a string representation of a region for debug use.
144 std::string getString() const;
145
146 virtual void dumpToStream(raw_ostream &os) const;
147
148 void dump() const;
149
150 /// \brief Print the region for use in diagnostics.
151 virtual void dumpPretty(raw_ostream &os) const;
152
getKind()153 Kind getKind() const { return kind; }
154
155 template<typename RegionTy> const RegionTy* getAs() const;
156
isBoundable()157 virtual bool isBoundable() const { return false; }
158
classof(const MemRegion *)159 static bool classof(const MemRegion*) { return true; }
160 };
161
162 /// MemSpaceRegion - A memory region that represents a "memory space";
163 /// for example, the set of global variables, the stack frame, etc.
164 class MemSpaceRegion : public MemRegion {
165 protected:
166 friend class MemRegionManager;
167
168 MemRegionManager *Mgr;
169
170 MemSpaceRegion(MemRegionManager *mgr, Kind k = GenericMemSpaceRegionKind)
MemRegion(k)171 : MemRegion(k), Mgr(mgr) {
172 assert(classof(this));
173 }
174
getMemRegionManager()175 MemRegionManager* getMemRegionManager() const { return Mgr; }
176
177 public:
isBoundable()178 bool isBoundable() const { return false; }
179
180 void Profile(llvm::FoldingSetNodeID &ID) const;
181
classof(const MemRegion * R)182 static bool classof(const MemRegion *R) {
183 Kind k = R->getKind();
184 return k >= BEG_MEMSPACES && k <= END_MEMSPACES;
185 }
186 };
187
188 class GlobalsSpaceRegion : public MemSpaceRegion {
189 virtual void anchor();
190 protected:
GlobalsSpaceRegion(MemRegionManager * mgr,Kind k)191 GlobalsSpaceRegion(MemRegionManager *mgr, Kind k)
192 : MemSpaceRegion(mgr, k) {}
193 public:
classof(const MemRegion * R)194 static bool classof(const MemRegion *R) {
195 Kind k = R->getKind();
196 return k >= BEG_GLOBAL_MEMSPACES && k <= END_GLOBAL_MEMSPACES;
197 }
198 };
199
200 /// \class The region of the static variables within the current CodeTextRegion
201 /// scope.
202 /// Currently, only the static locals are placed there, so we know that these
203 /// variables do not get invalidated by calls to other functions.
204 class StaticGlobalSpaceRegion : public GlobalsSpaceRegion {
205 friend class MemRegionManager;
206
207 const CodeTextRegion *CR;
208
StaticGlobalSpaceRegion(MemRegionManager * mgr,const CodeTextRegion * cr)209 StaticGlobalSpaceRegion(MemRegionManager *mgr, const CodeTextRegion *cr)
210 : GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) {}
211
212 public:
213 void Profile(llvm::FoldingSetNodeID &ID) const;
214
215 void dumpToStream(raw_ostream &os) const;
216
getCodeRegion()217 const CodeTextRegion *getCodeRegion() const { return CR; }
218
classof(const MemRegion * R)219 static bool classof(const MemRegion *R) {
220 return R->getKind() == StaticGlobalSpaceRegionKind;
221 }
222 };
223
224 /// \class The region for all the non-static global variables.
225 ///
226 /// This class is further split into subclasses for efficient implementation of
227 /// invalidating a set of related global values as is done in
228 /// RegionStoreManager::invalidateRegions (instead of finding all the dependent
229 /// globals, we invalidate the whole parent region).
230 class NonStaticGlobalSpaceRegion : public GlobalsSpaceRegion {
231 friend class MemRegionManager;
232
233 protected:
NonStaticGlobalSpaceRegion(MemRegionManager * mgr,Kind k)234 NonStaticGlobalSpaceRegion(MemRegionManager *mgr, Kind k)
235 : GlobalsSpaceRegion(mgr, k) {}
236
237 public:
238
239 void dumpToStream(raw_ostream &os) const;
240
classof(const MemRegion * R)241 static bool classof(const MemRegion *R) {
242 Kind k = R->getKind();
243 return k >= BEG_NON_STATIC_GLOBAL_MEMSPACES &&
244 k <= END_NON_STATIC_GLOBAL_MEMSPACES;
245 }
246 };
247
248 /// \class The region containing globals which are defined in system/external
249 /// headers and are considered modifiable by system calls (ex: errno).
250 class GlobalSystemSpaceRegion : public NonStaticGlobalSpaceRegion {
251 friend class MemRegionManager;
252
GlobalSystemSpaceRegion(MemRegionManager * mgr)253 GlobalSystemSpaceRegion(MemRegionManager *mgr)
254 : NonStaticGlobalSpaceRegion(mgr, GlobalSystemSpaceRegionKind) {}
255
256 public:
257
258 void dumpToStream(raw_ostream &os) const;
259
classof(const MemRegion * R)260 static bool classof(const MemRegion *R) {
261 return R->getKind() == GlobalSystemSpaceRegionKind;
262 }
263 };
264
265 /// \class The region containing globals which are considered not to be modified
266 /// or point to data which could be modified as a result of a function call
267 /// (system or internal). Ex: Const global scalars would be modeled as part of
268 /// this region. This region also includes most system globals since they have
269 /// low chance of being modified.
270 class GlobalImmutableSpaceRegion : public NonStaticGlobalSpaceRegion {
271 friend class MemRegionManager;
272
GlobalImmutableSpaceRegion(MemRegionManager * mgr)273 GlobalImmutableSpaceRegion(MemRegionManager *mgr)
274 : NonStaticGlobalSpaceRegion(mgr, GlobalImmutableSpaceRegionKind) {}
275
276 public:
277
278 void dumpToStream(raw_ostream &os) const;
279
classof(const MemRegion * R)280 static bool classof(const MemRegion *R) {
281 return R->getKind() == GlobalImmutableSpaceRegionKind;
282 }
283 };
284
285 /// \class The region containing globals which can be modified by calls to
286 /// "internally" defined functions - (for now just) functions other then system
287 /// calls.
288 class GlobalInternalSpaceRegion : public NonStaticGlobalSpaceRegion {
289 friend class MemRegionManager;
290
GlobalInternalSpaceRegion(MemRegionManager * mgr)291 GlobalInternalSpaceRegion(MemRegionManager *mgr)
292 : NonStaticGlobalSpaceRegion(mgr, GlobalInternalSpaceRegionKind) {}
293
294 public:
295
296 void dumpToStream(raw_ostream &os) const;
297
classof(const MemRegion * R)298 static bool classof(const MemRegion *R) {
299 return R->getKind() == GlobalInternalSpaceRegionKind;
300 }
301 };
302
303 class HeapSpaceRegion : public MemSpaceRegion {
304 virtual void anchor();
305 friend class MemRegionManager;
306
HeapSpaceRegion(MemRegionManager * mgr)307 HeapSpaceRegion(MemRegionManager *mgr)
308 : MemSpaceRegion(mgr, HeapSpaceRegionKind) {}
309 public:
classof(const MemRegion * R)310 static bool classof(const MemRegion *R) {
311 return R->getKind() == HeapSpaceRegionKind;
312 }
313 };
314
315 class UnknownSpaceRegion : public MemSpaceRegion {
316 virtual void anchor();
317 friend class MemRegionManager;
UnknownSpaceRegion(MemRegionManager * mgr)318 UnknownSpaceRegion(MemRegionManager *mgr)
319 : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {}
320 public:
classof(const MemRegion * R)321 static bool classof(const MemRegion *R) {
322 return R->getKind() == UnknownSpaceRegionKind;
323 }
324 };
325
326 class StackSpaceRegion : public MemSpaceRegion {
327 private:
328 const StackFrameContext *SFC;
329
330 protected:
StackSpaceRegion(MemRegionManager * mgr,Kind k,const StackFrameContext * sfc)331 StackSpaceRegion(MemRegionManager *mgr, Kind k, const StackFrameContext *sfc)
332 : MemSpaceRegion(mgr, k), SFC(sfc) {
333 assert(classof(this));
334 }
335
336 public:
getStackFrame()337 const StackFrameContext *getStackFrame() const { return SFC; }
338
339 void Profile(llvm::FoldingSetNodeID &ID) const;
340
classof(const MemRegion * R)341 static bool classof(const MemRegion *R) {
342 Kind k = R->getKind();
343 return k >= StackLocalsSpaceRegionKind &&
344 k <= StackArgumentsSpaceRegionKind;
345 }
346 };
347
348 class StackLocalsSpaceRegion : public StackSpaceRegion {
349 virtual void anchor();
350 friend class MemRegionManager;
StackLocalsSpaceRegion(MemRegionManager * mgr,const StackFrameContext * sfc)351 StackLocalsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
352 : StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {}
353 public:
classof(const MemRegion * R)354 static bool classof(const MemRegion *R) {
355 return R->getKind() == StackLocalsSpaceRegionKind;
356 }
357 };
358
359 class StackArgumentsSpaceRegion : public StackSpaceRegion {
360 private:
361 virtual void anchor();
362 friend class MemRegionManager;
StackArgumentsSpaceRegion(MemRegionManager * mgr,const StackFrameContext * sfc)363 StackArgumentsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
364 : StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {}
365 public:
classof(const MemRegion * R)366 static bool classof(const MemRegion *R) {
367 return R->getKind() == StackArgumentsSpaceRegionKind;
368 }
369 };
370
371
372 /// SubRegion - A region that subsets another larger region. Most regions
373 /// are subclasses of SubRegion.
374 class SubRegion : public MemRegion {
375 private:
376 virtual void anchor();
377 protected:
378 const MemRegion* superRegion;
SubRegion(const MemRegion * sReg,Kind k)379 SubRegion(const MemRegion* sReg, Kind k) : MemRegion(k), superRegion(sReg) {}
380 public:
getSuperRegion()381 const MemRegion* getSuperRegion() const {
382 return superRegion;
383 }
384
385 /// getExtent - Returns the size of the region in bytes.
getExtent(SValBuilder & svalBuilder)386 virtual DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const {
387 return UnknownVal();
388 }
389
390 MemRegionManager* getMemRegionManager() const;
391
392 bool isSubRegionOf(const MemRegion* R) const;
393
classof(const MemRegion * R)394 static bool classof(const MemRegion* R) {
395 return R->getKind() > END_MEMSPACES;
396 }
397 };
398
399 //===----------------------------------------------------------------------===//
400 // MemRegion subclasses.
401 //===----------------------------------------------------------------------===//
402
403 /// AllocaRegion - A region that represents an untyped blob of bytes created
404 /// by a call to 'alloca'.
405 class AllocaRegion : public SubRegion {
406 friend class MemRegionManager;
407 protected:
408 unsigned Cnt; // Block counter. Used to distinguish different pieces of
409 // memory allocated by alloca at the same call site.
410 const Expr *Ex;
411
AllocaRegion(const Expr * ex,unsigned cnt,const MemRegion * superRegion)412 AllocaRegion(const Expr *ex, unsigned cnt, const MemRegion *superRegion)
413 : SubRegion(superRegion, AllocaRegionKind), Cnt(cnt), Ex(ex) {}
414
415 public:
416
getExpr()417 const Expr *getExpr() const { return Ex; }
418
isBoundable()419 bool isBoundable() const { return true; }
420
421 DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const;
422
423 void Profile(llvm::FoldingSetNodeID& ID) const;
424
425 static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr *Ex,
426 unsigned Cnt, const MemRegion *superRegion);
427
428 void dumpToStream(raw_ostream &os) const;
429
classof(const MemRegion * R)430 static bool classof(const MemRegion* R) {
431 return R->getKind() == AllocaRegionKind;
432 }
433 };
434
435 /// TypedRegion - An abstract class representing regions that are typed.
436 class TypedRegion : public SubRegion {
437 public:
438 virtual void anchor();
439 protected:
TypedRegion(const MemRegion * sReg,Kind k)440 TypedRegion(const MemRegion* sReg, Kind k) : SubRegion(sReg, k) {}
441
442 public:
443 virtual QualType getLocationType() const = 0;
444
getDesugaredLocationType(ASTContext & Context)445 QualType getDesugaredLocationType(ASTContext &Context) const {
446 return getLocationType().getDesugaredType(Context);
447 }
448
isBoundable()449 bool isBoundable() const { return true; }
450
classof(const MemRegion * R)451 static bool classof(const MemRegion* R) {
452 unsigned k = R->getKind();
453 return k >= BEG_TYPED_REGIONS && k <= END_TYPED_REGIONS;
454 }
455 };
456
457 /// TypedValueRegion - An abstract class representing regions having a typed value.
458 class TypedValueRegion : public TypedRegion {
459 public:
460 virtual void anchor();
461 protected:
TypedValueRegion(const MemRegion * sReg,Kind k)462 TypedValueRegion(const MemRegion* sReg, Kind k) : TypedRegion(sReg, k) {}
463
464 public:
465 virtual QualType getValueType() const = 0;
466
getLocationType()467 virtual QualType getLocationType() const {
468 // FIXME: We can possibly optimize this later to cache this value.
469 QualType T = getValueType();
470 ASTContext &ctx = getContext();
471 if (T->getAs<ObjCObjectType>())
472 return ctx.getObjCObjectPointerType(T);
473 return ctx.getPointerType(getValueType());
474 }
475
getDesugaredValueType(ASTContext & Context)476 QualType getDesugaredValueType(ASTContext &Context) const {
477 QualType T = getValueType();
478 return T.getTypePtrOrNull() ? T.getDesugaredType(Context) : T;
479 }
480
classof(const MemRegion * R)481 static bool classof(const MemRegion* R) {
482 unsigned k = R->getKind();
483 return k >= BEG_TYPED_VALUE_REGIONS && k <= END_TYPED_VALUE_REGIONS;
484 }
485 };
486
487
488 class CodeTextRegion : public TypedRegion {
489 public:
490 virtual void anchor();
491 protected:
CodeTextRegion(const MemRegion * sreg,Kind k)492 CodeTextRegion(const MemRegion *sreg, Kind k) : TypedRegion(sreg, k) {}
493 public:
isBoundable()494 bool isBoundable() const { return false; }
495
classof(const MemRegion * R)496 static bool classof(const MemRegion* R) {
497 Kind k = R->getKind();
498 return k >= FunctionTextRegionKind && k <= BlockTextRegionKind;
499 }
500 };
501
502 /// FunctionTextRegion - A region that represents code texts of function.
503 class FunctionTextRegion : public CodeTextRegion {
504 const FunctionDecl *FD;
505 public:
FunctionTextRegion(const FunctionDecl * fd,const MemRegion * sreg)506 FunctionTextRegion(const FunctionDecl *fd, const MemRegion* sreg)
507 : CodeTextRegion(sreg, FunctionTextRegionKind), FD(fd) {}
508
getLocationType()509 QualType getLocationType() const {
510 return getContext().getPointerType(FD->getType());
511 }
512
getDecl()513 const FunctionDecl *getDecl() const {
514 return FD;
515 }
516
517 virtual void dumpToStream(raw_ostream &os) const;
518
519 void Profile(llvm::FoldingSetNodeID& ID) const;
520
521 static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FunctionDecl *FD,
522 const MemRegion*);
523
classof(const MemRegion * R)524 static bool classof(const MemRegion* R) {
525 return R->getKind() == FunctionTextRegionKind;
526 }
527 };
528
529
530 /// BlockTextRegion - A region that represents code texts of blocks (closures).
531 /// Blocks are represented with two kinds of regions. BlockTextRegions
532 /// represent the "code", while BlockDataRegions represent instances of blocks,
533 /// which correspond to "code+data". The distinction is important, because
534 /// like a closure a block captures the values of externally referenced
535 /// variables.
536 class BlockTextRegion : public CodeTextRegion {
537 friend class MemRegionManager;
538
539 const BlockDecl *BD;
540 AnalysisDeclContext *AC;
541 CanQualType locTy;
542
BlockTextRegion(const BlockDecl * bd,CanQualType lTy,AnalysisDeclContext * ac,const MemRegion * sreg)543 BlockTextRegion(const BlockDecl *bd, CanQualType lTy,
544 AnalysisDeclContext *ac, const MemRegion* sreg)
545 : CodeTextRegion(sreg, BlockTextRegionKind), BD(bd), AC(ac), locTy(lTy) {}
546
547 public:
getLocationType()548 QualType getLocationType() const {
549 return locTy;
550 }
551
getDecl()552 const BlockDecl *getDecl() const {
553 return BD;
554 }
555
getAnalysisDeclContext()556 AnalysisDeclContext *getAnalysisDeclContext() const { return AC; }
557
558 virtual void dumpToStream(raw_ostream &os) const;
559
560 void Profile(llvm::FoldingSetNodeID& ID) const;
561
562 static void ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD,
563 CanQualType, const AnalysisDeclContext*,
564 const MemRegion*);
565
classof(const MemRegion * R)566 static bool classof(const MemRegion* R) {
567 return R->getKind() == BlockTextRegionKind;
568 }
569 };
570
571 /// BlockDataRegion - A region that represents a block instance.
572 /// Blocks are represented with two kinds of regions. BlockTextRegions
573 /// represent the "code", while BlockDataRegions represent instances of blocks,
574 /// which correspond to "code+data". The distinction is important, because
575 /// like a closure a block captures the values of externally referenced
576 /// variables.
577 class BlockDataRegion : public SubRegion {
578 friend class MemRegionManager;
579 const BlockTextRegion *BC;
580 const LocationContext *LC; // Can be null */
581 void *ReferencedVars;
582
BlockDataRegion(const BlockTextRegion * bc,const LocationContext * lc,const MemRegion * sreg)583 BlockDataRegion(const BlockTextRegion *bc, const LocationContext *lc,
584 const MemRegion *sreg)
585 : SubRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), ReferencedVars(0) {}
586
587 public:
getCodeRegion()588 const BlockTextRegion *getCodeRegion() const { return BC; }
589
getDecl()590 const BlockDecl *getDecl() const { return BC->getDecl(); }
591
592 class referenced_vars_iterator {
593 const MemRegion * const *R;
594 public:
referenced_vars_iterator(const MemRegion * const * r)595 explicit referenced_vars_iterator(const MemRegion * const *r) : R(r) {}
596
597 operator const MemRegion * const *() const {
598 return R;
599 }
600
601 const VarRegion* operator*() const {
602 return cast<VarRegion>(*R);
603 }
604
605 bool operator==(const referenced_vars_iterator &I) const {
606 return I.R == R;
607 }
608 bool operator!=(const referenced_vars_iterator &I) const {
609 return I.R != R;
610 }
611 referenced_vars_iterator &operator++() {
612 ++R;
613 return *this;
614 }
615 };
616
617 referenced_vars_iterator referenced_vars_begin() const;
618 referenced_vars_iterator referenced_vars_end() const;
619
620 virtual void dumpToStream(raw_ostream &os) const;
621
622 void Profile(llvm::FoldingSetNodeID& ID) const;
623
624 static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockTextRegion *,
625 const LocationContext *, const MemRegion *);
626
classof(const MemRegion * R)627 static bool classof(const MemRegion* R) {
628 return R->getKind() == BlockDataRegionKind;
629 }
630 private:
631 void LazyInitializeReferencedVars();
632 };
633
634 /// SymbolicRegion - A special, "non-concrete" region. Unlike other region
635 /// clases, SymbolicRegion represents a region that serves as an alias for
636 /// either a real region, a NULL pointer, etc. It essentially is used to
637 /// map the concept of symbolic values into the domain of regions. Symbolic
638 /// regions do not need to be typed.
639 class SymbolicRegion : public SubRegion {
640 protected:
641 const SymbolRef sym;
642
643 public:
SymbolicRegion(const SymbolRef s,const MemRegion * sreg)644 SymbolicRegion(const SymbolRef s, const MemRegion* sreg)
645 : SubRegion(sreg, SymbolicRegionKind), sym(s) {}
646
getSymbol()647 SymbolRef getSymbol() const {
648 return sym;
649 }
650
isBoundable()651 bool isBoundable() const { return true; }
652
653 DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const;
654
655 void Profile(llvm::FoldingSetNodeID& ID) const;
656
657 static void ProfileRegion(llvm::FoldingSetNodeID& ID,
658 SymbolRef sym,
659 const MemRegion* superRegion);
660
661 void dumpToStream(raw_ostream &os) const;
662
classof(const MemRegion * R)663 static bool classof(const MemRegion* R) {
664 return R->getKind() == SymbolicRegionKind;
665 }
666 };
667
668 /// StringRegion - Region associated with a StringLiteral.
669 class StringRegion : public TypedValueRegion {
670 friend class MemRegionManager;
671 const StringLiteral* Str;
672 protected:
673
StringRegion(const StringLiteral * str,const MemRegion * sreg)674 StringRegion(const StringLiteral* str, const MemRegion* sreg)
675 : TypedValueRegion(sreg, StringRegionKind), Str(str) {}
676
677 static void ProfileRegion(llvm::FoldingSetNodeID& ID,
678 const StringLiteral* Str,
679 const MemRegion* superRegion);
680
681 public:
682
getStringLiteral()683 const StringLiteral* getStringLiteral() const { return Str; }
684
getValueType()685 QualType getValueType() const {
686 return Str->getType();
687 }
688
689 DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const;
690
isBoundable()691 bool isBoundable() const { return false; }
692
Profile(llvm::FoldingSetNodeID & ID)693 void Profile(llvm::FoldingSetNodeID& ID) const {
694 ProfileRegion(ID, Str, superRegion);
695 }
696
697 void dumpToStream(raw_ostream &os) const;
698
classof(const MemRegion * R)699 static bool classof(const MemRegion* R) {
700 return R->getKind() == StringRegionKind;
701 }
702 };
703
704 /// The region associated with an ObjCStringLiteral.
705 class ObjCStringRegion : public TypedValueRegion {
706 friend class MemRegionManager;
707 const ObjCStringLiteral* Str;
708 protected:
709
ObjCStringRegion(const ObjCStringLiteral * str,const MemRegion * sreg)710 ObjCStringRegion(const ObjCStringLiteral* str, const MemRegion* sreg)
711 : TypedValueRegion(sreg, ObjCStringRegionKind), Str(str) {}
712
713 static void ProfileRegion(llvm::FoldingSetNodeID& ID,
714 const ObjCStringLiteral* Str,
715 const MemRegion* superRegion);
716
717 public:
718
getObjCStringLiteral()719 const ObjCStringLiteral* getObjCStringLiteral() const { return Str; }
720
getValueType()721 QualType getValueType() const {
722 return Str->getType();
723 }
724
isBoundable()725 bool isBoundable() const { return false; }
726
Profile(llvm::FoldingSetNodeID & ID)727 void Profile(llvm::FoldingSetNodeID& ID) const {
728 ProfileRegion(ID, Str, superRegion);
729 }
730
731 void dumpToStream(raw_ostream &os) const;
732
classof(const MemRegion * R)733 static bool classof(const MemRegion* R) {
734 return R->getKind() == ObjCStringRegionKind;
735 }
736 };
737
738 /// CompoundLiteralRegion - A memory region representing a compound literal.
739 /// Compound literals are essentially temporaries that are stack allocated
740 /// or in the global constant pool.
741 class CompoundLiteralRegion : public TypedValueRegion {
742 private:
743 friend class MemRegionManager;
744 const CompoundLiteralExpr *CL;
745
CompoundLiteralRegion(const CompoundLiteralExpr * cl,const MemRegion * sReg)746 CompoundLiteralRegion(const CompoundLiteralExpr *cl, const MemRegion* sReg)
747 : TypedValueRegion(sReg, CompoundLiteralRegionKind), CL(cl) {}
748
749 static void ProfileRegion(llvm::FoldingSetNodeID& ID,
750 const CompoundLiteralExpr *CL,
751 const MemRegion* superRegion);
752 public:
getValueType()753 QualType getValueType() const {
754 return CL->getType();
755 }
756
isBoundable()757 bool isBoundable() const { return !CL->isFileScope(); }
758
759 void Profile(llvm::FoldingSetNodeID& ID) const;
760
761 void dumpToStream(raw_ostream &os) const;
762
getLiteralExpr()763 const CompoundLiteralExpr *getLiteralExpr() const { return CL; }
764
classof(const MemRegion * R)765 static bool classof(const MemRegion* R) {
766 return R->getKind() == CompoundLiteralRegionKind;
767 }
768 };
769
770 class DeclRegion : public TypedValueRegion {
771 protected:
772 const Decl *D;
773
DeclRegion(const Decl * d,const MemRegion * sReg,Kind k)774 DeclRegion(const Decl *d, const MemRegion* sReg, Kind k)
775 : TypedValueRegion(sReg, k), D(d) {}
776
777 static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl *D,
778 const MemRegion* superRegion, Kind k);
779
780 public:
getDecl()781 const Decl *getDecl() const { return D; }
782 void Profile(llvm::FoldingSetNodeID& ID) const;
783
784 DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const;
785
classof(const MemRegion * R)786 static bool classof(const MemRegion* R) {
787 unsigned k = R->getKind();
788 return k >= BEG_DECL_REGIONS && k <= END_DECL_REGIONS;
789 }
790 };
791
792 class VarRegion : public DeclRegion {
793 friend class MemRegionManager;
794
795 // Constructors and private methods.
VarRegion(const VarDecl * vd,const MemRegion * sReg)796 VarRegion(const VarDecl *vd, const MemRegion* sReg)
797 : DeclRegion(vd, sReg, VarRegionKind) {}
798
ProfileRegion(llvm::FoldingSetNodeID & ID,const VarDecl * VD,const MemRegion * superRegion)799 static void ProfileRegion(llvm::FoldingSetNodeID& ID, const VarDecl *VD,
800 const MemRegion *superRegion) {
801 DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind);
802 }
803
804 void Profile(llvm::FoldingSetNodeID& ID) const;
805
806 public:
getDecl()807 const VarDecl *getDecl() const { return cast<VarDecl>(D); }
808
809 const StackFrameContext *getStackFrame() const;
810
getValueType()811 QualType getValueType() const {
812 // FIXME: We can cache this if needed.
813 return getDecl()->getType();
814 }
815
816 void dumpToStream(raw_ostream &os) const;
817
classof(const MemRegion * R)818 static bool classof(const MemRegion* R) {
819 return R->getKind() == VarRegionKind;
820 }
821
822 void dumpPretty(raw_ostream &os) const;
823 };
824
825 /// CXXThisRegion - Represents the region for the implicit 'this' parameter
826 /// in a call to a C++ method. This region doesn't represent the object
827 /// referred to by 'this', but rather 'this' itself.
828 class CXXThisRegion : public TypedValueRegion {
829 friend class MemRegionManager;
CXXThisRegion(const PointerType * thisPointerTy,const MemRegion * sReg)830 CXXThisRegion(const PointerType *thisPointerTy,
831 const MemRegion *sReg)
832 : TypedValueRegion(sReg, CXXThisRegionKind), ThisPointerTy(thisPointerTy) {}
833
834 static void ProfileRegion(llvm::FoldingSetNodeID &ID,
835 const PointerType *PT,
836 const MemRegion *sReg);
837
838 void Profile(llvm::FoldingSetNodeID &ID) const;
839
840 public:
getValueType()841 QualType getValueType() const {
842 return QualType(ThisPointerTy, 0);
843 }
844
845 void dumpToStream(raw_ostream &os) const;
846
classof(const MemRegion * R)847 static bool classof(const MemRegion* R) {
848 return R->getKind() == CXXThisRegionKind;
849 }
850
851 private:
852 const PointerType *ThisPointerTy;
853 };
854
855 class FieldRegion : public DeclRegion {
856 friend class MemRegionManager;
857
FieldRegion(const FieldDecl * fd,const MemRegion * sReg)858 FieldRegion(const FieldDecl *fd, const MemRegion* sReg)
859 : DeclRegion(fd, sReg, FieldRegionKind) {}
860
861 public:
getDecl()862 const FieldDecl *getDecl() const { return cast<FieldDecl>(D); }
863
getValueType()864 QualType getValueType() const {
865 // FIXME: We can cache this if needed.
866 return getDecl()->getType();
867 }
868
869 DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const;
870
ProfileRegion(llvm::FoldingSetNodeID & ID,const FieldDecl * FD,const MemRegion * superRegion)871 static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl *FD,
872 const MemRegion* superRegion) {
873 DeclRegion::ProfileRegion(ID, FD, superRegion, FieldRegionKind);
874 }
875
classof(const MemRegion * R)876 static bool classof(const MemRegion* R) {
877 return R->getKind() == FieldRegionKind;
878 }
879
880 void dumpToStream(raw_ostream &os) const;
881 void dumpPretty(raw_ostream &os) const;
882 };
883
884 class ObjCIvarRegion : public DeclRegion {
885
886 friend class MemRegionManager;
887
888 ObjCIvarRegion(const ObjCIvarDecl *ivd, const MemRegion* sReg);
889
890 static void ProfileRegion(llvm::FoldingSetNodeID& ID, const ObjCIvarDecl *ivd,
891 const MemRegion* superRegion);
892
893 public:
894 const ObjCIvarDecl *getDecl() const;
895 QualType getValueType() const;
896
897 void dumpToStream(raw_ostream &os) const;
898
classof(const MemRegion * R)899 static bool classof(const MemRegion* R) {
900 return R->getKind() == ObjCIvarRegionKind;
901 }
902 };
903 //===----------------------------------------------------------------------===//
904 // Auxiliary data classes for use with MemRegions.
905 //===----------------------------------------------------------------------===//
906
907 class ElementRegion;
908
909 class RegionRawOffset {
910 private:
911 friend class ElementRegion;
912
913 const MemRegion *Region;
914 CharUnits Offset;
915
916 RegionRawOffset(const MemRegion* reg, CharUnits offset = CharUnits::Zero())
Region(reg)917 : Region(reg), Offset(offset) {}
918
919 public:
920 // FIXME: Eventually support symbolic offsets.
getOffset()921 CharUnits getOffset() const { return Offset; }
getRegion()922 const MemRegion *getRegion() const { return Region; }
923
924 void dumpToStream(raw_ostream &os) const;
925 void dump() const;
926 };
927
928 /// \brief ElementRegin is used to represent both array elements and casts.
929 class ElementRegion : public TypedValueRegion {
930 friend class MemRegionManager;
931
932 QualType ElementType;
933 NonLoc Index;
934
ElementRegion(QualType elementType,NonLoc Idx,const MemRegion * sReg)935 ElementRegion(QualType elementType, NonLoc Idx, const MemRegion* sReg)
936 : TypedValueRegion(sReg, ElementRegionKind),
937 ElementType(elementType), Index(Idx) {
938 assert((!isa<nonloc::ConcreteInt>(&Idx) ||
939 cast<nonloc::ConcreteInt>(&Idx)->getValue().isSigned()) &&
940 "The index must be signed");
941 }
942
943 static void ProfileRegion(llvm::FoldingSetNodeID& ID, QualType elementType,
944 SVal Idx, const MemRegion* superRegion);
945
946 public:
947
getIndex()948 NonLoc getIndex() const { return Index; }
949
getValueType()950 QualType getValueType() const {
951 return ElementType;
952 }
953
getElementType()954 QualType getElementType() const {
955 return ElementType;
956 }
957 /// Compute the offset within the array. The array might also be a subobject.
958 RegionRawOffset getAsArrayOffset() const;
959
960 void dumpToStream(raw_ostream &os) const;
961
962 void Profile(llvm::FoldingSetNodeID& ID) const;
963
classof(const MemRegion * R)964 static bool classof(const MemRegion* R) {
965 return R->getKind() == ElementRegionKind;
966 }
967 };
968
969 // C++ temporary object associated with an expression.
970 class CXXTempObjectRegion : public TypedValueRegion {
971 friend class MemRegionManager;
972
973 Expr const *Ex;
974
CXXTempObjectRegion(Expr const * E,MemRegion const * sReg)975 CXXTempObjectRegion(Expr const *E, MemRegion const *sReg)
976 : TypedValueRegion(sReg, CXXTempObjectRegionKind), Ex(E) {}
977
978 static void ProfileRegion(llvm::FoldingSetNodeID &ID,
979 Expr const *E, const MemRegion *sReg);
980
981 public:
getExpr()982 const Expr *getExpr() const { return Ex; }
983
getValueType()984 QualType getValueType() const {
985 return Ex->getType();
986 }
987
988 void dumpToStream(raw_ostream &os) const;
989
990 void Profile(llvm::FoldingSetNodeID &ID) const;
991
classof(const MemRegion * R)992 static bool classof(const MemRegion* R) {
993 return R->getKind() == CXXTempObjectRegionKind;
994 }
995 };
996
997 // CXXBaseObjectRegion represents a base object within a C++ object. It is
998 // identified by the base class declaration and the region of its parent object.
999 class CXXBaseObjectRegion : public TypedValueRegion {
1000 friend class MemRegionManager;
1001
1002 const CXXRecordDecl *decl;
1003
CXXBaseObjectRegion(const CXXRecordDecl * d,const MemRegion * sReg)1004 CXXBaseObjectRegion(const CXXRecordDecl *d, const MemRegion *sReg)
1005 : TypedValueRegion(sReg, CXXBaseObjectRegionKind), decl(d) {}
1006
1007 static void ProfileRegion(llvm::FoldingSetNodeID &ID,
1008 const CXXRecordDecl *decl, const MemRegion *sReg);
1009
1010 public:
getDecl()1011 const CXXRecordDecl *getDecl() const { return decl; }
1012
1013 QualType getValueType() const;
1014
1015 void dumpToStream(raw_ostream &os) const;
1016
1017 void Profile(llvm::FoldingSetNodeID &ID) const;
1018
classof(const MemRegion * region)1019 static bool classof(const MemRegion *region) {
1020 return region->getKind() == CXXBaseObjectRegionKind;
1021 }
1022 };
1023
1024 template<typename RegionTy>
getAs()1025 const RegionTy* MemRegion::getAs() const {
1026 if (const RegionTy* RT = dyn_cast<RegionTy>(this))
1027 return RT;
1028
1029 return NULL;
1030 }
1031
1032 //===----------------------------------------------------------------------===//
1033 // MemRegionManager - Factory object for creating regions.
1034 //===----------------------------------------------------------------------===//
1035
1036 class MemRegionManager {
1037 ASTContext &C;
1038 llvm::BumpPtrAllocator& A;
1039 llvm::FoldingSet<MemRegion> Regions;
1040
1041 GlobalInternalSpaceRegion *InternalGlobals;
1042 GlobalSystemSpaceRegion *SystemGlobals;
1043 GlobalImmutableSpaceRegion *ImmutableGlobals;
1044
1045
1046 llvm::DenseMap<const StackFrameContext *, StackLocalsSpaceRegion *>
1047 StackLocalsSpaceRegions;
1048 llvm::DenseMap<const StackFrameContext *, StackArgumentsSpaceRegion *>
1049 StackArgumentsSpaceRegions;
1050 llvm::DenseMap<const CodeTextRegion *, StaticGlobalSpaceRegion *>
1051 StaticsGlobalSpaceRegions;
1052
1053 HeapSpaceRegion *heap;
1054 UnknownSpaceRegion *unknown;
1055 MemSpaceRegion *code;
1056
1057 public:
MemRegionManager(ASTContext & c,llvm::BumpPtrAllocator & a)1058 MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator& a)
1059 : C(c), A(a), InternalGlobals(0), SystemGlobals(0), ImmutableGlobals(0),
1060 heap(0), unknown(0), code(0) {}
1061
1062 ~MemRegionManager();
1063
getContext()1064 ASTContext &getContext() { return C; }
1065
getAllocator()1066 llvm::BumpPtrAllocator &getAllocator() { return A; }
1067
1068 /// getStackLocalsRegion - Retrieve the memory region associated with the
1069 /// specified stack frame.
1070 const StackLocalsSpaceRegion *
1071 getStackLocalsRegion(const StackFrameContext *STC);
1072
1073 /// getStackArgumentsRegion - Retrieve the memory region associated with
1074 /// function/method arguments of the specified stack frame.
1075 const StackArgumentsSpaceRegion *
1076 getStackArgumentsRegion(const StackFrameContext *STC);
1077
1078 /// getGlobalsRegion - Retrieve the memory region associated with
1079 /// global variables.
1080 const GlobalsSpaceRegion *getGlobalsRegion(
1081 MemRegion::Kind K = MemRegion::GlobalInternalSpaceRegionKind,
1082 const CodeTextRegion *R = 0);
1083
1084 /// getHeapRegion - Retrieve the memory region associated with the
1085 /// generic "heap".
1086 const HeapSpaceRegion *getHeapRegion();
1087
1088 /// getUnknownRegion - Retrieve the memory region associated with unknown
1089 /// memory space.
1090 const MemSpaceRegion *getUnknownRegion();
1091
1092 const MemSpaceRegion *getCodeRegion();
1093
1094 /// getAllocaRegion - Retrieve a region associated with a call to alloca().
1095 const AllocaRegion *getAllocaRegion(const Expr *Ex, unsigned Cnt,
1096 const LocationContext *LC);
1097
1098 /// getCompoundLiteralRegion - Retrieve the region associated with a
1099 /// given CompoundLiteral.
1100 const CompoundLiteralRegion*
1101 getCompoundLiteralRegion(const CompoundLiteralExpr *CL,
1102 const LocationContext *LC);
1103
1104 /// getCXXThisRegion - Retrieve the [artificial] region associated with the
1105 /// parameter 'this'.
1106 const CXXThisRegion *getCXXThisRegion(QualType thisPointerTy,
1107 const LocationContext *LC);
1108
1109 /// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
1110 const SymbolicRegion* getSymbolicRegion(SymbolRef sym);
1111
1112 const StringRegion *getStringRegion(const StringLiteral* Str);
1113
1114 const ObjCStringRegion *getObjCStringRegion(const ObjCStringLiteral *Str);
1115
1116 /// getVarRegion - Retrieve or create the memory region associated with
1117 /// a specified VarDecl and LocationContext.
1118 const VarRegion* getVarRegion(const VarDecl *D, const LocationContext *LC);
1119
1120 /// getVarRegion - Retrieve or create the memory region associated with
1121 /// a specified VarDecl and super region.
1122 const VarRegion* getVarRegion(const VarDecl *D, const MemRegion *superR);
1123
1124 /// getElementRegion - Retrieve the memory region associated with the
1125 /// associated element type, index, and super region.
1126 const ElementRegion *getElementRegion(QualType elementType, NonLoc Idx,
1127 const MemRegion *superRegion,
1128 ASTContext &Ctx);
1129
getElementRegionWithSuper(const ElementRegion * ER,const MemRegion * superRegion)1130 const ElementRegion *getElementRegionWithSuper(const ElementRegion *ER,
1131 const MemRegion *superRegion) {
1132 return getElementRegion(ER->getElementType(), ER->getIndex(),
1133 superRegion, ER->getContext());
1134 }
1135
1136 /// getFieldRegion - Retrieve or create the memory region associated with
1137 /// a specified FieldDecl. 'superRegion' corresponds to the containing
1138 /// memory region (which typically represents the memory representing
1139 /// a structure or class).
1140 const FieldRegion *getFieldRegion(const FieldDecl *fd,
1141 const MemRegion* superRegion);
1142
getFieldRegionWithSuper(const FieldRegion * FR,const MemRegion * superRegion)1143 const FieldRegion *getFieldRegionWithSuper(const FieldRegion *FR,
1144 const MemRegion *superRegion) {
1145 return getFieldRegion(FR->getDecl(), superRegion);
1146 }
1147
1148 /// getObjCIvarRegion - Retrieve or create the memory region associated with
1149 /// a specified Objective-c instance variable. 'superRegion' corresponds
1150 /// to the containing region (which typically represents the Objective-C
1151 /// object).
1152 const ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl *ivd,
1153 const MemRegion* superRegion);
1154
1155 const CXXTempObjectRegion *getCXXTempObjectRegion(Expr const *Ex,
1156 LocationContext const *LC);
1157
1158 const CXXBaseObjectRegion *getCXXBaseObjectRegion(const CXXRecordDecl *decl,
1159 const MemRegion *superRegion);
1160
1161 /// Create a CXXBaseObjectRegion with the same CXXRecordDecl but a different
1162 /// super region.
1163 const CXXBaseObjectRegion *
getCXXBaseObjectRegionWithSuper(const CXXBaseObjectRegion * baseReg,const MemRegion * superRegion)1164 getCXXBaseObjectRegionWithSuper(const CXXBaseObjectRegion *baseReg,
1165 const MemRegion *superRegion) {
1166 return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion);
1167 }
1168
1169 const FunctionTextRegion *getFunctionTextRegion(const FunctionDecl *FD);
1170 const BlockTextRegion *getBlockTextRegion(const BlockDecl *BD,
1171 CanQualType locTy,
1172 AnalysisDeclContext *AC);
1173
1174 /// getBlockDataRegion - Get the memory region associated with an instance
1175 /// of a block. Unlike many other MemRegions, the LocationContext*
1176 /// argument is allowed to be NULL for cases where we have no known
1177 /// context.
1178 const BlockDataRegion *getBlockDataRegion(const BlockTextRegion *bc,
1179 const LocationContext *lc = NULL);
1180
1181 private:
1182 template <typename RegionTy, typename A1>
1183 RegionTy* getRegion(const A1 a1);
1184
1185 template <typename RegionTy, typename A1>
1186 RegionTy* getSubRegion(const A1 a1, const MemRegion* superRegion);
1187
1188 template <typename RegionTy, typename A1, typename A2>
1189 RegionTy* getRegion(const A1 a1, const A2 a2);
1190
1191 template <typename RegionTy, typename A1, typename A2>
1192 RegionTy* getSubRegion(const A1 a1, const A2 a2,
1193 const MemRegion* superRegion);
1194
1195 template <typename RegionTy, typename A1, typename A2, typename A3>
1196 RegionTy* getSubRegion(const A1 a1, const A2 a2, const A3 a3,
1197 const MemRegion* superRegion);
1198
1199 template <typename REG>
1200 const REG* LazyAllocate(REG*& region);
1201
1202 template <typename REG, typename ARG>
1203 const REG* LazyAllocate(REG*& region, ARG a);
1204 };
1205
1206 //===----------------------------------------------------------------------===//
1207 // Out-of-line member definitions.
1208 //===----------------------------------------------------------------------===//
1209
getContext()1210 inline ASTContext &MemRegion::getContext() const {
1211 return getMemRegionManager()->getContext();
1212 }
1213
1214 } // end GR namespace
1215
1216 } // end clang namespace
1217
1218 //===----------------------------------------------------------------------===//
1219 // Pretty-printing regions.
1220 //===----------------------------------------------------------------------===//
1221
1222 namespace llvm {
1223 static inline raw_ostream &operator<<(raw_ostream &os,
1224 const clang::ento::MemRegion* R) {
1225 R->dumpToStream(os);
1226 return os;
1227 }
1228 } // end llvm namespace
1229
1230 #endif
1231