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);
70 const CFGBlock *
Block) {
74 "Dst is non-null but Src is null. List must have the same length");
75 assert(Dst->getLength() == Src->getLength() &&
76 "Lists must have the same length");
79 Fact *F = FactMgr.createFact<OriginFlowFact>(Dst->getOuterOriginID(),
80 Src->getOuterOriginID(), Kill);
82 FactMgr.appendBlockFact(
Block, F);
84 CurrentBlockFacts.push_back(F);
85 Dst = Dst->peelOuterOrigin();
86 Src = Src->peelOuterOrigin();
98 const Expr *IssueExpr) {
120 llvm::TimeTraceScope TimeProfile(
"FactGenerator");
121 const CFG &Cfg = *AC.getCFG();
126 CurrentBlockFacts.clear();
127 EscapesInCurrentBlock.clear();
128 CurrentBlock =
Block;
130 CurrentBlockFacts.append(PlaceholderLoanFacts.begin(),
131 PlaceholderLoanFacts.end());
132 for (
unsigned I = 0; I <
Block->size(); ++I) {
134 if (std::optional<CFGStmt> CS = Element.
getAs<
CFGStmt>())
135 Visit(CS->getStmt());
136 else if (std::optional<CFGInitializer>
Initializer =
138 handleCXXCtorInitializer(
Initializer->getInitializer());
139 else if (std::optional<CFGLifetimeEnds> LifetimeEnds =
141 handleLifetimeEnds(*LifetimeEnds);
142 else if (std::optional<CFGFullExprCleanup> FullExprCleanup =
144 handleFullExprCleanup(*FullExprCleanup);
150 CurrentBlockFacts.append(EscapesInCurrentBlock.begin(),
151 EscapesInCurrentBlock.end());
152 FactMgr.addBlockFacts(
Block, CurrentBlockFacts);
154 FactMgr.computePersistentOrigins(Cfg);
169 if (
const auto *VD = dyn_cast<VarDecl>(D))
170 if (
const Expr *InitExpr = VD->getInit()) {
174 OriginList *InitList = getOriginsList(*InitExpr);
175 assert(InitList &&
"VarDecl had origins but InitExpr did not");
176 flow(VDList, InitList,
true);
198 "gl-value DRE of non-pointer type should have an origin list");
201 CurrentBlockFacts.push_back(
208 handleGSLPointerConstruction(CCE);
219 flow(getOriginsList(*CCE), ArgList,
true);
229 flow(getOriginsList(*CCE), ArgList,
true);
233 handleFunctionCall(CCE,
false);
238 killAndFlowOrigin(*DIE, *
Init);
245 killAndFlowOrigin(*FD, *CII->
getInit());
254 handleFunctionCall(MCE,
true);
257 handleFunctionCall(MCE,
false);
266 assert(List &&
"gl-value static member should have an origin list");
267 CurrentBlockFacts.push_back(
272 assert(ME->
isGLValue() &&
"Field member should be GL value");
274 assert(Dst &&
"Field member should have an origin list as it is GL value");
276 assert(Src &&
"Base expression should be a pointer/reference type");
286 handleFunctionCall(CE);
300 OriginList *Src = Dest ? getOriginsList(*SubExpr) :
nullptr;
303 case CK_LValueToRValue:
307 flow(Dest, readValue(SubExpr),
true);
310 handleAccess(SubExpr);
312 case CK_NullToPointer:
316 case CK_ConstructorConversion:
317 case CK_UserDefinedConversion:
318 flow(Dest, Src,
true);
320 case CK_UncheckedDerivedToBase:
321 case CK_DerivedToBase:
322 case CK_BaseToDerived:
328 flow(Dest, Src,
true);
330 case CK_ArrayToPointerDecay:
335 assert(Src &&
"Array expression should have origins as it is GL value");
339 case CK_FunctionToPointerDecay:
340 case CK_BuiltinFnToFnPtr:
347 flow(Dest, Src,
true);
349 case CK_LValueToRValueBitCast:
350 case CK_NonAtomicToAtomic:
351 case CK_AtomicToNonAtomic: {
360 flow(Dest, RVSrc,
true);
380 "Taking address of void is not valid in C++");
385 killAndFlowOrigin(*UO, *SubExpr);
390 killAndFlowOrigin(*UO, *SubExpr);
400 flow(getOriginsList(*UO), readValue(SubExpr),
true);
414 flow(getOriginsList(*UO),
425 if (
OriginList *List = getOriginsList(*RetExpr))
428 L->getOuterOriginID(), RetExpr));
432void FactsGenerator::handleAssignment(
const Expr *TargetExpr,
434 const Expr *RHSExpr) {
436 handleAccess(LHSExpr);
440 if (
const auto *DRE_LHS = dyn_cast<DeclRefExpr>(LHSExpr)) {
441 LHSList = getOriginsList(*DRE_LHS);
442 assert(LHSList &&
"LHS is a DRE and should have an origin list");
447 if (
const auto *ME_LHS = dyn_cast<MemberExpr>(LHSExpr)) {
448 LHSList = getOriginsList(*ME_LHS);
449 assert(LHSList &&
"LHS is a MemberExpr and should have an origin list");
459 CurrentBlockFacts.push_back(
460 FactMgr.
createFact<KillOriginFact>(LHSInner->getOuterOriginID()));
471 flow(getOriginsList(*TargetExpr), LHSList,
true);
474void FactsGenerator::handlePointerArithmetic(
const BinaryOperator *BO) {
475 if (Expr *RHS = BO->getRHS(); RHS->getType()->isPointerType()) {
476 killAndFlowOrigin(*BO, *RHS);
479 Expr *LHS = BO->getLHS();
480 assert(LHS->getType()->isPointerType() &&
481 "Pointer arithmetic must have a pointer operand");
482 killAndFlowOrigin(*BO, *LHS);
498 ? getOriginsList(*BO->
getLHS())
499 : readValue(BO->
getLHS());
506 killAndFlowOrigin(*BO, *BO->
getRHS());
510 handleAccess(BO->
getLHS());
516 flow(getOriginsList(*BO), IsCMode ? LHSList->
peelOuterOrigin() : LHSList,
522 handlePointerArithmetic(BO);
529 const Expr *ArmExpr) {
533 if (
const auto *OVE = dyn_cast<OpaqueValueExpr>(
Target))
534 if (
const Expr *Src = OVE->getSourceExpr())
535 Target = Src->IgnoreParenImpCasts();
541 if (
auto CS = Elt.getAs<
CFGStmt>())
542 if (
const auto *E = dyn_cast<Expr>(CS->getStmt()))
565 flow(getOriginsList(*CO), getOriginsList(*TrueExpr),
true, TBPred);
567 flow(getOriginsList(*CO), getOriginsList(*FalseExpr),
true,
594 MD && MD->isDefaulted()) {
600 handleFunctionCall(OCE);
607 if (handleTestPoint(FCE))
613 if (!hasOrigins(ILE))
620 if (!hasOrigins(ILE->
getInit(0)))
622 killAndFlowOrigin(*ILE, *ILE->
getInit(0));
638 assert((!SubExprList ||
640 "MTE top level origin should contain a loan to the MTE itself");
643 flow(RValMTEList, SubExprList,
true);
646 CurrentBlockFacts.push_back(
654 ExtendedTemporaries[ExtendingDecl].push_back(MTE);
659 if (
C.capturesThis())
660 FactMgr.setThisCapturedByLambda();
661 else if (
C.capturesVariable() &&
C.getCapturedVar()->isInitCapture()) {
665 if (
const auto *ME = dyn_cast<MemberExpr>(
Init->IgnoreParenImpCasts())) {
666 if (
const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl()))
667 FactMgr.addCapturedField(FD);
679 for (
const Expr *
Init : LE->capture_inits()) {
702 assert(ASE->
isGLValue() &&
"Array subscript should be a GL value");
704 assert(Dst &&
"Array subscript should have origins as it is a GL value");
706 assert(Src &&
"Base of array subscript should have origins");
711bool FactsGenerator::handlePlacementNew(
const CXXNewExpr *NE,
717 if (NE->getNumPlacementArgs() != 1)
721 if (OperatorNew->getNumParams() <= 1)
725 OperatorNew->getParamDecl(1)->getType()->getAs<
PointerType>();
726 if (!Arg || !Arg->isVoidPointerType())
731 const Expr *PlacementArg = NE->getPlacementArg(0);
732 if (
const auto *ICE = dyn_cast<ImplicitCastExpr>(PlacementArg);
733 ICE && ICE->getCastKind() == CK_BitCast &&
734 PlacementArg->getType()->isVoidPointerType())
735 PlacementArg = ICE->getSubExpr();
736 OriginList *PlacementList = getOriginsList(*PlacementArg);
740 handleAccess(PlacementArg);
752 const Expr *
Init = NE->getInitializer();
754 bool HandledAsPlacementNew =
false;
755 if (NE->getNumPlacementArgs() == 1)
756 HandledAsPlacementNew = handlePlacementNew(NE, NewList);
761 if (!HandledAsPlacementNew &&
762 (NE->getNumPlacementArgs() == 0 ||
763 (OperatorNew && OperatorNew->isReplaceableGlobalAllocationFunction()))) {
765 CurrentBlockFacts.push_back(
771 if (!NewList || !
Init)
777 flow(NewList, InitList,
true);
805 CurrentBlockFacts.push_back(
814 if (!CS || CS->body_empty())
816 const auto *
Last = dyn_cast<Expr>(CS->body_back());
821 flow(Dst, Src,
true);
824bool FactsGenerator::escapesViaReturn(
OriginID OID)
const {
825 return llvm::any_of(EscapesInCurrentBlock, [OID](
const Fact *F) {
827 return EF->getEscapedOriginID() == OID;
832void FactsGenerator::handleLifetimeEnds(
const CFGLifetimeEnds &LifetimeEnds) {
840 bool HasCleanup = LifetimeEndsVD->
hasAttr<CleanupAttr>();
841 bool IsDestructorUse =
845 if (HasCleanup || IsDestructorUse)
846 if (OriginList *List = getOriginsList(*LifetimeEndsVD))
847 CurrentBlockFacts.push_back(FactMgr.
createFact<UseFact>(
854 std::optional<OriginID> ExpiredOID;
855 if (OriginList *List = getOriginsList(*LifetimeEndsVD)) {
859 if (!escapesViaReturn(OID))
862 CurrentBlockFacts.push_back(FactMgr.
createFact<ExpireFact>(
863 AccessPath(LifetimeEndsVD), EndLoc, ExpiredOID));
864 if (
auto It = ExtendedTemporaries.find(LifetimeEndsVD);
865 It != ExtendedTemporaries.end())
866 for (
const MaterializeTemporaryExpr *MTE : It->second)
867 CurrentBlockFacts.push_back(
868 FactMgr.
createFact<ExpireFact>(AccessPath(MTE), EndLoc));
871void FactsGenerator::handleFullExprCleanup(
872 const CFGFullExprCleanup &FullExprCleanup) {
873 for (
const auto *MTE : FullExprCleanup.getExpiringMTEs())
874 CurrentBlockFacts.push_back(FactMgr.createFact<ExpireFact>(
875 AccessPath(MTE), FullExprCleanup.getCleanupLoc()));
878void FactsGenerator::handleExitBlock() {
879 bool IsDestructor = isa_and_nonnull<CXXDestructorDecl>(AC.getDecl());
880 for (
const Origin &O : FactMgr.getOriginMgr().getOrigins())
883 if (
auto *FD = dyn_cast_if_present<FieldDecl>(O.getDecl());
885 EscapesInCurrentBlock.push_back(
886 FactMgr.createFact<FieldEscapeFact>(O.ID, FD));
887 else if (
auto *VD = dyn_cast_if_present<VarDecl>(O.getDecl())) {
890 if (VD->hasGlobalStorage()) {
891 EscapesInCurrentBlock.push_back(
892 FactMgr.createFact<GlobalEscapeFact>(O.ID, VD));
902 if (
auto ThisOrigins = FactMgr.getOriginMgr().getThisOrigins();
903 ThisOrigins && !IsDestructor)
904 EscapesInCurrentBlock.push_back(FactMgr.createFact<ThisEscapeFact>(
905 (*ThisOrigins)->getOuterOriginID(), AC.getDecl()->getEndLoc()));
908void FactsGenerator::handleGSLPointerConstruction(
const CXXConstructExpr *CCE) {
910 if (CCE->getNumArgs() != 1)
913 const Expr *Arg = CCE->getArg(0);
919 OriginList *ArgList = readValue(Arg);
920 assert(ArgList &&
"GSL pointer argument should have an origin list");
921 flow(getOriginsList(*CCE), ArgList,
true);
922 }
else if (Arg->getType()->isPointerType()) {
927 OriginList *ArgList = getOriginsList(*Arg);
928 CurrentBlockFacts.push_back(FactMgr.createFact<OriginFlowFact>(
929 getOriginsList(*CCE)->getOuterOriginID(), ArgList->getOuterOriginID(),
934 handleFunctionCall(CCE,
true);
938void FactsGenerator::handleMovedArgsInCall(
const FunctionDecl *FD,
939 ArrayRef<const Expr *> Args) {
940 unsigned ImplicitObjectArgOffset = 0;
943 if (
const auto *MD = dyn_cast<CXXMethodDecl>(FD);
945 MD->isImplicitObjectMemberFunction()) {
946 ImplicitObjectArgOffset = 1;
951 const Expr *UniquePtrExpr = Args[0];
952 OriginList *MovedOrigins = getOriginsList(*UniquePtrExpr);
954 CurrentBlockFacts.push_back(FactMgr.createFact<MovedOriginFact>(
955 UniquePtrExpr, MovedOrigins->getOuterOriginID()));
960 for (
unsigned I = ImplicitObjectArgOffset;
961 I < Args.size() && I < FD->getNumParams() + ImplicitObjectArgOffset;
963 const ParmVarDecl *PVD = FD->getParamDecl(I - ImplicitObjectArgOffset);
966 if (PVD->isExplicitObjectParameter())
968 if (!PVD->getType()->isRValueReferenceType())
973 if (PVD->hasAttr<LifetimeBoundAttr>() ||
974 PVD->hasAttr<LifetimeCaptureByAttr>())
976 const Expr *Arg = Args[I];
977 OriginList *MovedOrigins = getOriginsList(*Arg);
978 assert(MovedOrigins->getLength() >= 1 &&
979 "unexpected length for r-value reference param");
981 CurrentBlockFacts.push_back(FactMgr.createFact<MovedOriginFact>(
982 Arg, MovedOrigins->getOuterOriginID()));
986void FactsGenerator::handleInvalidatingCall(
const Expr *
Call,
987 const FunctionDecl *FD,
988 ArrayRef<const Expr *> Args) {
989 const auto *MD = dyn_cast<CXXMethodDecl>(FD);
990 if (!MD || !MD->isInstance())
999 const Expr *Obj = Args[0]->IgnoreImpCasts();
1000 if (
const auto *ME = dyn_cast<MemberExpr>(Obj);
1004 OriginList *ThisList = getOriginsList(*Args[0]);
1006 CurrentBlockFacts.push_back(FactMgr.createFact<InvalidateOriginFact>(
1007 ThisList->getOuterOriginID(),
Call));
1010void FactsGenerator::handleDestructiveCall(
const Expr *
Call,
1011 const FunctionDecl *FD,
1012 ArrayRef<const Expr *> Args) {
1015 OriginList *ArgList = getOriginsList(*Args[0]);
1017 CurrentBlockFacts.push_back(FactMgr.createFact<InvalidateOriginFact>(
1018 ArgList->getOuterOriginID(),
Call));
1021void FactsGenerator::handleImplicitObjectFieldUses(
const Expr *
Call,
1022 const FunctionDecl *FD) {
1023 const auto *MemberCall = dyn_cast_or_null<CXXMemberCallExpr>(
Call);
1027 if (!isa_and_present<CXXThisExpr>(
1028 MemberCall->getImplicitObjectArgument()->IgnoreImpCasts()))
1031 const auto *MD = dyn_cast<CXXMethodDecl>(FD);
1032 assert(MD &&
"Function must be a CXXMethodDecl for member calls");
1034 const auto *ClassDecl = MD->getParent()->getDefinition();
1038 const auto UseFields = [&](
const CXXRecordDecl *RD) {
1039 for (
const auto *Field : RD->fields())
1040 if (
auto *FieldList = getOriginsList(*Field))
1041 CurrentBlockFacts.push_back(
1042 FactMgr.createFact<UseFact>(*
Call, FieldList));
1045 UseFields(ClassDecl);
1047 ClassDecl->forallBases([&](
const CXXRecordDecl *Base) {
1053void FactsGenerator::handleLifetimeCaptureBy(
const FunctionDecl *FD,
1054 ArrayRef<const Expr *> Args) {
1060 const auto *
Method = dyn_cast<CXXMethodDecl>(FD);
1061 bool HasImplicitObjectArg =
Method &&
1062 Method->isImplicitObjectMemberFunction() &&
1064 auto getArgCaptureByAttr =
1065 [FD, HasImplicitObjectArg](
1066 unsigned I) -> std::pair<const LifetimeCaptureByAttr *, QualType> {
1067 if (HasImplicitObjectArg) {
1070 QualType ParamType = MethodDecl->getFunctionObjectParameterType();
1073 if (I > 0 && I - 1 < FD->getNumParams()) {
1074 const ParmVarDecl *PVD = FD->getParamDecl(I - 1);
1075 return {PVD ? PVD->getAttr<LifetimeCaptureByAttr>() :
nullptr,
1079 if (I < FD->getNumParams()) {
1080 const ParmVarDecl *PVD = FD->getParamDecl(I);
1081 return {PVD ? PVD->getAttr<LifetimeCaptureByAttr>() :
nullptr,
1085 return {
nullptr, QualType()};
1087 for (
unsigned I = 0; I < Args.size(); ++I) {
1088 auto [Attr, ParamType] = getArgCaptureByAttr(I);
1091 OriginList *CapturedOriginList = getOriginsList(*Args[I]);
1092 if (!CapturedOriginList)
1096 if (!ParamType.isNull() &&
1097 (ParamType->isReferenceType() &&
1099 CapturedOriginList->getLength() > 1)
1100 CapturedOriginList = CapturedOriginList->peelOuterOrigin();
1101 for (
int CapturingArgIdx : Attr->params()) {
1103 if (CapturingArgIdx == LifetimeCaptureByAttr::Global ||
1104 CapturingArgIdx == LifetimeCaptureByAttr::Unknown ||
1105 CapturingArgIdx == LifetimeCaptureByAttr::Invalid)
1108 if (CapturingArgIdx != LifetimeCaptureByAttr::This &&
1109 (CapturingArgIdx < 0 ||
1110 static_cast<size_t>(CapturingArgIdx) >= Args.size()))
1112 const Expr *CapturedByArg = Args[CapturingArgIdx];
1113 assert(CapturedByArg &&
"Capturer expression must be valid");
1115 OriginList *Dest = readValue(CapturedByArg);
1122 CurrentBlockFacts.push_back(FactMgr.createFact<OriginFlowFact>(
1123 Dest->getOuterOriginID(), CapturedOriginList->getOuterOriginID(),
1129void FactsGenerator::handleFunctionCall(
const Expr *
Call,
1130 bool IsGslConstruction) {
1131 FunctionCallInfo CallInfo(
Call);
1132 llvm::ArrayRef<const Expr *> Args = CallInfo.Args;
1134 for (
const Expr *Arg : Args)
1138 OriginList *CallList = getOriginsList(*
Call);
1143 handleInvalidatingCall(
Call, FD, Args);
1144 handleDestructiveCall(
Call, FD, Args);
1145 handleMovedArgsInCall(FD, Args);
1146 handleImplicitObjectFieldUses(
Call, FD);
1147 handleLifetimeCaptureBy(FD, Args);
1151 assert(Args.size() == 1 &&
1152 "std reference cast builtins take exactly one argument");
1155 flow(CallList, getOriginsList(*Args[0]),
true);
1158 auto shouldTrackPointerImplicitObjectArg = [FD, &Args](
unsigned I) ->
bool {
1159 const auto *
Method = dyn_cast<CXXMethodDecl>(FD);
1169 bool KillSrc =
true;
1170 for (
unsigned I = 0; I < Args.size(); ++I) {
1171 OriginList *ArgList = getOriginsList(*Args[I]);
1175 if (IsGslConstruction) {
1179 assert(!Args[I]->isGLValue() || ArgList->getLength() >= 2);
1180 ArgList = readValue(Args[I]);
1186 CurrentBlockFacts.push_back(FactMgr.createFact<OriginFlowFact>(
1187 CallList->getOuterOriginID(), ArgList->getOuterOriginID(),
1190 }
else if (ShouldTrackArg) {
1197 CurrentBlockFacts.push_back(FactMgr.createFact<OriginFlowFact>(
1198 CallList->getOuterOriginID(), ArgList->getOuterOriginID(),
1202 }
else if (shouldTrackPointerImplicitObjectArg(I)) {
1203 assert(ArgList->getLength() >= 2 &&
1204 "Object arg of pointer type should have at least two origins");
1206 CurrentBlockFacts.push_back(FactMgr.createFact<OriginFlowFact>(
1207 CallList->getOuterOriginID(),
1208 ArgList->peelOuterOrigin()->getOuterOriginID(), KillSrc));
1210 }
else if (ShouldTrackArg) {
1214 CurrentBlockFacts.push_back(FactMgr.createFact<OriginFlowFact>(
1215 CallList->getOuterOriginID(), ArgList->getOuterOriginID(), KillSrc));
1223bool FactsGenerator::handleTestPoint(
const CXXFunctionalCastExpr *FCE) {
1224 if (!FCE->getType()->isVoidType())
1227 const auto *SubExpr = FCE->getSubExpr()->IgnoreParenImpCasts();
1228 if (
const auto *SL = dyn_cast<StringLiteral>(SubExpr)) {
1229 llvm::StringRef LiteralValue = SL->getString();
1230 const std::string Prefix =
"__lifetime_test_point_";
1232 if (LiteralValue.starts_with(Prefix)) {
1233 StringRef Annotation = LiteralValue.drop_front(Prefix.length());
1234 CurrentBlockFacts.push_back(
1235 FactMgr.createFact<TestPointFact>(Annotation));
1242bool FactsGenerator::namesDeclStorage(
const OriginList *List)
const {
1243 return FactMgr.getOriginMgr()
1244 .getOrigin(List->getOuterOriginID())
1248void FactsGenerator::handleAccess(
const Expr *E) {
1249 OriginList *List = getOriginsList(*E);
1250 if (!List || namesDeclStorage(List))
1252 CurrentBlockFacts.push_back(FactMgr.createFact<UseFact>(
1254 FactMgr.getOriginMgr().createSingleOriginList(List->getOuterOriginID())));
1257void FactsGenerator::handleUse(
const Expr *E) {
1258 OriginList *List = getOriginsList(*E);
1259 if (List && namesDeclStorage(List))
1260 List = List->peelOuterOrigin();
1262 CurrentBlockFacts.push_back(FactMgr.createFact<UseFact>(*E, List));
1268void FactsGenerator::issueFieldPlaceholderLoans(
1269 const CXXRecordDecl *ClassDef, llvm::SmallVectorImpl<Fact *> &Facts) {
1270 assert(ClassDef &&
"class methods have a defined parent");
1272 assert(ClassDef->isCompleteDefinition() || ClassDef->isBeingDefined());
1273 auto IssueForRecord = [&](
const CXXRecordDecl *RD) {
1274 for (
const FieldDecl *Field : RD->fields()) {
1279 if (
Field->isAnonymousStructOrUnion()) {
1280 if (
const CXXRecordDecl *Sub =
Field->getType()->getAsCXXRecordDecl()) {
1281 if (
const CXXRecordDecl *SubDef =
Sub->getDefinition()) {
1284 issueFieldPlaceholderLoans(SubDef, Facts);
1289 OriginList *FieldList = getOriginsList(*Field);
1292 const Loan *L = FactMgr.getLoanMgr().createPlaceholderLoan(Field);
1293 Facts.push_back(FactMgr.createFact<IssueFact>(
1294 L->getID(), FieldList->getOuterOriginID()));
1298 IssueForRecord(ClassDef);
1299 ClassDef->forallBases(IssueForRecord);
1305llvm::SmallVector<Fact *> FactsGenerator::issuePlaceholderLoans() {
1306 const auto *FD = dyn_cast<FunctionDecl>(AC.getDecl());
1310 llvm::SmallVector<Fact *> PlaceholderLoanFacts;
1311 if (
auto ThisOrigins = FactMgr.getOriginMgr().getThisOrigins()) {
1312 OriginList *List = *ThisOrigins;
1314 const Loan *L = FactMgr.getLoanMgr().createPlaceholderLoan(MD);
1315 PlaceholderLoanFacts.push_back(
1316 FactMgr.createFact<IssueFact>(L->getID(), List->getOuterOriginID()));
1318 issueFieldPlaceholderLoans(MD->getParent()->getDefinition(),
1319 PlaceholderLoanFacts);
1321 for (
const ParmVarDecl *PVD : FD->parameters()) {
1322 OriginList *List = getOriginsList(*PVD);
1325 const Loan *L = FactMgr.getLoanMgr().createPlaceholderLoan(PVD);
1326 PlaceholderLoanFacts.push_back(
1327 FactMgr.createFact<IssueFact>(L->getID(), List->getOuterOriginID()));
1329 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.
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
AbstractConditionalOperator - An abstract base class for ConditionalOperator and BinaryConditionalOpe...
Expr * getTrueExpr() const
getTrueExpr - Return the subexpression representing the value of the expression if the condition eval...
Expr * getFalseExpr() const
getFalseExpr - Return the subexpression representing the value of the expression if the condition eva...
ASTContext & getASTContext() const
ArraySubscriptExpr - [C99 6.5.2.1] Array Subscripting.
bool isOutputPlusConstraint(unsigned i) const
isOutputPlusConstraint - Return true if the specified output constraint is a "+" constraint (which is...
unsigned getNumOutputs() const
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 VarDecl * getVarDecl() const
LLVM_ATTRIBUTE_RETURNS_NONNULL const Stmt * getTriggerStmt() 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 a delete expression for memory deallocation and destructor calls, e.g.
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....
Expr * getImplicitObjectArgument() const
Retrieve the implicit object argument for the member call.
Represents a new-expression for memory allocation and constructor calls, e.g: "new CXXNewExpr(foo)".
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.
A C++ throw-expression (C++ [except.throw]).
const Expr * getSubExpr() const
A C++ typeid expression (C++ [expr.typeid]), which gets the type_info that corresponds to the supplie...
Expr * getExprOperand() const
bool isPotentiallyEvaluated() const
Determine whether this typeid has a type operand which is potentially evaluated, per C++11 [expr....
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.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
CastKind getCastKind() const
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...
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Represents a member of a struct/union/class.
Represents a function declaration or definition.
bool isDefaulted() const
Whether this function is defaulted.
This represents a GCC inline-assembly statement extension.
Expr * getOutputExpr(unsigned i)
Describes an C or C++ initializer list.
unsigned getNumInits() const
const Expr * getInit(unsigned Init) const
Describes the capture of a variable or of this, or of a C++1y init-capture.
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.
ValueDecl * getExtendingDecl()
Get the declaration which triggered the lifetime-extension of this temporary, if any.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
ValueDecl * getMemberDecl() const
Retrieve the member declaration to which this expression refers.
PointerType - C99 6.7.5.1 - Pointer Declarators.
A (possibly-)qualified type.
DestructionKind isDestructedType() const
Returns a nonzero value if objects of this type require non-trivial work to clean up after.
ReturnStmt - This represents a return, optionally of an expression: return; return 4;.
Encodes a location in the source.
StmtExpr - This is the GNU Statement Expression extension: ({int X=4; X;}).
CompoundStmt * getSubStmt()
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 isPointerOrReferenceType() const
bool isFunctionType() 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.
static UseSite scopeExit(SourceLocation Loc, const VarDecl &VD, UseKind Kind)
Represents the storage location being borrowed, e.g., a specific stack variable or a field within it:...
FactType * createFact(Args &&...args)
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 VisitCXXTypeidExpr(const CXXTypeidExpr *TE)
void VisitMemberExpr(const MemberExpr *ME)
void VisitAbstractConditionalOperator(const AbstractConditionalOperator *CO)
Visits conditional operators (e.g., cond ?
void VisitCXXDeleteExpr(const CXXDeleteExpr *DE)
void VisitCXXNewExpr(const CXXNewExpr *NE)
void VisitCXXFunctionalCastExpr(const CXXFunctionalCastExpr *FCE)
void VisitGCCAsmStmt(const GCCAsmStmt *AS)
void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *DIE)
void VisitInitListExpr(const InitListExpr *ILE)
void VisitLambdaExpr(const LambdaExpr *LE)
void VisitStmtExpr(const StmtExpr *SE)
void VisitCXXNullPtrLiteralExpr(const CXXNullPtrLiteralExpr *N)
void VisitCXXOperatorCallExpr(const CXXOperatorCallExpr *OCE)
void VisitArraySubscriptExpr(const ArraySubscriptExpr *ASE)
void VisitUnaryOperator(const UnaryOperator *UO)
void VisitCXXThrowExpr(const CXXThrowExpr *TE)
void VisitDeclStmt(const DeclStmt *DS)
void VisitCXXMemberCallExpr(const CXXMemberCallExpr *MCE)
void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE)
Represents that an origin's storage has been invalidated by a container operation (e....
Loan * createLoan(AccessPath Path, const Expr *IssueExpr=nullptr)
Represents a component of an access path: either a named field access or an abstract unnamed interior...
A list of origins representing levels of indirection for pointer-like types.
OriginID getOuterOriginID() const
OriginList * peelOuterOrigin() const
Represents that an origin escapes via a return statement.
bool Sub(InterpState &S, CodePtr OpPC)
utils::ID< struct OriginTag > OriginID
static const Loan * createLoan(FactManager &FactMgr, const ValueDecl &VD, const Expr *IssueExpr)
Creates a loan for the storage path of a given declaration.
static const CFGBlock * findPredBlockForExpr(const CFGBlock *MergeBlock, const Expr *ArmExpr)
bool doesDeclHaveStorage(const ValueDecl *D)
Returns true if the declaration has its own storage that can be borrowed.
bool isGslPointerType(QualType QT)
bool isStdCallableWrapperType(const CXXRecordDecl *RD)
bool shouldTrackImplicitObjectArg(const Expr &ImplicitObjectArgument, const CXXMethodDecl *Callee, bool RunningUnderLifetimeSafety)
bool isPointerLikeType(QualType QT)
bool isUniquePtrRelease(const CXXMethodDecl &MD)
bool isStdReferenceCast(const FunctionDecl *FD)
const FunctionDecl * getDeclWithMergedLifetimeBoundAttrs(const FunctionDecl *FD)
bool isInvalidationMethod(const CXXMethodDecl &MD)
bool destructsFirstArg(const FunctionDecl &FD)
bool isGslOwnerType(QualType QT)
std::optional< LifetimeBoundParamInfo > getTrackedArgInfo(const FunctionDecl *FD, llvm::ArrayRef< const Expr * > Args, unsigned I)
const LifetimeCaptureByAttr * getCaptureByAttrFromFunctionType(const FunctionDecl *FD)
bool isa(CodeGen::Address addr)
nullptr
This class represents a compute construct, representing a 'Kind' of ‘parallel’, 'serial',...
@ SD_Automatic
Automatic storage duration (most local variables).
U cast(CodeGen::Address addr)
bool CheckDestructorUses
Whether to model non-trivial destructors at scope exit as uses.