17#include "llvm/ADT/PointerIntPair.h"
63 llvm::PointerIntPair<const InitializedEntity *, 3, LifetimeKind>;
76 return {Entity, LK_Extended};
101 return {Entity, LK_Extended};
108 return {
nullptr, LK_FullExpression};
113 return {
nullptr, LK_FullExpression};
119 return {
nullptr, LK_Return};
124 return {
nullptr, LK_StmtExprResult};
130 return {
nullptr, LK_New};
138 return {
nullptr, LK_FullExpression};
148 return {InitField, LK_MemInitializer};
155 return {InitField, LK_MemInitializer};
163 return {
nullptr, LK_FullExpression};
167 return {
nullptr, LK_FullExpression};
174 return {
nullptr, LK_FullExpression};
177 llvm_unreachable(
"unknown entity kind");
186 RK_StdInitializerList,
199struct IndirectLocalPathEntry {
211 GslPointerAssignment,
217 const Decl *D =
nullptr;
220 IndirectLocalPathEntry() {}
221 IndirectLocalPathEntry(EntryKind K, Expr *E) : Kind(K), E(E) {}
222 IndirectLocalPathEntry(EntryKind K, Expr *E,
const Decl *D)
223 : Kind(K), E(E), D(D) {}
224 IndirectLocalPathEntry(EntryKind K, Expr *E,
const LambdaCapture *
Capture)
228using IndirectLocalPath = llvm::SmallVectorImpl<IndirectLocalPathEntry>;
230struct RevertToOldSizeRAII {
231 IndirectLocalPath &Path;
232 unsigned OldSize = Path.size();
233 RevertToOldSizeRAII(IndirectLocalPath &Path) : Path(Path) {}
234 ~RevertToOldSizeRAII() { Path.resize(OldSize); }
237using LocalVisitor = llvm::function_ref<
bool(IndirectLocalPath &Path, Local L,
243 if (E.Kind == IndirectLocalPathEntry::VarInit && E.D == VD)
249 return llvm::any_of(Path, [=](IndirectLocalPathEntry E) {
250 return E.Kind == IndirectLocalPathEntry::DefaultInit ||
251 E.Kind == IndirectLocalPathEntry::VarInit;
257 bool RevisitSubinits);
274 if (
const auto *ND = dyn_cast<NamespaceDecl>(DC))
276 StringRef Name = II->getName();
277 if (Name.size() >= 2 && Name.front() ==
'_' &&
288 if (
const auto *CTSD =
289 dyn_cast_if_present<ClassTemplateSpecializationDecl>(Container)) {
290 if (!CTSD->hasAttr<OwnerAttr>())
292 const auto &TAs = CTSD->getTemplateArgs();
300 dyn_cast_if_present<ClassTemplateSpecializationDecl>(Container);
303 if (!CTSD->hasAttr<OwnerAttr>())
305 const auto &TAs = CTSD->getTemplateArgs();
312 if (
const auto *CTSD =
313 dyn_cast_if_present<ClassTemplateSpecializationDecl>(RD)) {
314 const auto &TAs = CTSD->getTemplateArgs();
316 RD->
getName() ==
"initializer_list" && TAs.size() > 0 &&
324 if (
auto *Conv = dyn_cast_or_null<CXXConversionDecl>(Callee))
326 Callee->getParent()->hasAttr<OwnerAttr>())
334 if (!Callee->getIdentifier())
336 return llvm::StringSwitch<bool>(Callee->getName())
337 .Cases({
"begin",
"rbegin",
"cbegin",
"crbegin"},
true)
338 .Cases({
"end",
"rend",
"cend",
"crend"},
true)
339 .Cases({
"c_str",
"data",
"get"},
true)
341 .Cases({
"find",
"equal_range",
"lower_bound",
"upper_bound"},
true)
344 if (Callee->getReturnType()->isReferenceType()) {
345 if (!Callee->getIdentifier()) {
346 auto OO = Callee->getOverloadedOperator();
347 if (!Callee->getParent()->hasAttr<OwnerAttr>())
349 return OO == OverloadedOperatorKind::OO_Subscript ||
350 OO == OverloadedOperatorKind::OO_Star;
352 return llvm::StringSwitch<bool>(Callee->getName())
353 .Cases({
"front",
"back",
"at",
"top",
"value"},
true)
365 if (!RD->hasAttr<PointerAttr>() && !RD->hasAttr<OwnerAttr>())
369 return llvm::StringSwitch<bool>(FD->
getName())
370 .Cases({
"begin",
"rbegin",
"cbegin",
"crbegin"},
true)
371 .Cases({
"end",
"rend",
"cend",
"crend"},
true)
376 return llvm::StringSwitch<bool>(FD->
getName())
377 .Cases({
"get",
"any_cast"},
true)
388 const auto *ParamRefType =
394 if (
const auto *TST =
395 ParamRefType->getPointeeType()->getAs<TemplateSpecializationType>())
396 return TST->getTemplateName()
411 if (LHSRecordDecl->hasAttr<PointerAttr>())
468 if (
const auto *PrimaryCtorTemplate =
470 PrimaryCtorTemplate &&
472 PrimaryCtorTemplate->getTemplatedDecl()))) {
482 LocalVisitor Visit) {
486 if (
auto *CE = dyn_cast<CallExpr>(
Call)) {
487 Callee = CE->getDirectCallee();
491 Callee = CCE->getConstructor();
497 bool EnableGSLAnalysis = !Callee->getASTContext().getDiagnostics().isIgnored(
499 Expr *ObjectArg =
nullptr;
502 Args = Args.slice(1);
503 }
else if (
auto *MCE = dyn_cast<CXXMemberCallExpr>(
Call)) {
504 ObjectArg = MCE->getImplicitObjectArgument();
507 auto VisitLifetimeBoundArg = [&](
const Decl *D,
Expr *Arg) {
508 Path.push_back({IndirectLocalPathEntry::LifetimeBoundCall, Arg, D});
509 if (Arg->isGLValue())
517 auto ReturnType = Callee->getReturnType();
521 if (ReturnType->isReferenceType() &&
523 for (
const IndirectLocalPathEntry &PE : llvm::reverse(Path)) {
524 if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit ||
525 PE.Kind == IndirectLocalPathEntry::LifetimeBoundCall)
527 if (PE.Kind == IndirectLocalPathEntry::GslPointerInit ||
528 PE.Kind == IndirectLocalPathEntry::GslPointerAssignment)
533 Path.push_back({ReturnType->isReferenceType()
534 ? IndirectLocalPathEntry::GslReferenceInit
535 : IndirectLocalPathEntry::GslPointerInit,
537 if (Arg->isGLValue())
545 bool CheckCoroCall =
false;
546 if (
const auto *RD = Callee->getReturnType()->getAsRecordDecl()) {
547 CheckCoroCall = RD->hasAttr<CoroLifetimeBoundAttr>() &&
548 RD->hasAttr<CoroReturnTypeAttr>() &&
549 !Callee->hasAttr<CoroDisableLifetimeBoundAttr>();
553 bool CheckCoroObjArg = CheckCoroCall;
556 LE && LE->captures().empty())
557 CheckCoroObjArg =
false;
561 CheckCoroObjArg =
false;
564 VisitLifetimeBoundArg(Callee, ObjectArg);
565 else if (EnableGSLAnalysis) {
566 if (
auto *CME = dyn_cast<CXXMethodDecl>(Callee);
568 VisitGSLPointerArg(Callee, ObjectArg);
574 unsigned NP = std::min(Callee->getNumParams(), CanonCallee->
getNumParams());
575 for (
unsigned I = 0, N = std::min<unsigned>(NP, Args.size()); I != N; ++I) {
577 RevertToOldSizeRAII RAII(Path);
578 if (
auto *DAE = dyn_cast<CXXDefaultArgExpr>(Arg)) {
580 {IndirectLocalPathEntry::DefaultArg, DAE, DAE->getParam()});
581 Arg = DAE->getExpr();
585 VisitLifetimeBoundArg(CanonCallee->
getParamDecl(I), Arg);
586 else if (
const auto *CaptureAttr =
589 llvm::any_of(CaptureAttr->params(), [](
int ArgIdx) {
590 return ArgIdx == LifetimeCaptureByAttr::This;
605 VisitLifetimeBoundArg(CanonCallee->
getParamDecl(I), Arg);
606 else if (EnableGSLAnalysis && I == 0) {
609 VisitGSLPointerArg(CanonCallee, Arg);
610 }
else if (
auto *Ctor = dyn_cast<CXXConstructExpr>(
Call);
612 VisitGSLPointerArg(Ctor->getConstructor(), Arg);
622 LocalVisitor Visit) {
623 RevertToOldSizeRAII RAII(Path);
630 if (
auto *FE = dyn_cast<FullExpr>(
Init))
631 Init = FE->getSubExpr();
635 if (ILE->isTransparent())
636 Init = ILE->getInit(0);
639 if (
MemberExpr *ME = dyn_cast<MemberExpr>(
Init->IgnoreImpCasts()))
641 {IndirectLocalPathEntry::MemberExpr, ME, ME->getMemberDecl()});
644 Init =
const_cast<Expr *
>(
Init->skipRValueSubobjectAdjustments());
649 if (CE->getSubExpr()->isGLValue())
650 Init = CE->getSubExpr();
654 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(
Init)) {
655 Init = ASE->getBase();
656 auto *ICE = dyn_cast<ImplicitCastExpr>(
Init);
657 if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay)
658 Init = ICE->getSubExpr();
667 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(
Init)) {
669 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
670 Init = DIE->getExpr();
672 }
while (
Init != Old);
674 if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(
Init)) {
675 if (Visit(Path, Local(MTE), RK))
679 if (
auto *M = dyn_cast<MemberExpr>(
Init)) {
681 if (
auto *F = dyn_cast<FieldDecl>(M->getMemberDecl());
682 F && !F->getType()->isReferenceType())
689 switch (
Init->getStmtClass()) {
690 case Stmt::DeclRefExprClass: {
694 auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
695 if (VD && VD->hasLocalStorage() &&
696 !DRE->refersToEnclosingVariableOrCapture()) {
697 if (!VD->getType()->isReferenceType()) {
698 Visit(Path, Local(DRE), RK);
703 }
else if (VD->getInit() && !
isVarOnPath(Path, VD)) {
704 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
706 RK_ReferenceBinding, Visit);
712 case Stmt::UnaryOperatorClass: {
717 if (
U->getOpcode() == UO_Deref)
722 case Stmt::ArraySectionExprClass: {
728 case Stmt::ConditionalOperatorClass:
729 case Stmt::BinaryConditionalOperatorClass: {
731 if (!
C->getTrueExpr()->getType()->isVoidType())
733 if (!
C->getFalseExpr()->getType()->isVoidType())
738 case Stmt::CompoundLiteralExprClass: {
739 if (
auto *CLE = dyn_cast<CompoundLiteralExpr>(
Init)) {
740 if (!CLE->isFileScope())
741 Visit(Path, Local(CLE), RK);
757 bool RevisitSubinits) {
758 RevertToOldSizeRAII RAII(Path);
766 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(
Init)) {
768 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
769 Init = DIE->getExpr();
772 if (
auto *FE = dyn_cast<FullExpr>(
Init))
773 Init = FE->getSubExpr();
776 Init =
const_cast<Expr *
>(
Init->skipRValueSubobjectAdjustments());
779 Init = BTE->getSubExpr();
784 if (
auto *CE = dyn_cast<CastExpr>(
Init)) {
785 switch (CE->getCastKind()) {
786 case CK_LValueToRValue:
789 Path.push_back({IndirectLocalPathEntry::LValToRVal, CE});
791 Path,
Init, RK_ReferenceBinding,
792 [&](IndirectLocalPath &Path, Local L, ReferenceKind RK) ->
bool {
793 if (
auto *DRE = dyn_cast<DeclRefExpr>(L)) {
794 auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
795 if (VD && VD->getType().isConstQualified() && VD->getInit() &&
797 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
801 }
else if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L)) {
802 if (MTE->getType().isConstQualified())
815 case CK_BaseToDerived:
816 case CK_DerivedToBase:
817 case CK_UncheckedDerivedToBase:
820 case CK_UserDefinedConversion:
821 case CK_ConstructorConversion:
822 case CK_IntegralToPointer:
823 case CK_PointerToIntegral:
825 case CK_IntegralCast:
826 case CK_CPointerToObjCPointerCast:
827 case CK_BlockPointerToObjCPointerCast:
828 case CK_AnyPointerToBlockPointerCast:
829 case CK_AddressSpaceConversion:
832 case CK_ArrayToPointerDecay:
835 Path.push_back({IndirectLocalPathEntry::AddressOf, CE});
837 Path, CE->getSubExpr(), RK_ReferenceBinding, Visit);
843 Init = CE->getSubExpr();
845 }
while (Old !=
Init);
850 if (
auto *ILE = dyn_cast<CXXStdInitializerListExpr>(
Init))
852 RK_StdInitializerList, Visit);
858 if (!RevisitSubinits)
861 if (ILE->isTransparent())
865 if (ILE->getType()->isArrayType()) {
866 for (
unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
872 if (
CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) {
873 assert(RD->isAggregate() &&
"aggregate init on non-aggregate");
878 if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
879 ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
881 RK_ReferenceBinding, Visit);
884 for (; Index < RD->getNumBases() && Index < ILE->getNumInits(); ++Index)
887 for (
const auto *I : RD->fields()) {
888 if (Index >= ILE->getNumInits())
890 if (I->isUnnamedBitField())
892 Expr *SubInit = ILE->getInit(Index);
893 if (I->getType()->isReferenceType())
895 RK_ReferenceBinding, Visit);
911 if (
auto *LE = dyn_cast<LambdaExpr>(
Init)) {
913 for (
Expr *E : LE->capture_inits()) {
914 assert(CapI != LE->capture_end());
919 Path.push_back({IndirectLocalPathEntry::LambdaCaptureInit, E, &Cap});
932 if (
auto *CCE = dyn_cast<CXXConstructExpr>(
Init)) {
933 if (CCE->getConstructor()->isCopyOrMoveConstructor()) {
934 if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(CCE->getArg(0))) {
935 Expr *Arg = MTE->getSubExpr();
936 Path.push_back({IndirectLocalPathEntry::TemporaryCopy, Arg,
937 CCE->getConstructor()});
947 if (
auto *CPE = dyn_cast<CXXParenListInitExpr>(
Init)) {
948 RevertToOldSizeRAII RAII(Path);
949 Path.push_back({IndirectLocalPathEntry::ParenAggInit, CPE});
950 for (
auto *I : CPE->getInitExprs()) {
958 switch (
Init->getStmtClass()) {
959 case Stmt::UnaryOperatorClass: {
963 if (UO->getOpcode() == UO_AddrOf) {
970 Path.push_back({IndirectLocalPathEntry::AddressOf, UO});
972 RK_ReferenceBinding, Visit);
977 case Stmt::BinaryOperatorClass: {
981 if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub))
984 if (BO->getLHS()->getType()->isPointerType())
986 else if (BO->getRHS()->getType()->isPointerType())
991 case Stmt::ConditionalOperatorClass:
992 case Stmt::BinaryConditionalOperatorClass: {
996 if (!
C->getTrueExpr()->getType()->isVoidType())
998 if (!
C->getFalseExpr()->getType()->isVoidType())
1003 case Stmt::BlockExprClass:
1010 case Stmt::AddrLabelExprClass:
1032 for (
auto Elem : Path) {
1033 if (Elem.Kind == IndirectLocalPathEntry::MemberExpr ||
1034 Elem.Kind == IndirectLocalPathEntry::LambdaCaptureInit)
1036 return Elem.Kind == IndirectLocalPathEntry::DefaultInit
1046 for (
unsigned N = Path.size(); I != N; ++I) {
1047 switch (Path[I].Kind) {
1048 case IndirectLocalPathEntry::AddressOf:
1049 case IndirectLocalPathEntry::LValToRVal:
1050 case IndirectLocalPathEntry::LifetimeBoundCall:
1051 case IndirectLocalPathEntry::TemporaryCopy:
1052 case IndirectLocalPathEntry::GslReferenceInit:
1053 case IndirectLocalPathEntry::GslPointerInit:
1054 case IndirectLocalPathEntry::GslPointerAssignment:
1055 case IndirectLocalPathEntry::ParenAggInit:
1056 case IndirectLocalPathEntry::MemberExpr:
1061 case IndirectLocalPathEntry::VarInit:
1065 case IndirectLocalPathEntry::DefaultInit:
1066 return Path[I].E->getSourceRange();
1068 case IndirectLocalPathEntry::LambdaCaptureInit:
1069 if (!Path[I].
Capture->capturesVariable())
1071 return Path[I].E->getSourceRange();
1073 case IndirectLocalPathEntry::DefaultArg:
1081 for (
const auto &It : llvm::reverse(Path)) {
1083 case IndirectLocalPathEntry::VarInit:
1084 case IndirectLocalPathEntry::AddressOf:
1085 case IndirectLocalPathEntry::LifetimeBoundCall:
1086 case IndirectLocalPathEntry::MemberExpr:
1088 case IndirectLocalPathEntry::GslPointerInit:
1089 case IndirectLocalPathEntry::GslReferenceInit:
1090 case IndirectLocalPathEntry::GslPointerAssignment:
1113 Local L, LifetimeKind LK) {
1121 for (
const auto &E : Path) {
1122 if (E.Kind == IndirectLocalPathEntry::MemberExpr) {
1131 if (
const auto *FD = llvm::dyn_cast_or_null<FieldDecl>(E.D);
1132 FD && !FD->getType()->isReferenceType() &&
1147 if (Path.back().Kind == IndirectLocalPathEntry::LifetimeBoundCall) {
1150 llvm::dyn_cast_or_null<FunctionDecl>(Path.back().D);
1152 if (
const auto *PD = llvm::dyn_cast<ParmVarDecl>(Path.back().D))
1153 FD = llvm::dyn_cast<FunctionDecl>(PD->getDeclContext());
1155 if (isa_and_present<CXXConstructorDecl>(FD)) {
1185 auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
1187 bool IsGslPtrValueFromGslTempOwner =
1188 MTE && !MTE->getExtendingDecl() &&
isGslOwnerType(MTE->getType());
1193 if (!IsGslPtrValueFromGslTempOwner)
1201 diag::warn_dangling_lifetime_pointer_assignment,
SourceLocation());
1202 return (EnableGSLAssignmentWarnings &&
1213 assert(!AEntity || LK == LK_Assignment);
1214 assert(!CapEntity || LK == LK_LifetimeCapture);
1215 assert(!InitEntity || (LK != LK_Assignment && LK != LK_LifetimeCapture));
1218 if (LK == LK_FullExpression)
1223 auto TemporaryVisitor = [&](
const IndirectLocalPath &Path, Local L,
1224 ReferenceKind RK) ->
bool {
1228 auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
1230 bool IsGslPtrValueFromGslTempOwner =
true;
1237 IsGslPtrValueFromGslTempOwner =
false;
1244 case LK_FullExpression:
1245 llvm_unreachable(
"already handled this");
1261 MTE->setExtendingDecl(ExtendingEntity->
getDecl(),
1267 if (SemaRef.
getLangOpts().CPlusPlus23 && InitEntity) {
1269 dyn_cast_if_present<VarDecl>(InitEntity->
getDecl());
1275 if (IsGslPtrValueFromGslTempOwner && DiagLoc.
isValid()) {
1276 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1287 SemaRef.
Diag(DiagLoc, diag::warn_dangling_variable)
1290 << ExtendingEntity->
getDecl() <<
Init->isGLValue() << DiagRange;
1296 case LK_LifetimeCapture: {
1302 SemaRef.
Diag(DiagLoc, diag::warn_dangling_reference_captured)
1303 << CapEntity->
Entity << DiagRange;
1305 SemaRef.
Diag(DiagLoc, diag::warn_dangling_reference_captured_by_unknown)
1310 case LK_Assignment: {
1313 if (IsGslPtrValueFromGslTempOwner)
1314 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_assignment)
1315 << AEntity->
LHS << DiagRange;
1317 SemaRef.
Diag(DiagLoc, diag::warn_dangling_pointer_assignment)
1322 case LK_MemInitializer: {
1327 if (
auto *ExtendingDecl =
1328 ExtendingEntity ? ExtendingEntity->
getDecl() :
nullptr) {
1329 if (IsGslPtrValueFromGslTempOwner) {
1330 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_member)
1331 << ExtendingDecl << DiagRange;
1332 SemaRef.
Diag(ExtendingDecl->getLocation(),
1333 diag::note_ref_or_ptr_member_declared_here)
1337 bool IsSubobjectMember = ExtendingEntity != InitEntity;
1340 ? diag::err_dangling_member
1341 : diag::warn_dangling_member)
1342 << ExtendingDecl << IsSubobjectMember << RK << DiagRange;
1347 Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {
1348 SemaRef.
Diag(ExtendingDecl->getLocation(),
1349 diag::note_lifetime_extending_member_declared_here)
1350 << RK << IsSubobjectMember;
1368 auto *DRE = dyn_cast<DeclRefExpr>(L);
1375 auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) :
nullptr;
1383 ExtendingEntity ? ExtendingEntity->
getDecl() :
nullptr) {
1384 bool IsPointer = !
Member->getType()->isReferenceType();
1385 SemaRef.
Diag(DiagLoc,
1386 IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
1387 : diag::warn_bind_ref_member_to_parameter)
1390 diag::note_ref_or_ptr_member_declared_here)
1399 if (IsGslPtrValueFromGslTempOwner)
1400 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1403 SemaRef.
Diag(DiagLoc, RK == RK_ReferenceBinding
1404 ? diag::warn_new_dangling_reference
1405 : diag::warn_new_dangling_initializer_list)
1406 << !InitEntity->
getParent() << DiagRange;
1415 case LK_StmtExprResult:
1416 if (
auto *DRE = dyn_cast<DeclRefExpr>(L)) {
1419 if (LK == LK_StmtExprResult)
1421 SemaRef.
Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1426 SemaRef.
Diag(DiagLoc, diag::err_ret_local_block) << DiagRange;
1430 if (LK == LK_StmtExprResult)
1432 SemaRef.
Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange;
1433 }
else if (
auto *CLE = dyn_cast<CompoundLiteralExpr>(L)) {
1434 SemaRef.
Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1436 << 2 << (LK == LK_MustTail) << DiagRange;
1445 SemaRef.
Diag(DiagLoc, diag::err_ret_local_temp_ref)
1447 else if (LK == LK_MustTail)
1448 SemaRef.
Diag(DiagLoc, diag::warn_musttail_local_temp_addr_ref)
1451 SemaRef.
Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
1457 for (
unsigned I = 0; I != Path.size(); ++I) {
1458 auto Elem = Path[I];
1460 switch (Elem.Kind) {
1461 case IndirectLocalPathEntry::AddressOf:
1462 case IndirectLocalPathEntry::LValToRVal:
1463 case IndirectLocalPathEntry::ParenAggInit:
1468 case IndirectLocalPathEntry::LifetimeBoundCall:
1469 case IndirectLocalPathEntry::TemporaryCopy:
1470 case IndirectLocalPathEntry::MemberExpr:
1471 case IndirectLocalPathEntry::GslPointerInit:
1472 case IndirectLocalPathEntry::GslReferenceInit:
1473 case IndirectLocalPathEntry::GslPointerAssignment:
1477 case IndirectLocalPathEntry::DefaultInit: {
1479 SemaRef.
Diag(FD->getLocation(),
1480 diag::note_init_with_default_member_initializer)
1485 case IndirectLocalPathEntry::VarInit: {
1493 case IndirectLocalPathEntry::LambdaCaptureInit: {
1494 if (!Elem.Capture->capturesVariable())
1498 const ValueDecl *VD = Elem.Capture->getCapturedVar();
1499 SemaRef.
Diag(Elem.Capture->getLocation(),
1500 diag::note_lambda_capture_initializer)
1502 << (Elem.Capture->getCaptureKind() ==
LCK_ByRef) << VD
1507 case IndirectLocalPathEntry::DefaultArg: {
1510 SemaRef.
Diag(Param->getDefaultArgRange().getBegin(),
1511 diag::note_init_with_default_argument)
1525 case LK_Assignment: {
1529 ? IndirectLocalPathEntry::LifetimeBoundCall
1530 : IndirectLocalPathEntry::GslPointerAssignment,
1534 case LK_LifetimeCapture: {
1536 Path.push_back({IndirectLocalPathEntry::GslPointerInit,
Init});
1543 if (
Init->isGLValue())
1548 Path,
Init, TemporaryVisitor,
1556 LifetimeKind LK = LTResult.getInt();
1559 nullptr,
nullptr,
Init);
1565 nullptr,
nullptr,
Init);
1572 bool RunAnalysis = (EnableDanglingPointerAssignment &&
1580 nullptr, LK_Assignment, &Entity,
1589 diag::warn_dangling_reference_captured_by_unknown,
SourceLocation()))
1592 nullptr, LK_LifetimeCapture,
C Language Family Type Representation.
Represents binding an expression to a temporary.
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.
Represents a C++ constructor within a class.
Represents a static or instance method of a struct/union/class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Represents a C++ struct/union/class.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
bool isStdNamespace() const
Decl - This represents one declaration (or definition), e.g.
bool isInStdNamespace() const
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
SourceLocation getLocation() const
DeclContext * getDeclContext()
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
This represents one expression.
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
QualType getReturnType() const
FunctionTemplateDecl * getPrimaryTemplate() const
Retrieve the primary template that this function template specialization either specializes or was in...
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
size_t param_size() const
One of these records is kept for each identifier that is lexed.
Describes an C or C++ initializer list.
Describes an entity that is being initialized.
EntityKind getKind() const
Determine the kind of initialization.
unsigned allocateManglingNumber() const
QualType getType() const
Retrieve type being initialized.
ValueDecl * getDecl() const
Retrieve the variable, parameter, or field being initialized.
const InitializedEntity * getParent() const
Retrieve the parent of the entity being initialized, when the initialization itself is occurring with...
@ EK_Variable
The entity being initialized is a variable.
@ EK_Temporary
The entity being initialized is a temporary object.
@ EK_Binding
The entity being initialized is a structured binding of a decomposition declaration.
@ EK_BlockElement
The entity being initialized is a field of block descriptor for the copied-in c++ object.
@ EK_MatrixElement
The entity being initialized is an element of a matrix.
@ EK_Parameter_CF_Audited
The entity being initialized is a function parameter; function is member of group of audited CF APIs.
@ EK_LambdaToBlockConversionBlockElement
The entity being initialized is a field of block descriptor for the copied-in lambda object that's us...
@ EK_Member
The entity being initialized is a non-static data member subobject.
@ EK_Base
The entity being initialized is a base member subobject.
@ EK_Result
The entity being initialized is the result of a function call.
@ EK_TemplateParameter
The entity being initialized is a non-type template parameter.
@ EK_StmtExprResult
The entity being initialized is the result of a statement expression.
@ EK_ParenAggInitMember
The entity being initialized is a non-static data member subobject of an object initialized via paren...
@ EK_VectorElement
The entity being initialized is an element of a vector.
@ EK_New
The entity being initialized is an object (or array of objects) allocated via new.
@ EK_CompoundLiteralInit
The entity being initialized is the initializer for a compound literal.
@ EK_Parameter
The entity being initialized is a function parameter.
@ EK_Delegating
The initialization is being done by a delegating constructor.
@ EK_ComplexElement
The entity being initialized is the real or imaginary part of a complex number.
@ EK_ArrayElement
The entity being initialized is an element of an array.
@ EK_LambdaCapture
The entity being initialized is the field that captures a variable in a lambda.
@ EK_Exception
The entity being initialized is an exception object that is being thrown.
@ EK_RelatedResult
The entity being implicitly initialized back to the formal result type.
bool isDefaultMemberInitializer() const
Is this the default member initializer of a member (specified inside the class definition)?
Describes the capture of a variable or of this, or of a C++1y init-capture.
bool capturesVariable() const
Determine whether this capture handles a variable.
const LambdaCapture * capture_iterator
An iterator that walks over the captures of the lambda, both implicit and explicit.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Represents a parameter to a function.
A (possibly-)qualified type.
Represents a struct/union/class.
Base for LValueReferenceType and RValueReferenceType.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Sema - This implements semantic analysis and AST building for C.
DiagnosticsEngine & getDiagnostics() const
const LangOptions & getLangOpts() const
static bool CanBeGetReturnObject(const FunctionDecl *FD)
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
@ Type
The template argument is a type.
bool hasAttr(attr::Kind AK) const
Determine whether this type had the specified attribute applied to it (looking through top-level type...
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
bool isPointerType() const
bool isReferenceType() const
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isPointerOrReferenceType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isNullPtrType() const
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
bool isInitCapture() const
Whether this variable is the implicit variable for a lambda init-capture.
Represents a variable declaration or definition.
bool isCXXForRangeImplicitVar() const
Whether this variable is the implicit '__range' variable in C++ range-based for loops.
bool isGslPointerType(QualType QT)
bool isAssignmentOperatorLifetimeBound(const CXXMethodDecl *CMD)
bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD)
const FunctionDecl * getDeclWithMergedLifetimeBoundAttrs(const FunctionDecl *FD)
bool isGslOwnerType(QualType QT)
std::variant< struct RequiresDecl, struct HeaderDecl, struct UmbrellaDirDecl, struct ModuleDecl, struct ExcludeDecl, struct ExportDecl, struct ExportAsDecl, struct ExternModuleDecl, struct UseDecl, struct LinkDecl, struct ConfigMacrosDecl, struct ConflictDecl > Decl
All declarations that can appear in a module declaration.
static bool isStdInitializerListOfPointer(const RecordDecl *RD)
bool isGslPointerType(QualType QT)
static void checkExprLifetimeImpl(Sema &SemaRef, const InitializedEntity *InitEntity, const InitializedEntity *ExtendingEntity, LifetimeKind LK, const AssignedEntity *AEntity, const CapturingEntity *CapEntity, Expr *Init)
static bool shouldRunGSLAssignmentAnalysis(const Sema &SemaRef, const AssignedEntity &Entity)
static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, Expr *Init, ReferenceKind RK, LocalVisitor Visit)
Visit the locals that would be reachable through a reference bound to the glvalue expression Init.
void checkExprLifetimeMustTailArg(Sema &SemaRef, const InitializedEntity &Entity, Expr *Init)
Check that the lifetime of the given expr (and its subobjects) is sufficient, assuming that it is pas...
static bool pathOnlyHandlesGslPointer(const IndirectLocalPath &Path)
static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, Expr *Init, LocalVisitor Visit, bool RevisitSubinits)
Visit the locals that would be reachable through an object initialized by the prvalue expression Init...
static AnalysisResult analyzePathForGSLPointer(const IndirectLocalPath &Path, Local L, LifetimeKind LK)
static bool isInStlNamespace(const Decl *D)
static bool shouldTrackFirstArgument(const FunctionDecl *FD)
static bool isContainerOfOwner(const RecordDecl *Container)
static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I, Expr *E)
Find the range for the first interesting entry in the path at or after I.
static LifetimeResult getEntityLifetime(const InitializedEntity *Entity, const InitializedEntity *InitField=nullptr)
Determine the declaration which an initialized entity ultimately refers to, for the purpose of lifeti...
static bool isContainerOfPointer(const RecordDecl *Container)
void checkInitLifetime(Sema &SemaRef, const InitializedEntity &Entity, Expr *Init)
Check that the lifetime of the given expr (and its subobjects) is sufficient for initializing the ent...
static bool isCopyLikeConstructor(const CXXConstructorDecl *Ctor)
void checkAssignmentLifetime(Sema &SemaRef, const AssignedEntity &Entity, Expr *Init)
Check that the lifetime of the given expr (and its subobjects) is sufficient for assigning to the ent...
static bool shouldTrackFirstArgumentForConstructor(const CXXConstructExpr *Ctor)
bool isGslOwnerType(QualType QT)
PathLifetimeKind
Whether a path to an object supports lifetime extension.
@ NoExtend
Do not lifetime extend along this path.
@ Extend
Lifetime-extend along this path.
static bool isVarOnPath(const IndirectLocalPath &Path, VarDecl *VD)
static bool pathContainsInit(const IndirectLocalPath &Path)
static bool isPointerLikeType(QualType QT)
static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call, LocalVisitor Visit)
void checkCaptureByLifetime(Sema &SemaRef, const CapturingEntity &Entity, Expr *Init)
static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee)
static PathLifetimeKind shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path)
Determine whether this is an indirect path to a temporary that we are supposed to lifetime-extend alo...
bool isa(CodeGen::Address addr)
LLVM_READONLY bool isUppercase(unsigned char c)
Return true if this character is an uppercase ASCII letter: [A-Z].
@ LCK_ByRef
Capturing by reference.
U cast(CodeGen::Address addr)
Describes an entity that is being assigned.
CXXMethodDecl * AssignmentOperator