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"
60#define DEBUG_TYPE "MemRegion"
69[[maybe_unused]]
static bool isAReferenceTypedValueRegion(
const MemRegion *R) {
70 const auto *TyReg = llvm::dyn_cast<TypedValueRegion>(R);
71 return TyReg && TyReg->getValueType()->isReferenceType();
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 llvm::FoldingSetInsertToken InsertToken;
80 auto *
R = cast_or_null<RegionTy>(Regions.lookup(ID, InsertToken));
83 R =
new (A) RegionTy(arg1, superRegion);
84 Regions.insert(R, InsertToken);
85 assert(!isAReferenceTypedValueRegion(superRegion));
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 llvm::FoldingSetInsertToken InsertToken;
97 auto *
R = cast_or_null<RegionTy>(Regions.lookup(ID, InsertToken));
100 R =
new (A) RegionTy(arg1, arg2, superRegion);
101 Regions.insert(R, InsertToken);
102 assert(!isAReferenceTypedValueRegion(superRegion));
108template <
typename RegionTy,
typename SuperTy,
109 typename Arg1Ty,
typename Arg2Ty,
typename Arg3Ty>
110RegionTy* MemRegionManager::getSubRegion(
const Arg1Ty arg1,
const Arg2Ty arg2,
112 const SuperTy *superRegion) {
113 llvm::FoldingSetNodeID
ID;
114 RegionTy::ProfileRegion(ID, arg1, arg2, arg3, superRegion);
115 llvm::FoldingSetInsertToken InsertToken;
116 auto *
R = cast_or_null<RegionTy>(Regions.lookup(ID, InsertToken));
119 R =
new (A) RegionTy(arg1, arg2, arg3, superRegion);
120 Regions.insert(R, InsertToken);
121 assert(!isAReferenceTypedValueRegion(superRegion));
146 if (
const auto *sr = dyn_cast<SubRegion>(r))
147 r = sr->getSuperRegion();
150 }
while (r !=
nullptr);
158 if (
const auto *sr = dyn_cast<SubRegion>(
superRegion)) {
168 return SSR ? SSR->getStackFrame() :
nullptr;
173 return SSR ? SSR->getStackFrame() :
nullptr;
178 "A temporary object can only be allocated on the stack");
183 :
DeclRegion(sReg, ObjCIvarRegionKind), IVD(ivd) {
203 "`ParamVarRegion` support functions without `Decl` not implemented"
210 if (
const auto *FD = dyn_cast<FunctionDecl>(D)) {
211 assert(Index < FD->param_size());
212 return FD->parameters()[Index];
214 if (
const auto *BD = dyn_cast<BlockDecl>(D)) {
215 assert(Index < BD->param_size());
216 return BD->parameters()[Index];
218 if (
const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
219 assert(Index < MD->param_size());
220 return MD->parameters()[Index];
222 if (
const auto *CD = dyn_cast<CXXConstructorDecl>(D)) {
223 assert(Index < CD->param_size());
224 return CD->parameters()[Index];
226 llvm_unreachable(
"Unexpected Decl kind!");
234 ID.AddInteger(
static_cast<unsigned>(
getKind()));
238 ID.AddInteger(
static_cast<unsigned>(
getKind()));
243 ID.AddInteger(
static_cast<unsigned>(
getKind()));
247void StringRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
250 ID.AddInteger(
static_cast<unsigned>(StringRegionKind));
255void ObjCStringRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
258 ID.AddInteger(
static_cast<unsigned>(ObjCStringRegionKind));
263void AllocaRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
264 const Expr *Ex,
unsigned cnt,
266 ID.AddInteger(
static_cast<unsigned>(AllocaRegionKind));
280void CompoundLiteralRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
283 ID.AddInteger(
static_cast<unsigned>(CompoundLiteralRegionKind));
288void CXXThisRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
291 ID.AddInteger(
static_cast<unsigned>(CXXThisRegionKind));
293 ID.AddPointer(sRegion);
297 CXXThisRegion::ProfileRegion(ID, ThisPointerTy,
superRegion);
304void ObjCIvarRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
307 ID.AddInteger(
static_cast<unsigned>(ObjCIvarRegionKind));
316void NonParamVarRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
319 ID.AddInteger(
static_cast<unsigned>(NonParamVarRegionKind));
328void ParamVarRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
const Expr *OE,
330 ID.AddInteger(
static_cast<unsigned>(ParamVarRegionKind));
342 ID.AddInteger(
static_cast<unsigned>(MemRegion::SymbolicRegionKind));
351void ElementRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
354 ID.AddInteger(MemRegion::ElementRegionKind);
361 ElementRegion::ProfileRegion(ID, ElementType, Index,
superRegion);
364void FunctionCodeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
367 ID.AddInteger(MemRegion::FunctionCodeRegionKind);
372 FunctionCodeRegion::ProfileRegion(ID, FD,
superRegion);
375void BlockCodeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
379 ID.AddInteger(MemRegion::BlockCodeRegionKind);
384 BlockCodeRegion::ProfileRegion(ID, BD, locTy, AC,
superRegion);
387void BlockDataRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
391 ID.AddInteger(MemRegion::BlockDataRegionKind);
394 ID.AddInteger(BlkCount);
399 BlockDataRegion::ProfileRegion(ID, BC, SF, BlockCount,
getSuperRegion());
402void CXXTempObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
413void CXXLifetimeExtendedObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
423 llvm::FoldingSetNodeID &ID)
const {
427void CXXBaseObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
432 ID.AddBoolean(IsVirtual);
440void CXXDerivedObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
455void GlobalsSpaceRegion::anchor() {}
457void NonStaticGlobalSpaceRegion::anchor() {}
459void StackSpaceRegion::anchor() {}
461void TypedRegion::anchor() {}
463void TypedValueRegion::anchor() {}
465void CodeTextRegion::anchor() {}
467void SubRegion::anchor() {}
479 llvm::raw_string_ostream os(s);
485 os <<
"<Unknown Region>";
489 os <<
"alloca{S" << Ex->getID(
getContext()) <<
',' << Cnt <<
'}';
497 os <<
"block_code{" <<
static_cast<const void *
>(
this) <<
'}';
501 os <<
"block_data{" << BC;
504 os <<
"(" << Var.getCapturedRegion() <<
"<-" << Var.getOriginalRegion()
520 os <<
"lifetime_extended_object{" <<
getValueType() <<
", ";
524 os <<
"D" << ExD->getID();
555 assert(Str !=
nullptr &&
"Expecting non-null StringLiteral");
560 assert(Str !=
nullptr &&
"Expecting non-null ObjCStringLiteral");
567 os <<
"SymRegion{" << sym <<
'}';
574 os <<
"NonParamVarRegion{D" << VD->getID() <<
'}';
586 os <<
"CodeSpaceRegion";
590 os <<
"StaticGlobalsMemSpace{" << CR <<
'}';
594 os <<
"GlobalInternalSpaceRegion";
598 os <<
"GlobalSystemSpaceRegion";
602 os <<
"GlobalImmutableSpaceRegion";
606 os <<
"HeapSpaceRegion";
610 os <<
"UnknownSpaceRegion";
614 os <<
"StackArgumentsSpaceRegion";
618 os <<
"StackLocalsSpaceRegion";
624 "`ParamVarRegion` support functions without `Decl` not implemented"
629 os <<
"ParamVarRegion{P" << PVD->
getID() <<
'}';
643#define REGION(Id, Parent) \
646#include "clang/StaticAnalyzer/Core/PathSensitive/Regions.def"
649 llvm_unreachable(
"Unkown kind!");
653 assert(
canPrintPretty() &&
"This region cannot be printed pretty.");
660 llvm_unreachable(
"This region cannot be printed pretty.");
673 "`ParamVarRegion` support functions without `Decl` not implemented"
727 bool AllowFallback)
const {
728 std::string ArrayIndices;
731 llvm::raw_svector_ostream os(buf);
734 auto QuoteIfNeeded = [UseQuotes](
const Twine &Subject) -> std::string {
736 return (
"'" + Subject +
"'").str();
737 return Subject.str();
740 auto FallbackName = [
this, AllowFallback]() -> std::string {
745 if (StringRef Name = FR->getDecl()->getName(); !Name.empty())
746 return (llvm::Twine(
"the field '") + Name +
"'").str();
747 return "the unnamed field";
751 return "the memory returned by 'alloca'";
754 return "the heap area";
757 return "the string literal";
768 CI->getValue()->toString(Idx);
769 ArrayIndices = (llvm::Twine(
"[") + Idx.str() +
"]" + ArrayIndices).str();
775 return FallbackName();
777 const MemRegion *OR = SI->getAsSymbol()->getOriginRegion();
779 return FallbackName();
783 return FallbackName();
785 ArrayIndices = (llvm::Twine(
"[") + Idx +
"]" + ArrayIndices).str();
793 if (R->canPrintPrettyAsExpr()) {
794 R->printPrettyAsExpr(os);
795 return QuoteIfNeeded(llvm::Twine(os.str()) + ArrayIndices);
800 std::string Super = FR->getSuperRegion()->getDescriptiveName(
false);
802 return FallbackName();
803 return QuoteIfNeeded(Super +
"." + FR->getDecl()->getName());
807 return FallbackName();
812 if (
auto *FR = dyn_cast<FieldRegion>(
this)) {
813 return FR->getDecl()->getSourceRange();
817 return VR->getDecl()->getSourceRange();
833 switch (SR->getKind()) {
834 case MemRegion::AllocaRegionKind:
835 case MemRegion::SymbolicRegionKind:
837 case MemRegion::StringRegionKind:
841 case MemRegion::CompoundLiteralRegionKind:
842 case MemRegion::CXXBaseObjectRegionKind:
843 case MemRegion::CXXDerivedObjectRegionKind:
844 case MemRegion::CXXTempObjectRegionKind:
845 case MemRegion::CXXLifetimeExtendedObjectRegionKind:
846 case MemRegion::CXXThisRegionKind:
847 case MemRegion::ObjCIvarRegionKind:
848 case MemRegion::NonParamVarRegionKind:
849 case MemRegion::ParamVarRegionKind:
850 case MemRegion::ElementRegionKind:
851 case MemRegion::ObjCStringRegionKind: {
861 case MemRegion::FieldRegionKind: {
874 const auto isFlexibleArrayMemberCandidate =
879 auto IsIncompleteArray = [](
const ArrayType *AT) {
882 auto IsArrayOfZero = [](
const ArrayType *AT) {
883 const auto *CAT = dyn_cast<ConstantArrayType>(AT);
884 return CAT && CAT->isZeroSize();
886 auto IsArrayOfOne = [](
const ArrayType *AT) {
887 const auto *CAT = dyn_cast<ConstantArrayType>(AT);
888 return CAT && CAT->getSize() == 1;
892 const FAMKind StrictFlexArraysLevel =
893 Ctx.getLangOpts().getStrictFlexArraysLevel();
898 if (StrictFlexArraysLevel == FAMKind::Default)
899 return IsArrayOfOne(AT) || IsArrayOfZero(AT) || IsIncompleteArray(AT);
901 if (StrictFlexArraysLevel == FAMKind::OneZeroOrIncomplete)
902 return IsArrayOfOne(AT) || IsArrayOfZero(AT) || IsIncompleteArray(AT);
904 if (StrictFlexArraysLevel == FAMKind::ZeroOrIncomplete)
905 return IsArrayOfZero(AT) || IsIncompleteArray(AT);
907 assert(StrictFlexArraysLevel == FAMKind::IncompleteOnly);
908 return IsIncompleteArray(AT);
911 if (isFlexibleArrayMemberCandidate(Ctx.getAsArrayType(Ty)))
918 case MemRegion::BlockDataRegionKind:
919 case MemRegion::BlockCodeRegionKind:
920 case MemRegion::FunctionCodeRegionKind:
923 llvm_unreachable(
"Unhandled region");
927template <
typename REG>
928const REG *MemRegionManager::LazyAllocate(REG*& region) {
930 region =
new (A) REG(*
this);
935template <
typename REG,
typename ARG>
936const REG *MemRegionManager::LazyAllocate(REG*& region, ARG a) {
938 region =
new (A) REG(
this, a);
971 if (K == MemRegion::GlobalSystemSpaceRegionKind)
972 return LazyAllocate(SystemGlobals);
973 if (K == MemRegion::GlobalImmutableSpaceRegionKind)
974 return LazyAllocate(ImmutableGlobals);
975 assert(K == MemRegion::GlobalInternalSpaceRegionKind);
976 return LazyAllocate(InternalGlobals);
979 assert(K == MemRegion::StaticGlobalSpaceRegionKind);
989 return LazyAllocate(heap);
993 return LazyAllocate(unknown);
997 return LazyAllocate(code);
1005 return getSubRegion<StringRegion>(
1011 return getSubRegion<ObjCStringRegion>(
1018static llvm::PointerUnion<const StackFrame *, const VarRegion *>
1026 if (Frame.getData()) {
1031 if (
const auto *VR = dyn_cast<VarRegion>(OrigR)) {
1032 if (VR->getDecl() == VD)
1054 (N ==
"stdin" || N ==
"stdout" || N ==
"stderr");
1060 const auto *PVD = dyn_cast<ParmVarDecl>(D);
1062 unsigned Index = PVD->getFunctionScopeIndex();
1066 bool CurrentParam =
true;
1067 if (
const auto *FD = dyn_cast<FunctionDecl>(CalleeDecl)) {
1069 (Index < FD->param_size() && FD->getParamDecl(Index) == PVD);
1070 }
else if (
const auto *BD = dyn_cast<BlockDecl>(CalleeDecl)) {
1078 return getSubRegion<ParamVarRegion>(CallSite, Index,
1114 if (Ctx.getSourceManager().isInSystemHeader(D->
getLocation()) &&
1127 llvm::PointerUnion<const StackFrame *, const VarRegion *>
V =
1130 if (
const auto *VR = dyn_cast_if_present<const VarRegion *>(
V))
1151 else if (
const auto *BD = dyn_cast<BlockDecl>(STCD)) {
1189 return getSubRegion<NonParamVarRegion>(D, superR);
1196 return getSubRegion<ParamVarRegion>(OriginExpr, Index,
1209 bool IsArcManagedBlock = Ctx.getLangOpts().ObjCAutoRefCount;
1214 if (!IsArcManagedBlock && SF) {
1226 return getSubRegion<BlockDataRegion>(BC, SF, blockCount, sReg);
1234 if (
CL->isFileScope()) {
1241 return getSubRegion<CompoundLiteralRegion>(
CL, sReg);
1248 QualType T = Ctx.getCanonicalType(elementType).getUnqualifiedType();
1257 T = Ctx.getQualifiedType(
T, Quals);
1260 llvm::FoldingSetNodeID ID;
1261 ElementRegion::ProfileRegion(ID,
T, Idx, superRegion);
1263 llvm::FoldingSetInsertToken InsertToken;
1264 MemRegion *data = Regions.lookup(ID, InsertToken);
1265 auto *R = cast_or_null<ElementRegion>(data);
1269 Regions.insert(R, InsertToken);
1278 return getSubRegion<FunctionCodeRegion>(FD,
getCodeRegion());
1284 return getSubRegion<BlockCodeRegion>(BD, locTy, AC,
getCodeRegion());
1290 if (MemSpace ==
nullptr)
1292 return getSubRegion<SymbolicRegion>(sym, MemSpace);
1308 return getSubRegion<ObjCIvarRegion>(d, superRegion);
1322 return getSubRegion<CXXLifetimeExtendedObjectRegion>(
1329 return getSubRegion<CXXLifetimeExtendedObjectRegion>(
1339 BaseClass = BaseClass->getCanonicalDecl();
1348 for (
const auto &I : Class->bases()) {
1349 if (I.getType()->getAsCXXRecordDecl()->getCanonicalDecl() == BaseClass)
1367 while (
const auto *
Base = dyn_cast<CXXBaseObjectRegion>(Super))
1373 return getSubRegion<CXXBaseObjectRegion>(RD, IsVirtual, Super);
1379 return getSubRegion<CXXDerivedObjectRegion>(RD, Super);
1388 const auto *D = dyn_cast<CXXMethodDecl>(SF->
getDecl());
1392 while (!SF->
inTopFrame() && (!D || D->isStatic() ||
1395 D = dyn_cast<CXXMethodDecl>(SF->
getDecl());
1410 const auto *SR = dyn_cast<SubRegion>(
this);
1413 R = SR->getSuperRegion();
1414 SR = dyn_cast<SubRegion>(R);
1427 const MemSpaceRegion *
const *AssociatedSpace = State->get<MemSpacesMap>(MR);
1428 return AssociatedSpace ? *AssociatedSpace : RawSpace;
1440 return State->set<MemSpacesMap>(
Base, Space);
1448 switch (R->getKind()) {
1449 case MemRegion::ElementRegionKind:
1450 case MemRegion::FieldRegionKind:
1451 case MemRegion::ObjCIvarRegionKind:
1452 case MemRegion::CXXBaseObjectRegionKind:
1453 case MemRegion::CXXDerivedObjectRegionKind:
1467 while (
const auto *BR = dyn_cast<CXXBaseObjectRegion>(R))
1468 R = BR->getSuperRegion();
1483 switch (R->getKind()) {
1484 case ElementRegionKind: {
1486 if (!ER->getIndex().isZeroConstant())
1488 R = ER->getSuperRegion();
1491 case CXXBaseObjectRegionKind:
1492 case CXXDerivedObjectRegionKind:
1493 if (!StripBaseAndDerivedCasts)
1504 const auto *SubR = dyn_cast<SubRegion>(
this);
1507 if (
const auto *SymR = dyn_cast<SymbolicRegion>(SubR))
1509 SubR = dyn_cast<SubRegion>(SubR->getSuperRegion());
1516 const ElementRegion *ER =
this;
1529 if (int64_t i = CI->getValue()->getSExtValue(); i != 0) {
1538 int64_t size =
C.getTypeSizeInChars(elemType).getQuantity();
1539 if (
auto NewOffset = llvm::checkedMulAdd(i, size, offset)) {
1540 offset = *NewOffset;
1542 LLVM_DEBUG(llvm::dbgs() <<
"MemRegion::getAsArrayOffset: "
1543 <<
"offset overflowing, returning unknown\n");
1550 ER = dyn_cast<ElementRegion>(superR);
1557 assert(superR &&
"super region cannot be NULL");
1564 assert(Child &&
"Child must not be null");
1568 for (
const auto &I : Child->bases()) {
1569 if (I.getType()->getAsCXXRecordDecl() ==
Base)
1577 const MemRegion *SymbolicOffsetBase =
nullptr;
1581 switch (R->getKind()) {
1582 case MemRegion::CodeSpaceRegionKind:
1583 case MemRegion::StackLocalsSpaceRegionKind:
1584 case MemRegion::StackArgumentsSpaceRegionKind:
1585 case MemRegion::HeapSpaceRegionKind:
1586 case MemRegion::UnknownSpaceRegionKind:
1587 case MemRegion::StaticGlobalSpaceRegionKind:
1588 case MemRegion::GlobalInternalSpaceRegionKind:
1589 case MemRegion::GlobalSystemSpaceRegionKind:
1590 case MemRegion::GlobalImmutableSpaceRegionKind:
1592 assert(Offset == 0 && !SymbolicOffsetBase);
1595 case MemRegion::FunctionCodeRegionKind:
1596 case MemRegion::BlockCodeRegionKind:
1597 case MemRegion::BlockDataRegionKind:
1601 SymbolicOffsetBase = R;
1604 case MemRegion::SymbolicRegionKind:
1605 case MemRegion::AllocaRegionKind:
1606 case MemRegion::CompoundLiteralRegionKind:
1607 case MemRegion::CXXThisRegionKind:
1608 case MemRegion::StringRegionKind:
1609 case MemRegion::ObjCStringRegionKind:
1610 case MemRegion::NonParamVarRegionKind:
1611 case MemRegion::ParamVarRegionKind:
1612 case MemRegion::CXXTempObjectRegionKind:
1613 case MemRegion::CXXLifetimeExtendedObjectRegionKind:
1617 case MemRegion::ObjCIvarRegionKind:
1625 case MemRegion::CXXBaseObjectRegionKind: {
1627 R = BOR->getSuperRegion();
1630 bool RootIsSymbolic =
false;
1631 if (
const auto *TVR = dyn_cast<TypedValueRegion>(R)) {
1632 Ty = TVR->getDesugaredValueType(R->getContext());
1633 }
else if (
const auto *SR = dyn_cast<SymbolicRegion>(R)) {
1637 Ty = SR->getPointeeStaticType();
1638 RootIsSymbolic =
true;
1644 SymbolicOffsetBase = R;
1646 if (RootIsSymbolic) {
1650 if (BOR->isVirtual()) {
1651 if (!Child->isVirtuallyDerivedFrom(BOR->getDecl()))
1652 SymbolicOffsetBase = R;
1655 SymbolicOffsetBase = R;
1662 if (SymbolicOffsetBase)
1666 const ASTRecordLayout &Layout = R->getContext().getASTRecordLayout(Child);
1667 if (BOR->isVirtual())
1673 Offset += BaseOffset.
getQuantity() * R->getContext().getCharWidth();
1677 case MemRegion::CXXDerivedObjectRegionKind: {
1682 case MemRegion::ElementRegionKind: {
1684 R = ER->getSuperRegion();
1686 QualType EleTy = ER->getValueType();
1689 SymbolicOffsetBase = R;
1693 SVal Index = ER->getIndex();
1694 if (std::optional<nonloc::ConcreteInt> CI =
1698 if (SymbolicOffsetBase)
1701 int64_t i = CI->getValue()->getSExtValue();
1703 Offset += i * R->getContext().getTypeSize(EleTy);
1706 SymbolicOffsetBase = R;
1710 case MemRegion::FieldRegionKind: {
1712 R = FR->getSuperRegion();
1722 SymbolicOffsetBase = R;
1727 if (SymbolicOffsetBase)
1730 assert(FR->getDecl()->getCanonicalDecl() == FR->getDecl());
1731 auto MaybeFieldIdx = [FR, RD]() -> std::optional<unsigned> {
1732 for (
auto [Idx, Field] : llvm::enumerate(RD->
fields())) {
1733 if (FR->getDecl() == Field->getCanonicalDecl())
1736 return std::nullopt;
1739 if (!MaybeFieldIdx.has_value()) {
1740 assert(
false &&
"Field not found");
1744 const ASTRecordLayout &Layout = R->getContext().getASTRecordLayout(RD);
1753 if (SymbolicOffsetBase)
1761 return *cachedOffset;
1768std::pair<const VarRegion *, const VarRegion *>
1769BlockDataRegion::getCaptureRegions(
const VarDecl *VD) {
1787 return std::make_pair(VR, OriginalVR);
1790void BlockDataRegion::LazyInitializeReferencedVars() {
1797 std::distance(ReferencedBlockVars.begin(), ReferencedBlockVars.end());
1799 if (NumBlockVars == 0) {
1800 ReferencedVars = (
void*) 0x1;
1806 BumpVectorContext BC(A);
1808 using VarVec = BumpVector<const MemRegion *>;
1810 auto *BV =
new (A) VarVec(BC, NumBlockVars);
1811 auto *BVOriginal =
new (A) VarVec(BC, NumBlockVars);
1813 for (
const auto *VD : ReferencedBlockVars) {
1814 const VarRegion *VR =
nullptr;
1815 const VarRegion *OriginalVR =
nullptr;
1816 std::tie(VR, OriginalVR) = getCaptureRegions(VD);
1819 BV->push_back(VR, BC);
1820 BVOriginal->push_back(OriginalVR, BC);
1823 ReferencedVars = BV;
1824 OriginalVars = BVOriginal;
1829 const_cast<BlockDataRegion*
>(
this)->LazyInitializeReferencedVars();
1833 if (Vec == (
void*) 0x1)
1840 VecOriginal->begin());
1845 const_cast<BlockDataRegion*
>(
this)->LazyInitializeReferencedVars();
1849 if (Vec == (
void*) 0x1)
1856 VecOriginal->end());
1859llvm::iterator_range<BlockDataRegion::referenced_vars_iterator>
1866 if (I.getCapturedRegion() == R)
1867 return I.getOriginalRegion();
1878 SymTraitsMap[Sym] |= IK;
1884 if (
const auto *SR = dyn_cast<SymbolicRegion>(MR))
1887 MRTraitsMap[MR] |= IK;
1892 const_symbol_iterator I = SymTraitsMap.find(Sym);
1893 if (I != SymTraitsMap.end())
1894 return I->second & IK;
1904 if (
const auto *SR = dyn_cast<SymbolicRegion>(MR))
1905 return hasTrait(SR->getSymbol(), IK);
1907 const_region_iterator I = MRTraitsMap.find(MR);
1908 if (I != MRTraitsMap.end())
1909 return I->second & IK;
Defines the clang::ASTContext interface.
This file defines AnalysisDeclContext, a class that manages the analysis context data for context sen...
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
static bool isStdStreamVar(const VarDecl *D)
static llvm::PointerUnion< const StackFrame *, const VarRegion * > getStackOrCaptureRegionForDeclContext(const StackFrame *SF, const DeclContext *DC, const VarDecl *VD)
Look through a chain of StackFrames to either find the StackFrame that matches a DeclContext,...
static bool isImmediateBase(const CXXRecordDecl *Child, const CXXRecordDecl *Base)
Returns true if Base is an immediate base class of Child.
static bool isValidBaseClass(const CXXRecordDecl *BaseClass, const TypedValueRegion *Super, bool IsVirtual)
Checks whether BaseClass is a valid virtual or direct non-virtual base class of the type of Super.
static RegionOffset calculateOffset(const MemRegion *R)
#define REGISTER_MAP_WITH_PROGRAMSTATE(Name, Key, Value)
Declares an immutable map of type NameTy, suitable for placement into the ProgramState.
Defines the SourceManager interface.
C Language Family Type Representation.
static bool hasLayout(const RecordDecl *D)
Whether layout (offset and size) information can be queried for D.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
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.
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.
Represents a block literal declaration, which is like an unnamed FunctionDecl.
size_t param_size() const
bool hasCaptures() const
True if this block (or its nested blocks) captures anything of local storage from its enclosing scope...
const ParmVarDecl * getParamDecl(unsigned i) const
TypeSourceInfo * getSignatureAsWritten() const
Represents a C++ struct/union/class.
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.
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
CompoundLiteralExpr - [C99 6.5.2.5].
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
bool isTranslationUnit() const
Decl - This represents one declaration (or definition), e.g.
ASTContext & getASTContext() const LLVM_READONLY
SourceLocation getLocation() const
DeclContext * getDeclContext()
std::string getAsString() const
Retrieve the human-readable string for this name.
This represents one expression.
Represents a member of a struct/union/class.
FieldDecl * getCanonicalDecl() override
Retrieves the canonical declaration of this field.
FunctionType - C99 6.7.5.3 - Function Declarators.
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
StrictFlexArraysLevelKind
This represents a decl that may have a name.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
ObjCIvarDecl - Represents an ObjC instance variable.
ObjCStringLiteral, used for Objective-C string literals i.e.
Represents a parameter to a function.
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
LangAS getAddressSpace() const
Return the address space of this type.
QualType getCanonicalType() const
bool isConstQualified() const
Determine whether this type is const-qualified.
The collection of all-type qualifiers we support.
void setAddressSpace(LangAS space)
Represents a struct/union/class.
field_range fields() const
A trivial tuple used to represent a source range.
It represents a stack frame of the call stack.
LLVM_ATTRIBUTE_RETURNS_NONNULL AnalysisDeclContext * getAnalysisDeclContext() const
const Expr * getCallSite() const
const Decl * getDecl() const
const StackFrame * getParent() const
It might return null.
llvm::iterator_range< parent_iterator > parentsIncludingSelf() const
Iterates over this frame followed by all of its ancestors.
StringLiteral - This represents a string literal expression, e.g.
A container of type source information.
bool isFunctionReferenceType() const
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isPointerType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
const T * getAs() const
Member-template getAs<specific type>'.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Represents a variable declaration or definition.
VarDecl * getCanonicalDecl() override
Retrieves the "canonical" declaration of the given declaration.
bool hasGlobalStorage() const
Returns true for all variables that do not have local storage.
VarDecl * getDefinition(ASTContext &)
Get the real (not just tentative) definition for this declaration.
bool isStaticLocal() const
Returns true if a variable with function scope is a static local variable.
bool hasLocalStorage() const
Returns true if a variable with function scope is a non-static local variable.
AllocaRegion - A region that represents an untyped blob of bytes created by a call to 'alloca'.
void dumpToStream(raw_ostream &os) const override
void Profile(llvm::FoldingSetNodeID &ID) const override
BlockCodeRegion - A region that represents code texts of blocks (closures).
LLVM_ATTRIBUTE_RETURNS_NONNULL AnalysisDeclContext * getAnalysisDeclContext() const
void dumpToStream(raw_ostream &os) const override
LLVM_ATTRIBUTE_RETURNS_NONNULL const BlockDecl * getDecl() const
void Profile(llvm::FoldingSetNodeID &ID) const override
BlockDataRegion - A region that represents a block instance.
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
void Profile(llvm::FoldingSetNodeID &ID) const override
referenced_vars_iterator referenced_vars_end() const
void dumpToStream(raw_ostream &os) const override
friend class MemRegionManager
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
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
void Profile(llvm::FoldingSetNodeID &ID) const override
const StackFrame * getStackFrame() const
It might return null.
void dumpToStream(raw_ostream &os) const override
QualType getValueType() const override
QualType getValueType() const override
LLVM_ATTRIBUTE_RETURNS_NONNULL const StackFrame * getStackFrame() const
void Profile(llvm::FoldingSetNodeID &ID) const override
void dumpToStream(raw_ostream &os) const override
CXXThisRegion - Represents the region for the implicit 'this' parameter in a call to a C++ method.
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.
void dumpToStream(raw_ostream &os) const override
CompoundLiteralRegion - A memory region representing a compound literal.
void Profile(llvm::FoldingSetNodeID &ID) const override
void dumpToStream(raw_ostream &os) const override
ElementRegion is used to represent both array elements and casts.
QualType getElementType() const
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
FunctionCodeRegion - A region that represents code texts of function.
const NamedDecl * getDecl() const
void dumpToStream(raw_ostream &os) const override
void Profile(llvm::FoldingSetNodeID &ID) const override
void dumpToStream(raw_ostream &os) const override
void dumpToStream(raw_ostream &os) const override
void dumpToStream(raw_ostream &os) const override
void dumpToStream(raw_ostream &os) const override
const HeapSpaceRegion * getHeapRegion()
getHeapRegion - Retrieve the memory region associated with the generic "heap".
llvm::BumpPtrAllocator & getAllocator()
const StackLocalsSpaceRegion * getStackLocalsRegion(const StackFrame *SF)
getStackLocalsRegion - Retrieve the memory region associated with the specified stack frame.
const FieldRegion * getFieldRegion(const FieldDecl *FD, const SubRegion *SuperRegion)
getFieldRegion - Retrieve or create the memory region associated with a specified FieldDecl.
const ParamVarRegion * getParamVarRegion(const Expr *OriginExpr, unsigned Index, const StackFrame *SF)
getParamVarRegion - Retrieve or create the memory region associated with a specified CallExpr,...
const StackArgumentsSpaceRegion * getStackArgumentsRegion(const StackFrame *SF)
getStackArgumentsRegion - Retrieve the memory region associated with function/method arguments of the...
const BlockCodeRegion * getBlockCodeRegion(const BlockDecl *BD, CanQualType locTy, AnalysisDeclContext *AC)
const UnknownSpaceRegion * getUnknownRegion()
getUnknownRegion - Retrieve the memory region associated with unknown memory space.
const CXXDerivedObjectRegion * getCXXDerivedObjectRegion(const CXXRecordDecl *BaseClass, const SubRegion *Super)
Create a CXXDerivedObjectRegion with the given derived class for region Super.
const CXXLifetimeExtendedObjectRegion * getCXXLifetimeExtendedObjectRegion(Expr const *Ex, ValueDecl const *VD, StackFrame const *SF)
Create a CXXLifetimeExtendedObjectRegion for temporaries which are lifetime-extended by local referen...
const CompoundLiteralRegion * getCompoundLiteralRegion(const CompoundLiteralExpr *CL, const StackFrame *SF)
getCompoundLiteralRegion - Retrieve the region associated with a given CompoundLiteral.
const ElementRegion * getElementRegion(QualType elementType, NonLoc Idx, const SubRegion *superRegion, const ASTContext &Ctx)
getElementRegion - Retrieve the memory region associated with the associated element type,...
const NonParamVarRegion * getNonParamVarRegion(const VarDecl *VD, const MemRegion *superR)
getVarRegion - Retrieve or create the memory region associated with a specified VarDecl and StackFram...
const ObjCIvarRegion * getObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *superRegion)
getObjCIvarRegion - Retrieve or create the memory region associated with a specified Objective-c inst...
const VarRegion * getVarRegion(const VarDecl *VD, const StackFrame *SF)
getVarRegion - Retrieve or create the memory region associated with a specified VarDecl and StackFram...
const AllocaRegion * getAllocaRegion(const Expr *Ex, unsigned Cnt, const StackFrame *SF)
getAllocaRegion - Retrieve a region associated with a call to alloca().
const SymbolicRegion * getSymbolicHeapRegion(SymbolRef sym)
Return a unique symbolic region belonging to heap memory space.
const CXXTempObjectRegion * getCXXTempObjectRegion(Expr const *Ex, StackFrame const *SF)
const ObjCStringRegion * getObjCStringRegion(const ObjCStringLiteral *Str)
const StringRegion * getStringRegion(const StringLiteral *Str)
ASTContext & getContext()
DefinedOrUnknownSVal getStaticSize(const MemRegion *MR, SValBuilder &SVB) const
const CodeSpaceRegion * getCodeRegion()
const GlobalsSpaceRegion * getGlobalsRegion(MemRegion::Kind K=MemRegion::GlobalInternalSpaceRegionKind, const CodeTextRegion *R=nullptr)
getGlobalsRegion - Retrieve the memory region associated with global variables.
const CXXThisRegion * getCXXThisRegion(QualType thisPointerTy, const StackFrame *SF)
getCXXThisRegion - Retrieve the [artificial] region associated with the parameter 'this'.
const SymbolicRegion * getSymbolicRegion(SymbolRef Sym, const MemSpaceRegion *MemSpace=nullptr)
Retrieve or create a "symbolic" memory region.
const FunctionCodeRegion * getFunctionCodeRegion(const NamedDecl *FD)
const CXXBaseObjectRegion * getCXXBaseObjectRegion(const CXXRecordDecl *BaseClass, const SubRegion *Super, bool IsVirtual)
Create a CXXBaseObjectRegion with the given base class for region Super.
const CXXLifetimeExtendedObjectRegion * getCXXStaticLifetimeExtendedObjectRegion(const Expr *Ex, ValueDecl const *VD)
Create a CXXLifetimeExtendedObjectRegion for temporaries which are lifetime-extended by static refere...
const BlockDataRegion * getBlockDataRegion(const BlockCodeRegion *bc, const StackFrame *SF, unsigned blockCount)
getBlockDataRegion - Get the memory region associated with an instance of a block.
MemRegion - The root abstract class for all memory regions.
virtual bool canPrintPrettyAsExpr() const
Returns true if this region's textual representation can be used as part of a larger expression.
std::string getDescriptiveName(bool UseQuotes=true, bool AllowFallback=false) const
Get descriptive name for memory region.
StringRef getKindStr() const
RegionOffset getAsOffset() const
Compute the offset within the top level memory object.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * StripCasts(bool StripBaseAndDerivedCasts=true) const
ProgramStateRef setMemorySpace(ProgramStateRef State, const MemSpaceRegion *Space) const
Set the dynamically deduced memory space of a MemRegion that currently has UnknownSpaceRegion.
ASTContext & getContext() const
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemSpaceRegion * getMemorySpace(ProgramStateRef State) const
Returns the most specific memory space for this memory region in the given ProgramStateRef.
virtual bool isSubRegionOf(const MemRegion *R) const
Check if the region is a subregion of the given region.
virtual void dumpToStream(raw_ostream &os) const
const SymbolicRegion * getSymbolicBase() const
If this is a symbolic region, returns the region.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getBaseRegion() const
virtual void printPretty(raw_ostream &os) const
Print the region for use in diagnostics.
virtual void printPrettyAsExpr(raw_ostream &os) const
Print the region as expression.
std::string getString() const
Get a string representation of a region for debug use.
const RegionTy * getAs() const
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...
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
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.
void dumpToStream(raw_ostream &os) const override
ParamVarRegion - Represents a region for parameters.
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
const ParmVarDecl * getDecl() const override
TODO: What does this return?
unsigned getIndex() const
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.
bool hasTrait(SymbolRef Sym, InvalidationKinds IK) const
void setTrait(SymbolRef Sym, InvalidationKinds IK)
Represent a region's offset within the top level base region.
static const int64_t Symbolic
CharUnits getOffset() const
void dumpToStream(raw_ostream &os) const
const MemRegion * getRegion() const
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.
void Profile(llvm::FoldingSetNodeID &ID) const
std::optional< T > getAs() const
Convert to the specified SVal type, returning std::nullopt if this SVal is not of the desired type.
void dumpToStream(raw_ostream &os) const override
void dumpToStream(raw_ostream &os) const override
LLVM_ATTRIBUTE_RETURNS_NONNULL const StackFrame * getStackFrame() const
void Profile(llvm::FoldingSetNodeID &ID) const override
The region of the static variables within the current CodeTextRegion scope.
void Profile(llvm::FoldingSetNodeID &ID) const override
void dumpToStream(raw_ostream &os) const override
LLVM_ATTRIBUTE_RETURNS_NONNULL const CodeTextRegion * getCodeRegion() const
StringRegion - Region associated with a StringLiteral.
void dumpToStream(raw_ostream &os) const override
SubRegion - A region that subsets another larger region.
LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion * getSuperRegion() const
bool isSubRegionOf(const MemRegion *R) const override
Check if the region is a subregion of the given region.
SubRegion(const MemRegion *sReg, Kind k)
const MemRegion * superRegion
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.
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.
virtual QualType getValueType() const =0
void dumpToStream(raw_ostream &os) const override
const StackFrame * getStackFrame() const
It might return null.
Value representing integer constant.
Represents symbolic expression that isn't a location.
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
const SymExpr * SymbolRef
DefinedOrUnknownSVal getElementExtent(QualType Ty, SValBuilder &SVB)
Top level wrappers for InstallAPI frontend operations.
CanQual< Type > CanQualType
Represents a canonical, potentially-qualified type.
bool isa(CodeGen::Address addr)
const FunctionProtoType * T
LangAS
Defines the address space values used by the address space qualifier of QualType.
U cast(CodeGen::Address addr)
Extra information about a function prototype.
Describes how types, statements, expressions, and declarations should be printed.