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