MemRegion.cpp revision c35fb7d67d515659ad2325b4f6ec97c9fe64fb63
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 "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
17#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
18#include "clang/Analysis/AnalysisContext.h"
19#include "clang/Analysis/Support/BumpVector.h"
20#include "clang/AST/CharUnits.h"
21#include "clang/AST/DeclObjC.h"
22#include "clang/AST/RecordLayout.h"
23#include "clang/Basic/SourceManager.h"
24#include "llvm/Support/raw_ostream.h"
25
26using namespace clang;
27using namespace ento;
28
29//===----------------------------------------------------------------------===//
30// MemRegion Construction.
31//===----------------------------------------------------------------------===//
32
33template<typename RegionTy> struct MemRegionManagerTrait;
34
35template <typename RegionTy, typename A1>
36RegionTy* MemRegionManager::getRegion(const A1 a1) {
37
38  const typename MemRegionManagerTrait<RegionTy>::SuperRegionTy *superRegion =
39  MemRegionManagerTrait<RegionTy>::getSuperRegion(*this, a1);
40
41  llvm::FoldingSetNodeID ID;
42  RegionTy::ProfileRegion(ID, a1, superRegion);
43  void *InsertPos;
44  RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
45                                                                   InsertPos));
46
47  if (!R) {
48    R = (RegionTy*) A.Allocate<RegionTy>();
49    new (R) RegionTy(a1, superRegion);
50    Regions.InsertNode(R, InsertPos);
51  }
52
53  return R;
54}
55
56template <typename RegionTy, typename A1>
57RegionTy* MemRegionManager::getSubRegion(const A1 a1,
58                                         const MemRegion *superRegion) {
59  llvm::FoldingSetNodeID ID;
60  RegionTy::ProfileRegion(ID, a1, superRegion);
61  void *InsertPos;
62  RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
63                                                                   InsertPos));
64
65  if (!R) {
66    R = (RegionTy*) A.Allocate<RegionTy>();
67    new (R) RegionTy(a1, superRegion);
68    Regions.InsertNode(R, InsertPos);
69  }
70
71  return R;
72}
73
74template <typename RegionTy, typename A1, typename A2>
75RegionTy* MemRegionManager::getRegion(const A1 a1, const A2 a2) {
76
77  const typename MemRegionManagerTrait<RegionTy>::SuperRegionTy *superRegion =
78  MemRegionManagerTrait<RegionTy>::getSuperRegion(*this, a1, a2);
79
80  llvm::FoldingSetNodeID ID;
81  RegionTy::ProfileRegion(ID, a1, a2, superRegion);
82  void *InsertPos;
83  RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
84                                                                   InsertPos));
85
86  if (!R) {
87    R = (RegionTy*) A.Allocate<RegionTy>();
88    new (R) RegionTy(a1, a2, superRegion);
89    Regions.InsertNode(R, InsertPos);
90  }
91
92  return R;
93}
94
95template <typename RegionTy, typename A1, typename A2>
96RegionTy* MemRegionManager::getSubRegion(const A1 a1, const A2 a2,
97                                         const MemRegion *superRegion) {
98
99  llvm::FoldingSetNodeID ID;
100  RegionTy::ProfileRegion(ID, a1, a2, superRegion);
101  void *InsertPos;
102  RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
103                                                                   InsertPos));
104
105  if (!R) {
106    R = (RegionTy*) A.Allocate<RegionTy>();
107    new (R) RegionTy(a1, a2, superRegion);
108    Regions.InsertNode(R, InsertPos);
109  }
110
111  return R;
112}
113
114template <typename RegionTy, typename A1, typename A2, typename A3>
115RegionTy* MemRegionManager::getSubRegion(const A1 a1, const A2 a2, const A3 a3,
116                                         const MemRegion *superRegion) {
117
118  llvm::FoldingSetNodeID ID;
119  RegionTy::ProfileRegion(ID, a1, a2, a3, superRegion);
120  void *InsertPos;
121  RegionTy* R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID,
122                                                                   InsertPos));
123
124  if (!R) {
125    R = (RegionTy*) A.Allocate<RegionTy>();
126    new (R) RegionTy(a1, a2, a3, superRegion);
127    Regions.InsertNode(R, InsertPos);
128  }
129
130  return R;
131}
132
133//===----------------------------------------------------------------------===//
134// Object destruction.
135//===----------------------------------------------------------------------===//
136
137MemRegion::~MemRegion() {}
138
139MemRegionManager::~MemRegionManager() {
140  // All regions and their data are BumpPtrAllocated.  No need to call
141  // their destructors.
142}
143
144//===----------------------------------------------------------------------===//
145// Basic methods.
146//===----------------------------------------------------------------------===//
147
148bool SubRegion::isSubRegionOf(const MemRegion* R) const {
149  const MemRegion* r = getSuperRegion();
150  while (r != 0) {
151    if (r == R)
152      return true;
153    if (const SubRegion* sr = dyn_cast<SubRegion>(r))
154      r = sr->getSuperRegion();
155    else
156      break;
157  }
158  return false;
159}
160
161MemRegionManager* SubRegion::getMemRegionManager() const {
162  const SubRegion* r = this;
163  do {
164    const MemRegion *superRegion = r->getSuperRegion();
165    if (const SubRegion *sr = dyn_cast<SubRegion>(superRegion)) {
166      r = sr;
167      continue;
168    }
169    return superRegion->getMemRegionManager();
170  } while (1);
171}
172
173const StackFrameContext *VarRegion::getStackFrame() const {
174  const StackSpaceRegion *SSR = dyn_cast<StackSpaceRegion>(getMemorySpace());
175  return SSR ? SSR->getStackFrame() : NULL;
176}
177
178//===----------------------------------------------------------------------===//
179// Region extents.
180//===----------------------------------------------------------------------===//
181
182DefinedOrUnknownSVal DeclRegion::getExtent(SValBuilder &svalBuilder) const {
183  ASTContext &Ctx = svalBuilder.getContext();
184  QualType T = getDesugaredValueType(Ctx);
185
186  if (isa<VariableArrayType>(T))
187    return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this));
188  if (isa<IncompleteArrayType>(T))
189    return UnknownVal();
190
191  CharUnits size = Ctx.getTypeSizeInChars(T);
192  QualType sizeTy = svalBuilder.getArrayIndexType();
193  return svalBuilder.makeIntVal(size.getQuantity(), sizeTy);
194}
195
196DefinedOrUnknownSVal FieldRegion::getExtent(SValBuilder &svalBuilder) const {
197  DefinedOrUnknownSVal Extent = DeclRegion::getExtent(svalBuilder);
198
199  // A zero-length array at the end of a struct often stands for dynamically-
200  // allocated extra memory.
201  if (Extent.isZeroConstant()) {
202    QualType T = getDesugaredValueType(svalBuilder.getContext());
203
204    if (isa<ConstantArrayType>(T))
205      return UnknownVal();
206  }
207
208  return Extent;
209}
210
211DefinedOrUnknownSVal AllocaRegion::getExtent(SValBuilder &svalBuilder) const {
212  return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this));
213}
214
215DefinedOrUnknownSVal SymbolicRegion::getExtent(SValBuilder &svalBuilder) const {
216  return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this));
217}
218
219DefinedOrUnknownSVal StringRegion::getExtent(SValBuilder &svalBuilder) const {
220  return svalBuilder.makeIntVal(getStringLiteral()->getByteLength()+1,
221                                svalBuilder.getArrayIndexType());
222}
223
224ObjCIvarRegion::ObjCIvarRegion(const ObjCIvarDecl *ivd, const MemRegion* sReg)
225  : DeclRegion(ivd, sReg, ObjCIvarRegionKind) {}
226
227const ObjCIvarDecl *ObjCIvarRegion::getDecl() const {
228  return cast<ObjCIvarDecl>(D);
229}
230
231QualType ObjCIvarRegion::getValueType() const {
232  return getDecl()->getType();
233}
234
235QualType CXXBaseObjectRegion::getValueType() const {
236  return QualType(decl->getTypeForDecl(), 0);
237}
238
239//===----------------------------------------------------------------------===//
240// FoldingSet profiling.
241//===----------------------------------------------------------------------===//
242
243void MemSpaceRegion::Profile(llvm::FoldingSetNodeID& ID) const {
244  ID.AddInteger((unsigned)getKind());
245}
246
247void StackSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const {
248  ID.AddInteger((unsigned)getKind());
249  ID.AddPointer(getStackFrame());
250}
251
252void StaticGlobalSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const {
253  ID.AddInteger((unsigned)getKind());
254  ID.AddPointer(getCodeRegion());
255}
256
257void StringRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
258                                 const StringLiteral* Str,
259                                 const MemRegion* superRegion) {
260  ID.AddInteger((unsigned) StringRegionKind);
261  ID.AddPointer(Str);
262  ID.AddPointer(superRegion);
263}
264
265void AllocaRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
266                                 const Expr *Ex, unsigned cnt,
267                                 const MemRegion *) {
268  ID.AddInteger((unsigned) AllocaRegionKind);
269  ID.AddPointer(Ex);
270  ID.AddInteger(cnt);
271}
272
273void AllocaRegion::Profile(llvm::FoldingSetNodeID& ID) const {
274  ProfileRegion(ID, Ex, Cnt, superRegion);
275}
276
277void CompoundLiteralRegion::Profile(llvm::FoldingSetNodeID& ID) const {
278  CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion);
279}
280
281void CompoundLiteralRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
282                                          const CompoundLiteralExpr *CL,
283                                          const MemRegion* superRegion) {
284  ID.AddInteger((unsigned) CompoundLiteralRegionKind);
285  ID.AddPointer(CL);
286  ID.AddPointer(superRegion);
287}
288
289void CXXThisRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
290                                  const PointerType *PT,
291                                  const MemRegion *sRegion) {
292  ID.AddInteger((unsigned) CXXThisRegionKind);
293  ID.AddPointer(PT);
294  ID.AddPointer(sRegion);
295}
296
297void CXXThisRegion::Profile(llvm::FoldingSetNodeID &ID) const {
298  CXXThisRegion::ProfileRegion(ID, ThisPointerTy, superRegion);
299}
300
301void ObjCIvarRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
302                                   const ObjCIvarDecl *ivd,
303                                   const MemRegion* superRegion) {
304  DeclRegion::ProfileRegion(ID, ivd, superRegion, ObjCIvarRegionKind);
305}
306
307void DeclRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl *D,
308                               const MemRegion* superRegion, Kind k) {
309  ID.AddInteger((unsigned) k);
310  ID.AddPointer(D);
311  ID.AddPointer(superRegion);
312}
313
314void DeclRegion::Profile(llvm::FoldingSetNodeID& ID) const {
315  DeclRegion::ProfileRegion(ID, D, superRegion, getKind());
316}
317
318void VarRegion::Profile(llvm::FoldingSetNodeID &ID) const {
319  VarRegion::ProfileRegion(ID, getDecl(), superRegion);
320}
321
322void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym,
323                                   const MemRegion *sreg) {
324  ID.AddInteger((unsigned) MemRegion::SymbolicRegionKind);
325  ID.Add(sym);
326  ID.AddPointer(sreg);
327}
328
329void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const {
330  SymbolicRegion::ProfileRegion(ID, sym, getSuperRegion());
331}
332
333void ElementRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
334                                  QualType ElementType, SVal Idx,
335                                  const MemRegion* superRegion) {
336  ID.AddInteger(MemRegion::ElementRegionKind);
337  ID.Add(ElementType);
338  ID.AddPointer(superRegion);
339  Idx.Profile(ID);
340}
341
342void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const {
343  ElementRegion::ProfileRegion(ID, ElementType, Index, superRegion);
344}
345
346void FunctionTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
347                                       const FunctionDecl *FD,
348                                       const MemRegion*) {
349  ID.AddInteger(MemRegion::FunctionTextRegionKind);
350  ID.AddPointer(FD);
351}
352
353void FunctionTextRegion::Profile(llvm::FoldingSetNodeID& ID) const {
354  FunctionTextRegion::ProfileRegion(ID, FD, superRegion);
355}
356
357void BlockTextRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
358                                    const BlockDecl *BD, CanQualType,
359                                    const AnalysisDeclContext *AC,
360                                    const MemRegion*) {
361  ID.AddInteger(MemRegion::BlockTextRegionKind);
362  ID.AddPointer(BD);
363}
364
365void BlockTextRegion::Profile(llvm::FoldingSetNodeID& ID) const {
366  BlockTextRegion::ProfileRegion(ID, BD, locTy, AC, superRegion);
367}
368
369void BlockDataRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
370                                    const BlockTextRegion *BC,
371                                    const LocationContext *LC,
372                                    const MemRegion *sReg) {
373  ID.AddInteger(MemRegion::BlockDataRegionKind);
374  ID.AddPointer(BC);
375  ID.AddPointer(LC);
376  ID.AddPointer(sReg);
377}
378
379void BlockDataRegion::Profile(llvm::FoldingSetNodeID& ID) const {
380  BlockDataRegion::ProfileRegion(ID, BC, LC, getSuperRegion());
381}
382
383void CXXTempObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
384                                        Expr const *Ex,
385                                        const MemRegion *sReg) {
386  ID.AddPointer(Ex);
387  ID.AddPointer(sReg);
388}
389
390void CXXTempObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
391  ProfileRegion(ID, Ex, getSuperRegion());
392}
393
394void CXXBaseObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
395                                        const CXXRecordDecl *decl,
396                                        const MemRegion *sReg) {
397  ID.AddPointer(decl);
398  ID.AddPointer(sReg);
399}
400
401void CXXBaseObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
402  ProfileRegion(ID, decl, superRegion);
403}
404
405//===----------------------------------------------------------------------===//
406// Region anchors.
407//===----------------------------------------------------------------------===//
408
409void GlobalsSpaceRegion::anchor() { }
410void HeapSpaceRegion::anchor() { }
411void UnknownSpaceRegion::anchor() { }
412void StackLocalsSpaceRegion::anchor() { }
413void StackArgumentsSpaceRegion::anchor() { }
414void TypedRegion::anchor() { }
415void TypedValueRegion::anchor() { }
416void CodeTextRegion::anchor() { }
417void SubRegion::anchor() { }
418
419//===----------------------------------------------------------------------===//
420// Region pretty-printing.
421//===----------------------------------------------------------------------===//
422
423void MemRegion::dump() const {
424  dumpToStream(llvm::errs());
425}
426
427std::string MemRegion::getString() const {
428  std::string s;
429  llvm::raw_string_ostream os(s);
430  dumpToStream(os);
431  return os.str();
432}
433
434void MemRegion::dumpToStream(raw_ostream &os) const {
435  os << "<Unknown Region>";
436}
437
438void AllocaRegion::dumpToStream(raw_ostream &os) const {
439  os << "alloca{" << (void*) Ex << ',' << Cnt << '}';
440}
441
442void FunctionTextRegion::dumpToStream(raw_ostream &os) const {
443  os << "code{" << getDecl()->getDeclName().getAsString() << '}';
444}
445
446void BlockTextRegion::dumpToStream(raw_ostream &os) const {
447  os << "block_code{" << (void*) this << '}';
448}
449
450void BlockDataRegion::dumpToStream(raw_ostream &os) const {
451  os << "block_data{" << BC << '}';
452}
453
454void CompoundLiteralRegion::dumpToStream(raw_ostream &os) const {
455  // FIXME: More elaborate pretty-printing.
456  os << "{ " << (void*) CL <<  " }";
457}
458
459void CXXTempObjectRegion::dumpToStream(raw_ostream &os) const {
460  os << "temp_object{" << getValueType().getAsString() << ','
461     << (void*) Ex << '}';
462}
463
464void CXXBaseObjectRegion::dumpToStream(raw_ostream &os) const {
465  os << "base " << decl->getName();
466}
467
468void CXXThisRegion::dumpToStream(raw_ostream &os) const {
469  os << "this";
470}
471
472void ElementRegion::dumpToStream(raw_ostream &os) const {
473  os << "element{" << superRegion << ','
474     << Index << ',' << getElementType().getAsString() << '}';
475}
476
477void FieldRegion::dumpToStream(raw_ostream &os) const {
478  os << superRegion << "->" << *getDecl();
479}
480
481void ObjCIvarRegion::dumpToStream(raw_ostream &os) const {
482  os << "ivar{" << superRegion << ',' << *getDecl() << '}';
483}
484
485void StringRegion::dumpToStream(raw_ostream &os) const {
486  Str->printPretty(os, 0, PrintingPolicy(getContext().getLangOptions()));
487}
488
489void SymbolicRegion::dumpToStream(raw_ostream &os) const {
490  os << "SymRegion{" << sym << '}';
491}
492
493void VarRegion::dumpToStream(raw_ostream &os) const {
494  os << *cast<VarDecl>(D);
495}
496
497void RegionRawOffset::dump() const {
498  dumpToStream(llvm::errs());
499}
500
501void RegionRawOffset::dumpToStream(raw_ostream &os) const {
502  os << "raw_offset{" << getRegion() << ',' << getOffset().getQuantity() << '}';
503}
504
505void StaticGlobalSpaceRegion::dumpToStream(raw_ostream &os) const {
506  os << "StaticGlobalsMemSpace{" << CR << '}';
507}
508
509void NonStaticGlobalSpaceRegion::dumpToStream(raw_ostream &os) const {
510  os << "NonStaticGlobalSpaceRegion";
511}
512
513void GlobalInternalSpaceRegion::dumpToStream(raw_ostream &os) const {
514  os << "GlobalInternalSpaceRegion";
515}
516
517void GlobalSystemSpaceRegion::dumpToStream(raw_ostream &os) const {
518  os << "GlobalSystemSpaceRegion";
519}
520
521void GlobalImmutableSpaceRegion::dumpToStream(raw_ostream &os) const {
522  os << "GlobalImmutableSpaceRegion";
523}
524
525//===----------------------------------------------------------------------===//
526// MemRegionManager methods.
527//===----------------------------------------------------------------------===//
528
529template <typename REG>
530const REG *MemRegionManager::LazyAllocate(REG*& region) {
531  if (!region) {
532    region = (REG*) A.Allocate<REG>();
533    new (region) REG(this);
534  }
535
536  return region;
537}
538
539template <typename REG, typename ARG>
540const REG *MemRegionManager::LazyAllocate(REG*& region, ARG a) {
541  if (!region) {
542    region = (REG*) A.Allocate<REG>();
543    new (region) REG(this, a);
544  }
545
546  return region;
547}
548
549const StackLocalsSpaceRegion*
550MemRegionManager::getStackLocalsRegion(const StackFrameContext *STC) {
551  assert(STC);
552  StackLocalsSpaceRegion *&R = StackLocalsSpaceRegions[STC];
553
554  if (R)
555    return R;
556
557  R = A.Allocate<StackLocalsSpaceRegion>();
558  new (R) StackLocalsSpaceRegion(this, STC);
559  return R;
560}
561
562const StackArgumentsSpaceRegion *
563MemRegionManager::getStackArgumentsRegion(const StackFrameContext *STC) {
564  assert(STC);
565  StackArgumentsSpaceRegion *&R = StackArgumentsSpaceRegions[STC];
566
567  if (R)
568    return R;
569
570  R = A.Allocate<StackArgumentsSpaceRegion>();
571  new (R) StackArgumentsSpaceRegion(this, STC);
572  return R;
573}
574
575const GlobalsSpaceRegion
576*MemRegionManager::getGlobalsRegion(MemRegion::Kind K,
577                                    const CodeTextRegion *CR) {
578  if (!CR) {
579    if (K == MemRegion::GlobalSystemSpaceRegionKind)
580      return LazyAllocate(SystemGlobals);
581    if (K == MemRegion::GlobalImmutableSpaceRegionKind)
582      return LazyAllocate(ImmutableGlobals);
583    assert(K == MemRegion::GlobalInternalSpaceRegionKind);
584    return LazyAllocate(InternalGlobals);
585  }
586
587  assert(K == MemRegion::StaticGlobalSpaceRegionKind);
588  StaticGlobalSpaceRegion *&R = StaticsGlobalSpaceRegions[CR];
589  if (R)
590    return R;
591
592  R = A.Allocate<StaticGlobalSpaceRegion>();
593  new (R) StaticGlobalSpaceRegion(this, CR);
594  return R;
595}
596
597const HeapSpaceRegion *MemRegionManager::getHeapRegion() {
598  return LazyAllocate(heap);
599}
600
601const MemSpaceRegion *MemRegionManager::getUnknownRegion() {
602  return LazyAllocate(unknown);
603}
604
605const MemSpaceRegion *MemRegionManager::getCodeRegion() {
606  return LazyAllocate(code);
607}
608
609//===----------------------------------------------------------------------===//
610// Constructing regions.
611//===----------------------------------------------------------------------===//
612const StringRegion* MemRegionManager::getStringRegion(const StringLiteral* Str){
613  return getSubRegion<StringRegion>(Str, getGlobalsRegion());
614}
615
616const VarRegion* MemRegionManager::getVarRegion(const VarDecl *D,
617                                                const LocationContext *LC) {
618  const MemRegion *sReg = 0;
619
620  if (D->hasGlobalStorage() && !D->isStaticLocal()) {
621
622    // First handle the globals defined in system headers.
623    if (C.getSourceManager().isInSystemHeader(D->getLocation())) {
624      // Whitelist the system globals which often DO GET modified, assume the
625      // rest are immutable.
626      if (D->getName().find("errno") != StringRef::npos)
627        sReg = getGlobalsRegion(MemRegion::GlobalSystemSpaceRegionKind);
628      else
629        sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind);
630
631    // Treat other globals as GlobalInternal unless they are constants.
632    } else {
633      QualType GQT = D->getType();
634      const Type *GT = GQT.getTypePtrOrNull();
635      // TODO: We could walk the complex types here and see if everything is
636      // constified.
637      if (GT && GQT.isConstQualified() && GT->isArithmeticType())
638        sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind);
639      else
640        sReg = getGlobalsRegion();
641    }
642
643  // Finally handle static locals.
644  } else {
645    // FIXME: Once we implement scope handling, we will need to properly lookup
646    // 'D' to the proper LocationContext.
647    const DeclContext *DC = D->getDeclContext();
648    const StackFrameContext *STC = LC->getStackFrameForDeclContext(DC);
649
650    if (!STC)
651      sReg = getUnknownRegion();
652    else {
653      if (D->hasLocalStorage()) {
654        sReg = isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)
655               ? static_cast<const MemRegion*>(getStackArgumentsRegion(STC))
656               : static_cast<const MemRegion*>(getStackLocalsRegion(STC));
657      }
658      else {
659        assert(D->isStaticLocal());
660        const Decl *D = STC->getDecl();
661        if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
662          sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind,
663                                  getFunctionTextRegion(FD));
664        else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
665          const BlockTextRegion *BTR =
666            getBlockTextRegion(BD,
667                     C.getCanonicalType(BD->getSignatureAsWritten()->getType()),
668                     STC->getAnalysisDeclContext());
669          sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind,
670                                  BTR);
671        }
672        else {
673          // FIXME: For ObjC-methods, we need a new CodeTextRegion.  For now
674          // just use the main global memspace.
675          sReg = getGlobalsRegion();
676        }
677      }
678    }
679  }
680
681  return getSubRegion<VarRegion>(D, sReg);
682}
683
684const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D,
685                                                const MemRegion *superR) {
686  return getSubRegion<VarRegion>(D, superR);
687}
688
689const BlockDataRegion *
690MemRegionManager::getBlockDataRegion(const BlockTextRegion *BC,
691                                     const LocationContext *LC) {
692  const MemRegion *sReg = 0;
693
694  if (LC) {
695    // FIXME: Once we implement scope handling, we want the parent region
696    // to be the scope.
697    const StackFrameContext *STC = LC->getCurrentStackFrame();
698    assert(STC);
699    sReg = getStackLocalsRegion(STC);
700  }
701  else {
702    // We allow 'LC' to be NULL for cases where want BlockDataRegions
703    // without context-sensitivity.
704    sReg = getUnknownRegion();
705  }
706
707  return getSubRegion<BlockDataRegion>(BC, LC, sReg);
708}
709
710const CompoundLiteralRegion*
711MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr *CL,
712                                           const LocationContext *LC) {
713
714  const MemRegion *sReg = 0;
715
716  if (CL->isFileScope())
717    sReg = getGlobalsRegion();
718  else {
719    const StackFrameContext *STC = LC->getCurrentStackFrame();
720    assert(STC);
721    sReg = getStackLocalsRegion(STC);
722  }
723
724  return getSubRegion<CompoundLiteralRegion>(CL, sReg);
725}
726
727const ElementRegion*
728MemRegionManager::getElementRegion(QualType elementType, NonLoc Idx,
729                                   const MemRegion* superRegion,
730                                   ASTContext &Ctx){
731
732  QualType T = Ctx.getCanonicalType(elementType).getUnqualifiedType();
733
734  llvm::FoldingSetNodeID ID;
735  ElementRegion::ProfileRegion(ID, T, Idx, superRegion);
736
737  void *InsertPos;
738  MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
739  ElementRegion* R = cast_or_null<ElementRegion>(data);
740
741  if (!R) {
742    R = (ElementRegion*) A.Allocate<ElementRegion>();
743    new (R) ElementRegion(T, Idx, superRegion);
744    Regions.InsertNode(R, InsertPos);
745  }
746
747  return R;
748}
749
750const FunctionTextRegion *
751MemRegionManager::getFunctionTextRegion(const FunctionDecl *FD) {
752  return getSubRegion<FunctionTextRegion>(FD, getCodeRegion());
753}
754
755const BlockTextRegion *
756MemRegionManager::getBlockTextRegion(const BlockDecl *BD, CanQualType locTy,
757                                     AnalysisDeclContext *AC) {
758  return getSubRegion<BlockTextRegion>(BD, locTy, AC, getCodeRegion());
759}
760
761
762/// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
763const SymbolicRegion *MemRegionManager::getSymbolicRegion(SymbolRef sym) {
764  return getSubRegion<SymbolicRegion>(sym, getUnknownRegion());
765}
766
767const FieldRegion*
768MemRegionManager::getFieldRegion(const FieldDecl *d,
769                                 const MemRegion* superRegion){
770  return getSubRegion<FieldRegion>(d, superRegion);
771}
772
773const ObjCIvarRegion*
774MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl *d,
775                                    const MemRegion* superRegion) {
776  return getSubRegion<ObjCIvarRegion>(d, superRegion);
777}
778
779const CXXTempObjectRegion*
780MemRegionManager::getCXXTempObjectRegion(Expr const *E,
781                                         LocationContext const *LC) {
782  const StackFrameContext *SFC = LC->getCurrentStackFrame();
783  assert(SFC);
784  return getSubRegion<CXXTempObjectRegion>(E, getStackLocalsRegion(SFC));
785}
786
787const CXXBaseObjectRegion *
788MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl *decl,
789                                         const MemRegion *superRegion) {
790  return getSubRegion<CXXBaseObjectRegion>(decl, superRegion);
791}
792
793const CXXThisRegion*
794MemRegionManager::getCXXThisRegion(QualType thisPointerTy,
795                                   const LocationContext *LC) {
796  const StackFrameContext *STC = LC->getCurrentStackFrame();
797  assert(STC);
798  const PointerType *PT = thisPointerTy->getAs<PointerType>();
799  assert(PT);
800  return getSubRegion<CXXThisRegion>(PT, getStackArgumentsRegion(STC));
801}
802
803const AllocaRegion*
804MemRegionManager::getAllocaRegion(const Expr *E, unsigned cnt,
805                                  const LocationContext *LC) {
806  const StackFrameContext *STC = LC->getCurrentStackFrame();
807  assert(STC);
808  return getSubRegion<AllocaRegion>(E, cnt, getStackLocalsRegion(STC));
809}
810
811const MemSpaceRegion *MemRegion::getMemorySpace() const {
812  const MemRegion *R = this;
813  const SubRegion* SR = dyn_cast<SubRegion>(this);
814
815  while (SR) {
816    R = SR->getSuperRegion();
817    SR = dyn_cast<SubRegion>(R);
818  }
819
820  return dyn_cast<MemSpaceRegion>(R);
821}
822
823bool MemRegion::hasStackStorage() const {
824  return isa<StackSpaceRegion>(getMemorySpace());
825}
826
827bool MemRegion::hasStackNonParametersStorage() const {
828  return isa<StackLocalsSpaceRegion>(getMemorySpace());
829}
830
831bool MemRegion::hasStackParametersStorage() const {
832  return isa<StackArgumentsSpaceRegion>(getMemorySpace());
833}
834
835bool MemRegion::hasGlobalsOrParametersStorage() const {
836  const MemSpaceRegion *MS = getMemorySpace();
837  return isa<StackArgumentsSpaceRegion>(MS) ||
838         isa<GlobalsSpaceRegion>(MS);
839}
840
841// getBaseRegion strips away all elements and fields, and get the base region
842// of them.
843const MemRegion *MemRegion::getBaseRegion() const {
844  const MemRegion *R = this;
845  while (true) {
846    switch (R->getKind()) {
847      case MemRegion::ElementRegionKind:
848      case MemRegion::FieldRegionKind:
849      case MemRegion::ObjCIvarRegionKind:
850      case MemRegion::CXXBaseObjectRegionKind:
851        R = cast<SubRegion>(R)->getSuperRegion();
852        continue;
853      default:
854        break;
855    }
856    break;
857  }
858  return R;
859}
860
861//===----------------------------------------------------------------------===//
862// View handling.
863//===----------------------------------------------------------------------===//
864
865const MemRegion *MemRegion::StripCasts() const {
866  const MemRegion *R = this;
867  while (true) {
868    if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
869      // FIXME: generalize.  Essentially we want to strip away ElementRegions
870      // that were layered on a symbolic region because of casts.  We only
871      // want to strip away ElementRegions, however, where the index is 0.
872      SVal index = ER->getIndex();
873      if (nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&index)) {
874        if (CI->getValue().getSExtValue() == 0) {
875          R = ER->getSuperRegion();
876          continue;
877        }
878      }
879    }
880    break;
881  }
882  return R;
883}
884
885// FIXME: Merge with the implementation of the same method in Store.cpp
886static bool IsCompleteType(ASTContext &Ctx, QualType Ty) {
887  if (const RecordType *RT = Ty->getAs<RecordType>()) {
888    const RecordDecl *D = RT->getDecl();
889    if (!D->getDefinition())
890      return false;
891  }
892
893  return true;
894}
895
896RegionRawOffset ElementRegion::getAsArrayOffset() const {
897  CharUnits offset = CharUnits::Zero();
898  const ElementRegion *ER = this;
899  const MemRegion *superR = NULL;
900  ASTContext &C = getContext();
901
902  // FIXME: Handle multi-dimensional arrays.
903
904  while (ER) {
905    superR = ER->getSuperRegion();
906
907    // FIXME: generalize to symbolic offsets.
908    SVal index = ER->getIndex();
909    if (nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&index)) {
910      // Update the offset.
911      int64_t i = CI->getValue().getSExtValue();
912
913      if (i != 0) {
914        QualType elemType = ER->getElementType();
915
916        // If we are pointing to an incomplete type, go no further.
917        if (!IsCompleteType(C, elemType)) {
918          superR = ER;
919          break;
920        }
921
922        CharUnits size = C.getTypeSizeInChars(elemType);
923        offset += (i * size);
924      }
925
926      // Go to the next ElementRegion (if any).
927      ER = dyn_cast<ElementRegion>(superR);
928      continue;
929    }
930
931    return NULL;
932  }
933
934  assert(superR && "super region cannot be NULL");
935  return RegionRawOffset(superR, offset);
936}
937
938RegionOffset MemRegion::getAsOffset() const {
939  const MemRegion *R = this;
940  int64_t Offset = 0;
941
942  while (1) {
943    switch (R->getKind()) {
944    default:
945      return RegionOffset(0);
946    case SymbolicRegionKind:
947    case AllocaRegionKind:
948    case CompoundLiteralRegionKind:
949    case CXXThisRegionKind:
950    case StringRegionKind:
951    case VarRegionKind:
952    case CXXTempObjectRegionKind:
953      goto Finish;
954    case ElementRegionKind: {
955      const ElementRegion *ER = cast<ElementRegion>(R);
956      QualType EleTy = ER->getValueType();
957
958      if (!IsCompleteType(getContext(), EleTy))
959        return RegionOffset(0);
960
961      SVal Index = ER->getIndex();
962      if (const nonloc::ConcreteInt *CI=dyn_cast<nonloc::ConcreteInt>(&Index)) {
963        int64_t i = CI->getValue().getSExtValue();
964        CharUnits Size = getContext().getTypeSizeInChars(EleTy);
965        Offset += i * Size.getQuantity() * 8;
966      } else {
967        // We cannot compute offset for non-concrete index.
968        return RegionOffset(0);
969      }
970      R = ER->getSuperRegion();
971      break;
972    }
973    case FieldRegionKind: {
974      const FieldRegion *FR = cast<FieldRegion>(R);
975      const RecordDecl *RD = FR->getDecl()->getParent();
976      if (!RD->isCompleteDefinition())
977        // We cannot compute offset for incomplete type.
978        return RegionOffset(0);
979      // Get the field number.
980      unsigned idx = 0;
981      for (RecordDecl::field_iterator FI = RD->field_begin(),
982             FE = RD->field_end(); FI != FE; ++FI, ++idx)
983        if (FR->getDecl() == *FI)
984          break;
985
986      const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
987      // This is offset in bits.
988      Offset += Layout.getFieldOffset(idx);
989      R = FR->getSuperRegion();
990      break;
991    }
992    }
993  }
994
995 Finish:
996  return RegionOffset(R, Offset);
997}
998
999//===----------------------------------------------------------------------===//
1000// BlockDataRegion
1001//===----------------------------------------------------------------------===//
1002
1003void BlockDataRegion::LazyInitializeReferencedVars() {
1004  if (ReferencedVars)
1005    return;
1006
1007  AnalysisDeclContext *AC = getCodeRegion()->getAnalysisDeclContext();
1008  AnalysisDeclContext::referenced_decls_iterator I, E;
1009  llvm::tie(I, E) = AC->getReferencedBlockVars(BC->getDecl());
1010
1011  if (I == E) {
1012    ReferencedVars = (void*) 0x1;
1013    return;
1014  }
1015
1016  MemRegionManager &MemMgr = *getMemRegionManager();
1017  llvm::BumpPtrAllocator &A = MemMgr.getAllocator();
1018  BumpVectorContext BC(A);
1019
1020  typedef BumpVector<const MemRegion*> VarVec;
1021  VarVec *BV = (VarVec*) A.Allocate<VarVec>();
1022  new (BV) VarVec(BC, E - I);
1023
1024  for ( ; I != E; ++I) {
1025    const VarDecl *VD = *I;
1026    const VarRegion *VR = 0;
1027
1028    if (!VD->getAttr<BlocksAttr>() && VD->hasLocalStorage())
1029      VR = MemMgr.getVarRegion(VD, this);
1030    else {
1031      if (LC)
1032        VR = MemMgr.getVarRegion(VD, LC);
1033      else {
1034        VR = MemMgr.getVarRegion(VD, MemMgr.getUnknownRegion());
1035      }
1036    }
1037
1038    assert(VR);
1039    BV->push_back(VR, BC);
1040  }
1041
1042  ReferencedVars = BV;
1043}
1044
1045BlockDataRegion::referenced_vars_iterator
1046BlockDataRegion::referenced_vars_begin() const {
1047  const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars();
1048
1049  BumpVector<const MemRegion*> *Vec =
1050    static_cast<BumpVector<const MemRegion*>*>(ReferencedVars);
1051
1052  return BlockDataRegion::referenced_vars_iterator(Vec == (void*) 0x1 ?
1053                                                   NULL : Vec->begin());
1054}
1055
1056BlockDataRegion::referenced_vars_iterator
1057BlockDataRegion::referenced_vars_end() const {
1058  const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars();
1059
1060  BumpVector<const MemRegion*> *Vec =
1061    static_cast<BumpVector<const MemRegion*>*>(ReferencedVars);
1062
1063  return BlockDataRegion::referenced_vars_iterator(Vec == (void*) 0x1 ?
1064                                                   NULL : Vec->end());
1065}
1066