1 //===- MemRegion.cpp - Abstract memory regions for static analysis --------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines MemRegion and its subclasses. MemRegion defines a
10 // partially-typed abstraction of memory useful for path-sensitive dataflow
13 //===----------------------------------------------------------------------===//
15 #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
16 #include "clang/AST/ASTContext.h"
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"
23 #include "clang/AST/PrettyPrinter.h"
24 #include "clang/AST/RecordLayout.h"
25 #include "clang/AST/Type.h"
26 #include "clang/Analysis/AnalysisDeclContext.h"
27 #include "clang/Analysis/Support/BumpVector.h"
28 #include "clang/Basic/IdentifierTable.h"
29 #include "clang/Basic/LLVM.h"
30 #include "clang/Basic/SourceManager.h"
31 #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
32 #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
33 #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
34 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
35 #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
36 #include "llvm/ADT/APInt.h"
37 #include "llvm/ADT/FoldingSet.h"
38 #include "llvm/ADT/PointerUnion.h"
39 #include "llvm/ADT/SmallString.h"
40 #include "llvm/ADT/StringRef.h"
41 #include "llvm/ADT/Twine.h"
42 #include "llvm/ADT/iterator_range.h"
43 #include "llvm/Support/Allocator.h"
44 #include "llvm/Support/Casting.h"
45 #include "llvm/Support/CheckedArithmetic.h"
46 #include "llvm/Support/Compiler.h"
47 #include "llvm/Support/Debug.h"
48 #include "llvm/Support/ErrorHandling.h"
49 #include "llvm/Support/raw_ostream.h"
59 using namespace clang
;
62 #define DEBUG_TYPE "MemRegion"
64 //===----------------------------------------------------------------------===//
65 // MemRegion Construction.
66 //===----------------------------------------------------------------------===//
68 template <typename RegionTy
, typename SuperTy
, typename Arg1Ty
>
69 RegionTy
* MemRegionManager::getSubRegion(const Arg1Ty arg1
,
70 const SuperTy
*superRegion
) {
71 llvm::FoldingSetNodeID ID
;
72 RegionTy::ProfileRegion(ID
, arg1
, superRegion
);
74 auto *R
= cast_or_null
<RegionTy
>(Regions
.FindNodeOrInsertPos(ID
, InsertPos
));
77 R
= new (A
) RegionTy(arg1
, superRegion
);
78 Regions
.InsertNode(R
, InsertPos
);
84 template <typename RegionTy
, typename SuperTy
, typename Arg1Ty
, typename Arg2Ty
>
85 RegionTy
* MemRegionManager::getSubRegion(const Arg1Ty arg1
, const Arg2Ty arg2
,
86 const SuperTy
*superRegion
) {
87 llvm::FoldingSetNodeID ID
;
88 RegionTy::ProfileRegion(ID
, arg1
, arg2
, superRegion
);
90 auto *R
= cast_or_null
<RegionTy
>(Regions
.FindNodeOrInsertPos(ID
, InsertPos
));
93 R
= new (A
) RegionTy(arg1
, arg2
, superRegion
);
94 Regions
.InsertNode(R
, InsertPos
);
100 template <typename RegionTy
, typename SuperTy
,
101 typename Arg1Ty
, typename Arg2Ty
, typename Arg3Ty
>
102 RegionTy
* MemRegionManager::getSubRegion(const Arg1Ty arg1
, const Arg2Ty arg2
,
104 const SuperTy
*superRegion
) {
105 llvm::FoldingSetNodeID ID
;
106 RegionTy::ProfileRegion(ID
, arg1
, arg2
, arg3
, superRegion
);
108 auto *R
= cast_or_null
<RegionTy
>(Regions
.FindNodeOrInsertPos(ID
, InsertPos
));
111 R
= new (A
) RegionTy(arg1
, arg2
, arg3
, superRegion
);
112 Regions
.InsertNode(R
, InsertPos
);
118 //===----------------------------------------------------------------------===//
119 // Object destruction.
120 //===----------------------------------------------------------------------===//
122 MemRegion::~MemRegion() = default;
124 // All regions and their data are BumpPtrAllocated. No need to call their
126 MemRegionManager::~MemRegionManager() = default;
128 //===----------------------------------------------------------------------===//
130 //===----------------------------------------------------------------------===//
132 bool SubRegion::isSubRegionOf(const MemRegion
* R
) const {
133 const MemRegion
* r
= this;
137 if (const auto *sr
= dyn_cast
<SubRegion
>(r
))
138 r
= sr
->getSuperRegion();
141 } while (r
!= nullptr);
145 MemRegionManager
&SubRegion::getMemRegionManager() const {
146 const SubRegion
* r
= this;
148 const MemRegion
*superRegion
= r
->getSuperRegion();
149 if (const auto *sr
= dyn_cast
<SubRegion
>(superRegion
)) {
153 return superRegion
->getMemRegionManager();
157 const StackFrameContext
*VarRegion::getStackFrame() const {
158 const auto *SSR
= dyn_cast
<StackSpaceRegion
>(getMemorySpace());
159 return SSR
? SSR
->getStackFrame() : nullptr;
162 const StackFrameContext
*
163 CXXLifetimeExtendedObjectRegion::getStackFrame() const {
164 const auto *SSR
= dyn_cast
<StackSpaceRegion
>(getMemorySpace());
165 return SSR
? SSR
->getStackFrame() : nullptr;
168 const StackFrameContext
*CXXTempObjectRegion::getStackFrame() const {
169 assert(isa
<StackSpaceRegion
>(getMemorySpace()) &&
170 "A temporary object can only be allocated on the stack");
171 return cast
<StackSpaceRegion
>(getMemorySpace())->getStackFrame();
174 ObjCIvarRegion::ObjCIvarRegion(const ObjCIvarDecl
*ivd
, const SubRegion
*sReg
)
175 : DeclRegion(sReg
, ObjCIvarRegionKind
), IVD(ivd
) {
179 const ObjCIvarDecl
*ObjCIvarRegion::getDecl() const { return IVD
; }
181 QualType
ObjCIvarRegion::getValueType() const {
182 return getDecl()->getType();
185 QualType
CXXBaseObjectRegion::getValueType() const {
186 return QualType(getDecl()->getTypeForDecl(), 0);
189 QualType
CXXDerivedObjectRegion::getValueType() const {
190 return QualType(getDecl()->getTypeForDecl(), 0);
193 QualType
ParamVarRegion::getValueType() const {
195 "`ParamVarRegion` support functions without `Decl` not implemented"
197 return getDecl()->getType();
200 const ParmVarDecl
*ParamVarRegion::getDecl() const {
201 const Decl
*D
= getStackFrame()->getDecl();
203 if (const auto *FD
= dyn_cast
<FunctionDecl
>(D
)) {
204 assert(Index
< FD
->param_size());
205 return FD
->parameters()[Index
];
206 } else if (const auto *BD
= dyn_cast
<BlockDecl
>(D
)) {
207 assert(Index
< BD
->param_size());
208 return BD
->parameters()[Index
];
209 } else if (const auto *MD
= dyn_cast
<ObjCMethodDecl
>(D
)) {
210 assert(Index
< MD
->param_size());
211 return MD
->parameters()[Index
];
212 } else if (const auto *CD
= dyn_cast
<CXXConstructorDecl
>(D
)) {
213 assert(Index
< CD
->param_size());
214 return CD
->parameters()[Index
];
216 llvm_unreachable("Unexpected Decl kind!");
220 //===----------------------------------------------------------------------===//
221 // FoldingSet profiling.
222 //===----------------------------------------------------------------------===//
224 void MemSpaceRegion::Profile(llvm::FoldingSetNodeID
&ID
) const {
225 ID
.AddInteger(static_cast<unsigned>(getKind()));
228 void StackSpaceRegion::Profile(llvm::FoldingSetNodeID
&ID
) const {
229 ID
.AddInteger(static_cast<unsigned>(getKind()));
230 ID
.AddPointer(getStackFrame());
233 void StaticGlobalSpaceRegion::Profile(llvm::FoldingSetNodeID
&ID
) const {
234 ID
.AddInteger(static_cast<unsigned>(getKind()));
235 ID
.AddPointer(getCodeRegion());
238 void StringRegion::ProfileRegion(llvm::FoldingSetNodeID
&ID
,
239 const StringLiteral
*Str
,
240 const MemRegion
*superRegion
) {
241 ID
.AddInteger(static_cast<unsigned>(StringRegionKind
));
243 ID
.AddPointer(superRegion
);
246 void ObjCStringRegion::ProfileRegion(llvm::FoldingSetNodeID
&ID
,
247 const ObjCStringLiteral
*Str
,
248 const MemRegion
*superRegion
) {
249 ID
.AddInteger(static_cast<unsigned>(ObjCStringRegionKind
));
251 ID
.AddPointer(superRegion
);
254 void AllocaRegion::ProfileRegion(llvm::FoldingSetNodeID
& ID
,
255 const Expr
*Ex
, unsigned cnt
,
256 const MemRegion
*superRegion
) {
257 ID
.AddInteger(static_cast<unsigned>(AllocaRegionKind
));
260 ID
.AddPointer(superRegion
);
263 void AllocaRegion::Profile(llvm::FoldingSetNodeID
& ID
) const {
264 ProfileRegion(ID
, Ex
, Cnt
, superRegion
);
267 void CompoundLiteralRegion::Profile(llvm::FoldingSetNodeID
& ID
) const {
268 CompoundLiteralRegion::ProfileRegion(ID
, CL
, superRegion
);
271 void CompoundLiteralRegion::ProfileRegion(llvm::FoldingSetNodeID
& ID
,
272 const CompoundLiteralExpr
*CL
,
273 const MemRegion
* superRegion
) {
274 ID
.AddInteger(static_cast<unsigned>(CompoundLiteralRegionKind
));
276 ID
.AddPointer(superRegion
);
279 void CXXThisRegion::ProfileRegion(llvm::FoldingSetNodeID
&ID
,
280 const PointerType
*PT
,
281 const MemRegion
*sRegion
) {
282 ID
.AddInteger(static_cast<unsigned>(CXXThisRegionKind
));
284 ID
.AddPointer(sRegion
);
287 void CXXThisRegion::Profile(llvm::FoldingSetNodeID
&ID
) const {
288 CXXThisRegion::ProfileRegion(ID
, ThisPointerTy
, superRegion
);
291 void FieldRegion::Profile(llvm::FoldingSetNodeID
&ID
) const {
292 ProfileRegion(ID
, getDecl(), superRegion
);
295 void ObjCIvarRegion::ProfileRegion(llvm::FoldingSetNodeID
& ID
,
296 const ObjCIvarDecl
*ivd
,
297 const MemRegion
* superRegion
) {
298 ID
.AddInteger(static_cast<unsigned>(ObjCIvarRegionKind
));
300 ID
.AddPointer(superRegion
);
303 void ObjCIvarRegion::Profile(llvm::FoldingSetNodeID
&ID
) const {
304 ProfileRegion(ID
, getDecl(), superRegion
);
307 void NonParamVarRegion::ProfileRegion(llvm::FoldingSetNodeID
&ID
,
309 const MemRegion
*superRegion
) {
310 ID
.AddInteger(static_cast<unsigned>(NonParamVarRegionKind
));
312 ID
.AddPointer(superRegion
);
315 void NonParamVarRegion::Profile(llvm::FoldingSetNodeID
&ID
) const {
316 ProfileRegion(ID
, getDecl(), superRegion
);
319 void ParamVarRegion::ProfileRegion(llvm::FoldingSetNodeID
&ID
, const Expr
*OE
,
320 unsigned Idx
, const MemRegion
*SReg
) {
321 ID
.AddInteger(static_cast<unsigned>(ParamVarRegionKind
));
327 void ParamVarRegion::Profile(llvm::FoldingSetNodeID
&ID
) const {
328 ProfileRegion(ID
, getOriginExpr(), getIndex(), superRegion
);
331 void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID
& ID
, SymbolRef sym
,
332 const MemRegion
*sreg
) {
333 ID
.AddInteger(static_cast<unsigned>(MemRegion::SymbolicRegionKind
));
338 void SymbolicRegion::Profile(llvm::FoldingSetNodeID
& ID
) const {
339 SymbolicRegion::ProfileRegion(ID
, sym
, getSuperRegion());
342 void ElementRegion::ProfileRegion(llvm::FoldingSetNodeID
& ID
,
343 QualType ElementType
, SVal Idx
,
344 const MemRegion
* superRegion
) {
345 ID
.AddInteger(MemRegion::ElementRegionKind
);
347 ID
.AddPointer(superRegion
);
351 void ElementRegion::Profile(llvm::FoldingSetNodeID
& ID
) const {
352 ElementRegion::ProfileRegion(ID
, ElementType
, Index
, superRegion
);
355 void FunctionCodeRegion::ProfileRegion(llvm::FoldingSetNodeID
& ID
,
358 ID
.AddInteger(MemRegion::FunctionCodeRegionKind
);
362 void FunctionCodeRegion::Profile(llvm::FoldingSetNodeID
& ID
) const {
363 FunctionCodeRegion::ProfileRegion(ID
, FD
, superRegion
);
366 void BlockCodeRegion::ProfileRegion(llvm::FoldingSetNodeID
& ID
,
367 const BlockDecl
*BD
, CanQualType
,
368 const AnalysisDeclContext
*AC
,
370 ID
.AddInteger(MemRegion::BlockCodeRegionKind
);
374 void BlockCodeRegion::Profile(llvm::FoldingSetNodeID
& ID
) const {
375 BlockCodeRegion::ProfileRegion(ID
, BD
, locTy
, AC
, superRegion
);
378 void BlockDataRegion::ProfileRegion(llvm::FoldingSetNodeID
& ID
,
379 const BlockCodeRegion
*BC
,
380 const LocationContext
*LC
,
382 const MemRegion
*sReg
) {
383 ID
.AddInteger(MemRegion::BlockDataRegionKind
);
386 ID
.AddInteger(BlkCount
);
390 void BlockDataRegion::Profile(llvm::FoldingSetNodeID
& ID
) const {
391 BlockDataRegion::ProfileRegion(ID
, BC
, LC
, BlockCount
, getSuperRegion());
394 void CXXTempObjectRegion::ProfileRegion(llvm::FoldingSetNodeID
&ID
,
396 const MemRegion
*sReg
) {
401 void CXXTempObjectRegion::Profile(llvm::FoldingSetNodeID
&ID
) const {
402 ProfileRegion(ID
, Ex
, getSuperRegion());
405 void CXXLifetimeExtendedObjectRegion::ProfileRegion(llvm::FoldingSetNodeID
&ID
,
408 const MemRegion
*sReg
) {
414 void CXXLifetimeExtendedObjectRegion::Profile(
415 llvm::FoldingSetNodeID
&ID
) const {
416 ProfileRegion(ID
, Ex
, ExD
, getSuperRegion());
419 void CXXBaseObjectRegion::ProfileRegion(llvm::FoldingSetNodeID
&ID
,
420 const CXXRecordDecl
*RD
,
422 const MemRegion
*SReg
) {
424 ID
.AddBoolean(IsVirtual
);
428 void CXXBaseObjectRegion::Profile(llvm::FoldingSetNodeID
&ID
) const {
429 ProfileRegion(ID
, getDecl(), isVirtual(), superRegion
);
432 void CXXDerivedObjectRegion::ProfileRegion(llvm::FoldingSetNodeID
&ID
,
433 const CXXRecordDecl
*RD
,
434 const MemRegion
*SReg
) {
439 void CXXDerivedObjectRegion::Profile(llvm::FoldingSetNodeID
&ID
) const {
440 ProfileRegion(ID
, getDecl(), superRegion
);
443 //===----------------------------------------------------------------------===//
445 //===----------------------------------------------------------------------===//
447 void GlobalsSpaceRegion::anchor() {}
449 void NonStaticGlobalSpaceRegion::anchor() {}
451 void StackSpaceRegion::anchor() {}
453 void TypedRegion::anchor() {}
455 void TypedValueRegion::anchor() {}
457 void CodeTextRegion::anchor() {}
459 void SubRegion::anchor() {}
461 //===----------------------------------------------------------------------===//
462 // Region pretty-printing.
463 //===----------------------------------------------------------------------===//
465 LLVM_DUMP_METHOD
void MemRegion::dump() const {
466 dumpToStream(llvm::errs());
469 std::string
MemRegion::getString() const {
471 llvm::raw_string_ostream
os(s
);
476 void MemRegion::dumpToStream(raw_ostream
&os
) const {
477 os
<< "<Unknown Region>";
480 void AllocaRegion::dumpToStream(raw_ostream
&os
) const {
481 os
<< "alloca{S" << Ex
->getID(getContext()) << ',' << Cnt
<< '}';
484 void FunctionCodeRegion::dumpToStream(raw_ostream
&os
) const {
485 os
<< "code{" << getDecl()->getDeclName().getAsString() << '}';
488 void BlockCodeRegion::dumpToStream(raw_ostream
&os
) const {
489 os
<< "block_code{" << static_cast<const void *>(this) << '}';
492 void BlockDataRegion::dumpToStream(raw_ostream
&os
) const {
493 os
<< "block_data{" << BC
;
495 for (auto Var
: referenced_vars())
496 os
<< "(" << Var
.getCapturedRegion() << "<-" << Var
.getOriginalRegion()
501 void CompoundLiteralRegion::dumpToStream(raw_ostream
&os
) const {
502 // FIXME: More elaborate pretty-printing.
503 os
<< "{ S" << CL
->getID(getContext()) << " }";
506 void CXXTempObjectRegion::dumpToStream(raw_ostream
&os
) const {
507 os
<< "temp_object{" << getValueType() << ", "
508 << "S" << Ex
->getID(getContext()) << '}';
511 void CXXLifetimeExtendedObjectRegion::dumpToStream(raw_ostream
&os
) const {
512 os
<< "lifetime_extended_object{" << getValueType() << ", ";
513 if (const IdentifierInfo
*ID
= ExD
->getIdentifier())
516 os
<< "D" << ExD
->getID();
518 << "S" << Ex
->getID(getContext()) << '}';
521 void CXXBaseObjectRegion::dumpToStream(raw_ostream
&os
) const {
522 os
<< "Base{" << superRegion
<< ',' << getDecl()->getName() << '}';
525 void CXXDerivedObjectRegion::dumpToStream(raw_ostream
&os
) const {
526 os
<< "Derived{" << superRegion
<< ',' << getDecl()->getName() << '}';
529 void CXXThisRegion::dumpToStream(raw_ostream
&os
) const {
533 void ElementRegion::dumpToStream(raw_ostream
&os
) const {
534 os
<< "Element{" << superRegion
<< ',' << Index
<< ',' << getElementType()
538 void FieldRegion::dumpToStream(raw_ostream
&os
) const {
539 os
<< superRegion
<< "." << *getDecl();
542 void ObjCIvarRegion::dumpToStream(raw_ostream
&os
) const {
543 os
<< "Ivar{" << superRegion
<< ',' << *getDecl() << '}';
546 void StringRegion::dumpToStream(raw_ostream
&os
) const {
547 assert(Str
!= nullptr && "Expecting non-null StringLiteral");
548 Str
->printPretty(os
, nullptr, PrintingPolicy(getContext().getLangOpts()));
551 void ObjCStringRegion::dumpToStream(raw_ostream
&os
) const {
552 assert(Str
!= nullptr && "Expecting non-null ObjCStringLiteral");
553 Str
->printPretty(os
, nullptr, PrintingPolicy(getContext().getLangOpts()));
556 void SymbolicRegion::dumpToStream(raw_ostream
&os
) const {
557 if (isa
<HeapSpaceRegion
>(getSuperRegion()))
559 os
<< "SymRegion{" << sym
<< '}';
562 void NonParamVarRegion::dumpToStream(raw_ostream
&os
) const {
563 if (const IdentifierInfo
*ID
= VD
->getIdentifier())
566 os
<< "NonParamVarRegion{D" << VD
->getID() << '}';
569 LLVM_DUMP_METHOD
void RegionRawOffset::dump() const {
570 dumpToStream(llvm::errs());
573 void RegionRawOffset::dumpToStream(raw_ostream
&os
) const {
574 os
<< "raw_offset{" << getRegion() << ',' << getOffset().getQuantity() << '}';
577 void CodeSpaceRegion::dumpToStream(raw_ostream
&os
) const {
578 os
<< "CodeSpaceRegion";
581 void StaticGlobalSpaceRegion::dumpToStream(raw_ostream
&os
) const {
582 os
<< "StaticGlobalsMemSpace{" << CR
<< '}';
585 void GlobalInternalSpaceRegion::dumpToStream(raw_ostream
&os
) const {
586 os
<< "GlobalInternalSpaceRegion";
589 void GlobalSystemSpaceRegion::dumpToStream(raw_ostream
&os
) const {
590 os
<< "GlobalSystemSpaceRegion";
593 void GlobalImmutableSpaceRegion::dumpToStream(raw_ostream
&os
) const {
594 os
<< "GlobalImmutableSpaceRegion";
597 void HeapSpaceRegion::dumpToStream(raw_ostream
&os
) const {
598 os
<< "HeapSpaceRegion";
601 void UnknownSpaceRegion::dumpToStream(raw_ostream
&os
) const {
602 os
<< "UnknownSpaceRegion";
605 void StackArgumentsSpaceRegion::dumpToStream(raw_ostream
&os
) const {
606 os
<< "StackArgumentsSpaceRegion";
609 void StackLocalsSpaceRegion::dumpToStream(raw_ostream
&os
) const {
610 os
<< "StackLocalsSpaceRegion";
613 void ParamVarRegion::dumpToStream(raw_ostream
&os
) const {
614 const ParmVarDecl
*PVD
= getDecl();
616 "`ParamVarRegion` support functions without `Decl` not implemented"
618 if (const IdentifierInfo
*ID
= PVD
->getIdentifier()) {
621 os
<< "ParamVarRegion{P" << PVD
->getID() << '}';
625 bool MemRegion::canPrintPretty() const {
626 return canPrintPrettyAsExpr();
629 bool MemRegion::canPrintPrettyAsExpr() const {
633 void MemRegion::printPretty(raw_ostream
&os
) const {
634 assert(canPrintPretty() && "This region cannot be printed pretty.");
636 printPrettyAsExpr(os
);
640 void MemRegion::printPrettyAsExpr(raw_ostream
&) const {
641 llvm_unreachable("This region cannot be printed pretty.");
644 bool NonParamVarRegion::canPrintPrettyAsExpr() const { return true; }
646 void NonParamVarRegion::printPrettyAsExpr(raw_ostream
&os
) const {
647 os
<< getDecl()->getName();
650 bool ParamVarRegion::canPrintPrettyAsExpr() const { return true; }
652 void ParamVarRegion::printPrettyAsExpr(raw_ostream
&os
) const {
654 "`ParamVarRegion` support functions without `Decl` not implemented"
656 os
<< getDecl()->getName();
659 bool ObjCIvarRegion::canPrintPrettyAsExpr() const {
663 void ObjCIvarRegion::printPrettyAsExpr(raw_ostream
&os
) const {
664 os
<< getDecl()->getName();
667 bool FieldRegion::canPrintPretty() const {
671 bool FieldRegion::canPrintPrettyAsExpr() const {
672 return superRegion
->canPrintPrettyAsExpr();
675 void FieldRegion::printPrettyAsExpr(raw_ostream
&os
) const {
676 assert(canPrintPrettyAsExpr());
677 superRegion
->printPrettyAsExpr(os
);
678 os
<< "." << getDecl()->getName();
681 void FieldRegion::printPretty(raw_ostream
&os
) const {
682 if (canPrintPrettyAsExpr()) {
684 printPrettyAsExpr(os
);
687 os
<< "field " << "\'" << getDecl()->getName() << "'";
691 bool CXXBaseObjectRegion::canPrintPrettyAsExpr() const {
692 return superRegion
->canPrintPrettyAsExpr();
695 void CXXBaseObjectRegion::printPrettyAsExpr(raw_ostream
&os
) const {
696 superRegion
->printPrettyAsExpr(os
);
699 bool CXXDerivedObjectRegion::canPrintPrettyAsExpr() const {
700 return superRegion
->canPrintPrettyAsExpr();
703 void CXXDerivedObjectRegion::printPrettyAsExpr(raw_ostream
&os
) const {
704 superRegion
->printPrettyAsExpr(os
);
707 std::string
MemRegion::getDescriptiveName(bool UseQuotes
) const {
708 std::string VariableName
;
709 std::string ArrayIndices
;
710 const MemRegion
*R
= this;
712 llvm::raw_svector_ostream
os(buf
);
714 // Obtain array indices to add them to the variable name.
715 const ElementRegion
*ER
= nullptr;
716 while ((ER
= R
->getAs
<ElementRegion
>())) {
717 // Index is a ConcreteInt.
718 if (auto CI
= ER
->getIndex().getAs
<nonloc::ConcreteInt
>()) {
719 llvm::SmallString
<2> Idx
;
720 CI
->getValue().toString(Idx
);
721 ArrayIndices
= (llvm::Twine("[") + Idx
.str() + "]" + ArrayIndices
).str();
723 // If not a ConcreteInt, try to obtain the variable
724 // name by calling 'getDescriptiveName' recursively.
726 std::string Idx
= ER
->getDescriptiveName(false);
728 ArrayIndices
= (llvm::Twine("[") + Idx
+ "]" + ArrayIndices
).str();
731 R
= ER
->getSuperRegion();
734 // Get variable name.
735 if (R
&& R
->canPrintPrettyAsExpr()) {
736 R
->printPrettyAsExpr(os
);
738 return (llvm::Twine("'") + os
.str() + ArrayIndices
+ "'").str();
740 return (llvm::Twine(os
.str()) + ArrayIndices
).str();
746 SourceRange
MemRegion::sourceRange() const {
747 // Check for more specific regions first.
748 if (auto *FR
= dyn_cast
<FieldRegion
>(this)) {
749 return FR
->getDecl()->getSourceRange();
752 if (auto *VR
= dyn_cast
<VarRegion
>(this->getBaseRegion())) {
753 return VR
->getDecl()->getSourceRange();
756 // Return invalid source range (can be checked by client).
760 //===----------------------------------------------------------------------===//
761 // MemRegionManager methods.
762 //===----------------------------------------------------------------------===//
764 DefinedOrUnknownSVal
MemRegionManager::getStaticSize(const MemRegion
*MR
,
765 SValBuilder
&SVB
) const {
766 const auto *SR
= cast
<SubRegion
>(MR
);
767 SymbolManager
&SymMgr
= SVB
.getSymbolManager();
769 switch (SR
->getKind()) {
770 case MemRegion::AllocaRegionKind
:
771 case MemRegion::SymbolicRegionKind
:
772 return nonloc::SymbolVal(SymMgr
.getExtentSymbol(SR
));
773 case MemRegion::StringRegionKind
:
774 return SVB
.makeIntVal(
775 cast
<StringRegion
>(SR
)->getStringLiteral()->getByteLength() + 1,
776 SVB
.getArrayIndexType());
777 case MemRegion::CompoundLiteralRegionKind
:
778 case MemRegion::CXXBaseObjectRegionKind
:
779 case MemRegion::CXXDerivedObjectRegionKind
:
780 case MemRegion::CXXTempObjectRegionKind
:
781 case MemRegion::CXXLifetimeExtendedObjectRegionKind
:
782 case MemRegion::CXXThisRegionKind
:
783 case MemRegion::ObjCIvarRegionKind
:
784 case MemRegion::NonParamVarRegionKind
:
785 case MemRegion::ParamVarRegionKind
:
786 case MemRegion::ElementRegionKind
:
787 case MemRegion::ObjCStringRegionKind
: {
788 QualType Ty
= cast
<TypedValueRegion
>(SR
)->getDesugaredValueType(Ctx
);
789 if (isa
<VariableArrayType
>(Ty
))
790 return nonloc::SymbolVal(SymMgr
.getExtentSymbol(SR
));
792 if (Ty
->isIncompleteType())
795 return getElementExtent(Ty
, SVB
);
797 case MemRegion::FieldRegionKind
: {
798 // Force callers to deal with bitfields explicitly.
799 if (cast
<FieldRegion
>(SR
)->getDecl()->isBitField())
802 QualType Ty
= cast
<TypedValueRegion
>(SR
)->getDesugaredValueType(Ctx
);
803 const DefinedOrUnknownSVal Size
= getElementExtent(Ty
, SVB
);
805 // We currently don't model flexible array members (FAMs), which are:
806 // - int array[]; of IncompleteArrayType
807 // - int array[0]; of ConstantArrayType with size 0
808 // - int array[1]; of ConstantArrayType with size 1
809 // https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
810 const auto isFlexibleArrayMemberCandidate
=
811 [this](const ArrayType
*AT
) -> bool {
815 auto IsIncompleteArray
= [](const ArrayType
*AT
) {
816 return isa
<IncompleteArrayType
>(AT
);
818 auto IsArrayOfZero
= [](const ArrayType
*AT
) {
819 const auto *CAT
= dyn_cast
<ConstantArrayType
>(AT
);
820 return CAT
&& CAT
->getSize() == 0;
822 auto IsArrayOfOne
= [](const ArrayType
*AT
) {
823 const auto *CAT
= dyn_cast
<ConstantArrayType
>(AT
);
824 return CAT
&& CAT
->getSize() == 1;
827 using FAMKind
= LangOptions::StrictFlexArraysLevelKind
;
828 const FAMKind StrictFlexArraysLevel
=
829 Ctx
.getLangOpts().getStrictFlexArraysLevel();
831 // "Default": Any trailing array member is a FAM.
832 // Since we cannot tell at this point if this array is a trailing member
833 // or not, let's just do the same as for "OneZeroOrIncomplete".
834 if (StrictFlexArraysLevel
== FAMKind::Default
)
835 return IsArrayOfOne(AT
) || IsArrayOfZero(AT
) || IsIncompleteArray(AT
);
837 if (StrictFlexArraysLevel
== FAMKind::OneZeroOrIncomplete
)
838 return IsArrayOfOne(AT
) || IsArrayOfZero(AT
) || IsIncompleteArray(AT
);
840 if (StrictFlexArraysLevel
== FAMKind::ZeroOrIncomplete
)
841 return IsArrayOfZero(AT
) || IsIncompleteArray(AT
);
843 assert(StrictFlexArraysLevel
== FAMKind::IncompleteOnly
);
844 return IsIncompleteArray(AT
);
847 if (isFlexibleArrayMemberCandidate(Ctx
.getAsArrayType(Ty
)))
852 // FIXME: The following are being used in 'SimpleSValBuilder' and in
853 // 'ArrayBoundChecker::checkLocation' because there is no symbol to
854 // represent the regions more appropriately.
855 case MemRegion::BlockDataRegionKind
:
856 case MemRegion::BlockCodeRegionKind
:
857 case MemRegion::FunctionCodeRegionKind
:
858 return nonloc::SymbolVal(SymMgr
.getExtentSymbol(SR
));
860 llvm_unreachable("Unhandled region");
864 template <typename REG
>
865 const REG
*MemRegionManager::LazyAllocate(REG
*& region
) {
867 region
= new (A
) REG(*this);
873 template <typename REG
, typename ARG
>
874 const REG
*MemRegionManager::LazyAllocate(REG
*& region
, ARG a
) {
876 region
= new (A
) REG(this, a
);
882 const StackLocalsSpaceRegion
*
883 MemRegionManager::getStackLocalsRegion(const StackFrameContext
*STC
) {
885 StackLocalsSpaceRegion
*&R
= StackLocalsSpaceRegions
[STC
];
890 R
= new (A
) StackLocalsSpaceRegion(*this, STC
);
894 const StackArgumentsSpaceRegion
*
895 MemRegionManager::getStackArgumentsRegion(const StackFrameContext
*STC
) {
897 StackArgumentsSpaceRegion
*&R
= StackArgumentsSpaceRegions
[STC
];
902 R
= new (A
) StackArgumentsSpaceRegion(*this, STC
);
906 const GlobalsSpaceRegion
907 *MemRegionManager::getGlobalsRegion(MemRegion::Kind K
,
908 const CodeTextRegion
*CR
) {
910 if (K
== MemRegion::GlobalSystemSpaceRegionKind
)
911 return LazyAllocate(SystemGlobals
);
912 if (K
== MemRegion::GlobalImmutableSpaceRegionKind
)
913 return LazyAllocate(ImmutableGlobals
);
914 assert(K
== MemRegion::GlobalInternalSpaceRegionKind
);
915 return LazyAllocate(InternalGlobals
);
918 assert(K
== MemRegion::StaticGlobalSpaceRegionKind
);
919 StaticGlobalSpaceRegion
*&R
= StaticsGlobalSpaceRegions
[CR
];
923 R
= new (A
) StaticGlobalSpaceRegion(*this, CR
);
927 const HeapSpaceRegion
*MemRegionManager::getHeapRegion() {
928 return LazyAllocate(heap
);
931 const UnknownSpaceRegion
*MemRegionManager::getUnknownRegion() {
932 return LazyAllocate(unknown
);
935 const CodeSpaceRegion
*MemRegionManager::getCodeRegion() {
936 return LazyAllocate(code
);
939 //===----------------------------------------------------------------------===//
940 // Constructing regions.
941 //===----------------------------------------------------------------------===//
943 const StringRegion
*MemRegionManager::getStringRegion(const StringLiteral
*Str
){
944 return getSubRegion
<StringRegion
>(
945 Str
, cast
<GlobalInternalSpaceRegion
>(getGlobalsRegion()));
948 const ObjCStringRegion
*
949 MemRegionManager::getObjCStringRegion(const ObjCStringLiteral
*Str
){
950 return getSubRegion
<ObjCStringRegion
>(
951 Str
, cast
<GlobalInternalSpaceRegion
>(getGlobalsRegion()));
954 /// Look through a chain of LocationContexts to either find the
955 /// StackFrameContext that matches a DeclContext, or find a VarRegion
956 /// for a variable captured by a block.
957 static llvm::PointerUnion
<const StackFrameContext
*, const VarRegion
*>
958 getStackOrCaptureRegionForDeclContext(const LocationContext
*LC
,
959 const DeclContext
*DC
,
962 if (const auto *SFC
= dyn_cast
<StackFrameContext
>(LC
)) {
963 if (cast
<DeclContext
>(SFC
->getDecl()) == DC
)
966 if (const auto *BC
= dyn_cast
<BlockInvocationContext
>(LC
)) {
967 const auto *BR
= static_cast<const BlockDataRegion
*>(BC
->getData());
968 // FIXME: This can be made more efficient.
969 for (auto Var
: BR
->referenced_vars()) {
970 const TypedValueRegion
*OrigR
= Var
.getOriginalRegion();
971 if (const auto *VR
= dyn_cast
<VarRegion
>(OrigR
)) {
972 if (VR
->getDecl() == VD
)
973 return cast
<VarRegion
>(Var
.getCapturedRegion());
978 LC
= LC
->getParent();
980 return (const StackFrameContext
*)nullptr;
983 const VarRegion
*MemRegionManager::getVarRegion(const VarDecl
*D
,
984 const LocationContext
*LC
) {
985 const auto *PVD
= dyn_cast
<ParmVarDecl
>(D
);
987 unsigned Index
= PVD
->getFunctionScopeIndex();
988 const StackFrameContext
*SFC
= LC
->getStackFrame();
989 const Stmt
*CallSite
= SFC
->getCallSite();
991 const Decl
*D
= SFC
->getDecl();
992 if (const auto *FD
= dyn_cast
<FunctionDecl
>(D
)) {
993 if (Index
< FD
->param_size() && FD
->parameters()[Index
] == PVD
)
994 return getSubRegion
<ParamVarRegion
>(cast
<Expr
>(CallSite
), Index
,
995 getStackArgumentsRegion(SFC
));
996 } else if (const auto *BD
= dyn_cast
<BlockDecl
>(D
)) {
997 if (Index
< BD
->param_size() && BD
->parameters()[Index
] == PVD
)
998 return getSubRegion
<ParamVarRegion
>(cast
<Expr
>(CallSite
), Index
,
999 getStackArgumentsRegion(SFC
));
1001 return getSubRegion
<ParamVarRegion
>(cast
<Expr
>(CallSite
), Index
,
1002 getStackArgumentsRegion(SFC
));
1007 D
= D
->getCanonicalDecl();
1008 const MemRegion
*sReg
= nullptr;
1010 if (D
->hasGlobalStorage() && !D
->isStaticLocal()) {
1011 QualType Ty
= D
->getType();
1012 assert(!Ty
.isNull());
1013 if (Ty
.isConstQualified()) {
1014 sReg
= getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind
);
1015 } else if (Ctx
.getSourceManager().isInSystemHeader(D
->getLocation())) {
1016 sReg
= getGlobalsRegion(MemRegion::GlobalSystemSpaceRegionKind
);
1018 sReg
= getGlobalsRegion(MemRegion::GlobalInternalSpaceRegionKind
);
1021 // Finally handle static locals.
1023 // FIXME: Once we implement scope handling, we will need to properly lookup
1024 // 'D' to the proper LocationContext.
1025 const DeclContext
*DC
= D
->getDeclContext();
1026 llvm::PointerUnion
<const StackFrameContext
*, const VarRegion
*> V
=
1027 getStackOrCaptureRegionForDeclContext(LC
, DC
, D
);
1029 if (V
.is
<const VarRegion
*>())
1030 return V
.get
<const VarRegion
*>();
1032 const auto *STC
= V
.get
<const StackFrameContext
*>();
1035 // FIXME: Assign a more sensible memory space to static locals
1036 // we see from within blocks that we analyze as top-level declarations.
1037 sReg
= getUnknownRegion();
1039 if (D
->hasLocalStorage()) {
1041 isa
<ParmVarDecl
, ImplicitParamDecl
>(D
)
1042 ? static_cast<const MemRegion
*>(getStackArgumentsRegion(STC
))
1043 : static_cast<const MemRegion
*>(getStackLocalsRegion(STC
));
1046 assert(D
->isStaticLocal());
1047 const Decl
*STCD
= STC
->getDecl();
1048 if (isa
<FunctionDecl
, ObjCMethodDecl
>(STCD
))
1049 sReg
= getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind
,
1050 getFunctionCodeRegion(cast
<NamedDecl
>(STCD
)));
1051 else if (const auto *BD
= dyn_cast
<BlockDecl
>(STCD
)) {
1052 // FIXME: The fallback type here is totally bogus -- though it should
1053 // never be queried, it will prevent uniquing with the real
1054 // BlockCodeRegion. Ideally we'd fix the AST so that we always had a
1057 if (const TypeSourceInfo
*TSI
= BD
->getSignatureAsWritten())
1060 T
= getContext().VoidTy
;
1061 if (!T
->getAs
<FunctionType
>()) {
1062 FunctionProtoType::ExtProtoInfo Ext
;
1063 T
= getContext().getFunctionType(T
, std::nullopt
, Ext
);
1065 T
= getContext().getBlockPointerType(T
);
1067 const BlockCodeRegion
*BTR
=
1068 getBlockCodeRegion(BD
, Ctx
.getCanonicalType(T
),
1069 STC
->getAnalysisDeclContext());
1070 sReg
= getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind
,
1074 sReg
= getGlobalsRegion();
1080 return getNonParamVarRegion(D
, sReg
);
1083 const NonParamVarRegion
*
1084 MemRegionManager::getNonParamVarRegion(const VarDecl
*D
,
1085 const MemRegion
*superR
) {
1086 // Prefer the definition over the canonical decl as the canonical form.
1087 D
= D
->getCanonicalDecl();
1088 if (const VarDecl
*Def
= D
->getDefinition())
1090 return getSubRegion
<NonParamVarRegion
>(D
, superR
);
1093 const ParamVarRegion
*
1094 MemRegionManager::getParamVarRegion(const Expr
*OriginExpr
, unsigned Index
,
1095 const LocationContext
*LC
) {
1096 const StackFrameContext
*SFC
= LC
->getStackFrame();
1098 return getSubRegion
<ParamVarRegion
>(OriginExpr
, Index
,
1099 getStackArgumentsRegion(SFC
));
1102 const BlockDataRegion
*
1103 MemRegionManager::getBlockDataRegion(const BlockCodeRegion
*BC
,
1104 const LocationContext
*LC
,
1105 unsigned blockCount
) {
1106 const MemSpaceRegion
*sReg
= nullptr;
1107 const BlockDecl
*BD
= BC
->getDecl();
1108 if (!BD
->hasCaptures()) {
1109 // This handles 'static' blocks.
1110 sReg
= getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind
);
1113 bool IsArcManagedBlock
= Ctx
.getLangOpts().ObjCAutoRefCount
;
1115 // ARC managed blocks can be initialized on stack or directly in heap
1116 // depending on the implementations. So we initialize them with
1118 if (!IsArcManagedBlock
&& LC
) {
1119 // FIXME: Once we implement scope handling, we want the parent region
1121 const StackFrameContext
*STC
= LC
->getStackFrame();
1123 sReg
= getStackLocalsRegion(STC
);
1125 // We allow 'LC' to be NULL for cases where want BlockDataRegions
1126 // without context-sensitivity.
1127 sReg
= getUnknownRegion();
1131 return getSubRegion
<BlockDataRegion
>(BC
, LC
, blockCount
, sReg
);
1134 const CompoundLiteralRegion
*
1135 MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr
*CL
,
1136 const LocationContext
*LC
) {
1137 const MemSpaceRegion
*sReg
= nullptr;
1139 if (CL
->isFileScope())
1140 sReg
= getGlobalsRegion();
1142 const StackFrameContext
*STC
= LC
->getStackFrame();
1144 sReg
= getStackLocalsRegion(STC
);
1147 return getSubRegion
<CompoundLiteralRegion
>(CL
, sReg
);
1150 const ElementRegion
*
1151 MemRegionManager::getElementRegion(QualType elementType
, NonLoc Idx
,
1152 const SubRegion
* superRegion
,
1154 QualType T
= Ctx
.getCanonicalType(elementType
).getUnqualifiedType();
1156 llvm::FoldingSetNodeID ID
;
1157 ElementRegion::ProfileRegion(ID
, T
, Idx
, superRegion
);
1160 MemRegion
* data
= Regions
.FindNodeOrInsertPos(ID
, InsertPos
);
1161 auto *R
= cast_or_null
<ElementRegion
>(data
);
1164 R
= new (A
) ElementRegion(T
, Idx
, superRegion
);
1165 Regions
.InsertNode(R
, InsertPos
);
1171 const FunctionCodeRegion
*
1172 MemRegionManager::getFunctionCodeRegion(const NamedDecl
*FD
) {
1173 // To think: should we canonicalize the declaration here?
1174 return getSubRegion
<FunctionCodeRegion
>(FD
, getCodeRegion());
1177 const BlockCodeRegion
*
1178 MemRegionManager::getBlockCodeRegion(const BlockDecl
*BD
, CanQualType locTy
,
1179 AnalysisDeclContext
*AC
) {
1180 return getSubRegion
<BlockCodeRegion
>(BD
, locTy
, AC
, getCodeRegion());
1183 const SymbolicRegion
*
1184 MemRegionManager::getSymbolicRegion(SymbolRef sym
,
1185 const MemSpaceRegion
*MemSpace
) {
1186 if (MemSpace
== nullptr)
1187 MemSpace
= getUnknownRegion();
1188 return getSubRegion
<SymbolicRegion
>(sym
, MemSpace
);
1191 const SymbolicRegion
*MemRegionManager::getSymbolicHeapRegion(SymbolRef Sym
) {
1192 return getSubRegion
<SymbolicRegion
>(Sym
, getHeapRegion());
1196 MemRegionManager::getFieldRegion(const FieldDecl
*d
,
1197 const SubRegion
* superRegion
){
1198 return getSubRegion
<FieldRegion
>(d
, superRegion
);
1201 const ObjCIvarRegion
*
1202 MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl
*d
,
1203 const SubRegion
* superRegion
) {
1204 return getSubRegion
<ObjCIvarRegion
>(d
, superRegion
);
1207 const CXXTempObjectRegion
*
1208 MemRegionManager::getCXXTempObjectRegion(Expr
const *E
,
1209 LocationContext
const *LC
) {
1210 const StackFrameContext
*SFC
= LC
->getStackFrame();
1212 return getSubRegion
<CXXTempObjectRegion
>(E
, getStackLocalsRegion(SFC
));
1215 const CXXLifetimeExtendedObjectRegion
*
1216 MemRegionManager::getCXXLifetimeExtendedObjectRegion(
1217 const Expr
*Ex
, const ValueDecl
*VD
, const LocationContext
*LC
) {
1218 const StackFrameContext
*SFC
= LC
->getStackFrame();
1220 return getSubRegion
<CXXLifetimeExtendedObjectRegion
>(
1221 Ex
, VD
, getStackLocalsRegion(SFC
));
1224 const CXXLifetimeExtendedObjectRegion
*
1225 MemRegionManager::getCXXStaticLifetimeExtendedObjectRegion(
1226 const Expr
*Ex
, const ValueDecl
*VD
) {
1227 return getSubRegion
<CXXLifetimeExtendedObjectRegion
>(
1229 getGlobalsRegion(MemRegion::GlobalInternalSpaceRegionKind
, nullptr));
1232 /// Checks whether \p BaseClass is a valid virtual or direct non-virtual base
1233 /// class of the type of \p Super.
1234 static bool isValidBaseClass(const CXXRecordDecl
*BaseClass
,
1235 const TypedValueRegion
*Super
,
1237 BaseClass
= BaseClass
->getCanonicalDecl();
1239 const CXXRecordDecl
*Class
= Super
->getValueType()->getAsCXXRecordDecl();
1244 return Class
->isVirtuallyDerivedFrom(BaseClass
);
1246 for (const auto &I
: Class
->bases()) {
1247 if (I
.getType()->getAsCXXRecordDecl()->getCanonicalDecl() == BaseClass
)
1254 const CXXBaseObjectRegion
*
1255 MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl
*RD
,
1256 const SubRegion
*Super
,
1258 if (isa
<TypedValueRegion
>(Super
)) {
1259 assert(isValidBaseClass(RD
, cast
<TypedValueRegion
>(Super
), IsVirtual
));
1260 (void)&isValidBaseClass
;
1263 // Virtual base regions should not be layered, since the layout rules
1265 while (const auto *Base
= dyn_cast
<CXXBaseObjectRegion
>(Super
))
1266 Super
= cast
<SubRegion
>(Base
->getSuperRegion());
1267 assert(Super
&& !isa
<MemSpaceRegion
>(Super
));
1271 return getSubRegion
<CXXBaseObjectRegion
>(RD
, IsVirtual
, Super
);
1274 const CXXDerivedObjectRegion
*
1275 MemRegionManager::getCXXDerivedObjectRegion(const CXXRecordDecl
*RD
,
1276 const SubRegion
*Super
) {
1277 return getSubRegion
<CXXDerivedObjectRegion
>(RD
, Super
);
1280 const CXXThisRegion
*
1281 MemRegionManager::getCXXThisRegion(QualType thisPointerTy
,
1282 const LocationContext
*LC
) {
1283 const auto *PT
= thisPointerTy
->getAs
<PointerType
>();
1285 // Inside the body of the operator() of a lambda a this expr might refer to an
1286 // object in one of the parent location contexts.
1287 const auto *D
= dyn_cast
<CXXMethodDecl
>(LC
->getDecl());
1288 // FIXME: when operator() of lambda is analyzed as a top level function and
1289 // 'this' refers to a this to the enclosing scope, there is no right region to
1291 while (!LC
->inTopFrame() && (!D
|| D
->isStatic() ||
1292 PT
!= D
->getThisType()->getAs
<PointerType
>())) {
1293 LC
= LC
->getParent();
1294 D
= dyn_cast
<CXXMethodDecl
>(LC
->getDecl());
1296 const StackFrameContext
*STC
= LC
->getStackFrame();
1298 return getSubRegion
<CXXThisRegion
>(PT
, getStackArgumentsRegion(STC
));
1302 MemRegionManager::getAllocaRegion(const Expr
*E
, unsigned cnt
,
1303 const LocationContext
*LC
) {
1304 const StackFrameContext
*STC
= LC
->getStackFrame();
1306 return getSubRegion
<AllocaRegion
>(E
, cnt
, getStackLocalsRegion(STC
));
1309 const MemSpaceRegion
*MemRegion::getMemorySpace() const {
1310 const MemRegion
*R
= this;
1311 const auto *SR
= dyn_cast
<SubRegion
>(this);
1314 R
= SR
->getSuperRegion();
1315 SR
= dyn_cast
<SubRegion
>(R
);
1318 return cast
<MemSpaceRegion
>(R
);
1321 bool MemRegion::hasStackStorage() const {
1322 return isa
<StackSpaceRegion
>(getMemorySpace());
1325 bool MemRegion::hasStackNonParametersStorage() const {
1326 return isa
<StackLocalsSpaceRegion
>(getMemorySpace());
1329 bool MemRegion::hasStackParametersStorage() const {
1330 return isa
<StackArgumentsSpaceRegion
>(getMemorySpace());
1333 // Strips away all elements and fields.
1334 // Returns the base region of them.
1335 const MemRegion
*MemRegion::getBaseRegion() const {
1336 const MemRegion
*R
= this;
1338 switch (R
->getKind()) {
1339 case MemRegion::ElementRegionKind
:
1340 case MemRegion::FieldRegionKind
:
1341 case MemRegion::ObjCIvarRegionKind
:
1342 case MemRegion::CXXBaseObjectRegionKind
:
1343 case MemRegion::CXXDerivedObjectRegionKind
:
1344 R
= cast
<SubRegion
>(R
)->getSuperRegion();
1354 // Returns the region of the root class of a C++ class hierarchy.
1355 const MemRegion
*MemRegion::getMostDerivedObjectRegion() const {
1356 const MemRegion
*R
= this;
1357 while (const auto *BR
= dyn_cast
<CXXBaseObjectRegion
>(R
))
1358 R
= BR
->getSuperRegion();
1362 bool MemRegion::isSubRegionOf(const MemRegion
*) const {
1366 //===----------------------------------------------------------------------===//
1368 //===----------------------------------------------------------------------===//
1370 const MemRegion
*MemRegion::StripCasts(bool StripBaseAndDerivedCasts
) const {
1371 const MemRegion
*R
= this;
1373 switch (R
->getKind()) {
1374 case ElementRegionKind
: {
1375 const auto *ER
= cast
<ElementRegion
>(R
);
1376 if (!ER
->getIndex().isZeroConstant())
1378 R
= ER
->getSuperRegion();
1381 case CXXBaseObjectRegionKind
:
1382 case CXXDerivedObjectRegionKind
:
1383 if (!StripBaseAndDerivedCasts
)
1385 R
= cast
<TypedValueRegion
>(R
)->getSuperRegion();
1393 const SymbolicRegion
*MemRegion::getSymbolicBase() const {
1394 const auto *SubR
= dyn_cast
<SubRegion
>(this);
1397 if (const auto *SymR
= dyn_cast
<SymbolicRegion
>(SubR
))
1399 SubR
= dyn_cast
<SubRegion
>(SubR
->getSuperRegion());
1404 RegionRawOffset
ElementRegion::getAsArrayOffset() const {
1406 const ElementRegion
*ER
= this;
1407 const MemRegion
*superR
= nullptr;
1408 ASTContext
&C
= getContext();
1410 // FIXME: Handle multi-dimensional arrays.
1413 superR
= ER
->getSuperRegion();
1415 // FIXME: generalize to symbolic offsets.
1416 SVal index
= ER
->getIndex();
1417 if (auto CI
= index
.getAs
<nonloc::ConcreteInt
>()) {
1418 // Update the offset.
1419 int64_t i
= CI
->getValue().getSExtValue();
1422 QualType elemType
= ER
->getElementType();
1424 // If we are pointing to an incomplete type, go no further.
1425 if (elemType
->isIncompleteType()) {
1430 int64_t size
= C
.getTypeSizeInChars(elemType
).getQuantity();
1431 if (auto NewOffset
= llvm::checkedMulAdd(i
, size
, offset
)) {
1432 offset
= *NewOffset
;
1434 LLVM_DEBUG(llvm::dbgs() << "MemRegion::getAsArrayOffset: "
1435 << "offset overflowing, returning unknown\n");
1441 // Go to the next ElementRegion (if any).
1442 ER
= dyn_cast
<ElementRegion
>(superR
);
1449 assert(superR
&& "super region cannot be NULL");
1450 return RegionRawOffset(superR
, CharUnits::fromQuantity(offset
));
1453 /// Returns true if \p Base is an immediate base class of \p Child
1454 static bool isImmediateBase(const CXXRecordDecl
*Child
,
1455 const CXXRecordDecl
*Base
) {
1456 assert(Child
&& "Child must not be null");
1457 // Note that we do NOT canonicalize the base class here, because
1458 // ASTRecordLayout doesn't either. If that leads us down the wrong path,
1459 // so be it; at least we won't crash.
1460 for (const auto &I
: Child
->bases()) {
1461 if (I
.getType()->getAsCXXRecordDecl() == Base
)
1468 static RegionOffset
calculateOffset(const MemRegion
*R
) {
1469 const MemRegion
*SymbolicOffsetBase
= nullptr;
1473 switch (R
->getKind()) {
1474 case MemRegion::CodeSpaceRegionKind
:
1475 case MemRegion::StackLocalsSpaceRegionKind
:
1476 case MemRegion::StackArgumentsSpaceRegionKind
:
1477 case MemRegion::HeapSpaceRegionKind
:
1478 case MemRegion::UnknownSpaceRegionKind
:
1479 case MemRegion::StaticGlobalSpaceRegionKind
:
1480 case MemRegion::GlobalInternalSpaceRegionKind
:
1481 case MemRegion::GlobalSystemSpaceRegionKind
:
1482 case MemRegion::GlobalImmutableSpaceRegionKind
:
1483 // Stores can bind directly to a region space to set a default value.
1484 assert(Offset
== 0 && !SymbolicOffsetBase
);
1487 case MemRegion::FunctionCodeRegionKind
:
1488 case MemRegion::BlockCodeRegionKind
:
1489 case MemRegion::BlockDataRegionKind
:
1490 // These will never have bindings, but may end up having values requested
1491 // if the user does some strange casting.
1493 SymbolicOffsetBase
= R
;
1496 case MemRegion::SymbolicRegionKind
:
1497 case MemRegion::AllocaRegionKind
:
1498 case MemRegion::CompoundLiteralRegionKind
:
1499 case MemRegion::CXXThisRegionKind
:
1500 case MemRegion::StringRegionKind
:
1501 case MemRegion::ObjCStringRegionKind
:
1502 case MemRegion::NonParamVarRegionKind
:
1503 case MemRegion::ParamVarRegionKind
:
1504 case MemRegion::CXXTempObjectRegionKind
:
1505 case MemRegion::CXXLifetimeExtendedObjectRegionKind
:
1506 // Usual base regions.
1509 case MemRegion::ObjCIvarRegionKind
:
1510 // This is a little strange, but it's a compromise between
1511 // ObjCIvarRegions having unknown compile-time offsets (when using the
1512 // non-fragile runtime) and yet still being distinct, non-overlapping
1513 // regions. Thus we treat them as "like" base regions for the purposes
1514 // of computing offsets.
1517 case MemRegion::CXXBaseObjectRegionKind
: {
1518 const auto *BOR
= cast
<CXXBaseObjectRegion
>(R
);
1519 R
= BOR
->getSuperRegion();
1522 bool RootIsSymbolic
= false;
1523 if (const auto *TVR
= dyn_cast
<TypedValueRegion
>(R
)) {
1524 Ty
= TVR
->getDesugaredValueType(R
->getContext());
1525 } else if (const auto *SR
= dyn_cast
<SymbolicRegion
>(R
)) {
1526 // If our base region is symbolic, we don't know what type it really is.
1527 // Pretend the type of the symbol is the true dynamic type.
1528 // (This will at least be self-consistent for the life of the symbol.)
1529 Ty
= SR
->getPointeeStaticType();
1530 RootIsSymbolic
= true;
1533 const CXXRecordDecl
*Child
= Ty
->getAsCXXRecordDecl();
1535 // We cannot compute the offset of the base class.
1536 SymbolicOffsetBase
= R
;
1538 if (RootIsSymbolic
) {
1539 // Base layers on symbolic regions may not be type-correct.
1540 // Double-check the inheritance here, and revert to a symbolic offset
1541 // if it's invalid (e.g. due to a reinterpret_cast).
1542 if (BOR
->isVirtual()) {
1543 if (!Child
->isVirtuallyDerivedFrom(BOR
->getDecl()))
1544 SymbolicOffsetBase
= R
;
1546 if (!isImmediateBase(Child
, BOR
->getDecl()))
1547 SymbolicOffsetBase
= R
;
1552 // Don't bother calculating precise offsets if we already have a
1553 // symbolic offset somewhere in the chain.
1554 if (SymbolicOffsetBase
)
1557 CharUnits BaseOffset
;
1558 const ASTRecordLayout
&Layout
= R
->getContext().getASTRecordLayout(Child
);
1559 if (BOR
->isVirtual())
1560 BaseOffset
= Layout
.getVBaseClassOffset(BOR
->getDecl());
1562 BaseOffset
= Layout
.getBaseClassOffset(BOR
->getDecl());
1564 // The base offset is in chars, not in bits.
1565 Offset
+= BaseOffset
.getQuantity() * R
->getContext().getCharWidth();
1569 case MemRegion::CXXDerivedObjectRegionKind
: {
1570 // TODO: Store the base type in the CXXDerivedObjectRegion and use it.
1574 case MemRegion::ElementRegionKind
: {
1575 const auto *ER
= cast
<ElementRegion
>(R
);
1576 R
= ER
->getSuperRegion();
1578 QualType EleTy
= ER
->getValueType();
1579 if (EleTy
->isIncompleteType()) {
1580 // We cannot compute the offset of the base class.
1581 SymbolicOffsetBase
= R
;
1585 SVal Index
= ER
->getIndex();
1586 if (std::optional
<nonloc::ConcreteInt
> CI
=
1587 Index
.getAs
<nonloc::ConcreteInt
>()) {
1588 // Don't bother calculating precise offsets if we already have a
1589 // symbolic offset somewhere in the chain.
1590 if (SymbolicOffsetBase
)
1593 int64_t i
= CI
->getValue().getSExtValue();
1594 // This type size is in bits.
1595 Offset
+= i
* R
->getContext().getTypeSize(EleTy
);
1597 // We cannot compute offset for non-concrete index.
1598 SymbolicOffsetBase
= R
;
1602 case MemRegion::FieldRegionKind
: {
1603 const auto *FR
= cast
<FieldRegion
>(R
);
1604 R
= FR
->getSuperRegion();
1607 const RecordDecl
*RD
= FR
->getDecl()->getParent();
1608 if (RD
->isUnion() || !RD
->isCompleteDefinition()) {
1609 // We cannot compute offset for incomplete type.
1610 // For unions, we could treat everything as offset 0, but we'd rather
1611 // treat each field as a symbolic offset so they aren't stored on top
1612 // of each other, since we depend on things in typed regions actually
1613 // matching their types.
1614 SymbolicOffsetBase
= R
;
1617 // Don't bother calculating precise offsets if we already have a
1618 // symbolic offset somewhere in the chain.
1619 if (SymbolicOffsetBase
)
1622 // Get the field number.
1624 for (RecordDecl::field_iterator FI
= RD
->field_begin(),
1625 FE
= RD
->field_end(); FI
!= FE
; ++FI
, ++idx
) {
1626 if (FR
->getDecl() == *FI
)
1629 const ASTRecordLayout
&Layout
= R
->getContext().getASTRecordLayout(RD
);
1630 // This is offset in bits.
1631 Offset
+= Layout
.getFieldOffset(idx
);
1638 if (SymbolicOffsetBase
)
1639 return RegionOffset(SymbolicOffsetBase
, RegionOffset::Symbolic
);
1640 return RegionOffset(R
, Offset
);
1643 RegionOffset
MemRegion::getAsOffset() const {
1645 cachedOffset
= calculateOffset(this);
1646 return *cachedOffset
;
1649 //===----------------------------------------------------------------------===//
1651 //===----------------------------------------------------------------------===//
1653 std::pair
<const VarRegion
*, const VarRegion
*>
1654 BlockDataRegion::getCaptureRegions(const VarDecl
*VD
) {
1655 MemRegionManager
&MemMgr
= getMemRegionManager();
1656 const VarRegion
*VR
= nullptr;
1657 const VarRegion
*OriginalVR
= nullptr;
1659 if (!VD
->hasAttr
<BlocksAttr
>() && VD
->hasLocalStorage()) {
1660 VR
= MemMgr
.getNonParamVarRegion(VD
, this);
1661 OriginalVR
= MemMgr
.getVarRegion(VD
, LC
);
1665 VR
= MemMgr
.getVarRegion(VD
, LC
);
1669 VR
= MemMgr
.getNonParamVarRegion(VD
, MemMgr
.getUnknownRegion());
1670 OriginalVR
= MemMgr
.getVarRegion(VD
, LC
);
1673 return std::make_pair(VR
, OriginalVR
);
1676 void BlockDataRegion::LazyInitializeReferencedVars() {
1680 AnalysisDeclContext
*AC
= getCodeRegion()->getAnalysisDeclContext();
1681 const auto &ReferencedBlockVars
= AC
->getReferencedBlockVars(BC
->getDecl());
1683 std::distance(ReferencedBlockVars
.begin(), ReferencedBlockVars
.end());
1685 if (NumBlockVars
== 0) {
1686 ReferencedVars
= (void*) 0x1;
1690 MemRegionManager
&MemMgr
= getMemRegionManager();
1691 llvm::BumpPtrAllocator
&A
= MemMgr
.getAllocator();
1692 BumpVectorContext
BC(A
);
1694 using VarVec
= BumpVector
<const MemRegion
*>;
1696 auto *BV
= new (A
) VarVec(BC
, NumBlockVars
);
1697 auto *BVOriginal
= new (A
) VarVec(BC
, NumBlockVars
);
1699 for (const auto *VD
: ReferencedBlockVars
) {
1700 const VarRegion
*VR
= nullptr;
1701 const VarRegion
*OriginalVR
= nullptr;
1702 std::tie(VR
, OriginalVR
) = getCaptureRegions(VD
);
1705 BV
->push_back(VR
, BC
);
1706 BVOriginal
->push_back(OriginalVR
, BC
);
1709 ReferencedVars
= BV
;
1710 OriginalVars
= BVOriginal
;
1713 BlockDataRegion::referenced_vars_iterator
1714 BlockDataRegion::referenced_vars_begin() const {
1715 const_cast<BlockDataRegion
*>(this)->LazyInitializeReferencedVars();
1717 auto *Vec
= static_cast<BumpVector
<const MemRegion
*> *>(ReferencedVars
);
1719 if (Vec
== (void*) 0x1)
1720 return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr);
1723 static_cast<BumpVector
<const MemRegion
*> *>(OriginalVars
);
1725 return BlockDataRegion::referenced_vars_iterator(Vec
->begin(),
1726 VecOriginal
->begin());
1729 BlockDataRegion::referenced_vars_iterator
1730 BlockDataRegion::referenced_vars_end() const {
1731 const_cast<BlockDataRegion
*>(this)->LazyInitializeReferencedVars();
1733 auto *Vec
= static_cast<BumpVector
<const MemRegion
*> *>(ReferencedVars
);
1735 if (Vec
== (void*) 0x1)
1736 return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr);
1739 static_cast<BumpVector
<const MemRegion
*> *>(OriginalVars
);
1741 return BlockDataRegion::referenced_vars_iterator(Vec
->end(),
1742 VecOriginal
->end());
1745 llvm::iterator_range
<BlockDataRegion::referenced_vars_iterator
>
1746 BlockDataRegion::referenced_vars() const {
1747 return llvm::make_range(referenced_vars_begin(), referenced_vars_end());
1750 const VarRegion
*BlockDataRegion::getOriginalRegion(const VarRegion
*R
) const {
1751 for (const auto &I
: referenced_vars()) {
1752 if (I
.getCapturedRegion() == R
)
1753 return I
.getOriginalRegion();
1758 //===----------------------------------------------------------------------===//
1759 // RegionAndSymbolInvalidationTraits
1760 //===----------------------------------------------------------------------===//
1762 void RegionAndSymbolInvalidationTraits::setTrait(SymbolRef Sym
,
1763 InvalidationKinds IK
) {
1764 SymTraitsMap
[Sym
] |= IK
;
1767 void RegionAndSymbolInvalidationTraits::setTrait(const MemRegion
*MR
,
1768 InvalidationKinds IK
) {
1770 if (const auto *SR
= dyn_cast
<SymbolicRegion
>(MR
))
1771 setTrait(SR
->getSymbol(), IK
);
1773 MRTraitsMap
[MR
] |= IK
;
1776 bool RegionAndSymbolInvalidationTraits::hasTrait(SymbolRef Sym
,
1777 InvalidationKinds IK
) const {
1778 const_symbol_iterator I
= SymTraitsMap
.find(Sym
);
1779 if (I
!= SymTraitsMap
.end())
1780 return I
->second
& IK
;
1785 bool RegionAndSymbolInvalidationTraits::hasTrait(const MemRegion
*MR
,
1786 InvalidationKinds IK
) const {
1790 if (const auto *SR
= dyn_cast
<SymbolicRegion
>(MR
))
1791 return hasTrait(SR
->getSymbol(), IK
);
1793 const_region_iterator I
= MRTraitsMap
.find(MR
);
1794 if (I
!= MRTraitsMap
.end())
1795 return I
->second
& IK
;