clang 24.0.0git
MemRegion.cpp
Go to the documentation of this file.
1//===- MemRegion.cpp - Abstract memory regions for static analysis --------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines MemRegion and its subclasses. MemRegion defines a
10// partially-typed abstraction of memory useful for path-sensitive dataflow
11// analyses.
12//
13//===----------------------------------------------------------------------===//
14
17#include "clang/AST/Attr.h"
18#include "clang/AST/CharUnits.h"
19#include "clang/AST/Decl.h"
20#include "clang/AST/DeclCXX.h"
21#include "clang/AST/DeclObjC.h"
22#include "clang/AST/Expr.h"
25#include "clang/AST/Type.h"
29#include "clang/Basic/LLVM.h"
35#include "llvm/ADT/APInt.h"
36#include "llvm/ADT/FoldingSet.h"
37#include "llvm/ADT/PointerUnion.h"
38#include "llvm/ADT/SmallString.h"
39#include "llvm/ADT/StringRef.h"
40#include "llvm/ADT/Twine.h"
41#include "llvm/ADT/iterator_range.h"
42#include "llvm/Support/Allocator.h"
43#include "llvm/Support/Casting.h"
44#include "llvm/Support/CheckedArithmetic.h"
45#include "llvm/Support/Compiler.h"
46#include "llvm/Support/Debug.h"
47#include "llvm/Support/ErrorHandling.h"
48#include "llvm/Support/raw_ostream.h"
49#include <cassert>
50#include <cstdint>
51#include <iterator>
52#include <optional>
53#include <string>
54#include <tuple>
55#include <utility>
56
57using namespace clang;
58using namespace ento;
59
60#define DEBUG_TYPE "MemRegion"
61
63 const MemSpaceRegion *)
64
65//===----------------------------------------------------------------------===//
66// MemRegion Construction.
67//===----------------------------------------------------------------------===//
68
69[[maybe_unused]] static bool isAReferenceTypedValueRegion(const MemRegion *R) {
70 const auto *TyReg = llvm::dyn_cast<TypedValueRegion>(R);
71 return TyReg && TyReg->getValueType()->isReferenceType();
72}
73
74template <typename RegionTy, typename SuperTy, typename Arg1Ty>
75RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1,
76 const SuperTy *superRegion) {
77 llvm::FoldingSetNodeID ID;
78 RegionTy::ProfileRegion(ID, arg1, superRegion);
79 void *InsertPos;
80 auto *R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, InsertPos));
81
82 if (!R) {
83 R = new (A) RegionTy(arg1, superRegion);
84 Regions.InsertNode(R, InsertPos);
85 assert(!isAReferenceTypedValueRegion(superRegion));
86 }
87
88 return R;
89}
90
91template <typename RegionTy, typename SuperTy, typename Arg1Ty, typename Arg2Ty>
92RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2,
93 const SuperTy *superRegion) {
94 llvm::FoldingSetNodeID ID;
95 RegionTy::ProfileRegion(ID, arg1, arg2, superRegion);
96 void *InsertPos;
97 auto *R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, InsertPos));
98
99 if (!R) {
100 R = new (A) RegionTy(arg1, arg2, superRegion);
101 Regions.InsertNode(R, InsertPos);
102 assert(!isAReferenceTypedValueRegion(superRegion));
103 }
104
105 return R;
106}
107
108template <typename RegionTy, typename SuperTy,
109 typename Arg1Ty, typename Arg2Ty, typename Arg3Ty>
110RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2,
111 const Arg3Ty arg3,
112 const SuperTy *superRegion) {
113 llvm::FoldingSetNodeID ID;
114 RegionTy::ProfileRegion(ID, arg1, arg2, arg3, superRegion);
115 void *InsertPos;
116 auto *R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, InsertPos));
117
118 if (!R) {
119 R = new (A) RegionTy(arg1, arg2, arg3, superRegion);
120 Regions.InsertNode(R, InsertPos);
121 assert(!isAReferenceTypedValueRegion(superRegion));
122 }
123
124 return R;
125}
126
127//===----------------------------------------------------------------------===//
128// Object destruction.
129//===----------------------------------------------------------------------===//
130
131MemRegion::~MemRegion() = default;
132
133// All regions and their data are BumpPtrAllocated. No need to call their
134// destructors.
136
137//===----------------------------------------------------------------------===//
138// Basic methods.
139//===----------------------------------------------------------------------===//
140
142 const MemRegion* r = this;
143 do {
144 if (r == R)
145 return true;
146 if (const auto *sr = dyn_cast<SubRegion>(r))
147 r = sr->getSuperRegion();
148 else
149 break;
150 } while (r != nullptr);
151 return false;
152}
153
155 const SubRegion* r = this;
156 do {
158 if (const auto *sr = dyn_cast<SubRegion>(superRegion)) {
159 r = sr;
160 continue;
161 }
162 return superRegion->getMemRegionManager();
163 } while (true);
164}
165
167 const auto *SSR = dyn_cast<StackSpaceRegion>(getRawMemorySpace());
168 return SSR ? SSR->getStackFrame() : nullptr;
169}
170
172 const auto *SSR = dyn_cast<StackSpaceRegion>(getRawMemorySpace());
173 return SSR ? SSR->getStackFrame() : nullptr;
174}
175
178 "A temporary object can only be allocated on the stack");
179 return cast<StackSpaceRegion>(getRawMemorySpace())->getStackFrame();
180}
181
182ObjCIvarRegion::ObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *sReg)
183 : DeclRegion(sReg, ObjCIvarRegionKind), IVD(ivd) {
184 assert(IVD);
185}
186
187const ObjCIvarDecl *ObjCIvarRegion::getDecl() const { return IVD; }
188
190 return getDecl()->getType();
191}
192
196
200
202 assert(getDecl() &&
203 "`ParamVarRegion` support functions without `Decl` not implemented"
204 " yet.");
205 return getDecl()->getType();
206}
207
209 const Decl *D = getStackFrame()->getDecl();
210
211 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
212 assert(Index < FD->param_size());
213 return FD->parameters()[Index];
214 } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
215 assert(Index < BD->param_size());
216 return BD->parameters()[Index];
217 } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
218 assert(Index < MD->param_size());
219 return MD->parameters()[Index];
220 } else if (const auto *CD = dyn_cast<CXXConstructorDecl>(D)) {
221 assert(Index < CD->param_size());
222 return CD->parameters()[Index];
223 } else {
224 llvm_unreachable("Unexpected Decl kind!");
225 }
226}
227
228//===----------------------------------------------------------------------===//
229// FoldingSet profiling.
230//===----------------------------------------------------------------------===//
231
232void MemSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const {
233 ID.AddInteger(static_cast<unsigned>(getKind()));
234}
235
236void StackSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const {
237 ID.AddInteger(static_cast<unsigned>(getKind()));
238 ID.AddPointer(getStackFrame());
239}
240
241void StaticGlobalSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const {
242 ID.AddInteger(static_cast<unsigned>(getKind()));
243 ID.AddPointer(getCodeRegion());
244}
245
246void StringRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
247 const StringLiteral *Str,
248 const MemRegion *superRegion) {
249 ID.AddInteger(static_cast<unsigned>(StringRegionKind));
250 ID.AddPointer(Str);
251 ID.AddPointer(superRegion);
252}
253
254void ObjCStringRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
255 const ObjCStringLiteral *Str,
256 const MemRegion *superRegion) {
257 ID.AddInteger(static_cast<unsigned>(ObjCStringRegionKind));
258 ID.AddPointer(Str);
259 ID.AddPointer(superRegion);
260}
261
262void AllocaRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
263 const Expr *Ex, unsigned cnt,
264 const MemRegion *superRegion) {
265 ID.AddInteger(static_cast<unsigned>(AllocaRegionKind));
266 ID.AddPointer(Ex);
267 ID.AddInteger(cnt);
268 ID.AddPointer(superRegion);
269}
270
271void AllocaRegion::Profile(llvm::FoldingSetNodeID& ID) const {
272 ProfileRegion(ID, Ex, Cnt, superRegion);
273}
274
275void CompoundLiteralRegion::Profile(llvm::FoldingSetNodeID& ID) const {
276 CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion);
277}
278
279void CompoundLiteralRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
280 const CompoundLiteralExpr *CL,
281 const MemRegion* superRegion) {
282 ID.AddInteger(static_cast<unsigned>(CompoundLiteralRegionKind));
283 ID.AddPointer(CL);
284 ID.AddPointer(superRegion);
285}
286
287void CXXThisRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
288 const PointerType *PT,
289 const MemRegion *sRegion) {
290 ID.AddInteger(static_cast<unsigned>(CXXThisRegionKind));
291 ID.AddPointer(PT);
292 ID.AddPointer(sRegion);
293}
294
295void CXXThisRegion::Profile(llvm::FoldingSetNodeID &ID) const {
296 CXXThisRegion::ProfileRegion(ID, ThisPointerTy, superRegion);
297}
298
299void FieldRegion::Profile(llvm::FoldingSetNodeID &ID) const {
300 ProfileRegion(ID, getDecl(), superRegion);
301}
302
303void ObjCIvarRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
304 const ObjCIvarDecl *ivd,
305 const MemRegion* superRegion) {
306 ID.AddInteger(static_cast<unsigned>(ObjCIvarRegionKind));
307 ID.AddPointer(ivd);
308 ID.AddPointer(superRegion);
309}
310
311void ObjCIvarRegion::Profile(llvm::FoldingSetNodeID &ID) const {
312 ProfileRegion(ID, getDecl(), superRegion);
313}
314
315void NonParamVarRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
316 const VarDecl *VD,
317 const MemRegion *superRegion) {
318 ID.AddInteger(static_cast<unsigned>(NonParamVarRegionKind));
319 ID.AddPointer(VD);
320 ID.AddPointer(superRegion);
321}
322
323void NonParamVarRegion::Profile(llvm::FoldingSetNodeID &ID) const {
324 ProfileRegion(ID, getDecl(), superRegion);
325}
326
327void ParamVarRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, const Expr *OE,
328 unsigned Idx, const MemRegion *SReg) {
329 ID.AddInteger(static_cast<unsigned>(ParamVarRegionKind));
330 ID.AddPointer(OE);
331 ID.AddInteger(Idx);
332 ID.AddPointer(SReg);
333}
334
335void ParamVarRegion::Profile(llvm::FoldingSetNodeID &ID) const {
336 ProfileRegion(ID, getOriginExpr(), getIndex(), superRegion);
337}
338
339void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym,
340 const MemRegion *sreg) {
341 ID.AddInteger(static_cast<unsigned>(MemRegion::SymbolicRegionKind));
342 ID.Add(sym);
343 ID.AddPointer(sreg);
344}
345
346void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const {
348}
349
350void ElementRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
351 QualType ElementType, SVal Idx,
352 const MemRegion* superRegion) {
353 ID.AddInteger(MemRegion::ElementRegionKind);
354 ID.Add(ElementType);
355 ID.AddPointer(superRegion);
356 Idx.Profile(ID);
357}
358
359void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const {
360 ElementRegion::ProfileRegion(ID, ElementType, Index, superRegion);
361}
362
363void FunctionCodeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
364 const NamedDecl *FD,
365 const MemRegion*) {
366 ID.AddInteger(MemRegion::FunctionCodeRegionKind);
367 ID.AddPointer(FD);
368}
369
370void FunctionCodeRegion::Profile(llvm::FoldingSetNodeID& ID) const {
371 FunctionCodeRegion::ProfileRegion(ID, FD, superRegion);
372}
373
374void BlockCodeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
375 const BlockDecl *BD, CanQualType,
376 const AnalysisDeclContext *AC,
377 const MemRegion*) {
378 ID.AddInteger(MemRegion::BlockCodeRegionKind);
379 ID.AddPointer(BD);
380}
381
382void BlockCodeRegion::Profile(llvm::FoldingSetNodeID& ID) const {
383 BlockCodeRegion::ProfileRegion(ID, BD, locTy, AC, superRegion);
384}
385
386void BlockDataRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
387 const BlockCodeRegion *BC,
388 const StackFrame *SF, unsigned BlkCount,
389 const MemRegion *sReg) {
390 ID.AddInteger(MemRegion::BlockDataRegionKind);
391 ID.AddPointer(BC);
392 ID.AddPointer(SF);
393 ID.AddInteger(BlkCount);
394 ID.AddPointer(sReg);
395}
396
397void BlockDataRegion::Profile(llvm::FoldingSetNodeID& ID) const {
398 BlockDataRegion::ProfileRegion(ID, BC, SF, BlockCount, getSuperRegion());
399}
400
401void CXXTempObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
402 Expr const *Ex,
403 const MemRegion *sReg) {
404 ID.AddPointer(Ex);
405 ID.AddPointer(sReg);
406}
407
408void CXXTempObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
409 ProfileRegion(ID, Ex, getSuperRegion());
410}
411
412void CXXLifetimeExtendedObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
413 const Expr *E,
414 const ValueDecl *D,
415 const MemRegion *sReg) {
416 ID.AddPointer(E);
417 ID.AddPointer(D);
418 ID.AddPointer(sReg);
419}
420
422 llvm::FoldingSetNodeID &ID) const {
423 ProfileRegion(ID, Ex, ExD, getSuperRegion());
424}
425
426void CXXBaseObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
427 const CXXRecordDecl *RD,
428 bool IsVirtual,
429 const MemRegion *SReg) {
430 ID.AddPointer(RD);
431 ID.AddBoolean(IsVirtual);
432 ID.AddPointer(SReg);
433}
434
435void CXXBaseObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
436 ProfileRegion(ID, getDecl(), isVirtual(), superRegion);
437}
438
439void CXXDerivedObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
440 const CXXRecordDecl *RD,
441 const MemRegion *SReg) {
442 ID.AddPointer(RD);
443 ID.AddPointer(SReg);
444}
445
446void CXXDerivedObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
447 ProfileRegion(ID, getDecl(), superRegion);
448}
449
450//===----------------------------------------------------------------------===//
451// Region anchors.
452//===----------------------------------------------------------------------===//
453
454void GlobalsSpaceRegion::anchor() {}
455
456void NonStaticGlobalSpaceRegion::anchor() {}
457
458void StackSpaceRegion::anchor() {}
459
460void TypedRegion::anchor() {}
461
462void TypedValueRegion::anchor() {}
463
464void CodeTextRegion::anchor() {}
465
466void SubRegion::anchor() {}
467
468//===----------------------------------------------------------------------===//
469// Region pretty-printing.
470//===----------------------------------------------------------------------===//
471
472LLVM_DUMP_METHOD void MemRegion::dump() const {
473 dumpToStream(llvm::errs());
474}
475
476std::string MemRegion::getString() const {
477 std::string s;
478 llvm::raw_string_ostream os(s);
479 dumpToStream(os);
480 return s;
481}
482
483void MemRegion::dumpToStream(raw_ostream &os) const {
484 os << "<Unknown Region>";
485}
486
487void AllocaRegion::dumpToStream(raw_ostream &os) const {
488 os << "alloca{S" << Ex->getID(getContext()) << ',' << Cnt << '}';
489}
490
491void FunctionCodeRegion::dumpToStream(raw_ostream &os) const {
492 os << "code{" << getDecl()->getDeclName().getAsString() << '}';
493}
494
495void BlockCodeRegion::dumpToStream(raw_ostream &os) const {
496 os << "block_code{" << static_cast<const void *>(this) << '}';
497}
498
499void BlockDataRegion::dumpToStream(raw_ostream &os) const {
500 os << "block_data{" << BC;
501 os << "; ";
502 for (auto Var : referenced_vars())
503 os << "(" << Var.getCapturedRegion() << "<-" << Var.getOriginalRegion()
504 << ") ";
505 os << '}';
506}
507
508void CompoundLiteralRegion::dumpToStream(raw_ostream &os) const {
509 // FIXME: More elaborate pretty-printing.
510 os << "{ S" << CL->getID(getContext()) << " }";
511}
512
513void CXXTempObjectRegion::dumpToStream(raw_ostream &os) const {
514 os << "temp_object{" << getValueType() << ", "
515 << "S" << Ex->getID(getContext()) << '}';
516}
517
519 os << "lifetime_extended_object{" << getValueType() << ", ";
520 if (const IdentifierInfo *ID = ExD->getIdentifier())
521 os << ID->getName();
522 else
523 os << "D" << ExD->getID();
524 os << ", "
525 << "S" << Ex->getID(getContext()) << '}';
526}
527
528void CXXBaseObjectRegion::dumpToStream(raw_ostream &os) const {
529 os << "Base{" << superRegion << ',' << getDecl()->getName() << '}';
530}
531
532void CXXDerivedObjectRegion::dumpToStream(raw_ostream &os) const {
533 os << "Derived{" << superRegion << ',' << getDecl()->getName() << '}';
534}
535
536void CXXThisRegion::dumpToStream(raw_ostream &os) const {
537 os << "this";
538}
539
540void ElementRegion::dumpToStream(raw_ostream &os) const {
541 os << "Element{" << superRegion << ',' << Index << ',' << getElementType()
542 << '}';
543}
544
545void FieldRegion::dumpToStream(raw_ostream &os) const {
546 os << superRegion << "." << *getDecl();
547}
548
549void ObjCIvarRegion::dumpToStream(raw_ostream &os) const {
550 os << "Ivar{" << superRegion << ',' << *getDecl() << '}';
551}
552
553void StringRegion::dumpToStream(raw_ostream &os) const {
554 assert(Str != nullptr && "Expecting non-null StringLiteral");
555 Str->printPretty(os, nullptr, PrintingPolicy(getContext().getLangOpts()));
556}
557
558void ObjCStringRegion::dumpToStream(raw_ostream &os) const {
559 assert(Str != nullptr && "Expecting non-null ObjCStringLiteral");
560 Str->printPretty(os, nullptr, PrintingPolicy(getContext().getLangOpts()));
561}
562
563void SymbolicRegion::dumpToStream(raw_ostream &os) const {
565 os << "Heap";
566 os << "SymRegion{" << sym << '}';
567}
568
569void NonParamVarRegion::dumpToStream(raw_ostream &os) const {
570 if (const IdentifierInfo *ID = VD->getIdentifier())
571 os << ID->getName();
572 else
573 os << "NonParamVarRegion{D" << VD->getID() << '}';
574}
575
576LLVM_DUMP_METHOD void RegionRawOffset::dump() const {
577 dumpToStream(llvm::errs());
578}
579
580void RegionRawOffset::dumpToStream(raw_ostream &os) const {
581 os << "raw_offset{" << getRegion() << ',' << getOffset().getQuantity() << '}';
582}
583
584void CodeSpaceRegion::dumpToStream(raw_ostream &os) const {
585 os << "CodeSpaceRegion";
586}
587
588void StaticGlobalSpaceRegion::dumpToStream(raw_ostream &os) const {
589 os << "StaticGlobalsMemSpace{" << CR << '}';
590}
591
592void GlobalInternalSpaceRegion::dumpToStream(raw_ostream &os) const {
593 os << "GlobalInternalSpaceRegion";
594}
595
596void GlobalSystemSpaceRegion::dumpToStream(raw_ostream &os) const {
597 os << "GlobalSystemSpaceRegion";
598}
599
600void GlobalImmutableSpaceRegion::dumpToStream(raw_ostream &os) const {
601 os << "GlobalImmutableSpaceRegion";
602}
603
604void HeapSpaceRegion::dumpToStream(raw_ostream &os) const {
605 os << "HeapSpaceRegion";
606}
607
608void UnknownSpaceRegion::dumpToStream(raw_ostream &os) const {
609 os << "UnknownSpaceRegion";
610}
611
612void StackArgumentsSpaceRegion::dumpToStream(raw_ostream &os) const {
613 os << "StackArgumentsSpaceRegion";
614}
615
616void StackLocalsSpaceRegion::dumpToStream(raw_ostream &os) const {
617 os << "StackLocalsSpaceRegion";
618}
619
620void ParamVarRegion::dumpToStream(raw_ostream &os) const {
621 const ParmVarDecl *PVD = getDecl();
622 assert(PVD &&
623 "`ParamVarRegion` support functions without `Decl` not implemented"
624 " yet.");
625 if (const IdentifierInfo *ID = PVD->getIdentifier()) {
626 os << ID->getName();
627 } else {
628 os << "ParamVarRegion{P" << PVD->getID() << '}';
629 }
630}
631
633 return canPrintPrettyAsExpr();
634}
635
637 return false;
638}
639
640StringRef MemRegion::getKindStr() const {
641 switch (getKind()) {
642#define REGION(Id, Parent) \
643 case Id##Kind: \
644 return #Id;
645#include "clang/StaticAnalyzer/Core/PathSensitive/Regions.def"
646#undef REGION
647 }
648 llvm_unreachable("Unkown kind!");
649}
650
651void MemRegion::printPretty(raw_ostream &os) const {
652 assert(canPrintPretty() && "This region cannot be printed pretty.");
653 os << "'";
655 os << "'";
656}
657
658void MemRegion::printPrettyAsExpr(raw_ostream &) const {
659 llvm_unreachable("This region cannot be printed pretty.");
660}
661
662bool NonParamVarRegion::canPrintPrettyAsExpr() const { return true; }
663
664void NonParamVarRegion::printPrettyAsExpr(raw_ostream &os) const {
665 os << getDecl()->getName();
666}
667
668bool ParamVarRegion::canPrintPrettyAsExpr() const { return true; }
669
670void ParamVarRegion::printPrettyAsExpr(raw_ostream &os) const {
671 assert(getDecl() &&
672 "`ParamVarRegion` support functions without `Decl` not implemented"
673 " yet.");
674 os << getDecl()->getName();
675}
676
678 return true;
679}
680
681void ObjCIvarRegion::printPrettyAsExpr(raw_ostream &os) const {
682 os << getDecl()->getName();
683}
684
686 return true;
687}
688
690 return superRegion->canPrintPrettyAsExpr();
691}
692
693void FieldRegion::printPrettyAsExpr(raw_ostream &os) const {
694 assert(canPrintPrettyAsExpr());
695 superRegion->printPrettyAsExpr(os);
696 os << "." << getDecl()->getName();
697}
698
699void FieldRegion::printPretty(raw_ostream &os) const {
700 if (canPrintPrettyAsExpr()) {
701 os << "\'";
703 os << "'";
704 } else {
705 os << "field " << "\'" << getDecl()->getName() << "'";
706 }
707}
708
710 return superRegion->canPrintPrettyAsExpr();
711}
712
713void CXXBaseObjectRegion::printPrettyAsExpr(raw_ostream &os) const {
714 superRegion->printPrettyAsExpr(os);
715}
716
718 return superRegion->canPrintPrettyAsExpr();
719}
720
721void CXXDerivedObjectRegion::printPrettyAsExpr(raw_ostream &os) const {
722 superRegion->printPrettyAsExpr(os);
723}
724
725std::string MemRegion::getDescriptiveName(bool UseQuotes,
726 bool AllowFallback) const {
727 std::string ArrayIndices;
728 const MemRegion *R = this;
729 SmallString<50> buf;
730 llvm::raw_svector_ostream os(buf);
731
732 // Enclose subject with single quotes if needed.
733 auto QuoteIfNeeded = [UseQuotes](const Twine &Subject) -> std::string {
734 if (UseQuotes)
735 return ("'" + Subject + "'").str();
736 return Subject.str();
737 };
738
739 auto FallbackName = [this, AllowFallback]() -> std::string {
740 if (!AllowFallback)
741 return "";
742
743 if (const auto *FR = getAs<FieldRegion>()) {
744 if (StringRef Name = FR->getDecl()->getName(); !Name.empty())
745 return (llvm::Twine("the field '") + Name + "'").str();
746 return "the unnamed field";
747 }
748
749 if (isa<AllocaRegion>(this))
750 return "the memory returned by 'alloca'";
751
753 return "the heap area";
754
755 if (isa<StringRegion>(this))
756 return "the string literal";
757
758 return "the region";
759 };
760
761 // Obtain array indices to add them to the variable name.
762 const ElementRegion *ER = nullptr;
763 while ((ER = R->getAs<ElementRegion>())) {
764 // Index is a ConcreteInt.
765 if (auto CI = ER->getIndex().getAs<nonloc::ConcreteInt>()) {
767 CI->getValue()->toString(Idx);
768 ArrayIndices = (llvm::Twine("[") + Idx.str() + "]" + ArrayIndices).str();
769 }
770 // Index is symbolic, but may have a descriptive name.
771 else {
772 auto SI = ER->getIndex().getAs<nonloc::SymbolVal>();
773 if (!SI)
774 return FallbackName();
775
776 const MemRegion *OR = SI->getAsSymbol()->getOriginRegion();
777 if (!OR)
778 return FallbackName();
779
780 std::string Idx = OR->getDescriptiveName(false);
781 if (Idx.empty())
782 return FallbackName();
783
784 ArrayIndices = (llvm::Twine("[") + Idx + "]" + ArrayIndices).str();
785 }
786 R = ER->getSuperRegion();
787 }
788
789 // Get variable name.
790 if (R) {
791 // MemRegion can be pretty printed.
792 if (R->canPrintPrettyAsExpr()) {
793 R->printPrettyAsExpr(os);
794 return QuoteIfNeeded(llvm::Twine(os.str()) + ArrayIndices);
795 }
796
797 // FieldRegion may have ElementRegion as SuperRegion.
798 if (const auto *FR = R->getAs<FieldRegion>()) {
799 std::string Super = FR->getSuperRegion()->getDescriptiveName(false);
800 if (Super.empty())
801 return FallbackName();
802 return QuoteIfNeeded(Super + "." + FR->getDecl()->getName());
803 }
804 }
805
806 return FallbackName();
807}
808
810 // Check for more specific regions first.
811 if (auto *FR = dyn_cast<FieldRegion>(this)) {
812 return FR->getDecl()->getSourceRange();
813 }
814
815 if (auto *VR = dyn_cast<VarRegion>(this->getBaseRegion())) {
816 return VR->getDecl()->getSourceRange();
817 }
818
819 // Return invalid source range (can be checked by client).
820 return {};
821}
822
823//===----------------------------------------------------------------------===//
824// MemRegionManager methods.
825//===----------------------------------------------------------------------===//
826
828 SValBuilder &SVB) const {
829 const auto *SR = cast<SubRegion>(MR);
830 SymbolManager &SymMgr = SVB.getSymbolManager();
831
832 switch (SR->getKind()) {
833 case MemRegion::AllocaRegionKind:
834 case MemRegion::SymbolicRegionKind:
835 return nonloc::SymbolVal(SymMgr.acquire<SymbolExtent>(SR));
836 case MemRegion::StringRegionKind:
837 return SVB.makeIntVal(
838 cast<StringRegion>(SR)->getStringLiteral()->getByteLength() + 1,
839 SVB.getArrayIndexType());
840 case MemRegion::CompoundLiteralRegionKind:
841 case MemRegion::CXXBaseObjectRegionKind:
842 case MemRegion::CXXDerivedObjectRegionKind:
843 case MemRegion::CXXTempObjectRegionKind:
844 case MemRegion::CXXLifetimeExtendedObjectRegionKind:
845 case MemRegion::CXXThisRegionKind:
846 case MemRegion::ObjCIvarRegionKind:
847 case MemRegion::NonParamVarRegionKind:
848 case MemRegion::ParamVarRegionKind:
849 case MemRegion::ElementRegionKind:
850 case MemRegion::ObjCStringRegionKind: {
851 QualType Ty = cast<TypedValueRegion>(SR)->getDesugaredValueType(Ctx);
853 return nonloc::SymbolVal(SymMgr.acquire<SymbolExtent>(SR));
854
855 if (Ty->isIncompleteType())
856 return UnknownVal();
857
858 return getElementExtent(Ty, SVB);
859 }
860 case MemRegion::FieldRegionKind: {
861 // Force callers to deal with bitfields explicitly.
862 if (cast<FieldRegion>(SR)->getDecl()->isBitField())
863 return UnknownVal();
864
865 QualType Ty = cast<TypedValueRegion>(SR)->getDesugaredValueType(Ctx);
866 const DefinedOrUnknownSVal Size = getElementExtent(Ty, SVB);
867
868 // We currently don't model flexible array members (FAMs), which are:
869 // - int array[]; of IncompleteArrayType
870 // - int array[0]; of ConstantArrayType with size 0
871 // - int array[1]; of ConstantArrayType with size 1
872 // https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
873 const auto isFlexibleArrayMemberCandidate =
874 [this](const ArrayType *AT) -> bool {
875 if (!AT)
876 return false;
877
878 auto IsIncompleteArray = [](const ArrayType *AT) {
879 return isa<IncompleteArrayType>(AT);
880 };
881 auto IsArrayOfZero = [](const ArrayType *AT) {
882 const auto *CAT = dyn_cast<ConstantArrayType>(AT);
883 return CAT && CAT->isZeroSize();
884 };
885 auto IsArrayOfOne = [](const ArrayType *AT) {
886 const auto *CAT = dyn_cast<ConstantArrayType>(AT);
887 return CAT && CAT->getSize() == 1;
888 };
889
891 const FAMKind StrictFlexArraysLevel =
892 Ctx.getLangOpts().getStrictFlexArraysLevel();
893
894 // "Default": Any trailing array member is a FAM.
895 // Since we cannot tell at this point if this array is a trailing member
896 // or not, let's just do the same as for "OneZeroOrIncomplete".
897 if (StrictFlexArraysLevel == FAMKind::Default)
898 return IsArrayOfOne(AT) || IsArrayOfZero(AT) || IsIncompleteArray(AT);
899
900 if (StrictFlexArraysLevel == FAMKind::OneZeroOrIncomplete)
901 return IsArrayOfOne(AT) || IsArrayOfZero(AT) || IsIncompleteArray(AT);
902
903 if (StrictFlexArraysLevel == FAMKind::ZeroOrIncomplete)
904 return IsArrayOfZero(AT) || IsIncompleteArray(AT);
905
906 assert(StrictFlexArraysLevel == FAMKind::IncompleteOnly);
907 return IsIncompleteArray(AT);
908 };
909
910 if (isFlexibleArrayMemberCandidate(Ctx.getAsArrayType(Ty)))
911 return UnknownVal();
912
913 return Size;
914 }
915 // FIXME: The following are being used in 'SimpleSValBuilder' because there
916 // is no symbol to represent the regions more appropriately.
917 case MemRegion::BlockDataRegionKind:
918 case MemRegion::BlockCodeRegionKind:
919 case MemRegion::FunctionCodeRegionKind:
920 return nonloc::SymbolVal(SymMgr.acquire<SymbolExtent>(SR));
921 default:
922 llvm_unreachable("Unhandled region");
923 }
924}
925
926template <typename REG>
927const REG *MemRegionManager::LazyAllocate(REG*& region) {
928 if (!region) {
929 region = new (A) REG(*this);
930 }
931
932 return region;
933}
934
935template <typename REG, typename ARG>
936const REG *MemRegionManager::LazyAllocate(REG*& region, ARG a) {
937 if (!region) {
938 region = new (A) REG(this, a);
939 }
940
941 return region;
942}
943
946 assert(SF);
947 StackLocalsSpaceRegion *&R = StackLocalsSpaceRegions[SF];
948
949 if (R)
950 return R;
951
952 R = new (A) StackLocalsSpaceRegion(*this, SF);
953 return R;
954}
955
958 assert(SF);
959 StackArgumentsSpaceRegion *&R = StackArgumentsSpaceRegions[SF];
960
961 if (R)
962 return R;
963
964 R = new (A) StackArgumentsSpaceRegion(*this, SF);
965 return R;
966}
967
970 const CodeTextRegion *CR) {
971 if (!CR) {
972 if (K == MemRegion::GlobalSystemSpaceRegionKind)
973 return LazyAllocate(SystemGlobals);
974 if (K == MemRegion::GlobalImmutableSpaceRegionKind)
975 return LazyAllocate(ImmutableGlobals);
976 assert(K == MemRegion::GlobalInternalSpaceRegionKind);
977 return LazyAllocate(InternalGlobals);
978 }
979
980 assert(K == MemRegion::StaticGlobalSpaceRegionKind);
981 StaticGlobalSpaceRegion *&R = StaticsGlobalSpaceRegions[CR];
982 if (R)
983 return R;
984
985 R = new (A) StaticGlobalSpaceRegion(*this, CR);
986 return R;
987}
988
990 return LazyAllocate(heap);
991}
992
994 return LazyAllocate(unknown);
995}
996
998 return LazyAllocate(code);
999}
1000
1001//===----------------------------------------------------------------------===//
1002// Constructing regions.
1003//===----------------------------------------------------------------------===//
1004
1006 return getSubRegion<StringRegion>(
1008}
1009
1010const ObjCStringRegion *
1012 return getSubRegion<ObjCStringRegion>(
1014}
1015
1016/// Look through a chain of StackFrames to either find the
1017/// StackFrame that matches a DeclContext, or find a VarRegion
1018/// for a variable captured by a block.
1019static llvm::PointerUnion<const StackFrame *, const VarRegion *>
1021 const DeclContext *DC,
1022 const VarDecl *VD) {
1023 if (SF)
1024 for (const StackFrame &Frame : SF->parentsIncludingSelf()) {
1025 if (cast<DeclContext>(Frame.getDecl()) == DC)
1026 return &Frame;
1027 if (Frame.getData()) {
1028 // FIXME: This can be made more efficient.
1029 for (auto Var : static_cast<const BlockDataRegion *>(Frame.getData())
1030 ->referenced_vars()) {
1031 const TypedValueRegion *OrigR = Var.getOriginalRegion();
1032 if (const auto *VR = dyn_cast<VarRegion>(OrigR)) {
1033 if (VR->getDecl() == VD)
1034 return cast<VarRegion>(Var.getCapturedRegion());
1035 }
1036 }
1037 }
1038 }
1039 return (const StackFrame *)nullptr;
1040}
1041
1042static bool isStdStreamVar(const VarDecl *D) {
1043 const IdentifierInfo *II = D->getIdentifier();
1044 if (!II)
1045 return false;
1046 if (!D->getDeclContext()->isTranslationUnit())
1047 return false;
1048 StringRef N = II->getName();
1049 QualType FILETy = D->getASTContext().getFILEType();
1050 if (FILETy.isNull())
1051 return false;
1052 FILETy = FILETy.getCanonicalType();
1053 QualType Ty = D->getType().getCanonicalType();
1054 return Ty->isPointerType() && Ty->getPointeeType() == FILETy &&
1055 (N == "stdin" || N == "stdout" || N == "stderr");
1056}
1057
1059 const StackFrame *SF) {
1060 assert(SF);
1061 const auto *PVD = dyn_cast<ParmVarDecl>(D);
1062 if (PVD) {
1063 unsigned Index = PVD->getFunctionScopeIndex();
1064 const Expr *CallSite = SF->getCallSite();
1065 if (CallSite) {
1066 const Decl *CalleeDecl = SF->getDecl();
1067 bool CurrentParam = true;
1068 if (const auto *FD = dyn_cast<FunctionDecl>(CalleeDecl)) {
1069 CurrentParam =
1070 (Index < FD->param_size() && FD->getParamDecl(Index) == PVD);
1071 } else if (const auto *BD = dyn_cast<BlockDecl>(CalleeDecl)) {
1072 CurrentParam =
1073 (Index < BD->param_size() && BD->getParamDecl(Index) == PVD);
1074 }
1075
1076 if (CurrentParam) {
1077 // If this is a parameter of the *current* stack frame, we can
1078 // represent it with a `ParamVarRegion`.
1079 return getSubRegion<ParamVarRegion>(CallSite, Index,
1081 } else {
1082 // TODO: Parameters of other stack frames (which may have been be
1083 // captured by a lambda or a block) are currently represented by
1084 // `NonParamVarRegion`s. This behavior is present since commit
1085 // 98db1f990fc273adc1ae36d4ce97ce66fd27ac30 which introduced
1086 // `ParamVarRegion` in 2020; and appears to work (at least to some
1087 // extent); but it would be nice to clean this up (if somebody has time
1088 // and knowledge for a proper investigation).
1089 }
1090 } else {
1091 // TODO: Parameters of the entrypoint stack frame (where `CallSite` is
1092 // null) are currently represented by `NonParamVarRegion`s. This behavior
1093 // is also present since 98db1f990fc273adc1ae36d4ce97ce66fd27ac30 which
1094 // introduced `ParamVarRegion` in 2020, but it would be nice to clean it
1095 // up for the sake of clarity and consistency.
1096 }
1097 }
1098
1099 D = D->getCanonicalDecl();
1100 const MemRegion *sReg = nullptr;
1101
1102 if (D->hasGlobalStorage() && !D->isStaticLocal()) {
1103 QualType Ty = D->getType();
1104 assert(!Ty.isNull());
1105 if (Ty.isConstQualified()) {
1106 sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind);
1107 } else {
1108 // Pointer value of C standard streams is usually not modified by calls
1109 // to functions declared in system headers. This means that they should
1110 // not get invalidated by calls to functions declared in system headers,
1111 // so they are placed in the global internal space, which is not
1112 // invalidated by calls to functions declared in system headers.
1113 if (Ctx.getSourceManager().isInSystemHeader(D->getLocation()) &&
1114 !isStdStreamVar(D)) {
1115 sReg = getGlobalsRegion(MemRegion::GlobalSystemSpaceRegionKind);
1116 } else {
1117 sReg = getGlobalsRegion(MemRegion::GlobalInternalSpaceRegionKind);
1118 }
1119 }
1120
1121 // Finally handle static locals.
1122 } else {
1123 // FIXME: Once we implement scope handling, we will need to properly lookup
1124 // 'D' to the proper StackFrame.
1125 const DeclContext *DC = D->getDeclContext();
1126 llvm::PointerUnion<const StackFrame *, const VarRegion *> V =
1128
1129 if (const auto *VR = dyn_cast_if_present<const VarRegion *>(V))
1130 return VR;
1131
1132 const auto *SF = cast<const StackFrame *>(V);
1133
1134 if (!SF) {
1135 // FIXME: Assign a more sensible memory space to static locals
1136 // we see from within blocks that we analyze as top-level declarations.
1137 sReg = getUnknownRegion();
1138 } else {
1139 if (D->hasLocalStorage()) {
1141 ? static_cast<const MemRegion *>(getStackArgumentsRegion(SF))
1142 : static_cast<const MemRegion *>(getStackLocalsRegion(SF));
1143 }
1144 else {
1145 assert(D->isStaticLocal());
1146 const Decl *STCD = SF->getDecl();
1148 sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind,
1150 else if (const auto *BD = dyn_cast<BlockDecl>(STCD)) {
1151 // FIXME: The fallback type here is totally bogus -- though it should
1152 // never be queried, it will prevent uniquing with the real
1153 // BlockCodeRegion. Ideally we'd fix the AST so that we always had a
1154 // signature.
1155 QualType T;
1156 if (const TypeSourceInfo *TSI = BD->getSignatureAsWritten())
1157 T = TSI->getType();
1158 if (T.isNull())
1159 T = getContext().VoidTy;
1160 if (!T->getAs<FunctionType>()) {
1162 T = getContext().getFunctionType(T, {}, Ext);
1163 }
1165
1167 BD, Ctx.getCanonicalType(T), SF->getAnalysisDeclContext());
1168 sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind,
1169 BTR);
1170 }
1171 else {
1172 sReg = getGlobalsRegion();
1173 }
1174 }
1175 }
1176 }
1177
1178 return getNonParamVarRegion(D, sReg);
1179}
1180
1181const NonParamVarRegion *
1183 const MemRegion *superR) {
1184 // Prefer the definition over the canonical decl as the canonical form.
1185 D = D->getCanonicalDecl();
1186 if (const VarDecl *Def = D->getDefinition())
1187 D = Def;
1188 return getSubRegion<NonParamVarRegion>(D, superR);
1189}
1190
1191const ParamVarRegion *
1192MemRegionManager::getParamVarRegion(const Expr *OriginExpr, unsigned Index,
1193 const StackFrame *SF) {
1194 assert(SF);
1195 return getSubRegion<ParamVarRegion>(OriginExpr, Index,
1197}
1198
1200 const BlockCodeRegion *BC, const StackFrame *SF, unsigned blockCount) {
1201 const MemSpaceRegion *sReg = nullptr;
1202 const BlockDecl *BD = BC->getDecl();
1203 if (!BD->hasCaptures()) {
1204 // This handles 'static' blocks.
1205 sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind);
1206 }
1207 else {
1208 bool IsArcManagedBlock = Ctx.getLangOpts().ObjCAutoRefCount;
1209
1210 // ARC managed blocks can be initialized on stack or directly in heap
1211 // depending on the implementations. So we initialize them with
1212 // UnknownRegion.
1213 if (!IsArcManagedBlock && SF) {
1214 // FIXME: Once we implement scope handling, we want the parent region
1215 // to be the scope.
1216 assert(SF);
1217 sReg = getStackLocalsRegion(SF);
1218 } else {
1219 // We allow 'SF' to be NULL for cases where want BlockDataRegions
1220 // without context-sensitivity.
1221 sReg = getUnknownRegion();
1222 }
1223 }
1224
1225 return getSubRegion<BlockDataRegion>(BC, SF, blockCount, sReg);
1226}
1227
1230 const StackFrame *SF) {
1231 const MemSpaceRegion *sReg = nullptr;
1232
1233 if (CL->isFileScope())
1234 sReg = getGlobalsRegion();
1235 else {
1236 assert(SF);
1237 sReg = getStackLocalsRegion(SF);
1238 }
1239
1240 return getSubRegion<CompoundLiteralRegion>(CL, sReg);
1241}
1242
1243const ElementRegion *
1245 const SubRegion *superRegion,
1246 const ASTContext &Ctx) {
1247 QualType T = Ctx.getCanonicalType(elementType).getUnqualifiedType();
1248
1249 // The address space must be preserved because some target-specific address
1250 // spaces influence the size of the pointer value which is represented by the
1251 // element region.
1252 LangAS AS = elementType.getAddressSpace();
1253 if (AS != LangAS::Default) {
1254 Qualifiers Quals;
1255 Quals.setAddressSpace(AS);
1256 T = Ctx.getQualifiedType(T, Quals);
1257 }
1258
1259 llvm::FoldingSetNodeID ID;
1260 ElementRegion::ProfileRegion(ID, T, Idx, superRegion);
1261
1262 void *InsertPos;
1263 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
1264 auto *R = cast_or_null<ElementRegion>(data);
1265
1266 if (!R) {
1267 R = new (A) ElementRegion(T, Idx, superRegion);
1268 Regions.InsertNode(R, InsertPos);
1269 }
1270
1271 return R;
1272}
1273
1274const FunctionCodeRegion *
1276 // To think: should we canonicalize the declaration here?
1277 return getSubRegion<FunctionCodeRegion>(FD, getCodeRegion());
1278}
1279
1280const BlockCodeRegion *
1282 AnalysisDeclContext *AC) {
1283 return getSubRegion<BlockCodeRegion>(BD, locTy, AC, getCodeRegion());
1284}
1285
1286const SymbolicRegion *
1288 const MemSpaceRegion *MemSpace) {
1289 if (MemSpace == nullptr)
1290 MemSpace = getUnknownRegion();
1291 return getSubRegion<SymbolicRegion>(sym, MemSpace);
1292}
1293
1295 return getSubRegion<SymbolicRegion>(Sym, getHeapRegion());
1296}
1297
1298const FieldRegion *
1300 const SubRegion *SuperRegion) {
1301 return getSubRegion<FieldRegion>(FD->getCanonicalDecl(), SuperRegion);
1302}
1303
1304const ObjCIvarRegion*
1306 const SubRegion* superRegion) {
1307 return getSubRegion<ObjCIvarRegion>(d, superRegion);
1308}
1309
1310const CXXTempObjectRegion *
1312 assert(SF);
1313 return getSubRegion<CXXTempObjectRegion>(E, getStackLocalsRegion(SF));
1314}
1315
1318 const ValueDecl *VD,
1319 const StackFrame *SF) {
1320 assert(SF);
1321 return getSubRegion<CXXLifetimeExtendedObjectRegion>(
1322 Ex, VD, getStackLocalsRegion(SF));
1323}
1324
1327 const Expr *Ex, const ValueDecl *VD) {
1328 return getSubRegion<CXXLifetimeExtendedObjectRegion>(
1329 Ex, VD,
1330 getGlobalsRegion(MemRegion::GlobalInternalSpaceRegionKind, nullptr));
1331}
1332
1333/// Checks whether \p BaseClass is a valid virtual or direct non-virtual base
1334/// class of the type of \p Super.
1335static bool isValidBaseClass(const CXXRecordDecl *BaseClass,
1336 const TypedValueRegion *Super,
1337 bool IsVirtual) {
1338 BaseClass = BaseClass->getCanonicalDecl();
1339
1340 const CXXRecordDecl *Class = Super->getValueType()->getAsCXXRecordDecl();
1341 if (!Class)
1342 return true;
1343
1344 if (IsVirtual)
1345 return Class->isVirtuallyDerivedFrom(BaseClass);
1346
1347 for (const auto &I : Class->bases()) {
1348 if (I.getType()->getAsCXXRecordDecl()->getCanonicalDecl() == BaseClass)
1349 return true;
1350 }
1351
1352 return false;
1353}
1354
1355const CXXBaseObjectRegion *
1357 const SubRegion *Super,
1358 bool IsVirtual) {
1359 if (isa<TypedValueRegion>(Super)) {
1360 assert(isValidBaseClass(RD, cast<TypedValueRegion>(Super), IsVirtual));
1361 (void)&isValidBaseClass;
1362
1363 if (IsVirtual) {
1364 // Virtual base regions should not be layered, since the layout rules
1365 // are different.
1366 while (const auto *Base = dyn_cast<CXXBaseObjectRegion>(Super))
1367 Super = cast<SubRegion>(Base->getSuperRegion());
1368 assert(Super && !isa<MemSpaceRegion>(Super));
1369 }
1370 }
1371
1372 return getSubRegion<CXXBaseObjectRegion>(RD, IsVirtual, Super);
1373}
1374
1377 const SubRegion *Super) {
1378 return getSubRegion<CXXDerivedObjectRegion>(RD, Super);
1379}
1380
1382 const StackFrame *SF) {
1383 const auto *PT = thisPointerTy->getAs<PointerType>();
1384 assert(PT);
1385 // Inside the body of the operator() of a lambda a this expr might refer to an
1386 // object in one of the parent stack frames.
1387 const auto *D = dyn_cast<CXXMethodDecl>(SF->getDecl());
1388 // FIXME: when operator() of lambda is analyzed as a top level function and
1389 // 'this' refers to a this to the enclosing scope, there is no right region to
1390 // return.
1391 while (!SF->inTopFrame() && (!D || D->isStatic() ||
1392 PT != D->getThisType()->getAs<PointerType>())) {
1393 SF = SF->getParent();
1394 D = dyn_cast<CXXMethodDecl>(SF->getDecl());
1395 }
1396 assert(SF);
1397 return getSubRegion<CXXThisRegion>(PT, getStackArgumentsRegion(SF));
1398}
1399
1401 unsigned cnt,
1402 const StackFrame *SF) {
1403 assert(SF);
1404 return getSubRegion<AllocaRegion>(E, cnt, getStackLocalsRegion(SF));
1405}
1406
1408 const MemRegion *R = this;
1409 const auto *SR = dyn_cast<SubRegion>(this);
1410
1411 while (SR) {
1412 R = SR->getSuperRegion();
1413 SR = dyn_cast<SubRegion>(R);
1414 }
1415
1416 return cast<MemSpaceRegion>(R);
1417}
1418
1420 const MemRegion *MR = getBaseRegion();
1421
1422 const MemSpaceRegion *RawSpace = MR->getRawMemorySpace();
1423 if (!isa<UnknownSpaceRegion>(RawSpace))
1424 return RawSpace;
1425
1426 const MemSpaceRegion *const *AssociatedSpace = State->get<MemSpacesMap>(MR);
1427 return AssociatedSpace ? *AssociatedSpace : RawSpace;
1428}
1429
1431 const MemSpaceRegion *Space) const {
1432 const MemRegion *Base = getBaseRegion();
1433
1434 // Shouldn't set unknown space.
1435 assert(!isa<UnknownSpaceRegion>(Space));
1436
1437 // Currently, it we should have no accurate memspace for this region.
1438 assert(Base->hasMemorySpace<UnknownSpaceRegion>(State));
1439 return State->set<MemSpacesMap>(Base, Space);
1440}
1441
1442// Strips away all elements and fields.
1443// Returns the base region of them.
1445 const MemRegion *R = this;
1446 while (true) {
1447 switch (R->getKind()) {
1448 case MemRegion::ElementRegionKind:
1449 case MemRegion::FieldRegionKind:
1450 case MemRegion::ObjCIvarRegionKind:
1451 case MemRegion::CXXBaseObjectRegionKind:
1452 case MemRegion::CXXDerivedObjectRegionKind:
1453 R = cast<SubRegion>(R)->getSuperRegion();
1454 continue;
1455 default:
1456 break;
1457 }
1458 break;
1459 }
1460 return R;
1461}
1462
1463// Returns the region of the root class of a C++ class hierarchy.
1465 const MemRegion *R = this;
1466 while (const auto *BR = dyn_cast<CXXBaseObjectRegion>(R))
1467 R = BR->getSuperRegion();
1468 return R;
1469}
1470
1472 return false;
1473}
1474
1475//===----------------------------------------------------------------------===//
1476// View handling.
1477//===----------------------------------------------------------------------===//
1478
1479const MemRegion *MemRegion::StripCasts(bool StripBaseAndDerivedCasts) const {
1480 const MemRegion *R = this;
1481 while (true) {
1482 switch (R->getKind()) {
1483 case ElementRegionKind: {
1484 const auto *ER = cast<ElementRegion>(R);
1485 if (!ER->getIndex().isZeroConstant())
1486 return R;
1487 R = ER->getSuperRegion();
1488 break;
1489 }
1490 case CXXBaseObjectRegionKind:
1491 case CXXDerivedObjectRegionKind:
1492 if (!StripBaseAndDerivedCasts)
1493 return R;
1494 R = cast<TypedValueRegion>(R)->getSuperRegion();
1495 break;
1496 default:
1497 return R;
1498 }
1499 }
1500}
1501
1503 const auto *SubR = dyn_cast<SubRegion>(this);
1504
1505 while (SubR) {
1506 if (const auto *SymR = dyn_cast<SymbolicRegion>(SubR))
1507 return SymR;
1508 SubR = dyn_cast<SubRegion>(SubR->getSuperRegion());
1509 }
1510 return nullptr;
1511}
1512
1514 int64_t offset = 0;
1515 const ElementRegion *ER = this;
1516 const MemRegion *superR = nullptr;
1517 ASTContext &C = getContext();
1518
1519 // FIXME: Handle multi-dimensional arrays.
1520
1521 while (ER) {
1522 superR = ER->getSuperRegion();
1523
1524 // FIXME: generalize to symbolic offsets.
1525 SVal index = ER->getIndex();
1526 if (auto CI = index.getAs<nonloc::ConcreteInt>()) {
1527 // Update the offset.
1528 if (int64_t i = CI->getValue()->getSExtValue(); i != 0) {
1529 QualType elemType = ER->getElementType();
1530
1531 // If we are pointing to an incomplete type, go no further.
1532 if (elemType->isIncompleteType()) {
1533 superR = ER;
1534 break;
1535 }
1536
1537 int64_t size = C.getTypeSizeInChars(elemType).getQuantity();
1538 if (auto NewOffset = llvm::checkedMulAdd(i, size, offset)) {
1539 offset = *NewOffset;
1540 } else {
1541 LLVM_DEBUG(llvm::dbgs() << "MemRegion::getAsArrayOffset: "
1542 << "offset overflowing, returning unknown\n");
1543
1544 return nullptr;
1545 }
1546 }
1547
1548 // Go to the next ElementRegion (if any).
1549 ER = dyn_cast<ElementRegion>(superR);
1550 continue;
1551 }
1552
1553 return nullptr;
1554 }
1555
1556 assert(superR && "super region cannot be NULL");
1557 return RegionRawOffset(superR, CharUnits::fromQuantity(offset));
1558}
1559
1560/// Returns true if \p Base is an immediate base class of \p Child
1561static bool isImmediateBase(const CXXRecordDecl *Child,
1562 const CXXRecordDecl *Base) {
1563 assert(Child && "Child must not be null");
1564 // Note that we do NOT canonicalize the base class here, because
1565 // ASTRecordLayout doesn't either. If that leads us down the wrong path,
1566 // so be it; at least we won't crash.
1567 for (const auto &I : Child->bases()) {
1568 if (I.getType()->getAsCXXRecordDecl() == Base)
1569 return true;
1570 }
1571
1572 return false;
1573}
1574
1576 const MemRegion *SymbolicOffsetBase = nullptr;
1577 int64_t Offset = 0;
1578
1579 while (true) {
1580 switch (R->getKind()) {
1581 case MemRegion::CodeSpaceRegionKind:
1582 case MemRegion::StackLocalsSpaceRegionKind:
1583 case MemRegion::StackArgumentsSpaceRegionKind:
1584 case MemRegion::HeapSpaceRegionKind:
1585 case MemRegion::UnknownSpaceRegionKind:
1586 case MemRegion::StaticGlobalSpaceRegionKind:
1587 case MemRegion::GlobalInternalSpaceRegionKind:
1588 case MemRegion::GlobalSystemSpaceRegionKind:
1589 case MemRegion::GlobalImmutableSpaceRegionKind:
1590 // Stores can bind directly to a region space to set a default value.
1591 assert(Offset == 0 && !SymbolicOffsetBase);
1592 goto Finish;
1593
1594 case MemRegion::FunctionCodeRegionKind:
1595 case MemRegion::BlockCodeRegionKind:
1596 case MemRegion::BlockDataRegionKind:
1597 // These will never have bindings, but may end up having values requested
1598 // if the user does some strange casting.
1599 if (Offset != 0)
1600 SymbolicOffsetBase = R;
1601 goto Finish;
1602
1603 case MemRegion::SymbolicRegionKind:
1604 case MemRegion::AllocaRegionKind:
1605 case MemRegion::CompoundLiteralRegionKind:
1606 case MemRegion::CXXThisRegionKind:
1607 case MemRegion::StringRegionKind:
1608 case MemRegion::ObjCStringRegionKind:
1609 case MemRegion::NonParamVarRegionKind:
1610 case MemRegion::ParamVarRegionKind:
1611 case MemRegion::CXXTempObjectRegionKind:
1612 case MemRegion::CXXLifetimeExtendedObjectRegionKind:
1613 // Usual base regions.
1614 goto Finish;
1615
1616 case MemRegion::ObjCIvarRegionKind:
1617 // This is a little strange, but it's a compromise between
1618 // ObjCIvarRegions having unknown compile-time offsets (when using the
1619 // non-fragile runtime) and yet still being distinct, non-overlapping
1620 // regions. Thus we treat them as "like" base regions for the purposes
1621 // of computing offsets.
1622 goto Finish;
1623
1624 case MemRegion::CXXBaseObjectRegionKind: {
1625 const auto *BOR = cast<CXXBaseObjectRegion>(R);
1626 R = BOR->getSuperRegion();
1627
1628 QualType Ty;
1629 bool RootIsSymbolic = false;
1630 if (const auto *TVR = dyn_cast<TypedValueRegion>(R)) {
1631 Ty = TVR->getDesugaredValueType(R->getContext());
1632 } else if (const auto *SR = dyn_cast<SymbolicRegion>(R)) {
1633 // If our base region is symbolic, we don't know what type it really is.
1634 // Pretend the type of the symbol is the true dynamic type.
1635 // (This will at least be self-consistent for the life of the symbol.)
1636 Ty = SR->getPointeeStaticType();
1637 RootIsSymbolic = true;
1638 }
1639
1640 const CXXRecordDecl *Child = Ty->getAsCXXRecordDecl();
1641 if (!Child) {
1642 // We cannot compute the offset of the base class.
1643 SymbolicOffsetBase = R;
1644 } else {
1645 if (RootIsSymbolic) {
1646 // Base layers on symbolic regions may not be type-correct.
1647 // Double-check the inheritance here, and revert to a symbolic offset
1648 // if it's invalid (e.g. due to a reinterpret_cast).
1649 if (BOR->isVirtual()) {
1650 if (!Child->isVirtuallyDerivedFrom(BOR->getDecl()))
1651 SymbolicOffsetBase = R;
1652 } else {
1653 if (!isImmediateBase(Child, BOR->getDecl()))
1654 SymbolicOffsetBase = R;
1655 }
1656 }
1657 }
1658
1659 // Don't bother calculating precise offsets if we already have a
1660 // symbolic offset somewhere in the chain.
1661 if (SymbolicOffsetBase)
1662 continue;
1663
1664 CharUnits BaseOffset;
1665 const ASTRecordLayout &Layout = R->getContext().getASTRecordLayout(Child);
1666 if (BOR->isVirtual())
1667 BaseOffset = Layout.getVBaseClassOffset(BOR->getDecl());
1668 else
1669 BaseOffset = Layout.getBaseClassOffset(BOR->getDecl());
1670
1671 // The base offset is in chars, not in bits.
1672 Offset += BaseOffset.getQuantity() * R->getContext().getCharWidth();
1673 break;
1674 }
1675
1676 case MemRegion::CXXDerivedObjectRegionKind: {
1677 // TODO: Store the base type in the CXXDerivedObjectRegion and use it.
1678 goto Finish;
1679 }
1680
1681 case MemRegion::ElementRegionKind: {
1682 const auto *ER = cast<ElementRegion>(R);
1683 R = ER->getSuperRegion();
1684
1685 QualType EleTy = ER->getValueType();
1686 if (EleTy->isIncompleteType()) {
1687 // We cannot compute the offset of the base class.
1688 SymbolicOffsetBase = R;
1689 continue;
1690 }
1691
1692 SVal Index = ER->getIndex();
1693 if (std::optional<nonloc::ConcreteInt> CI =
1694 Index.getAs<nonloc::ConcreteInt>()) {
1695 // Don't bother calculating precise offsets if we already have a
1696 // symbolic offset somewhere in the chain.
1697 if (SymbolicOffsetBase)
1698 continue;
1699
1700 int64_t i = CI->getValue()->getSExtValue();
1701 // This type size is in bits.
1702 Offset += i * R->getContext().getTypeSize(EleTy);
1703 } else {
1704 // We cannot compute offset for non-concrete index.
1705 SymbolicOffsetBase = R;
1706 }
1707 break;
1708 }
1709 case MemRegion::FieldRegionKind: {
1710 const auto *FR = cast<FieldRegion>(R);
1711 R = FR->getSuperRegion();
1712 assert(R);
1713
1714 const RecordDecl *RD = FR->getDecl()->getParent();
1715 if (RD->isUnion() || !RD->isCompleteDefinition()) {
1716 // We cannot compute offset for incomplete type.
1717 // For unions, we could treat everything as offset 0, but we'd rather
1718 // treat each field as a symbolic offset so they aren't stored on top
1719 // of each other, since we depend on things in typed regions actually
1720 // matching their types.
1721 SymbolicOffsetBase = R;
1722 }
1723
1724 // Don't bother calculating precise offsets if we already have a
1725 // symbolic offset somewhere in the chain.
1726 if (SymbolicOffsetBase)
1727 continue;
1728
1729 assert(FR->getDecl()->getCanonicalDecl() == FR->getDecl());
1730 auto MaybeFieldIdx = [FR, RD]() -> std::optional<unsigned> {
1731 for (auto [Idx, Field] : llvm::enumerate(RD->fields())) {
1732 if (FR->getDecl() == Field->getCanonicalDecl())
1733 return Idx;
1734 }
1735 return std::nullopt;
1736 }();
1737
1738 if (!MaybeFieldIdx.has_value()) {
1739 assert(false && "Field not found");
1740 goto Finish; // Invalid offset.
1741 }
1742
1743 const ASTRecordLayout &Layout = R->getContext().getASTRecordLayout(RD);
1744 // This is offset in bits.
1745 Offset += Layout.getFieldOffset(MaybeFieldIdx.value());
1746 break;
1747 }
1748 }
1749 }
1750
1751 Finish:
1752 if (SymbolicOffsetBase)
1753 return RegionOffset(SymbolicOffsetBase, RegionOffset::Symbolic);
1754 return RegionOffset(R, Offset);
1755}
1756
1758 if (!cachedOffset)
1759 cachedOffset = calculateOffset(this);
1760 return *cachedOffset;
1761}
1762
1763//===----------------------------------------------------------------------===//
1764// BlockDataRegion
1765//===----------------------------------------------------------------------===//
1766
1767std::pair<const VarRegion *, const VarRegion *>
1768BlockDataRegion::getCaptureRegions(const VarDecl *VD) {
1770 const VarRegion *VR = nullptr;
1771 const VarRegion *OriginalVR = nullptr;
1772
1773 if (!VD->hasAttr<BlocksAttr>() && VD->hasLocalStorage()) {
1774 VR = MemMgr.getNonParamVarRegion(VD, this);
1775 OriginalVR = MemMgr.getVarRegion(VD, SF);
1776 }
1777 else {
1778 if (SF) {
1779 VR = MemMgr.getVarRegion(VD, SF);
1780 OriginalVR = VR;
1781 } else {
1782 VR = MemMgr.getNonParamVarRegion(VD, MemMgr.getUnknownRegion());
1783 OriginalVR = MemMgr.getVarRegion(VD, SF);
1784 }
1785 }
1786 return std::make_pair(VR, OriginalVR);
1787}
1788
1789void BlockDataRegion::LazyInitializeReferencedVars() {
1790 if (ReferencedVars)
1791 return;
1792
1793 AnalysisDeclContext *AC = getCodeRegion()->getAnalysisDeclContext();
1794 const auto &ReferencedBlockVars = AC->getReferencedBlockVars(BC->getDecl());
1795 auto NumBlockVars =
1796 std::distance(ReferencedBlockVars.begin(), ReferencedBlockVars.end());
1797
1798 if (NumBlockVars == 0) {
1799 ReferencedVars = (void*) 0x1;
1800 return;
1801 }
1802
1804 llvm::BumpPtrAllocator &A = MemMgr.getAllocator();
1805 BumpVectorContext BC(A);
1806
1807 using VarVec = BumpVector<const MemRegion *>;
1808
1809 auto *BV = new (A) VarVec(BC, NumBlockVars);
1810 auto *BVOriginal = new (A) VarVec(BC, NumBlockVars);
1811
1812 for (const auto *VD : ReferencedBlockVars) {
1813 const VarRegion *VR = nullptr;
1814 const VarRegion *OriginalVR = nullptr;
1815 std::tie(VR, OriginalVR) = getCaptureRegions(VD);
1816 assert(VR);
1817 assert(OriginalVR);
1818 BV->push_back(VR, BC);
1819 BVOriginal->push_back(OriginalVR, BC);
1820 }
1821
1822 ReferencedVars = BV;
1823 OriginalVars = BVOriginal;
1824}
1825
1828 const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars();
1829
1830 auto *Vec = static_cast<BumpVector<const MemRegion *> *>(ReferencedVars);
1831
1832 if (Vec == (void*) 0x1)
1833 return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr);
1834
1835 auto *VecOriginal =
1836 static_cast<BumpVector<const MemRegion *> *>(OriginalVars);
1837
1839 VecOriginal->begin());
1840}
1841
1844 const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars();
1845
1846 auto *Vec = static_cast<BumpVector<const MemRegion *> *>(ReferencedVars);
1847
1848 if (Vec == (void*) 0x1)
1849 return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr);
1850
1851 auto *VecOriginal =
1852 static_cast<BumpVector<const MemRegion *> *>(OriginalVars);
1853
1855 VecOriginal->end());
1856}
1857
1858llvm::iterator_range<BlockDataRegion::referenced_vars_iterator>
1860 return llvm::make_range(referenced_vars_begin(), referenced_vars_end());
1861}
1862
1864 for (const auto &I : referenced_vars()) {
1865 if (I.getCapturedRegion() == R)
1866 return I.getOriginalRegion();
1867 }
1868 return nullptr;
1869}
1870
1871//===----------------------------------------------------------------------===//
1872// RegionAndSymbolInvalidationTraits
1873//===----------------------------------------------------------------------===//
1874
1876 InvalidationKinds IK) {
1877 SymTraitsMap[Sym] |= IK;
1878}
1879
1881 InvalidationKinds IK) {
1882 assert(MR);
1883 if (const auto *SR = dyn_cast<SymbolicRegion>(MR))
1884 setTrait(SR->getSymbol(), IK);
1885 else
1886 MRTraitsMap[MR] |= IK;
1887}
1888
1890 InvalidationKinds IK) const {
1891 const_symbol_iterator I = SymTraitsMap.find(Sym);
1892 if (I != SymTraitsMap.end())
1893 return I->second & IK;
1894
1895 return false;
1896}
1897
1899 InvalidationKinds IK) const {
1900 if (!MR)
1901 return false;
1902
1903 if (const auto *SR = dyn_cast<SymbolicRegion>(MR))
1904 return hasTrait(SR->getSymbol(), IK);
1905
1906 const_region_iterator I = MRTraitsMap.find(MR);
1907 if (I != MRTraitsMap.end())
1908 return I->second & IK;
1909
1910 return false;
1911}
Defines the clang::ASTContext interface.
#define V(N, I)
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static bool isStdStreamVar(const VarDecl *D)
static llvm::PointerUnion< const StackFrame *, const VarRegion * > getStackOrCaptureRegionForDeclContext(const StackFrame *SF, const DeclContext *DC, const VarDecl *VD)
Look through a chain of StackFrames to either find the StackFrame that matches a DeclContext,...
static bool isImmediateBase(const CXXRecordDecl *Child, const CXXRecordDecl *Base)
Returns true if Base is an immediate base class of Child.
static bool isValidBaseClass(const CXXRecordDecl *BaseClass, const TypedValueRegion *Super, bool IsVirtual)
Checks whether BaseClass is a valid virtual or direct non-virtual base class of the type of Super.
static RegionOffset calculateOffset(const MemRegion *R)
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
Defines the SourceManager interface.
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:223
QualType getBlockPointerType(QualType T) const
Return the uniqued reference to the type for a block of the specified type.
QualType getFILEType() const
Retrieve the C FILE type.
CanQualType VoidTy
QualType getFunctionType(QualType ResultTy, ArrayRef< QualType > Args, const FunctionProtoType::ExtProtoInfo &EPI) const
Return a normal function type with a typed argument list.
CanQualType getCanonicalTagType(const TagDecl *TD) const
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
AnalysisDeclContext contains the context data for the function, method or block under analysis.
llvm::iterator_range< referenced_decls_iterator > getReferencedBlockVars(const BlockDecl *BD)
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3833
Represents a block literal declaration, which is like an unnamed FunctionDecl.
Definition Decl.h:4716
size_t param_size() const
Definition Decl.h:4818
bool hasCaptures() const
True if this block (or its nested blocks) captures anything of local storage from its enclosing scope...
Definition Decl.h:4835
const ParmVarDecl * getParamDecl(unsigned i) const
Definition Decl.h:4822
TypeSourceInfo * getSignatureAsWritten() const
Definition Decl.h:4799
Represents a C++ struct/union/class.
Definition DeclCXX.h:258
bool isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const
Determine whether this class is virtually derived from the class Base.
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:63
CompoundLiteralExpr - [C99 6.5.2.5].
Definition Expr.h:3611
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1466
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2126
bool isTranslationUnit() const
Definition DeclBase.h:2202
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
ASTContext & getASTContext() const LLVM_READONLY
Definition DeclBase.cpp:550
int64_t getID() const
SourceLocation getLocation() const
Definition DeclBase.h:447
DeclContext * getDeclContext()
Definition DeclBase.h:456
bool hasAttr() const
Definition DeclBase.h:585
std::string getAsString() const
Retrieve the human-readable string for this name.
This represents one expression.
Definition Expr.h:112
Represents a member of a struct/union/class.
Definition Decl.h:3204
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
Definition Decl.h:3451
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition TypeBase.h:4614
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
This represents a decl that may have a name.
Definition Decl.h:274
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
Definition Decl.h:295
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Definition Decl.h:301
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition Decl.h:340
ObjCIvarDecl - Represents an ObjC instance variable.
Definition DeclObjC.h:1958
ObjCStringLiteral, used for Objective-C string literals i.e.
Definition ExprObjC.h:84
Represents a parameter to a function.
Definition Decl.h:1819
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3405
A (possibly-)qualified type.
Definition TypeBase.h:938
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1005
LangAS getAddressSpace() const
Return the address space of this type.
Definition TypeBase.h:8627
QualType getCanonicalType() const
Definition TypeBase.h:8553
bool isConstQualified() const
Determine whether this type is const-qualified.
Definition TypeBase.h:8574
The collection of all-type qualifiers we support.
Definition TypeBase.h:332
void setAddressSpace(LangAS space)
Definition TypeBase.h:592
Represents a struct/union/class.
Definition Decl.h:4369
field_range fields() const
Definition Decl.h:4572
A trivial tuple used to represent a source range.
It represents a stack frame of the call stack.
LLVM_ATTRIBUTE_RETURNS_NONNULL AnalysisDeclContext * getAnalysisDeclContext() const
const Expr * getCallSite() const
const Decl * getDecl() const
const StackFrame * getParent() const
It might return null.
llvm::iterator_range< parent_iterator > parentsIncludingSelf() const
Iterates over this frame followed by all of its ancestors.
StringLiteral - This represents a string literal expression, e.g.
Definition Expr.h:1805
bool isCompleteDefinition() const
Return true if this decl has its body fully specified.
Definition Decl.h:3862
bool isUnion() const
Definition Decl.h:3972
A container of type source information.
Definition TypeBase.h:8472
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
bool isPointerType() const
Definition TypeBase.h:8738
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition Type.cpp:2531
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9337
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:712
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:932
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
Definition Decl.cpp:2238
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
Definition Decl.h:1247
VarDecl * getDefinition(ASTContext &)
Get the real (not just tentative) definition for this declaration.
Definition Decl.cpp:2347
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
Definition Decl.h:1214
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
Definition Decl.h:1190
AllocaRegion - A region that represents an untyped blob of bytes created by a call to 'alloca'.
Definition MemRegion.h:512
void dumpToStream(raw_ostream &os) const override
void Profile(llvm::FoldingSetNodeID &ID) const override
BlockCodeRegion - A region that represents code texts of blocks (closures).
Definition MemRegion.h:665
LLVM_ATTRIBUTE_RETURNS_NONNULL AnalysisDeclContext * getAnalysisDeclContext() const
Definition MemRegion.h:695
void dumpToStream(raw_ostream &os) const override
LLVM_ATTRIBUTE_RETURNS_NONNULL const BlockDecl * getDecl() const
Definition MemRegion.h:690
void Profile(llvm::FoldingSetNodeID &ID) const override
BlockDataRegion - A region that represents a block instance.
Definition MemRegion.h:712
const VarRegion * getOriginalRegion(const VarRegion *VR) const
Return the original region for a captured region, if one exists.
referenced_vars_iterator referenced_vars_begin() const
LLVM_ATTRIBUTE_RETURNS_NONNULL const BlockCodeRegion * getCodeRegion() const
Definition MemRegion.h:738
void Profile(llvm::FoldingSetNodeID &ID) const override
referenced_vars_iterator referenced_vars_end() const
void dumpToStream(raw_ostream &os) const override
llvm::iterator_range< referenced_vars_iterator > referenced_vars() const
void printPrettyAsExpr(raw_ostream &os) const override
Print the region as expression.
LLVM_ATTRIBUTE_RETURNS_NONNULL const CXXRecordDecl * getDecl() const
Definition MemRegion.h:1365
bool canPrintPrettyAsExpr() const override
Returns true if this region's textual representation can be used as part of a larger expression.
void Profile(llvm::FoldingSetNodeID &ID) const override
void dumpToStream(raw_ostream &os) const override
QualType getValueType() const override
void printPrettyAsExpr(raw_ostream &os) const override
Print the region as expression.
void Profile(llvm::FoldingSetNodeID &ID) const override
QualType getValueType() const override
void dumpToStream(raw_ostream &os) const override
bool canPrintPrettyAsExpr() const override
Returns true if this region's textual representation can be used as part of a larger expression.
LLVM_ATTRIBUTE_RETURNS_NONNULL const CXXRecordDecl * getDecl() const
Definition MemRegion.h:1408
void Profile(llvm::FoldingSetNodeID &ID) const override
const StackFrame * getStackFrame() const
It might return null.
void dumpToStream(raw_ostream &os) const override
QualType getValueType() const override
Definition MemRegion.h:1297
LLVM_ATTRIBUTE_RETURNS_NONNULL const StackFrame * getStackFrame() const
void Profile(llvm::FoldingSetNodeID &ID) const override
void dumpToStream(raw_ostream &os) const override
CXXThisRegion - Represents the region for the implicit 'this' parameter in a call to a C++ method.
Definition MemRegion.h:1112
void Profile(llvm::FoldingSetNodeID &ID) const override
void dumpToStream(raw_ostream &os) const override
CodeSpaceRegion - The memory space that holds the executable code of functions and blocks.
Definition MemRegion.h:265
void dumpToStream(raw_ostream &os) const override
CompoundLiteralRegion - A memory region representing a compound literal.
Definition MemRegion.h:933
void Profile(llvm::FoldingSetNodeID &ID) const override
void dumpToStream(raw_ostream &os) const override
ElementRegion is used to represent both array elements and casts.
Definition MemRegion.h:1237
QualType getElementType() const
Definition MemRegion.h:1261
void Profile(llvm::FoldingSetNodeID &ID) const override
RegionRawOffset getAsArrayOffset() const
Compute the offset within the array. The array might also be a subobject.
void dumpToStream(raw_ostream &os) const override
void printPrettyAsExpr(raw_ostream &os) const override
Print the region as expression.
bool canPrintPretty() const override
Returns true if this region can be printed in a user-friendly way.
bool canPrintPrettyAsExpr() const override
Returns true if this region's textual representation can be used as part of a larger expression.
void dumpToStream(raw_ostream &os) const override
void printPretty(raw_ostream &os) const override
Print the region for use in diagnostics.
void Profile(llvm::FoldingSetNodeID &ID) const override
LLVM_ATTRIBUTE_RETURNS_NONNULL const FieldDecl * getDecl() const override
Definition MemRegion.h:1163
FunctionCodeRegion - A region that represents code texts of function.
Definition MemRegion.h:618
const NamedDecl * getDecl() const
Definition MemRegion.h:646
void dumpToStream(raw_ostream &os) const override
void Profile(llvm::FoldingSetNodeID &ID) const override
void dumpToStream(raw_ostream &os) const override
void dumpToStream(raw_ostream &os) const override
void dumpToStream(raw_ostream &os) const override
void dumpToStream(raw_ostream &os) const override
const HeapSpaceRegion * getHeapRegion()
getHeapRegion - Retrieve the memory region associated with the generic "heap".
llvm::BumpPtrAllocator & getAllocator()
Definition MemRegion.h:1470
const StackLocalsSpaceRegion * getStackLocalsRegion(const StackFrame *SF)
getStackLocalsRegion - Retrieve the memory region associated with the specified stack frame.
const FieldRegion * getFieldRegion(const FieldDecl *FD, const SubRegion *SuperRegion)
getFieldRegion - Retrieve or create the memory region associated with a specified FieldDecl.
const ParamVarRegion * getParamVarRegion(const Expr *OriginExpr, unsigned Index, const StackFrame *SF)
getParamVarRegion - Retrieve or create the memory region associated with a specified CallExpr,...
const StackArgumentsSpaceRegion * getStackArgumentsRegion(const StackFrame *SF)
getStackArgumentsRegion - Retrieve the memory region associated with function/method arguments of the...
const BlockCodeRegion * getBlockCodeRegion(const BlockDecl *BD, CanQualType locTy, AnalysisDeclContext *AC)
const UnknownSpaceRegion * getUnknownRegion()
getUnknownRegion - Retrieve the memory region associated with unknown memory space.
const CXXDerivedObjectRegion * getCXXDerivedObjectRegion(const CXXRecordDecl *BaseClass, const SubRegion *Super)
Create a CXXDerivedObjectRegion with the given derived class for region Super.
const CXXLifetimeExtendedObjectRegion * getCXXLifetimeExtendedObjectRegion(Expr const *Ex, ValueDecl const *VD, StackFrame const *SF)
Create a CXXLifetimeExtendedObjectRegion for temporaries which are lifetime-extended by local referen...
const CompoundLiteralRegion * getCompoundLiteralRegion(const CompoundLiteralExpr *CL, const StackFrame *SF)
getCompoundLiteralRegion - Retrieve the region associated with a given CompoundLiteral.
const ElementRegion * getElementRegion(QualType elementType, NonLoc Idx, const SubRegion *superRegion, const ASTContext &Ctx)
getElementRegion - Retrieve the memory region associated with the associated element type,...
const NonParamVarRegion * getNonParamVarRegion(const VarDecl *VD, const MemRegion *superR)
getVarRegion - Retrieve or create the memory region associated with a specified VarDecl and StackFram...
const ObjCIvarRegion * getObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *superRegion)
getObjCIvarRegion - Retrieve or create the memory region associated with a specified Objective-c inst...
const VarRegion * getVarRegion(const VarDecl *VD, const StackFrame *SF)
getVarRegion - Retrieve or create the memory region associated with a specified VarDecl and StackFram...
const AllocaRegion * getAllocaRegion(const Expr *Ex, unsigned Cnt, const StackFrame *SF)
getAllocaRegion - Retrieve a region associated with a call to alloca().
const SymbolicRegion * getSymbolicHeapRegion(SymbolRef sym)
Return a unique symbolic region belonging to heap memory space.
const CXXTempObjectRegion * getCXXTempObjectRegion(Expr const *Ex, StackFrame const *SF)
const ObjCStringRegion * getObjCStringRegion(const ObjCStringLiteral *Str)
const StringRegion * getStringRegion(const StringLiteral *Str)
DefinedOrUnknownSVal getStaticSize(const MemRegion *MR, SValBuilder &SVB) const
const CodeSpaceRegion * getCodeRegion()
const GlobalsSpaceRegion * getGlobalsRegion(MemRegion::Kind K=MemRegion::GlobalInternalSpaceRegionKind, const CodeTextRegion *R=nullptr)
getGlobalsRegion - Retrieve the memory region associated with global variables.
const CXXThisRegion * getCXXThisRegion(QualType thisPointerTy, const StackFrame *SF)
getCXXThisRegion - Retrieve the [artificial] region associated with the parameter 'this'.
const SymbolicRegion * getSymbolicRegion(SymbolRef Sym, const MemSpaceRegion *MemSpace=nullptr)
Retrieve or create a "symbolic" memory region.
const FunctionCodeRegion * getFunctionCodeRegion(const NamedDecl *FD)
const CXXBaseObjectRegion * getCXXBaseObjectRegion(const CXXRecordDecl *BaseClass, const SubRegion *Super, bool IsVirtual)
Create a CXXBaseObjectRegion with the given base class for region Super.
const CXXLifetimeExtendedObjectRegion * getCXXStaticLifetimeExtendedObjectRegion(const Expr *Ex, ValueDecl const *VD)
Create a CXXLifetimeExtendedObjectRegion for temporaries which are lifetime-extended by static refere...
const BlockDataRegion * getBlockDataRegion(const BlockCodeRegion *bc, const StackFrame *SF, unsigned blockCount)
getBlockDataRegion - Get the memory region associated with an instance of a block.
MemRegion - The root abstract class for all memory regions.
Definition MemRegion.h:97
virtual bool canPrintPrettyAsExpr() const
Returns true if this region's textual representation can be used as part of a larger expression.
std::string getDescriptiveName(bool UseQuotes=true, bool AllowFallback=false) const
Get descriptive name for memory region.
StringRef getKindStr() const
RegionOffset getAsOffset() const
Compute the offset within the top level memory object.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * StripCasts(bool StripBaseAndDerivedCasts=true) const
ProgramStateRef setMemorySpace(ProgramStateRef State, const MemSpaceRegion *Space) const
Set the dynamically deduced memory space of a MemRegion that currently has UnknownSpaceRegion.
ASTContext & getContext() const
Definition MemRegion.h:1654
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemSpaceRegion * getMemorySpace(ProgramStateRef State) const
Returns the most specific memory space for this memory region in the given ProgramStateRef.
virtual bool isSubRegionOf(const MemRegion *R) const
Check if the region is a subregion of the given region.
virtual void dumpToStream(raw_ostream &os) const
const SymbolicRegion * getSymbolicBase() const
If this is a symbolic region, returns the region.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const
virtual void printPretty(raw_ostream &os) const
Print the region for use in diagnostics.
virtual void printPrettyAsExpr(raw_ostream &os) const
Print the region as expression.
std::string getString() const
Get a string representation of a region for debug use.
const RegionTy * getAs() const
Definition MemRegion.h:1426
Kind getKind() const
Definition MemRegion.h:202
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getMostDerivedObjectRegion() const
Recursively retrieve the region of the most derived class instance of regions of C++ base class insta...
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemSpaceRegion * getRawMemorySpace() const
Deprecated.
virtual bool canPrintPretty() const
Returns true if this region can be printed in a user-friendly way.
SourceRange sourceRange() const
Retrieve source range from memory region.
MemSpaceRegion - A memory region that represents a "memory space"; for example, the set of global var...
Definition MemRegion.h:242
void Profile(llvm::FoldingSetNodeID &ID) const override
bool canPrintPrettyAsExpr() const override
Returns true if this region's textual representation can be used as part of a larger expression.
void Profile(llvm::FoldingSetNodeID &ID) const override
void printPrettyAsExpr(raw_ostream &os) const override
Print the region as expression.
void dumpToStream(raw_ostream &os) const override
LLVM_ATTRIBUTE_RETURNS_NONNULL const VarDecl * getDecl() const override
Definition MemRegion.h:1043
bool canPrintPrettyAsExpr() const override
Returns true if this region's textual representation can be used as part of a larger expression.
void Profile(llvm::FoldingSetNodeID &ID) const override
QualType getValueType() const override
void printPrettyAsExpr(raw_ostream &os) const override
Print the region as expression.
LLVM_ATTRIBUTE_RETURNS_NONNULL const ObjCIvarDecl * getDecl() const override
void dumpToStream(raw_ostream &os) const override
The region associated with an ObjCStringLiteral.
Definition MemRegion.h:896
void dumpToStream(raw_ostream &os) const override
ParamVarRegion - Represents a region for parameters.
Definition MemRegion.h:1072
bool canPrintPrettyAsExpr() const override
Returns true if this region's textual representation can be used as part of a larger expression.
LLVM_ATTRIBUTE_RETURNS_NONNULL const Expr * getOriginExpr() const
Definition MemRegion.h:1089
const ParmVarDecl * getDecl() const override
TODO: What does this return?
unsigned getIndex() const
Definition MemRegion.h:1090
void Profile(llvm::FoldingSetNodeID &ID) const override
QualType getValueType() const override
void dumpToStream(raw_ostream &os) const override
void printPrettyAsExpr(raw_ostream &os) const override
Print the region as expression.
InvalidationKinds
Describes different invalidation traits.
Definition MemRegion.h:1676
bool hasTrait(SymbolRef Sym, InvalidationKinds IK) const
void setTrait(SymbolRef Sym, InvalidationKinds IK)
Represent a region's offset within the top level base region.
Definition MemRegion.h:64
static const int64_t Symbolic
Definition MemRegion.h:74
CharUnits getOffset() const
Definition MemRegion.h:1227
void dumpToStream(raw_ostream &os) const
const MemRegion * getRegion() const
Definition MemRegion.h:1230
nonloc::ConcreteInt makeIntVal(const IntegerLiteral *integer)
QualType getArrayIndexType() const
SymbolManager & getSymbolManager()
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
Definition SVals.h:57
void Profile(llvm::FoldingSetNodeID &ID) const
Definition SVals.h:98
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
Definition SVals.h:88
void dumpToStream(raw_ostream &os) const override
void dumpToStream(raw_ostream &os) const override
LLVM_ATTRIBUTE_RETURNS_NONNULL const StackFrame * getStackFrame() const
Definition MemRegion.h:439
void Profile(llvm::FoldingSetNodeID &ID) const override
The region of the static variables within the current CodeTextRegion scope.
Definition MemRegion.h:299
void Profile(llvm::FoldingSetNodeID &ID) const override
void dumpToStream(raw_ostream &os) const override
LLVM_ATTRIBUTE_RETURNS_NONNULL const CodeTextRegion * getCodeRegion() const
Definition MemRegion.h:315
StringRegion - Region associated with a StringLiteral.
Definition MemRegion.h:862
void dumpToStream(raw_ostream &os) const override
SubRegion - A region that subsets another larger region.
Definition MemRegion.h:480
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getSuperRegion() const
Definition MemRegion.h:493
bool isSubRegionOf(const MemRegion *R) const override
Check if the region is a subregion of the given region.
SubRegion(const MemRegion *sReg, Kind k)
Definition MemRegion.h:486
const MemRegion * superRegion
Definition MemRegion.h:484
MemRegionManager & getMemRegionManager() const override
SymbolExtent - Represents the extent (size in bytes) of a bounded region.
const SymExprT * acquire(Args &&...args)
Create or retrieve a SymExpr of type SymExprT for the given arguments.
SymbolicRegion - A special, "non-concrete" region.
Definition MemRegion.h:813
void dumpToStream(raw_ostream &os) const override
void Profile(llvm::FoldingSetNodeID &ID) const override
static void ProfileRegion(llvm::FoldingSetNodeID &ID, SymbolRef sym, const MemRegion *superRegion)
TypedValueRegion - An abstract class representing regions having a typed value.
Definition MemRegion.h:569
virtual QualType getValueType() const =0
void dumpToStream(raw_ostream &os) const override
const StackFrame * getStackFrame() const
It might return null.
Value representing integer constant.
Definition SVals.h:306
Represents symbolic expression that isn't a location.
Definition SVals.h:285
Definition SPIR.cpp:35
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
const SymExpr * SymbolRef
Definition SymExpr.h:133
DefinedOrUnknownSVal getElementExtent(QualType Ty, SValBuilder &SVB)
Top level wrappers for InstallAPI frontend operations.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
Definition Address.h:330
const FunctionProtoType * T
LangAS
Defines the address space values used by the address space qualifier of QualType.
U cast(CodeGen::Address addr)
Definition Address.h:327
Extra information about a function prototype.
Definition TypeBase.h:5503
Describes how types, statements, expressions, and declarations should be printed.