12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754 |
- //===- MemRegion.cpp - Abstract memory regions for static analysis --------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This file defines MemRegion and its subclasses. MemRegion defines a
- // partially-typed abstraction of memory useful for path-sensitive dataflow
- // analyses.
- //
- //===----------------------------------------------------------------------===//
- #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
- #include "clang/AST/ASTContext.h"
- #include "clang/AST/Attr.h"
- #include "clang/AST/CharUnits.h"
- #include "clang/AST/Decl.h"
- #include "clang/AST/DeclCXX.h"
- #include "clang/AST/DeclObjC.h"
- #include "clang/AST/Expr.h"
- #include "clang/AST/PrettyPrinter.h"
- #include "clang/AST/RecordLayout.h"
- #include "clang/AST/Type.h"
- #include "clang/Analysis/AnalysisDeclContext.h"
- #include "clang/Analysis/Support/BumpVector.h"
- #include "clang/Basic/IdentifierTable.h"
- #include "clang/Basic/LLVM.h"
- #include "clang/Basic/SourceManager.h"
- #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
- #include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
- #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
- #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
- #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
- #include "llvm/ADT/APInt.h"
- #include "llvm/ADT/FoldingSet.h"
- #include "llvm/ADT/Optional.h"
- #include "llvm/ADT/PointerUnion.h"
- #include "llvm/ADT/SmallString.h"
- #include "llvm/ADT/StringRef.h"
- #include "llvm/ADT/Twine.h"
- #include "llvm/Support/Allocator.h"
- #include "llvm/Support/Casting.h"
- #include "llvm/Support/CheckedArithmetic.h"
- #include "llvm/Support/Compiler.h"
- #include "llvm/Support/Debug.h"
- #include "llvm/Support/ErrorHandling.h"
- #include "llvm/Support/raw_ostream.h"
- #include <cassert>
- #include <cstdint>
- #include <functional>
- #include <iterator>
- #include <string>
- #include <tuple>
- #include <utility>
- using namespace clang;
- using namespace ento;
- #define DEBUG_TYPE "MemRegion"
- //===----------------------------------------------------------------------===//
- // MemRegion Construction.
- //===----------------------------------------------------------------------===//
- template <typename RegionTy, typename SuperTy, typename Arg1Ty>
- RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1,
- const SuperTy *superRegion) {
- llvm::FoldingSetNodeID ID;
- RegionTy::ProfileRegion(ID, arg1, superRegion);
- void *InsertPos;
- auto *R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, InsertPos));
- if (!R) {
- R = A.Allocate<RegionTy>();
- new (R) RegionTy(arg1, superRegion);
- Regions.InsertNode(R, InsertPos);
- }
- return R;
- }
- template <typename RegionTy, typename SuperTy, typename Arg1Ty, typename Arg2Ty>
- RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2,
- const SuperTy *superRegion) {
- llvm::FoldingSetNodeID ID;
- RegionTy::ProfileRegion(ID, arg1, arg2, superRegion);
- void *InsertPos;
- auto *R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, InsertPos));
- if (!R) {
- R = A.Allocate<RegionTy>();
- new (R) RegionTy(arg1, arg2, superRegion);
- Regions.InsertNode(R, InsertPos);
- }
- return R;
- }
- template <typename RegionTy, typename SuperTy,
- typename Arg1Ty, typename Arg2Ty, typename Arg3Ty>
- RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2,
- const Arg3Ty arg3,
- const SuperTy *superRegion) {
- llvm::FoldingSetNodeID ID;
- RegionTy::ProfileRegion(ID, arg1, arg2, arg3, superRegion);
- void *InsertPos;
- auto *R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, InsertPos));
- if (!R) {
- R = A.Allocate<RegionTy>();
- new (R) RegionTy(arg1, arg2, arg3, superRegion);
- Regions.InsertNode(R, InsertPos);
- }
- return R;
- }
- //===----------------------------------------------------------------------===//
- // Object destruction.
- //===----------------------------------------------------------------------===//
- MemRegion::~MemRegion() = default;
- // All regions and their data are BumpPtrAllocated. No need to call their
- // destructors.
- MemRegionManager::~MemRegionManager() = default;
- //===----------------------------------------------------------------------===//
- // Basic methods.
- //===----------------------------------------------------------------------===//
- bool SubRegion::isSubRegionOf(const MemRegion* R) const {
- const MemRegion* r = this;
- do {
- if (r == R)
- return true;
- if (const auto *sr = dyn_cast<SubRegion>(r))
- r = sr->getSuperRegion();
- else
- break;
- } while (r != nullptr);
- return false;
- }
- MemRegionManager &SubRegion::getMemRegionManager() const {
- const SubRegion* r = this;
- do {
- const MemRegion *superRegion = r->getSuperRegion();
- if (const auto *sr = dyn_cast<SubRegion>(superRegion)) {
- r = sr;
- continue;
- }
- return superRegion->getMemRegionManager();
- } while (true);
- }
- const StackFrameContext *VarRegion::getStackFrame() const {
- const auto *SSR = dyn_cast<StackSpaceRegion>(getMemorySpace());
- return SSR ? SSR->getStackFrame() : nullptr;
- }
- ObjCIvarRegion::ObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *sReg)
- : DeclRegion(sReg, ObjCIvarRegionKind), IVD(ivd) {}
- const ObjCIvarDecl *ObjCIvarRegion::getDecl() const { return IVD; }
- QualType ObjCIvarRegion::getValueType() const {
- return getDecl()->getType();
- }
- QualType CXXBaseObjectRegion::getValueType() const {
- return QualType(getDecl()->getTypeForDecl(), 0);
- }
- QualType CXXDerivedObjectRegion::getValueType() const {
- return QualType(getDecl()->getTypeForDecl(), 0);
- }
- QualType ParamVarRegion::getValueType() const {
- assert(getDecl() &&
- "`ParamVarRegion` support functions without `Decl` not implemented"
- " yet.");
- return getDecl()->getType();
- }
- const ParmVarDecl *ParamVarRegion::getDecl() const {
- const Decl *D = getStackFrame()->getDecl();
- if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
- assert(Index < FD->param_size());
- return FD->parameters()[Index];
- } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
- assert(Index < BD->param_size());
- return BD->parameters()[Index];
- } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
- assert(Index < MD->param_size());
- return MD->parameters()[Index];
- } else if (const auto *CD = dyn_cast<CXXConstructorDecl>(D)) {
- assert(Index < CD->param_size());
- return CD->parameters()[Index];
- } else {
- llvm_unreachable("Unexpected Decl kind!");
- }
- }
- //===----------------------------------------------------------------------===//
- // FoldingSet profiling.
- //===----------------------------------------------------------------------===//
- void MemSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const {
- ID.AddInteger(static_cast<unsigned>(getKind()));
- }
- void StackSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const {
- ID.AddInteger(static_cast<unsigned>(getKind()));
- ID.AddPointer(getStackFrame());
- }
- void StaticGlobalSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const {
- ID.AddInteger(static_cast<unsigned>(getKind()));
- ID.AddPointer(getCodeRegion());
- }
- void StringRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
- const StringLiteral *Str,
- const MemRegion *superRegion) {
- ID.AddInteger(static_cast<unsigned>(StringRegionKind));
- ID.AddPointer(Str);
- ID.AddPointer(superRegion);
- }
- void ObjCStringRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
- const ObjCStringLiteral *Str,
- const MemRegion *superRegion) {
- ID.AddInteger(static_cast<unsigned>(ObjCStringRegionKind));
- ID.AddPointer(Str);
- ID.AddPointer(superRegion);
- }
- void AllocaRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
- const Expr *Ex, unsigned cnt,
- const MemRegion *superRegion) {
- ID.AddInteger(static_cast<unsigned>(AllocaRegionKind));
- ID.AddPointer(Ex);
- ID.AddInteger(cnt);
- ID.AddPointer(superRegion);
- }
- void AllocaRegion::Profile(llvm::FoldingSetNodeID& ID) const {
- ProfileRegion(ID, Ex, Cnt, superRegion);
- }
- void CompoundLiteralRegion::Profile(llvm::FoldingSetNodeID& ID) const {
- CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion);
- }
- void CompoundLiteralRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
- const CompoundLiteralExpr *CL,
- const MemRegion* superRegion) {
- ID.AddInteger(static_cast<unsigned>(CompoundLiteralRegionKind));
- ID.AddPointer(CL);
- ID.AddPointer(superRegion);
- }
- void CXXThisRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
- const PointerType *PT,
- const MemRegion *sRegion) {
- ID.AddInteger(static_cast<unsigned>(CXXThisRegionKind));
- ID.AddPointer(PT);
- ID.AddPointer(sRegion);
- }
- void CXXThisRegion::Profile(llvm::FoldingSetNodeID &ID) const {
- CXXThisRegion::ProfileRegion(ID, ThisPointerTy, superRegion);
- }
- void FieldRegion::Profile(llvm::FoldingSetNodeID &ID) const {
- ProfileRegion(ID, getDecl(), superRegion);
- }
- void ObjCIvarRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
- const ObjCIvarDecl *ivd,
- const MemRegion* superRegion) {
- ID.AddInteger(static_cast<unsigned>(ObjCIvarRegionKind));
- ID.AddPointer(ivd);
- ID.AddPointer(superRegion);
- }
- void ObjCIvarRegion::Profile(llvm::FoldingSetNodeID &ID) const {
- ProfileRegion(ID, getDecl(), superRegion);
- }
- void NonParamVarRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
- const VarDecl *VD,
- const MemRegion *superRegion) {
- ID.AddInteger(static_cast<unsigned>(NonParamVarRegionKind));
- ID.AddPointer(VD);
- ID.AddPointer(superRegion);
- }
- void NonParamVarRegion::Profile(llvm::FoldingSetNodeID &ID) const {
- ProfileRegion(ID, getDecl(), superRegion);
- }
- void ParamVarRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, const Expr *OE,
- unsigned Idx, const MemRegion *SReg) {
- ID.AddInteger(static_cast<unsigned>(ParamVarRegionKind));
- ID.AddPointer(OE);
- ID.AddInteger(Idx);
- ID.AddPointer(SReg);
- }
- void ParamVarRegion::Profile(llvm::FoldingSetNodeID &ID) const {
- ProfileRegion(ID, getOriginExpr(), getIndex(), superRegion);
- }
- void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym,
- const MemRegion *sreg) {
- ID.AddInteger(static_cast<unsigned>(MemRegion::SymbolicRegionKind));
- ID.Add(sym);
- ID.AddPointer(sreg);
- }
- void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const {
- SymbolicRegion::ProfileRegion(ID, sym, getSuperRegion());
- }
- void ElementRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
- QualType ElementType, SVal Idx,
- const MemRegion* superRegion) {
- ID.AddInteger(MemRegion::ElementRegionKind);
- ID.Add(ElementType);
- ID.AddPointer(superRegion);
- Idx.Profile(ID);
- }
- void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const {
- ElementRegion::ProfileRegion(ID, ElementType, Index, superRegion);
- }
- void FunctionCodeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
- const NamedDecl *FD,
- const MemRegion*) {
- ID.AddInteger(MemRegion::FunctionCodeRegionKind);
- ID.AddPointer(FD);
- }
- void FunctionCodeRegion::Profile(llvm::FoldingSetNodeID& ID) const {
- FunctionCodeRegion::ProfileRegion(ID, FD, superRegion);
- }
- void BlockCodeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
- const BlockDecl *BD, CanQualType,
- const AnalysisDeclContext *AC,
- const MemRegion*) {
- ID.AddInteger(MemRegion::BlockCodeRegionKind);
- ID.AddPointer(BD);
- }
- void BlockCodeRegion::Profile(llvm::FoldingSetNodeID& ID) const {
- BlockCodeRegion::ProfileRegion(ID, BD, locTy, AC, superRegion);
- }
- void BlockDataRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
- const BlockCodeRegion *BC,
- const LocationContext *LC,
- unsigned BlkCount,
- const MemRegion *sReg) {
- ID.AddInteger(MemRegion::BlockDataRegionKind);
- ID.AddPointer(BC);
- ID.AddPointer(LC);
- ID.AddInteger(BlkCount);
- ID.AddPointer(sReg);
- }
- void BlockDataRegion::Profile(llvm::FoldingSetNodeID& ID) const {
- BlockDataRegion::ProfileRegion(ID, BC, LC, BlockCount, getSuperRegion());
- }
- void CXXTempObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
- Expr const *Ex,
- const MemRegion *sReg) {
- ID.AddPointer(Ex);
- ID.AddPointer(sReg);
- }
- void CXXTempObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
- ProfileRegion(ID, Ex, getSuperRegion());
- }
- void CXXBaseObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
- const CXXRecordDecl *RD,
- bool IsVirtual,
- const MemRegion *SReg) {
- ID.AddPointer(RD);
- ID.AddBoolean(IsVirtual);
- ID.AddPointer(SReg);
- }
- void CXXBaseObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
- ProfileRegion(ID, getDecl(), isVirtual(), superRegion);
- }
- void CXXDerivedObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
- const CXXRecordDecl *RD,
- const MemRegion *SReg) {
- ID.AddPointer(RD);
- ID.AddPointer(SReg);
- }
- void CXXDerivedObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
- ProfileRegion(ID, getDecl(), superRegion);
- }
- //===----------------------------------------------------------------------===//
- // Region anchors.
- //===----------------------------------------------------------------------===//
- void GlobalsSpaceRegion::anchor() {}
- void NonStaticGlobalSpaceRegion::anchor() {}
- void StackSpaceRegion::anchor() {}
- void TypedRegion::anchor() {}
- void TypedValueRegion::anchor() {}
- void CodeTextRegion::anchor() {}
- void SubRegion::anchor() {}
- //===----------------------------------------------------------------------===//
- // Region pretty-printing.
- //===----------------------------------------------------------------------===//
- LLVM_DUMP_METHOD void MemRegion::dump() const {
- dumpToStream(llvm::errs());
- }
- std::string MemRegion::getString() const {
- std::string s;
- llvm::raw_string_ostream os(s);
- dumpToStream(os);
- return s;
- }
- void MemRegion::dumpToStream(raw_ostream &os) const {
- os << "<Unknown Region>";
- }
- void AllocaRegion::dumpToStream(raw_ostream &os) const {
- os << "alloca{S" << Ex->getID(getContext()) << ',' << Cnt << '}';
- }
- void FunctionCodeRegion::dumpToStream(raw_ostream &os) const {
- os << "code{" << getDecl()->getDeclName().getAsString() << '}';
- }
- void BlockCodeRegion::dumpToStream(raw_ostream &os) const {
- os << "block_code{" << static_cast<const void *>(this) << '}';
- }
- void BlockDataRegion::dumpToStream(raw_ostream &os) const {
- os << "block_data{" << BC;
- os << "; ";
- for (BlockDataRegion::referenced_vars_iterator
- I = referenced_vars_begin(),
- E = referenced_vars_end(); I != E; ++I)
- os << "(" << I.getCapturedRegion() << "<-" <<
- I.getOriginalRegion() << ") ";
- os << '}';
- }
- void CompoundLiteralRegion::dumpToStream(raw_ostream &os) const {
- // FIXME: More elaborate pretty-printing.
- os << "{ S" << CL->getID(getContext()) << " }";
- }
- void CXXTempObjectRegion::dumpToStream(raw_ostream &os) const {
- os << "temp_object{" << getValueType().getAsString() << ", "
- << "S" << Ex->getID(getContext()) << '}';
- }
- void CXXBaseObjectRegion::dumpToStream(raw_ostream &os) const {
- os << "Base{" << superRegion << ',' << getDecl()->getName() << '}';
- }
- void CXXDerivedObjectRegion::dumpToStream(raw_ostream &os) const {
- os << "Derived{" << superRegion << ',' << getDecl()->getName() << '}';
- }
- void CXXThisRegion::dumpToStream(raw_ostream &os) const {
- os << "this";
- }
- void ElementRegion::dumpToStream(raw_ostream &os) const {
- os << "Element{" << superRegion << ','
- << Index << ',' << getElementType().getAsString() << '}';
- }
- void FieldRegion::dumpToStream(raw_ostream &os) const {
- os << superRegion << "." << *getDecl();
- }
- void ObjCIvarRegion::dumpToStream(raw_ostream &os) const {
- os << "Ivar{" << superRegion << ',' << *getDecl() << '}';
- }
- void StringRegion::dumpToStream(raw_ostream &os) const {
- assert(Str != nullptr && "Expecting non-null StringLiteral");
- Str->printPretty(os, nullptr, PrintingPolicy(getContext().getLangOpts()));
- }
- void ObjCStringRegion::dumpToStream(raw_ostream &os) const {
- assert(Str != nullptr && "Expecting non-null ObjCStringLiteral");
- Str->printPretty(os, nullptr, PrintingPolicy(getContext().getLangOpts()));
- }
- void SymbolicRegion::dumpToStream(raw_ostream &os) const {
- if (isa<HeapSpaceRegion>(getSuperRegion()))
- os << "Heap";
- os << "SymRegion{" << sym << '}';
- }
- void NonParamVarRegion::dumpToStream(raw_ostream &os) const {
- if (const IdentifierInfo *ID = VD->getIdentifier())
- os << ID->getName();
- else
- os << "NonParamVarRegion{D" << VD->getID() << '}';
- }
- LLVM_DUMP_METHOD void RegionRawOffset::dump() const {
- dumpToStream(llvm::errs());
- }
- void RegionRawOffset::dumpToStream(raw_ostream &os) const {
- os << "raw_offset{" << getRegion() << ',' << getOffset().getQuantity() << '}';
- }
- void CodeSpaceRegion::dumpToStream(raw_ostream &os) const {
- os << "CodeSpaceRegion";
- }
- void StaticGlobalSpaceRegion::dumpToStream(raw_ostream &os) const {
- os << "StaticGlobalsMemSpace{" << CR << '}';
- }
- void GlobalInternalSpaceRegion::dumpToStream(raw_ostream &os) const {
- os << "GlobalInternalSpaceRegion";
- }
- void GlobalSystemSpaceRegion::dumpToStream(raw_ostream &os) const {
- os << "GlobalSystemSpaceRegion";
- }
- void GlobalImmutableSpaceRegion::dumpToStream(raw_ostream &os) const {
- os << "GlobalImmutableSpaceRegion";
- }
- void HeapSpaceRegion::dumpToStream(raw_ostream &os) const {
- os << "HeapSpaceRegion";
- }
- void UnknownSpaceRegion::dumpToStream(raw_ostream &os) const {
- os << "UnknownSpaceRegion";
- }
- void StackArgumentsSpaceRegion::dumpToStream(raw_ostream &os) const {
- os << "StackArgumentsSpaceRegion";
- }
- void StackLocalsSpaceRegion::dumpToStream(raw_ostream &os) const {
- os << "StackLocalsSpaceRegion";
- }
- void ParamVarRegion::dumpToStream(raw_ostream &os) const {
- const ParmVarDecl *PVD = getDecl();
- assert(PVD &&
- "`ParamVarRegion` support functions without `Decl` not implemented"
- " yet.");
- if (const IdentifierInfo *ID = PVD->getIdentifier()) {
- os << ID->getName();
- } else {
- os << "ParamVarRegion{P" << PVD->getID() << '}';
- }
- }
- bool MemRegion::canPrintPretty() const {
- return canPrintPrettyAsExpr();
- }
- bool MemRegion::canPrintPrettyAsExpr() const {
- return false;
- }
- void MemRegion::printPretty(raw_ostream &os) const {
- assert(canPrintPretty() && "This region cannot be printed pretty.");
- os << "'";
- printPrettyAsExpr(os);
- os << "'";
- }
- void MemRegion::printPrettyAsExpr(raw_ostream &) const {
- llvm_unreachable("This region cannot be printed pretty.");
- }
- bool NonParamVarRegion::canPrintPrettyAsExpr() const { return true; }
- void NonParamVarRegion::printPrettyAsExpr(raw_ostream &os) const {
- os << getDecl()->getName();
- }
- bool ParamVarRegion::canPrintPrettyAsExpr() const { return true; }
- void ParamVarRegion::printPrettyAsExpr(raw_ostream &os) const {
- assert(getDecl() &&
- "`ParamVarRegion` support functions without `Decl` not implemented"
- " yet.");
- os << getDecl()->getName();
- }
- bool ObjCIvarRegion::canPrintPrettyAsExpr() const {
- return true;
- }
- void ObjCIvarRegion::printPrettyAsExpr(raw_ostream &os) const {
- os << getDecl()->getName();
- }
- bool FieldRegion::canPrintPretty() const {
- return true;
- }
- bool FieldRegion::canPrintPrettyAsExpr() const {
- return superRegion->canPrintPrettyAsExpr();
- }
- void FieldRegion::printPrettyAsExpr(raw_ostream &os) const {
- assert(canPrintPrettyAsExpr());
- superRegion->printPrettyAsExpr(os);
- os << "." << getDecl()->getName();
- }
- void FieldRegion::printPretty(raw_ostream &os) const {
- if (canPrintPrettyAsExpr()) {
- os << "\'";
- printPrettyAsExpr(os);
- os << "'";
- } else {
- os << "field " << "\'" << getDecl()->getName() << "'";
- }
- }
- bool CXXBaseObjectRegion::canPrintPrettyAsExpr() const {
- return superRegion->canPrintPrettyAsExpr();
- }
- void CXXBaseObjectRegion::printPrettyAsExpr(raw_ostream &os) const {
- superRegion->printPrettyAsExpr(os);
- }
- bool CXXDerivedObjectRegion::canPrintPrettyAsExpr() const {
- return superRegion->canPrintPrettyAsExpr();
- }
- void CXXDerivedObjectRegion::printPrettyAsExpr(raw_ostream &os) const {
- superRegion->printPrettyAsExpr(os);
- }
- std::string MemRegion::getDescriptiveName(bool UseQuotes) const {
- std::string VariableName;
- std::string ArrayIndices;
- const MemRegion *R = this;
- SmallString<50> buf;
- llvm::raw_svector_ostream os(buf);
- // Obtain array indices to add them to the variable name.
- const ElementRegion *ER = nullptr;
- while ((ER = R->getAs<ElementRegion>())) {
- // Index is a ConcreteInt.
- if (auto CI = ER->getIndex().getAs<nonloc::ConcreteInt>()) {
- llvm::SmallString<2> Idx;
- CI->getValue().toString(Idx);
- ArrayIndices = (llvm::Twine("[") + Idx.str() + "]" + ArrayIndices).str();
- }
- // If not a ConcreteInt, try to obtain the variable
- // name by calling 'getDescriptiveName' recursively.
- else {
- std::string Idx = ER->getDescriptiveName(false);
- if (!Idx.empty()) {
- ArrayIndices = (llvm::Twine("[") + Idx + "]" + ArrayIndices).str();
- }
- }
- R = ER->getSuperRegion();
- }
- // Get variable name.
- if (R && R->canPrintPrettyAsExpr()) {
- R->printPrettyAsExpr(os);
- if (UseQuotes)
- return (llvm::Twine("'") + os.str() + ArrayIndices + "'").str();
- else
- return (llvm::Twine(os.str()) + ArrayIndices).str();
- }
- return VariableName;
- }
- SourceRange MemRegion::sourceRange() const {
- const auto *const VR = dyn_cast<VarRegion>(this->getBaseRegion());
- const auto *const FR = dyn_cast<FieldRegion>(this);
- // Check for more specific regions first.
- // FieldRegion
- if (FR) {
- return FR->getDecl()->getSourceRange();
- }
- // VarRegion
- else if (VR) {
- return VR->getDecl()->getSourceRange();
- }
- // Return invalid source range (can be checked by client).
- else
- return {};
- }
- //===----------------------------------------------------------------------===//
- // MemRegionManager methods.
- //===----------------------------------------------------------------------===//
- DefinedOrUnknownSVal MemRegionManager::getStaticSize(const MemRegion *MR,
- SValBuilder &SVB) const {
- const auto *SR = cast<SubRegion>(MR);
- SymbolManager &SymMgr = SVB.getSymbolManager();
- switch (SR->getKind()) {
- case MemRegion::AllocaRegionKind:
- case MemRegion::SymbolicRegionKind:
- return nonloc::SymbolVal(SymMgr.getExtentSymbol(SR));
- case MemRegion::StringRegionKind:
- return SVB.makeIntVal(
- cast<StringRegion>(SR)->getStringLiteral()->getByteLength() + 1,
- SVB.getArrayIndexType());
- case MemRegion::CompoundLiteralRegionKind:
- case MemRegion::CXXBaseObjectRegionKind:
- case MemRegion::CXXDerivedObjectRegionKind:
- case MemRegion::CXXTempObjectRegionKind:
- case MemRegion::CXXThisRegionKind:
- case MemRegion::ObjCIvarRegionKind:
- case MemRegion::NonParamVarRegionKind:
- case MemRegion::ParamVarRegionKind:
- case MemRegion::ElementRegionKind:
- case MemRegion::ObjCStringRegionKind: {
- QualType Ty = cast<TypedValueRegion>(SR)->getDesugaredValueType(Ctx);
- if (isa<VariableArrayType>(Ty))
- return nonloc::SymbolVal(SymMgr.getExtentSymbol(SR));
- if (Ty->isIncompleteType())
- return UnknownVal();
- return getElementExtent(Ty, SVB);
- }
- case MemRegion::FieldRegionKind: {
- // Force callers to deal with bitfields explicitly.
- if (cast<FieldRegion>(SR)->getDecl()->isBitField())
- return UnknownVal();
- QualType Ty = cast<TypedValueRegion>(SR)->getDesugaredValueType(Ctx);
- const DefinedOrUnknownSVal Size = getElementExtent(Ty, SVB);
- // We currently don't model flexible array members (FAMs), which are:
- // - int array[]; of IncompleteArrayType
- // - int array[0]; of ConstantArrayType with size 0
- // - int array[1]; of ConstantArrayType with size 1 (*)
- // (*): Consider single element array object members as FAM candidates only
- // if the consider-single-element-arrays-as-flexible-array-members
- // analyzer option is true.
- // https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
- const auto isFlexibleArrayMemberCandidate = [this,
- &SVB](QualType Ty) -> bool {
- const ArrayType *AT = Ctx.getAsArrayType(Ty);
- if (!AT)
- return false;
- if (isa<IncompleteArrayType>(AT))
- return true;
- if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) {
- const llvm::APInt &Size = CAT->getSize();
- if (Size.isZero())
- return true;
- const AnalyzerOptions &Opts = SVB.getAnalyzerOptions();
- if (Opts.ShouldConsiderSingleElementArraysAsFlexibleArrayMembers &&
- Size.isOne())
- return true;
- }
- return false;
- };
- if (isFlexibleArrayMemberCandidate(Ty))
- return UnknownVal();
- return Size;
- }
- // FIXME: The following are being used in 'SimpleSValBuilder' and in
- // 'ArrayBoundChecker::checkLocation' because there is no symbol to
- // represent the regions more appropriately.
- case MemRegion::BlockDataRegionKind:
- case MemRegion::BlockCodeRegionKind:
- case MemRegion::FunctionCodeRegionKind:
- return nonloc::SymbolVal(SymMgr.getExtentSymbol(SR));
- default:
- llvm_unreachable("Unhandled region");
- }
- }
- template <typename REG>
- const REG *MemRegionManager::LazyAllocate(REG*& region) {
- if (!region) {
- region = A.Allocate<REG>();
- new (region) REG(*this);
- }
- return region;
- }
- template <typename REG, typename ARG>
- const REG *MemRegionManager::LazyAllocate(REG*& region, ARG a) {
- if (!region) {
- region = A.Allocate<REG>();
- new (region) REG(this, a);
- }
- return region;
- }
- const StackLocalsSpaceRegion*
- MemRegionManager::getStackLocalsRegion(const StackFrameContext *STC) {
- assert(STC);
- StackLocalsSpaceRegion *&R = StackLocalsSpaceRegions[STC];
- if (R)
- return R;
- R = A.Allocate<StackLocalsSpaceRegion>();
- new (R) StackLocalsSpaceRegion(*this, STC);
- return R;
- }
- const StackArgumentsSpaceRegion *
- MemRegionManager::getStackArgumentsRegion(const StackFrameContext *STC) {
- assert(STC);
- StackArgumentsSpaceRegion *&R = StackArgumentsSpaceRegions[STC];
- if (R)
- return R;
- R = A.Allocate<StackArgumentsSpaceRegion>();
- new (R) StackArgumentsSpaceRegion(*this, STC);
- return R;
- }
- const GlobalsSpaceRegion
- *MemRegionManager::getGlobalsRegion(MemRegion::Kind K,
- const CodeTextRegion *CR) {
- if (!CR) {
- if (K == MemRegion::GlobalSystemSpaceRegionKind)
- return LazyAllocate(SystemGlobals);
- if (K == MemRegion::GlobalImmutableSpaceRegionKind)
- return LazyAllocate(ImmutableGlobals);
- assert(K == MemRegion::GlobalInternalSpaceRegionKind);
- return LazyAllocate(InternalGlobals);
- }
- assert(K == MemRegion::StaticGlobalSpaceRegionKind);
- StaticGlobalSpaceRegion *&R = StaticsGlobalSpaceRegions[CR];
- if (R)
- return R;
- R = A.Allocate<StaticGlobalSpaceRegion>();
- new (R) StaticGlobalSpaceRegion(*this, CR);
- return R;
- }
- const HeapSpaceRegion *MemRegionManager::getHeapRegion() {
- return LazyAllocate(heap);
- }
- const UnknownSpaceRegion *MemRegionManager::getUnknownRegion() {
- return LazyAllocate(unknown);
- }
- const CodeSpaceRegion *MemRegionManager::getCodeRegion() {
- return LazyAllocate(code);
- }
- //===----------------------------------------------------------------------===//
- // Constructing regions.
- //===----------------------------------------------------------------------===//
- const StringRegion *MemRegionManager::getStringRegion(const StringLiteral *Str){
- return getSubRegion<StringRegion>(
- Str, cast<GlobalInternalSpaceRegion>(getGlobalsRegion()));
- }
- const ObjCStringRegion *
- MemRegionManager::getObjCStringRegion(const ObjCStringLiteral *Str){
- return getSubRegion<ObjCStringRegion>(
- Str, cast<GlobalInternalSpaceRegion>(getGlobalsRegion()));
- }
- /// Look through a chain of LocationContexts to either find the
- /// StackFrameContext that matches a DeclContext, or find a VarRegion
- /// for a variable captured by a block.
- static llvm::PointerUnion<const StackFrameContext *, const VarRegion *>
- getStackOrCaptureRegionForDeclContext(const LocationContext *LC,
- const DeclContext *DC,
- const VarDecl *VD) {
- while (LC) {
- if (const auto *SFC = dyn_cast<StackFrameContext>(LC)) {
- if (cast<DeclContext>(SFC->getDecl()) == DC)
- return SFC;
- }
- if (const auto *BC = dyn_cast<BlockInvocationContext>(LC)) {
- const auto *BR = static_cast<const BlockDataRegion *>(BC->getData());
- // FIXME: This can be made more efficient.
- for (BlockDataRegion::referenced_vars_iterator
- I = BR->referenced_vars_begin(),
- E = BR->referenced_vars_end(); I != E; ++I) {
- const TypedValueRegion *OrigR = I.getOriginalRegion();
- if (const auto *VR = dyn_cast<VarRegion>(OrigR)) {
- if (VR->getDecl() == VD)
- return cast<VarRegion>(I.getCapturedRegion());
- }
- }
- }
- LC = LC->getParent();
- }
- return (const StackFrameContext *)nullptr;
- }
- const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D,
- const LocationContext *LC) {
- const auto *PVD = dyn_cast<ParmVarDecl>(D);
- if (PVD) {
- unsigned Index = PVD->getFunctionScopeIndex();
- const StackFrameContext *SFC = LC->getStackFrame();
- const Stmt *CallSite = SFC->getCallSite();
- if (CallSite) {
- const Decl *D = SFC->getDecl();
- if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
- if (Index < FD->param_size() && FD->parameters()[Index] == PVD)
- return getSubRegion<ParamVarRegion>(cast<Expr>(CallSite), Index,
- getStackArgumentsRegion(SFC));
- } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
- if (Index < BD->param_size() && BD->parameters()[Index] == PVD)
- return getSubRegion<ParamVarRegion>(cast<Expr>(CallSite), Index,
- getStackArgumentsRegion(SFC));
- } else {
- return getSubRegion<ParamVarRegion>(cast<Expr>(CallSite), Index,
- getStackArgumentsRegion(SFC));
- }
- }
- }
- D = D->getCanonicalDecl();
- const MemRegion *sReg = nullptr;
- if (D->hasGlobalStorage() && !D->isStaticLocal()) {
- // First handle the globals defined in system headers.
- if (Ctx.getSourceManager().isInSystemHeader(D->getLocation())) {
- // Allow the system globals which often DO GET modified, assume the
- // rest are immutable.
- if (D->getName().contains("errno"))
- sReg = getGlobalsRegion(MemRegion::GlobalSystemSpaceRegionKind);
- else
- sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind);
- // Treat other globals as GlobalInternal unless they are constants.
- } else {
- QualType GQT = D->getType();
- const Type *GT = GQT.getTypePtrOrNull();
- // TODO: We could walk the complex types here and see if everything is
- // constified.
- if (GT && GQT.isConstQualified() && GT->isArithmeticType())
- sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind);
- else
- sReg = getGlobalsRegion();
- }
- // Finally handle static locals.
- } else {
- // FIXME: Once we implement scope handling, we will need to properly lookup
- // 'D' to the proper LocationContext.
- const DeclContext *DC = D->getDeclContext();
- llvm::PointerUnion<const StackFrameContext *, const VarRegion *> V =
- getStackOrCaptureRegionForDeclContext(LC, DC, D);
- if (V.is<const VarRegion*>())
- return V.get<const VarRegion*>();
- const auto *STC = V.get<const StackFrameContext *>();
- if (!STC) {
- // FIXME: Assign a more sensible memory space to static locals
- // we see from within blocks that we analyze as top-level declarations.
- sReg = getUnknownRegion();
- } else {
- if (D->hasLocalStorage()) {
- sReg =
- isa<ParmVarDecl, ImplicitParamDecl>(D)
- ? static_cast<const MemRegion *>(getStackArgumentsRegion(STC))
- : static_cast<const MemRegion *>(getStackLocalsRegion(STC));
- }
- else {
- assert(D->isStaticLocal());
- const Decl *STCD = STC->getDecl();
- if (isa<FunctionDecl, ObjCMethodDecl>(STCD))
- sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind,
- getFunctionCodeRegion(cast<NamedDecl>(STCD)));
- else if (const auto *BD = dyn_cast<BlockDecl>(STCD)) {
- // FIXME: The fallback type here is totally bogus -- though it should
- // never be queried, it will prevent uniquing with the real
- // BlockCodeRegion. Ideally we'd fix the AST so that we always had a
- // signature.
- QualType T;
- if (const TypeSourceInfo *TSI = BD->getSignatureAsWritten())
- T = TSI->getType();
- if (T.isNull())
- T = getContext().VoidTy;
- if (!T->getAs<FunctionType>())
- T = getContext().getFunctionNoProtoType(T);
- T = getContext().getBlockPointerType(T);
- const BlockCodeRegion *BTR =
- getBlockCodeRegion(BD, Ctx.getCanonicalType(T),
- STC->getAnalysisDeclContext());
- sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind,
- BTR);
- }
- else {
- sReg = getGlobalsRegion();
- }
- }
- }
- }
- return getSubRegion<NonParamVarRegion>(D, sReg);
- }
- const NonParamVarRegion *
- MemRegionManager::getNonParamVarRegion(const VarDecl *D,
- const MemRegion *superR) {
- D = D->getCanonicalDecl();
- return getSubRegion<NonParamVarRegion>(D, superR);
- }
- const ParamVarRegion *
- MemRegionManager::getParamVarRegion(const Expr *OriginExpr, unsigned Index,
- const LocationContext *LC) {
- const StackFrameContext *SFC = LC->getStackFrame();
- assert(SFC);
- return getSubRegion<ParamVarRegion>(OriginExpr, Index,
- getStackArgumentsRegion(SFC));
- }
- const BlockDataRegion *
- MemRegionManager::getBlockDataRegion(const BlockCodeRegion *BC,
- const LocationContext *LC,
- unsigned blockCount) {
- const MemSpaceRegion *sReg = nullptr;
- const BlockDecl *BD = BC->getDecl();
- if (!BD->hasCaptures()) {
- // This handles 'static' blocks.
- sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind);
- }
- else {
- if (LC) {
- // FIXME: Once we implement scope handling, we want the parent region
- // to be the scope.
- const StackFrameContext *STC = LC->getStackFrame();
- assert(STC);
- sReg = getStackLocalsRegion(STC);
- }
- else {
- // We allow 'LC' to be NULL for cases where want BlockDataRegions
- // without context-sensitivity.
- sReg = getUnknownRegion();
- }
- }
- return getSubRegion<BlockDataRegion>(BC, LC, blockCount, sReg);
- }
- const CXXTempObjectRegion *
- MemRegionManager::getCXXStaticTempObjectRegion(const Expr *Ex) {
- return getSubRegion<CXXTempObjectRegion>(
- Ex, getGlobalsRegion(MemRegion::GlobalInternalSpaceRegionKind, nullptr));
- }
- const CompoundLiteralRegion*
- MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr *CL,
- const LocationContext *LC) {
- const MemSpaceRegion *sReg = nullptr;
- if (CL->isFileScope())
- sReg = getGlobalsRegion();
- else {
- const StackFrameContext *STC = LC->getStackFrame();
- assert(STC);
- sReg = getStackLocalsRegion(STC);
- }
- return getSubRegion<CompoundLiteralRegion>(CL, sReg);
- }
- const ElementRegion*
- MemRegionManager::getElementRegion(QualType elementType, NonLoc Idx,
- const SubRegion* superRegion,
- ASTContext &Ctx){
- QualType T = Ctx.getCanonicalType(elementType).getUnqualifiedType();
- llvm::FoldingSetNodeID ID;
- ElementRegion::ProfileRegion(ID, T, Idx, superRegion);
- void *InsertPos;
- MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
- auto *R = cast_or_null<ElementRegion>(data);
- if (!R) {
- R = A.Allocate<ElementRegion>();
- new (R) ElementRegion(T, Idx, superRegion);
- Regions.InsertNode(R, InsertPos);
- }
- return R;
- }
- const FunctionCodeRegion *
- MemRegionManager::getFunctionCodeRegion(const NamedDecl *FD) {
- // To think: should we canonicalize the declaration here?
- return getSubRegion<FunctionCodeRegion>(FD, getCodeRegion());
- }
- const BlockCodeRegion *
- MemRegionManager::getBlockCodeRegion(const BlockDecl *BD, CanQualType locTy,
- AnalysisDeclContext *AC) {
- return getSubRegion<BlockCodeRegion>(BD, locTy, AC, getCodeRegion());
- }
- /// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
- const SymbolicRegion *MemRegionManager::getSymbolicRegion(SymbolRef sym) {
- return getSubRegion<SymbolicRegion>(sym, getUnknownRegion());
- }
- const SymbolicRegion *MemRegionManager::getSymbolicHeapRegion(SymbolRef Sym) {
- return getSubRegion<SymbolicRegion>(Sym, getHeapRegion());
- }
- const FieldRegion*
- MemRegionManager::getFieldRegion(const FieldDecl *d,
- const SubRegion* superRegion){
- return getSubRegion<FieldRegion>(d, superRegion);
- }
- const ObjCIvarRegion*
- MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl *d,
- const SubRegion* superRegion) {
- return getSubRegion<ObjCIvarRegion>(d, superRegion);
- }
- const CXXTempObjectRegion*
- MemRegionManager::getCXXTempObjectRegion(Expr const *E,
- LocationContext const *LC) {
- const StackFrameContext *SFC = LC->getStackFrame();
- assert(SFC);
- return getSubRegion<CXXTempObjectRegion>(E, getStackLocalsRegion(SFC));
- }
- /// Checks whether \p BaseClass is a valid virtual or direct non-virtual base
- /// class of the type of \p Super.
- static bool isValidBaseClass(const CXXRecordDecl *BaseClass,
- const TypedValueRegion *Super,
- bool IsVirtual) {
- BaseClass = BaseClass->getCanonicalDecl();
- const CXXRecordDecl *Class = Super->getValueType()->getAsCXXRecordDecl();
- if (!Class)
- return true;
- if (IsVirtual)
- return Class->isVirtuallyDerivedFrom(BaseClass);
- for (const auto &I : Class->bases()) {
- if (I.getType()->getAsCXXRecordDecl()->getCanonicalDecl() == BaseClass)
- return true;
- }
- return false;
- }
- const CXXBaseObjectRegion *
- MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl *RD,
- const SubRegion *Super,
- bool IsVirtual) {
- if (isa<TypedValueRegion>(Super)) {
- assert(isValidBaseClass(RD, cast<TypedValueRegion>(Super), IsVirtual));
- (void)&isValidBaseClass;
- if (IsVirtual) {
- // Virtual base regions should not be layered, since the layout rules
- // are different.
- while (const auto *Base = dyn_cast<CXXBaseObjectRegion>(Super))
- Super = cast<SubRegion>(Base->getSuperRegion());
- assert(Super && !isa<MemSpaceRegion>(Super));
- }
- }
- return getSubRegion<CXXBaseObjectRegion>(RD, IsVirtual, Super);
- }
- const CXXDerivedObjectRegion *
- MemRegionManager::getCXXDerivedObjectRegion(const CXXRecordDecl *RD,
- const SubRegion *Super) {
- return getSubRegion<CXXDerivedObjectRegion>(RD, Super);
- }
- const CXXThisRegion*
- MemRegionManager::getCXXThisRegion(QualType thisPointerTy,
- const LocationContext *LC) {
- const auto *PT = thisPointerTy->getAs<PointerType>();
- assert(PT);
- // Inside the body of the operator() of a lambda a this expr might refer to an
- // object in one of the parent location contexts.
- const auto *D = dyn_cast<CXXMethodDecl>(LC->getDecl());
- // FIXME: when operator() of lambda is analyzed as a top level function and
- // 'this' refers to a this to the enclosing scope, there is no right region to
- // return.
- while (!LC->inTopFrame() && (!D || D->isStatic() ||
- PT != D->getThisType()->getAs<PointerType>())) {
- LC = LC->getParent();
- D = dyn_cast<CXXMethodDecl>(LC->getDecl());
- }
- const StackFrameContext *STC = LC->getStackFrame();
- assert(STC);
- return getSubRegion<CXXThisRegion>(PT, getStackArgumentsRegion(STC));
- }
- const AllocaRegion*
- MemRegionManager::getAllocaRegion(const Expr *E, unsigned cnt,
- const LocationContext *LC) {
- const StackFrameContext *STC = LC->getStackFrame();
- assert(STC);
- return getSubRegion<AllocaRegion>(E, cnt, getStackLocalsRegion(STC));
- }
- const MemSpaceRegion *MemRegion::getMemorySpace() const {
- const MemRegion *R = this;
- const auto *SR = dyn_cast<SubRegion>(this);
- while (SR) {
- R = SR->getSuperRegion();
- SR = dyn_cast<SubRegion>(R);
- }
- return dyn_cast<MemSpaceRegion>(R);
- }
- bool MemRegion::hasStackStorage() const {
- return isa<StackSpaceRegion>(getMemorySpace());
- }
- bool MemRegion::hasStackNonParametersStorage() const {
- return isa<StackLocalsSpaceRegion>(getMemorySpace());
- }
- bool MemRegion::hasStackParametersStorage() const {
- return isa<StackArgumentsSpaceRegion>(getMemorySpace());
- }
- bool MemRegion::hasGlobalsOrParametersStorage() const {
- return isa<StackArgumentsSpaceRegion, GlobalsSpaceRegion>(getMemorySpace());
- }
- // getBaseRegion strips away all elements and fields, and get the base region
- // of them.
- const MemRegion *MemRegion::getBaseRegion() const {
- const MemRegion *R = this;
- while (true) {
- switch (R->getKind()) {
- case MemRegion::ElementRegionKind:
- case MemRegion::FieldRegionKind:
- case MemRegion::ObjCIvarRegionKind:
- case MemRegion::CXXBaseObjectRegionKind:
- case MemRegion::CXXDerivedObjectRegionKind:
- R = cast<SubRegion>(R)->getSuperRegion();
- continue;
- default:
- break;
- }
- break;
- }
- return R;
- }
- // getgetMostDerivedObjectRegion gets the region of the root class of a C++
- // class hierarchy.
- const MemRegion *MemRegion::getMostDerivedObjectRegion() const {
- const MemRegion *R = this;
- while (const auto *BR = dyn_cast<CXXBaseObjectRegion>(R))
- R = BR->getSuperRegion();
- return R;
- }
- bool MemRegion::isSubRegionOf(const MemRegion *) const {
- return false;
- }
- //===----------------------------------------------------------------------===//
- // View handling.
- //===----------------------------------------------------------------------===//
- const MemRegion *MemRegion::StripCasts(bool StripBaseAndDerivedCasts) const {
- const MemRegion *R = this;
- while (true) {
- switch (R->getKind()) {
- case ElementRegionKind: {
- const auto *ER = cast<ElementRegion>(R);
- if (!ER->getIndex().isZeroConstant())
- return R;
- R = ER->getSuperRegion();
- break;
- }
- case CXXBaseObjectRegionKind:
- case CXXDerivedObjectRegionKind:
- if (!StripBaseAndDerivedCasts)
- return R;
- R = cast<TypedValueRegion>(R)->getSuperRegion();
- break;
- default:
- return R;
- }
- }
- }
- const SymbolicRegion *MemRegion::getSymbolicBase() const {
- const auto *SubR = dyn_cast<SubRegion>(this);
- while (SubR) {
- if (const auto *SymR = dyn_cast<SymbolicRegion>(SubR))
- return SymR;
- SubR = dyn_cast<SubRegion>(SubR->getSuperRegion());
- }
- return nullptr;
- }
- RegionRawOffset ElementRegion::getAsArrayOffset() const {
- int64_t offset = 0;
- const ElementRegion *ER = this;
- const MemRegion *superR = nullptr;
- ASTContext &C = getContext();
- // FIXME: Handle multi-dimensional arrays.
- while (ER) {
- superR = ER->getSuperRegion();
- // FIXME: generalize to symbolic offsets.
- SVal index = ER->getIndex();
- if (auto CI = index.getAs<nonloc::ConcreteInt>()) {
- // Update the offset.
- int64_t i = CI->getValue().getSExtValue();
- if (i != 0) {
- QualType elemType = ER->getElementType();
- // If we are pointing to an incomplete type, go no further.
- if (elemType->isIncompleteType()) {
- superR = ER;
- break;
- }
- int64_t size = C.getTypeSizeInChars(elemType).getQuantity();
- if (auto NewOffset = llvm::checkedMulAdd(i, size, offset)) {
- offset = *NewOffset;
- } else {
- LLVM_DEBUG(llvm::dbgs() << "MemRegion::getAsArrayOffset: "
- << "offset overflowing, returning unknown\n");
- return nullptr;
- }
- }
- // Go to the next ElementRegion (if any).
- ER = dyn_cast<ElementRegion>(superR);
- continue;
- }
- return nullptr;
- }
- assert(superR && "super region cannot be NULL");
- return RegionRawOffset(superR, CharUnits::fromQuantity(offset));
- }
- /// Returns true if \p Base is an immediate base class of \p Child
- static bool isImmediateBase(const CXXRecordDecl *Child,
- const CXXRecordDecl *Base) {
- assert(Child && "Child must not be null");
- // Note that we do NOT canonicalize the base class here, because
- // ASTRecordLayout doesn't either. If that leads us down the wrong path,
- // so be it; at least we won't crash.
- for (const auto &I : Child->bases()) {
- if (I.getType()->getAsCXXRecordDecl() == Base)
- return true;
- }
- return false;
- }
- static RegionOffset calculateOffset(const MemRegion *R) {
- const MemRegion *SymbolicOffsetBase = nullptr;
- int64_t Offset = 0;
- while (true) {
- switch (R->getKind()) {
- case MemRegion::CodeSpaceRegionKind:
- case MemRegion::StackLocalsSpaceRegionKind:
- case MemRegion::StackArgumentsSpaceRegionKind:
- case MemRegion::HeapSpaceRegionKind:
- case MemRegion::UnknownSpaceRegionKind:
- case MemRegion::StaticGlobalSpaceRegionKind:
- case MemRegion::GlobalInternalSpaceRegionKind:
- case MemRegion::GlobalSystemSpaceRegionKind:
- case MemRegion::GlobalImmutableSpaceRegionKind:
- // Stores can bind directly to a region space to set a default value.
- assert(Offset == 0 && !SymbolicOffsetBase);
- goto Finish;
- case MemRegion::FunctionCodeRegionKind:
- case MemRegion::BlockCodeRegionKind:
- case MemRegion::BlockDataRegionKind:
- // These will never have bindings, but may end up having values requested
- // if the user does some strange casting.
- if (Offset != 0)
- SymbolicOffsetBase = R;
- goto Finish;
- case MemRegion::SymbolicRegionKind:
- case MemRegion::AllocaRegionKind:
- case MemRegion::CompoundLiteralRegionKind:
- case MemRegion::CXXThisRegionKind:
- case MemRegion::StringRegionKind:
- case MemRegion::ObjCStringRegionKind:
- case MemRegion::NonParamVarRegionKind:
- case MemRegion::ParamVarRegionKind:
- case MemRegion::CXXTempObjectRegionKind:
- // Usual base regions.
- goto Finish;
- case MemRegion::ObjCIvarRegionKind:
- // This is a little strange, but it's a compromise between
- // ObjCIvarRegions having unknown compile-time offsets (when using the
- // non-fragile runtime) and yet still being distinct, non-overlapping
- // regions. Thus we treat them as "like" base regions for the purposes
- // of computing offsets.
- goto Finish;
- case MemRegion::CXXBaseObjectRegionKind: {
- const auto *BOR = cast<CXXBaseObjectRegion>(R);
- R = BOR->getSuperRegion();
- QualType Ty;
- bool RootIsSymbolic = false;
- if (const auto *TVR = dyn_cast<TypedValueRegion>(R)) {
- Ty = TVR->getDesugaredValueType(R->getContext());
- } else if (const auto *SR = dyn_cast<SymbolicRegion>(R)) {
- // If our base region is symbolic, we don't know what type it really is.
- // Pretend the type of the symbol is the true dynamic type.
- // (This will at least be self-consistent for the life of the symbol.)
- Ty = SR->getSymbol()->getType()->getPointeeType();
- RootIsSymbolic = true;
- }
- const CXXRecordDecl *Child = Ty->getAsCXXRecordDecl();
- if (!Child) {
- // We cannot compute the offset of the base class.
- SymbolicOffsetBase = R;
- } else {
- if (RootIsSymbolic) {
- // Base layers on symbolic regions may not be type-correct.
- // Double-check the inheritance here, and revert to a symbolic offset
- // if it's invalid (e.g. due to a reinterpret_cast).
- if (BOR->isVirtual()) {
- if (!Child->isVirtuallyDerivedFrom(BOR->getDecl()))
- SymbolicOffsetBase = R;
- } else {
- if (!isImmediateBase(Child, BOR->getDecl()))
- SymbolicOffsetBase = R;
- }
- }
- }
- // Don't bother calculating precise offsets if we already have a
- // symbolic offset somewhere in the chain.
- if (SymbolicOffsetBase)
- continue;
- CharUnits BaseOffset;
- const ASTRecordLayout &Layout = R->getContext().getASTRecordLayout(Child);
- if (BOR->isVirtual())
- BaseOffset = Layout.getVBaseClassOffset(BOR->getDecl());
- else
- BaseOffset = Layout.getBaseClassOffset(BOR->getDecl());
- // The base offset is in chars, not in bits.
- Offset += BaseOffset.getQuantity() * R->getContext().getCharWidth();
- break;
- }
- case MemRegion::CXXDerivedObjectRegionKind: {
- // TODO: Store the base type in the CXXDerivedObjectRegion and use it.
- goto Finish;
- }
- case MemRegion::ElementRegionKind: {
- const auto *ER = cast<ElementRegion>(R);
- R = ER->getSuperRegion();
- QualType EleTy = ER->getValueType();
- if (EleTy->isIncompleteType()) {
- // We cannot compute the offset of the base class.
- SymbolicOffsetBase = R;
- continue;
- }
- SVal Index = ER->getIndex();
- if (Optional<nonloc::ConcreteInt> CI =
- Index.getAs<nonloc::ConcreteInt>()) {
- // Don't bother calculating precise offsets if we already have a
- // symbolic offset somewhere in the chain.
- if (SymbolicOffsetBase)
- continue;
- int64_t i = CI->getValue().getSExtValue();
- // This type size is in bits.
- Offset += i * R->getContext().getTypeSize(EleTy);
- } else {
- // We cannot compute offset for non-concrete index.
- SymbolicOffsetBase = R;
- }
- break;
- }
- case MemRegion::FieldRegionKind: {
- const auto *FR = cast<FieldRegion>(R);
- R = FR->getSuperRegion();
- assert(R);
- const RecordDecl *RD = FR->getDecl()->getParent();
- if (RD->isUnion() || !RD->isCompleteDefinition()) {
- // We cannot compute offset for incomplete type.
- // For unions, we could treat everything as offset 0, but we'd rather
- // treat each field as a symbolic offset so they aren't stored on top
- // of each other, since we depend on things in typed regions actually
- // matching their types.
- SymbolicOffsetBase = R;
- }
- // Don't bother calculating precise offsets if we already have a
- // symbolic offset somewhere in the chain.
- if (SymbolicOffsetBase)
- continue;
- // Get the field number.
- unsigned idx = 0;
- for (RecordDecl::field_iterator FI = RD->field_begin(),
- FE = RD->field_end(); FI != FE; ++FI, ++idx) {
- if (FR->getDecl() == *FI)
- break;
- }
- const ASTRecordLayout &Layout = R->getContext().getASTRecordLayout(RD);
- // This is offset in bits.
- Offset += Layout.getFieldOffset(idx);
- break;
- }
- }
- }
- Finish:
- if (SymbolicOffsetBase)
- return RegionOffset(SymbolicOffsetBase, RegionOffset::Symbolic);
- return RegionOffset(R, Offset);
- }
- RegionOffset MemRegion::getAsOffset() const {
- if (!cachedOffset)
- cachedOffset = calculateOffset(this);
- return *cachedOffset;
- }
- //===----------------------------------------------------------------------===//
- // BlockDataRegion
- //===----------------------------------------------------------------------===//
- std::pair<const VarRegion *, const VarRegion *>
- BlockDataRegion::getCaptureRegions(const VarDecl *VD) {
- MemRegionManager &MemMgr = getMemRegionManager();
- const VarRegion *VR = nullptr;
- const VarRegion *OriginalVR = nullptr;
- if (!VD->hasAttr<BlocksAttr>() && VD->hasLocalStorage()) {
- VR = MemMgr.getNonParamVarRegion(VD, this);
- OriginalVR = MemMgr.getVarRegion(VD, LC);
- }
- else {
- if (LC) {
- VR = MemMgr.getVarRegion(VD, LC);
- OriginalVR = VR;
- }
- else {
- VR = MemMgr.getNonParamVarRegion(VD, MemMgr.getUnknownRegion());
- OriginalVR = MemMgr.getVarRegion(VD, LC);
- }
- }
- return std::make_pair(VR, OriginalVR);
- }
- void BlockDataRegion::LazyInitializeReferencedVars() {
- if (ReferencedVars)
- return;
- AnalysisDeclContext *AC = getCodeRegion()->getAnalysisDeclContext();
- const auto &ReferencedBlockVars = AC->getReferencedBlockVars(BC->getDecl());
- auto NumBlockVars =
- std::distance(ReferencedBlockVars.begin(), ReferencedBlockVars.end());
- if (NumBlockVars == 0) {
- ReferencedVars = (void*) 0x1;
- return;
- }
- MemRegionManager &MemMgr = getMemRegionManager();
- llvm::BumpPtrAllocator &A = MemMgr.getAllocator();
- BumpVectorContext BC(A);
- using VarVec = BumpVector<const MemRegion *>;
- auto *BV = A.Allocate<VarVec>();
- new (BV) VarVec(BC, NumBlockVars);
- auto *BVOriginal = A.Allocate<VarVec>();
- new (BVOriginal) VarVec(BC, NumBlockVars);
- for (const auto *VD : ReferencedBlockVars) {
- const VarRegion *VR = nullptr;
- const VarRegion *OriginalVR = nullptr;
- std::tie(VR, OriginalVR) = getCaptureRegions(VD);
- assert(VR);
- assert(OriginalVR);
- BV->push_back(VR, BC);
- BVOriginal->push_back(OriginalVR, BC);
- }
- ReferencedVars = BV;
- OriginalVars = BVOriginal;
- }
- BlockDataRegion::referenced_vars_iterator
- BlockDataRegion::referenced_vars_begin() const {
- const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars();
- auto *Vec = static_cast<BumpVector<const MemRegion *> *>(ReferencedVars);
- if (Vec == (void*) 0x1)
- return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr);
- auto *VecOriginal =
- static_cast<BumpVector<const MemRegion *> *>(OriginalVars);
- return BlockDataRegion::referenced_vars_iterator(Vec->begin(),
- VecOriginal->begin());
- }
- BlockDataRegion::referenced_vars_iterator
- BlockDataRegion::referenced_vars_end() const {
- const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars();
- auto *Vec = static_cast<BumpVector<const MemRegion *> *>(ReferencedVars);
- if (Vec == (void*) 0x1)
- return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr);
- auto *VecOriginal =
- static_cast<BumpVector<const MemRegion *> *>(OriginalVars);
- return BlockDataRegion::referenced_vars_iterator(Vec->end(),
- VecOriginal->end());
- }
- const VarRegion *BlockDataRegion::getOriginalRegion(const VarRegion *R) const {
- for (referenced_vars_iterator I = referenced_vars_begin(),
- E = referenced_vars_end();
- I != E; ++I) {
- if (I.getCapturedRegion() == R)
- return I.getOriginalRegion();
- }
- return nullptr;
- }
- //===----------------------------------------------------------------------===//
- // RegionAndSymbolInvalidationTraits
- //===----------------------------------------------------------------------===//
- void RegionAndSymbolInvalidationTraits::setTrait(SymbolRef Sym,
- InvalidationKinds IK) {
- SymTraitsMap[Sym] |= IK;
- }
- void RegionAndSymbolInvalidationTraits::setTrait(const MemRegion *MR,
- InvalidationKinds IK) {
- assert(MR);
- if (const auto *SR = dyn_cast<SymbolicRegion>(MR))
- setTrait(SR->getSymbol(), IK);
- else
- MRTraitsMap[MR] |= IK;
- }
- bool RegionAndSymbolInvalidationTraits::hasTrait(SymbolRef Sym,
- InvalidationKinds IK) const {
- const_symbol_iterator I = SymTraitsMap.find(Sym);
- if (I != SymTraitsMap.end())
- return I->second & IK;
- return false;
- }
- bool RegionAndSymbolInvalidationTraits::hasTrait(const MemRegion *MR,
- InvalidationKinds IK) const {
- if (!MR)
- return false;
- if (const auto *SR = dyn_cast<SymbolicRegion>(MR))
- return hasTrait(SR->getSymbol(), IK);
- const_region_iterator I = MRTraitsMap.find(MR);
- if (I != MRTraitsMap.end())
- return I->second & IK;
- return false;
- }
|