24#include "llvm/ADT/ArrayRef.h"
25#include "llvm/ADT/STLExtras.h"
26#include "llvm/Support/Casting.h"
27#include "llvm/Support/Signals.h"
28#include "llvm/Support/TimeProfiler.h"
31using llvm::isa_and_present;
33OriginList *FactsGenerator::getOriginsList(
const ValueDecl &D) {
34 return FactMgr.getOriginMgr().getOrCreateList(&D);
36OriginList *FactsGenerator::getOriginsList(
const Expr &E) {
37 return FactMgr.getOriginMgr().getOrCreateList(&E);
40bool FactsGenerator::hasOrigins(QualType QT)
const {
41 return FactMgr.getOriginMgr().hasOrigins(QT);
44bool FactsGenerator::hasOrigins(
const Expr *E)
const {
45 return FactMgr.getOriginMgr().hasOrigins(E);
65 "Dst is non-null but Src is null. List must have the same length");
66 assert(Dst->getLength() == Src->getLength() &&
67 "Lists must have the same length");
70 CurrentBlockFacts.push_back(FactMgr.createFact<OriginFlowFact>(
71 Dst->getOuterOriginID(), Src->getOuterOriginID(), Kill));
72 Dst = Dst->peelOuterOrigin();
73 Src = Src->peelOuterOrigin();
98 llvm::TimeTraceScope TimeProfile(
"FactGenerator");
99 const CFG &Cfg = *AC.getCFG();
104 CurrentBlockFacts.clear();
105 EscapesInCurrentBlock.clear();
106 CurrentBlock =
Block;
108 CurrentBlockFacts.append(PlaceholderLoanFacts.begin(),
109 PlaceholderLoanFacts.end());
110 for (
unsigned I = 0; I <
Block->size(); ++I) {
112 if (std::optional<CFGStmt> CS = Element.
getAs<
CFGStmt>())
113 Visit(CS->getStmt());
114 else if (std::optional<CFGInitializer>
Initializer =
116 handleCXXCtorInitializer(
Initializer->getInitializer());
117 else if (std::optional<CFGLifetimeEnds> LifetimeEnds =
119 handleLifetimeEnds(*LifetimeEnds);
120 else if (std::optional<CFGFullExprCleanup> FullExprCleanup =
122 handleFullExprCleanup(*FullExprCleanup);
128 CurrentBlockFacts.append(EscapesInCurrentBlock.begin(),
129 EscapesInCurrentBlock.end());
130 FactMgr.addBlockFacts(
Block, CurrentBlockFacts);
149 if (
const auto *VD = dyn_cast<VarDecl>(D))
150 if (
const Expr *InitExpr = VD->getInit()) {
154 OriginList *InitList = getOriginsList(*InitExpr);
155 assert(InitList &&
"VarDecl had origins but InitExpr did not");
156 flow(VDList, InitList,
true);
179 "gl-value DRE of non-pointer type should have an origin list");
182 CurrentBlockFacts.push_back(
189 handleGSLPointerConstruction(CCE);
200 flow(getOriginsList(*CCE), ArgList,
true);
210 flow(getOriginsList(*CCE), ArgList,
true);
215 {CCE->getArgs(), CCE->getNumArgs()},
221 killAndFlowOrigin(*DIE, *
Init);
228 killAndFlowOrigin(*FD, *CII->
getInit());
239 {MCE->getImplicitObjectArgument()},
250 handleFunctionCall(MCE,
Method, Args,
false);
257 assert(ME->
isGLValue() &&
"Field member should be GL value");
259 assert(Dst &&
"Field member should have an origin list as it is GL value");
261 assert(Src &&
"Base expression should be a pointer/reference type");
272 {CE->getArgs(), CE->getNumArgs()});
290 case CK_LValueToRValue:
294 assert(Src &&
"LValue being cast to RValue has no origin list");
302 case CK_NullToPointer:
307 case CK_ConstructorConversion:
308 case CK_UserDefinedConversion:
309 flow(Dest, Src,
true);
311 case CK_UncheckedDerivedToBase:
312 case CK_DerivedToBase:
316 flow(Dest, Src,
true);
318 case CK_ArrayToPointerDecay:
319 assert(Src &&
"Array expression should have origins as it is GL value");
323 case CK_FunctionToPointerDecay:
324 case CK_BuiltinFnToFnPtr:
340 killAndFlowOrigin(*UO, *SubExpr);
345 killAndFlowOrigin(*UO, *SubExpr);
355 if (
OriginList *List = getOriginsList(*RetExpr))
358 L->getOuterOriginID(), RetExpr));
362void FactsGenerator::handleAssignment(
const Expr *LHSExpr,
363 const Expr *RHSExpr) {
367 if (
const auto *DRE_LHS = dyn_cast<DeclRefExpr>(LHSExpr)) {
368 LHSList = getOriginsList(*DRE_LHS);
369 assert(LHSList &&
"LHS is a DRE and should have an origin list");
374 if (
const auto *ME_LHS = dyn_cast<MemberExpr>(LHSExpr)) {
375 LHSList = getOriginsList(*ME_LHS);
376 assert(LHSList &&
"LHS is a MemberExpr and should have an origin list");
380 OriginList *RHSList = getOriginsList(*RHSExpr);
388 if (
const auto *DRE_LHS = dyn_cast<DeclRefExpr>(LHSExpr)) {
389 QualType QT = DRE_LHS->getDecl()->getType();
396 if (UseFact *UF = UseFacts.lookup(DRE_LHS)) {
397 const OriginList *FullList = UF->getUsedOrigins();
400 FullList->getOuterOriginID()));
401 if (
const OriginList *InnerList = FullList->peelOuterOrigin()) {
402 UseFact *WriteUF = FactMgr.
createFact<UseFact>(DRE_LHS, InnerList);
403 WriteUF->markAsWritten();
404 CurrentBlockFacts.push_back(WriteUF);
409 markUseAsWrite(DRE_LHS);
416 CurrentBlockFacts.push_back(
417 FactMgr.createFact<KillOriginFact>(LHSInner->getOuterOriginID()));
425void FactsGenerator::handlePointerArithmetic(
const BinaryOperator *BO) {
426 if (Expr *RHS = BO->getRHS(); RHS->getType()->isPointerType()) {
427 killAndFlowOrigin(*BO, *RHS);
430 Expr *LHS = BO->getLHS();
431 assert(LHS->getType()->isPointerType() &&
432 "Pointer arithmetic must have a pointer operand");
433 killAndFlowOrigin(*BO, *LHS);
440 handlePointerArithmetic(BO);
454 const auto Preds = CurrentBlock->preds();
458 bool TBHasEdge =
true;
459 bool FBHasEdge =
true;
461 switch (CurrentBlock->pred_size()) {
465 TBHasEdge = llvm::any_of(**Preds.begin(),
468 if (auto CS = Elt.getAs<CFGStmt>())
469 return CS->getStmt() == ExpectedStmt;
472 FBHasEdge = !TBHasEdge;
476 const auto *It = Preds.begin();
477 TBHasEdge = It->isReachable();
478 FBHasEdge = (++It)->isReachable();
482 llvm_unreachable(
"expected at most 2 predecessors");
486 bool FirstFlow =
true;
487 auto HandleFlow = [&](
const Expr *E) {
489 killAndFlowOrigin(*CO, *E);
497 HandleFlow(TrueExpr);
499 HandleFlow(FalseExpr);
525 MD && MD->isDefaulted()) {
535 Args = Args.slice(1);
543 if (handleTestPoint(FCE))
549 if (!hasOrigins(ILE))
554 killAndFlowOrigin(*ILE, *ILE->
getInit(0));
569 assert((!SubExprList ||
571 "MTE top level origin should contain a loan to the MTE itself");
574 flow(RValMTEList, SubExprList,
true);
579 CurrentBlockFacts.push_back(
592 for (
const Expr *
Init : LE->capture_inits()) {
609 assert(ASE->
isGLValue() &&
"Array subscript should be a GL value");
611 assert(Dst &&
"Array subscript should have origins as it is a GL value");
613 assert(Src &&
"Base of array subscript should have origins");
618bool FactsGenerator::escapesViaReturn(
OriginID OID)
const {
619 return llvm::any_of(EscapesInCurrentBlock, [OID](
const Fact *F) {
621 return EF->getEscapedOriginID() == OID;
626void FactsGenerator::handleLifetimeEnds(
const CFGLifetimeEnds &LifetimeEnds) {
632 std::optional<OriginID> ExpiredOID;
633 if (OriginList *List = getOriginsList(*LifetimeEndsVD)) {
634 OriginID OID = List->getOuterOriginID();
637 if (!escapesViaReturn(OID))
640 CurrentBlockFacts.push_back(FactMgr.
createFact<ExpireFact>(
645void FactsGenerator::handleFullExprCleanup(
646 const CFGFullExprCleanup &FullExprCleanup) {
647 for (
const auto *MTE : FullExprCleanup.getExpiringMTEs())
648 CurrentBlockFacts.push_back(
649 FactMgr.createFact<ExpireFact>(AccessPath(MTE), MTE->getEndLoc()));
652void FactsGenerator::handleExitBlock() {
653 for (
const Origin &O : FactMgr.getOriginMgr().getOrigins())
654 if (
auto *FD = dyn_cast_if_present<FieldDecl>(O.getDecl()))
656 EscapesInCurrentBlock.push_back(
657 FactMgr.createFact<FieldEscapeFact>(O.ID, FD));
658 else if (
auto *VD = dyn_cast_if_present<VarDecl>(O.getDecl())) {
661 if (VD->hasGlobalStorage()) {
662 EscapesInCurrentBlock.push_back(
663 FactMgr.createFact<GlobalEscapeFact>(O.ID, VD));
668void FactsGenerator::handleGSLPointerConstruction(
const CXXConstructExpr *CCE) {
670 if (CCE->getNumArgs() != 1)
673 const Expr *Arg = CCE->getArg(0);
675 OriginList *ArgList = getOriginsList(*Arg);
676 assert(ArgList &&
"GSL pointer argument should have an origin list");
682 flow(getOriginsList(*CCE), ArgList,
true);
683 }
else if (Arg->getType()->isPointerType()) {
688 OriginList *ArgList = getOriginsList(*Arg);
689 CurrentBlockFacts.push_back(FactMgr.createFact<OriginFlowFact>(
690 getOriginsList(*CCE)->getOuterOriginID(), ArgList->getOuterOriginID(),
695 handleFunctionCall(CCE, CCE->getConstructor(),
696 {CCE->getArgs(), CCE->getNumArgs()},
701void FactsGenerator::handleMovedArgsInCall(
const FunctionDecl *FD,
702 ArrayRef<const Expr *> Args) {
703 unsigned IsInstance = 0;
704 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD);
711 const Expr *UniquePtrExpr = Args[0];
712 OriginList *MovedOrigins = getOriginsList(*UniquePtrExpr);
714 CurrentBlockFacts.push_back(FactMgr.createFact<MovedOriginFact>(
715 UniquePtrExpr, MovedOrigins->getOuterOriginID()));
720 for (
unsigned I = IsInstance;
721 I < Args.size() && I < FD->getNumParams() + IsInstance; ++I) {
722 const ParmVarDecl *PVD = FD->getParamDecl(I - IsInstance);
723 if (!PVD->getType()->isRValueReferenceType())
725 const Expr *Arg = Args[I];
726 OriginList *MovedOrigins = getOriginsList(*Arg);
727 assert(MovedOrigins->getLength() >= 1 &&
728 "unexpected length for r-value reference param");
730 CurrentBlockFacts.push_back(FactMgr.createFact<MovedOriginFact>(
731 Arg, MovedOrigins->getOuterOriginID()));
735void FactsGenerator::handleInvalidatingCall(
const Expr *
Call,
736 const FunctionDecl *FD,
737 ArrayRef<const Expr *> Args) {
738 const auto *MD = dyn_cast<CXXMethodDecl>(FD);
739 if (!MD || !MD->isInstance())
745 auto *DRE = dyn_cast<DeclRefExpr>(Args[0]);
746 if (!DRE || DRE->getDecl()->getType()->isReferenceType())
749 OriginList *ThisList = getOriginsList(*Args[0]);
751 CurrentBlockFacts.push_back(FactMgr.createFact<InvalidateOriginFact>(
752 ThisList->getOuterOriginID(),
Call));
755void FactsGenerator::handleImplicitObjectFieldUses(
const Expr *
Call,
756 const FunctionDecl *FD) {
757 const auto *MemberCall = dyn_cast_or_null<CXXMemberCallExpr>(
Call);
761 if (!isa_and_present<CXXThisExpr>(
762 MemberCall->getImplicitObjectArgument()->IgnoreImpCasts()))
765 const auto *MD = dyn_cast<CXXMethodDecl>(FD);
766 assert(MD &&
"Function must be a CXXMethodDecl for member calls");
768 const auto *ClassDecl = MD->getParent()->getDefinition();
772 const auto UseFields = [&](
const CXXRecordDecl *RD) {
773 for (
const auto *Field : RD->fields())
774 if (
auto *FieldList = getOriginsList(*Field))
775 CurrentBlockFacts.push_back(
776 FactMgr.createFact<UseFact>(
Call, FieldList));
779 UseFields(ClassDecl);
781 ClassDecl->forallBases([&](
const CXXRecordDecl *Base) {
787void FactsGenerator::handleFunctionCall(
const Expr *
Call,
788 const FunctionDecl *FD,
789 ArrayRef<const Expr *> Args,
790 bool IsGslConstruction) {
791 OriginList *CallList = getOriginsList(*
Call);
797 for (
const Expr *Arg : Args)
799 handleInvalidatingCall(
Call, FD, Args);
800 handleMovedArgsInCall(FD, Args);
801 handleImplicitObjectFieldUses(
Call, FD);
804 auto IsArgLifetimeBound = [FD](
unsigned I) ->
bool {
805 const ParmVarDecl *PVD =
nullptr;
806 if (
const auto *
Method = dyn_cast<CXXMethodDecl>(FD);
813 if ((I - 1) <
Method->getNumParams())
816 PVD =
Method->getParamDecl(I - 1);
819 }
else if (I < FD->getNumParams()) {
821 PVD = FD->getParamDecl(I);
823 return PVD ? PVD->hasAttr<clang::LifetimeBoundAttr>() :
false;
825 auto shouldTrackPointerImplicitObjectArg = [FD](
unsigned I) ->
bool {
826 const auto *
Method = dyn_cast<CXXMethodDecl>(FD);
837 for (
unsigned I = 0; I < Args.size(); ++I) {
838 OriginList *ArgList = getOriginsList(*Args[I]);
841 if (IsGslConstruction) {
845 assert(!Args[I]->isGLValue() || ArgList->getLength() >= 2);
852 CurrentBlockFacts.push_back(FactMgr.createFact<OriginFlowFact>(
853 CallList->getOuterOriginID(), ArgList->getOuterOriginID(),
856 }
else if (IsArgLifetimeBound(I)) {
863 CurrentBlockFacts.push_back(FactMgr.createFact<OriginFlowFact>(
864 CallList->getOuterOriginID(), ArgList->getOuterOriginID(),
868 }
else if (shouldTrackPointerImplicitObjectArg(I)) {
869 assert(ArgList->getLength() >= 2 &&
870 "Object arg of pointer type should have atleast two origins");
872 CurrentBlockFacts.push_back(FactMgr.createFact<OriginFlowFact>(
873 CallList->getOuterOriginID(),
874 ArgList->peelOuterOrigin()->getOuterOriginID(), KillSrc));
876 }
else if (IsArgLifetimeBound(I)) {
880 CurrentBlockFacts.push_back(FactMgr.createFact<OriginFlowFact>(
881 CallList->getOuterOriginID(), ArgList->getOuterOriginID(), KillSrc));
889bool FactsGenerator::handleTestPoint(
const CXXFunctionalCastExpr *FCE) {
890 if (!FCE->getType()->isVoidType())
893 const auto *SubExpr = FCE->getSubExpr()->IgnoreParenImpCasts();
894 if (
const auto *SL = dyn_cast<StringLiteral>(SubExpr)) {
895 llvm::StringRef LiteralValue = SL->getString();
896 const std::string Prefix =
"__lifetime_test_point_";
898 if (LiteralValue.starts_with(Prefix)) {
899 StringRef Annotation = LiteralValue.drop_front(Prefix.length());
900 CurrentBlockFacts.push_back(
901 FactMgr.createFact<TestPointFact>(Annotation));
908void FactsGenerator::handleUse(
const Expr *E) {
909 OriginList *List = getOriginsList(*E);
915 if (
auto *DRE = dyn_cast<DeclRefExpr>(E);
916 DRE && !DRE->getDecl()->
getType()->isReferenceType())
921 if (!UseFacts.contains(E)) {
922 UseFact *UF = FactMgr.createFact<UseFact>(E, List);
923 CurrentBlockFacts.push_back(UF);
928void FactsGenerator::markUseAsWrite(
const DeclRefExpr *DRE) {
929 if (UseFacts.contains(DRE))
930 UseFacts[DRE]->markAsWritten();
935llvm::SmallVector<Fact *> FactsGenerator::issuePlaceholderLoans() {
936 const auto *FD = dyn_cast<FunctionDecl>(AC.getDecl());
940 llvm::SmallVector<Fact *> PlaceholderLoanFacts;
941 if (
auto ThisOrigins = FactMgr.getOriginMgr().getThisOrigins()) {
942 OriginList *List = *ThisOrigins;
943 const Loan *L = FactMgr.getLoanMgr().createLoan(
946 PlaceholderLoanFacts.push_back(
947 FactMgr.createFact<IssueFact>(L->getID(), List->getOuterOriginID()));
949 for (
const ParmVarDecl *PVD : FD->parameters()) {
950 OriginList *List = getOriginsList(*PVD);
953 const Loan *L = FactMgr.getLoanMgr().createLoan(
955 PlaceholderLoanFacts.push_back(
956 FactMgr.createFact<IssueFact>(L->getID(), List->getOuterOriginID()));
958 return PlaceholderLoanFacts;
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::Expr interface and subclasses for C++ expressions.
Defines an enumeration for C++ overloaded operators.
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
A builtin binary operation expression such as "x + y" or "x <= y".
static bool isAdditiveOp(Opcode Opc)
static bool isAssignmentOp(Opcode Opc)
static bool isCompoundAssignmentOp(Opcode Opc)
Represents a single basic block in a source-level CFG.
Represents a top-level expression in a basic block.
std::optional< T > getAs() const
Convert to the specified CFGElement type, returning std::nullopt if this CFGElement is not of the des...
Represents C++ base or member initializer from constructor's initialization list.
Represents the point where the lifetime of an automatic object ends.
const Stmt * getTriggerStmt() const
const VarDecl * getVarDecl() const
Represents a source-level, intra-procedural CFG that represents the control-flow of a Stmt.
Represents binding an expression to a temporary.
const Expr * getSubExpr() const
Represents a call to a C++ constructor.
Expr * getArg(unsigned Arg)
Return the specified argument.
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
unsigned getNumArgs() const
Return the number of arguments to the constructor call.
bool isCopyOrMoveConstructor(unsigned &TypeQuals) const
Determine whether this is a copy or move constructor.
Represents a C++ base or member initializer.
Expr * getInit() const
Get the initializer.
FieldDecl * getAnyMember() const
A use of a default initializer in a constructor or in aggregate initialization.
Expr * getExpr()
Get the initialization expression that will be used.
Represents an explicit C++ type conversion that uses "functional" notation (C++ [expr....
Represents a call to a member function that may be written either with member call syntax (e....
CXXMethodDecl * getMethodDecl() const
Retrieve the declaration of the called method.
Expr * getImplicitObjectArgument() const
Retrieve the implicit object argument for the member call.
Represents a static or instance method of a struct/union/class.
The null pointer literal (C++11 [lex.nullptr])
A call to an overloaded operator written using operator syntax.
OverloadedOperatorKind getOperator() const
Returns the kind of overloaded operator that this expression refers to.
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return null.
unsigned getNumArgs() const
getNumArgs - Return the number of actual arguments to this call.
Expr ** getArgs()
Retrieve the call arguments.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
CastKind getCastKind() const
ConditionalOperator - The ?
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
A reference to a declared variable, function, enum, etc.
NamedDecl * getFoundDecl()
Get the NamedDecl through which this reference occurred.
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Decl - This represents one declaration (or definition), e.g.
bool isFunctionOrFunctionTemplate() const
Whether this declaration is a function or function template.
This represents one expression.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Represents a member of a struct/union/class.
bool isDefaulted() const
Whether this function is defaulted.
Describes an C or C++ initializer list.
unsigned getNumInits() const
const Expr * getInit(unsigned Init) const
A C++ lambda expression, which produces a function object (of unspecified type) that can be invoked l...
Represents a prvalue temporary that is written into memory so that a reference can bind to it.
StorageDuration getStorageDuration() const
Retrieve the storage duration for the materialized temporary.
Expr * getSubExpr() const
Retrieve the temporary-generating subexpression whose value will be materialized into a glvalue.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
A (possibly-)qualified type.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
RetTy Visit(PTR(Stmt) S, ParamTys... P)
SourceLocation getEndLoc() const LLVM_READONLY
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool isPointerType() const
bool isReferenceType() const
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isPointerOrReferenceType() const
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Expr * getSubExpr() const
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.
Represents the storage location being borrowed, e.g., a specific stack variable or a field within it:...
static AccessPath Placeholder(const ParmVarDecl *PVD)
FactType * createFact(Args &&...args)
OriginManager & getOriginMgr()
LoanManager & getLoanMgr()
An abstract base class for a single, atomic lifetime-relevant event.
void VisitDeclRefExpr(const DeclRefExpr *DRE)
void VisitBinaryOperator(const BinaryOperator *BO)
void VisitCallExpr(const CallExpr *CE)
void VisitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *MTE)
void VisitCastExpr(const CastExpr *CE)
void VisitReturnStmt(const ReturnStmt *RS)
void VisitCXXConstructExpr(const CXXConstructExpr *CCE)
void VisitMemberExpr(const MemberExpr *ME)
void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *FCE)
void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *DIE)
void VisitInitListExpr(const InitListExpr *ILE)
void VisitLambdaExpr(const LambdaExpr *LE)
void VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *N)
void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *OCE)
void VisitArraySubscriptExpr(const ArraySubscriptExpr *ASE)
void VisitUnaryOperator(const UnaryOperator *UO)
void VisitDeclStmt(const DeclStmt *DS)
void VisitConditionalOperator(const ConditionalOperator *CO)
void VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE)
void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE)
Loan * createLoan(AccessPath Path, const Expr *IssueExpr)
Represents lending a storage location.
A list of origins representing levels of indirection for pointer-like types.
OriginID getOuterOriginID() const
OriginList * peelOuterOrigin() const
OriginList * createSingleOriginList(OriginID OID)
Wraps an existing OriginID in a new single-element OriginList, so a fact can refer to a single level ...
Represents that an origin escapes via a return statement.
utils::ID< struct OriginTag > OriginID
static OriginList * getRValueOrigins(const Expr *E, OriginList *List)
Simulates LValueToRValue conversion by peeling the outer lvalue origin if the expression is a GLValue...
bool doesDeclHaveStorage(const ValueDecl *D)
Returns true if the declaration has its own storage that can be borrowed.
static const Loan * createLoan(FactManager &FactMgr, const DeclRefExpr *DRE)
Creates a loan for the storage path of a given declaration reference.
bool isGslPointerType(QualType QT)
bool isStdCallableWrapperType(const CXXRecordDecl *RD)
bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee, bool RunningUnderLifetimeSafety)
bool shouldTrackFirstArgument(const FunctionDecl *FD)
bool isContainerInvalidationMethod(const CXXMethodDecl &MD)
bool isUniquePtrRelease(const CXXMethodDecl &MD)
bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD)
const FunctionDecl * getDeclWithMergedLifetimeBoundAttrs(const FunctionDecl *FD)
bool isGslOwnerType(QualType QT)
bool isa(CodeGen::Address addr)
@ SD_FullExpression
Full-expression storage duration (for temporaries).
U cast(CodeGen::Address addr)
llvm::Expected< Stmt * > ExpectedStmt