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);
266 if (
const auto *CTSD =
267 dyn_cast_if_present<ClassTemplateSpecializationDecl>(Container)) {
268 if (!CTSD->hasAttr<OwnerAttr>())
270 const auto &TAs = CTSD->getTemplateArgs();
278 dyn_cast_if_present<ClassTemplateSpecializationDecl>(Container);
281 if (!CTSD->hasAttr<OwnerAttr>())
283 const auto &TAs = CTSD->getTemplateArgs();
290 if (
const auto *CTSD =
291 dyn_cast_if_present<ClassTemplateSpecializationDecl>(RD)) {
292 const auto &TAs = CTSD->getTemplateArgs();
294 RD->
getName() ==
"initializer_list" && TAs.size() > 0 &&
306 const auto *ParamRefType =
312 if (
const auto *TST =
313 ParamRefType->getPointeeType()->getAs<TemplateSpecializationType>())
314 return TST->getTemplateName()
329 if (LHSRecordDecl->hasAttr<PointerAttr>())
386 if (
const auto *PrimaryCtorTemplate =
388 PrimaryCtorTemplate &&
390 PrimaryCtorTemplate->getTemplatedDecl()))) {
400 LocalVisitor Visit) {
404 if (
auto *CE = dyn_cast<CallExpr>(
Call)) {
405 Callee = CE->getDirectCallee();
409 Callee = CCE->getConstructor();
415 bool EnableGSLAnalysis = !Callee->getASTContext().getDiagnostics().isIgnored(
417 Expr *ObjectArg =
nullptr;
420 Args = Args.slice(1);
421 }
else if (
auto *MCE = dyn_cast<CXXMemberCallExpr>(
Call)) {
422 ObjectArg = MCE->getImplicitObjectArgument();
425 auto VisitLifetimeBoundArg = [&](
const Decl *D,
Expr *Arg) {
426 Path.push_back({IndirectLocalPathEntry::LifetimeBoundCall, Arg, D});
427 if (Arg->isGLValue())
435 auto ReturnType = Callee->getReturnType();
439 if (ReturnType->isReferenceType() &&
441 for (
const IndirectLocalPathEntry &PE : llvm::reverse(Path)) {
442 if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit ||
443 PE.Kind == IndirectLocalPathEntry::LifetimeBoundCall)
445 if (PE.Kind == IndirectLocalPathEntry::GslPointerInit ||
446 PE.Kind == IndirectLocalPathEntry::GslPointerAssignment)
451 Path.push_back({ReturnType->isReferenceType()
452 ? IndirectLocalPathEntry::GslReferenceInit
453 : IndirectLocalPathEntry::GslPointerInit,
455 if (Arg->isGLValue())
463 bool CheckCoroCall =
false;
464 if (
const auto *RD = Callee->getReturnType()->getAsRecordDecl()) {
465 CheckCoroCall = RD->hasAttr<CoroLifetimeBoundAttr>() &&
466 RD->hasAttr<CoroReturnTypeAttr>() &&
467 !Callee->hasAttr<CoroDisableLifetimeBoundAttr>();
471 bool CheckCoroObjArg = CheckCoroCall;
474 LE && LE->captures().empty())
475 CheckCoroObjArg =
false;
479 CheckCoroObjArg =
false;
482 VisitLifetimeBoundArg(Callee, ObjectArg);
483 else if (EnableGSLAnalysis) {
484 if (
auto *CME = dyn_cast<CXXMethodDecl>(Callee);
486 *ObjectArg, CME,
false))
487 VisitGSLPointerArg(Callee, ObjectArg);
493 unsigned NP = std::min(Callee->getNumParams(), CanonCallee->
getNumParams());
494 for (
unsigned I = 0, N = std::min<unsigned>(NP, Args.size()); I != N; ++I) {
496 RevertToOldSizeRAII RAII(Path);
497 if (
auto *DAE = dyn_cast<CXXDefaultArgExpr>(Arg)) {
499 {IndirectLocalPathEntry::DefaultArg, DAE, DAE->getParam()});
500 Arg = DAE->getExpr();
504 VisitLifetimeBoundArg(CanonCallee->
getParamDecl(I), Arg);
508 [](
const LifetimeCaptureByAttr *CaptureAttr) {
509 return llvm::is_contained(
510 CaptureAttr->params(),
511 LifetimeCaptureByAttr::This);
526 VisitLifetimeBoundArg(CanonCallee->
getParamDecl(I), Arg);
527 else if (EnableGSLAnalysis && I == 0) {
530 VisitGSLPointerArg(CanonCallee, Arg);
531 }
else if (
auto *Ctor = dyn_cast<CXXConstructExpr>(
Call);
533 VisitGSLPointerArg(Ctor->getConstructor(), Arg);
543 LocalVisitor Visit) {
544 RevertToOldSizeRAII RAII(Path);
551 if (
auto *FE = dyn_cast<FullExpr>(
Init))
552 Init = FE->getSubExpr();
556 if (ILE->isTransparent())
557 Init = ILE->getInit(0);
560 if (
MemberExpr *ME = dyn_cast<MemberExpr>(
Init->IgnoreImpCasts()))
562 {IndirectLocalPathEntry::MemberExpr, ME, ME->getMemberDecl()});
565 Init =
const_cast<Expr *
>(
Init->skipRValueSubobjectAdjustments());
570 if (CE->getSubExpr()->isGLValue())
571 Init = CE->getSubExpr();
575 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(
Init)) {
576 Init = ASE->getBase();
577 auto *ICE = dyn_cast<ImplicitCastExpr>(
Init);
578 if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay)
579 Init = ICE->getSubExpr();
588 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(
Init)) {
590 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
591 Init = DIE->getExpr();
593 }
while (
Init != Old);
595 if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(
Init)) {
596 if (Visit(Path, Local(MTE), RK))
600 if (
auto *M = dyn_cast<MemberExpr>(
Init)) {
602 if (
auto *F = dyn_cast<FieldDecl>(M->getMemberDecl());
603 F && !F->getType()->isReferenceType())
610 switch (
Init->getStmtClass()) {
611 case Stmt::DeclRefExprClass: {
615 auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
616 if (VD && VD->hasLocalStorage() &&
617 !DRE->refersToEnclosingVariableOrCapture()) {
618 if (!VD->getType()->isReferenceType()) {
619 Visit(Path, Local(DRE), RK);
624 }
else if (VD->getInit() && !
isVarOnPath(Path, VD)) {
625 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
627 RK_ReferenceBinding, Visit);
633 case Stmt::UnaryOperatorClass: {
638 if (
U->getOpcode() == UO_Deref)
643 case Stmt::ArraySectionExprClass: {
649 case Stmt::ConditionalOperatorClass:
650 case Stmt::BinaryConditionalOperatorClass: {
652 if (!
C->getTrueExpr()->getType()->isVoidType())
654 if (!
C->getFalseExpr()->getType()->isVoidType())
659 case Stmt::CompoundLiteralExprClass: {
660 if (
auto *CLE = dyn_cast<CompoundLiteralExpr>(
Init)) {
661 if (!CLE->isFileScope())
662 Visit(Path, Local(CLE), RK);
678 bool RevisitSubinits) {
679 RevertToOldSizeRAII RAII(Path);
687 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(
Init)) {
689 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
690 Init = DIE->getExpr();
693 if (
auto *FE = dyn_cast<FullExpr>(
Init))
694 Init = FE->getSubExpr();
697 Init =
const_cast<Expr *
>(
Init->skipRValueSubobjectAdjustments());
700 Init = BTE->getSubExpr();
705 if (
auto *CE = dyn_cast<CastExpr>(
Init)) {
706 switch (CE->getCastKind()) {
707 case CK_LValueToRValue:
710 Path.push_back({IndirectLocalPathEntry::LValToRVal, CE});
712 Path,
Init, RK_ReferenceBinding,
713 [&](IndirectLocalPath &Path, Local L, ReferenceKind RK) ->
bool {
714 if (
auto *DRE = dyn_cast<DeclRefExpr>(L)) {
715 auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
716 if (VD && VD->getType().isConstQualified() && VD->getInit() &&
718 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
722 }
else if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L)) {
723 if (MTE->getType().isConstQualified())
736 case CK_BaseToDerived:
737 case CK_DerivedToBase:
738 case CK_UncheckedDerivedToBase:
741 case CK_UserDefinedConversion:
742 case CK_ConstructorConversion:
743 case CK_IntegralToPointer:
744 case CK_PointerToIntegral:
746 case CK_IntegralCast:
747 case CK_CPointerToObjCPointerCast:
748 case CK_BlockPointerToObjCPointerCast:
749 case CK_AnyPointerToBlockPointerCast:
750 case CK_AddressSpaceConversion:
753 case CK_ArrayToPointerDecay:
756 Path.push_back({IndirectLocalPathEntry::AddressOf, CE});
758 Path, CE->getSubExpr(), RK_ReferenceBinding, Visit);
764 Init = CE->getSubExpr();
766 }
while (Old !=
Init);
771 if (
auto *ILE = dyn_cast<CXXStdInitializerListExpr>(
Init))
773 RK_StdInitializerList, Visit);
779 if (!RevisitSubinits)
782 if (ILE->isTransparent())
786 if (ILE->getType()->isArrayType()) {
787 for (
unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
793 if (
CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) {
794 assert(RD->isAggregate() &&
"aggregate init on non-aggregate");
799 if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
800 ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
802 RK_ReferenceBinding, Visit);
805 for (; Index < RD->getNumBases() && Index < ILE->getNumInits(); ++Index)
808 for (
const auto *I : RD->fields()) {
809 if (Index >= ILE->getNumInits())
811 if (I->isUnnamedBitField())
813 Expr *SubInit = ILE->getInit(Index);
814 if (I->getType()->isReferenceType())
816 RK_ReferenceBinding, Visit);
832 if (
auto *LE = dyn_cast<LambdaExpr>(
Init)) {
834 for (
Expr *E : LE->capture_inits()) {
835 assert(CapI != LE->capture_end());
840 Path.push_back({IndirectLocalPathEntry::LambdaCaptureInit, E, &Cap});
853 if (
auto *CCE = dyn_cast<CXXConstructExpr>(
Init)) {
854 if (CCE->getConstructor()->isCopyOrMoveConstructor()) {
855 if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(CCE->getArg(0))) {
856 Expr *Arg = MTE->getSubExpr();
857 Path.push_back({IndirectLocalPathEntry::TemporaryCopy, Arg,
858 CCE->getConstructor()});
868 if (
auto *CPE = dyn_cast<CXXParenListInitExpr>(
Init)) {
869 RevertToOldSizeRAII RAII(Path);
870 Path.push_back({IndirectLocalPathEntry::ParenAggInit, CPE});
871 for (
auto *I : CPE->getInitExprs()) {
879 switch (
Init->getStmtClass()) {
880 case Stmt::UnaryOperatorClass: {
884 if (UO->getOpcode() == UO_AddrOf) {
891 Path.push_back({IndirectLocalPathEntry::AddressOf, UO});
893 RK_ReferenceBinding, Visit);
898 case Stmt::BinaryOperatorClass: {
902 if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub))
905 if (BO->getLHS()->getType()->isPointerType())
907 else if (BO->getRHS()->getType()->isPointerType())
912 case Stmt::ConditionalOperatorClass:
913 case Stmt::BinaryConditionalOperatorClass: {
917 if (!
C->getTrueExpr()->getType()->isVoidType())
919 if (!
C->getFalseExpr()->getType()->isVoidType())
924 case Stmt::BlockExprClass:
931 case Stmt::AddrLabelExprClass:
953 for (
auto Elem : Path) {
954 if (Elem.Kind == IndirectLocalPathEntry::MemberExpr ||
955 Elem.Kind == IndirectLocalPathEntry::LambdaCaptureInit)
957 return Elem.Kind == IndirectLocalPathEntry::DefaultInit
967 for (
unsigned N = Path.size(); I != N; ++I) {
968 switch (Path[I].Kind) {
969 case IndirectLocalPathEntry::AddressOf:
970 case IndirectLocalPathEntry::LValToRVal:
971 case IndirectLocalPathEntry::LifetimeBoundCall:
972 case IndirectLocalPathEntry::TemporaryCopy:
973 case IndirectLocalPathEntry::GslReferenceInit:
974 case IndirectLocalPathEntry::GslPointerInit:
975 case IndirectLocalPathEntry::GslPointerAssignment:
976 case IndirectLocalPathEntry::ParenAggInit:
977 case IndirectLocalPathEntry::MemberExpr:
982 case IndirectLocalPathEntry::VarInit:
986 case IndirectLocalPathEntry::DefaultInit:
987 return Path[I].E->getSourceRange();
989 case IndirectLocalPathEntry::LambdaCaptureInit:
990 if (!Path[I].
Capture->capturesVariable())
992 return Path[I].E->getSourceRange();
994 case IndirectLocalPathEntry::DefaultArg:
1002 for (
const auto &It : llvm::reverse(Path)) {
1004 case IndirectLocalPathEntry::VarInit:
1005 case IndirectLocalPathEntry::AddressOf:
1006 case IndirectLocalPathEntry::LifetimeBoundCall:
1007 case IndirectLocalPathEntry::MemberExpr:
1009 case IndirectLocalPathEntry::GslPointerInit:
1010 case IndirectLocalPathEntry::GslReferenceInit:
1011 case IndirectLocalPathEntry::GslPointerAssignment:
1034 Local L, LifetimeKind LK) {
1042 for (
const auto &E : Path) {
1043 if (E.Kind == IndirectLocalPathEntry::MemberExpr) {
1052 if (
const auto *FD = llvm::dyn_cast_or_null<FieldDecl>(E.D);
1053 FD && !FD->getType()->isReferenceType() &&
1068 if (Path.back().Kind == IndirectLocalPathEntry::LifetimeBoundCall) {
1071 llvm::dyn_cast_or_null<FunctionDecl>(Path.back().D);
1073 if (
const auto *PD = llvm::dyn_cast<ParmVarDecl>(Path.back().D))
1074 FD = llvm::dyn_cast<FunctionDecl>(PD->getDeclContext());
1076 if (isa_and_present<CXXConstructorDecl>(FD)) {
1106 auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
1108 bool IsGslPtrValueFromGslTempOwner =
1109 MTE && !MTE->getExtendingDecl() &&
isGslOwnerType(MTE->getType());
1114 if (!IsGslPtrValueFromGslTempOwner)
1122 diag::warn_dangling_lifetime_pointer_assignment,
SourceLocation());
1123 return (EnableGSLAssignmentWarnings &&
1134 assert(!AEntity || LK == LK_Assignment);
1135 assert(!CapEntity || LK == LK_LifetimeCapture);
1136 assert(!InitEntity || (LK != LK_Assignment && LK != LK_LifetimeCapture));
1139 if (LK == LK_FullExpression)
1144 auto TemporaryVisitor = [&](
const IndirectLocalPath &Path, Local L,
1145 ReferenceKind RK) ->
bool {
1149 auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
1151 bool IsGslPtrValueFromGslTempOwner =
true;
1158 IsGslPtrValueFromGslTempOwner =
false;
1165 case LK_FullExpression:
1166 llvm_unreachable(
"already handled this");
1182 MTE->setExtendingDecl(ExtendingEntity->
getDecl(),
1188 if (SemaRef.
getLangOpts().CPlusPlus23 && InitEntity) {
1190 dyn_cast_if_present<VarDecl>(InitEntity->
getDecl());
1196 if (IsGslPtrValueFromGslTempOwner && DiagLoc.
isValid()) {
1197 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1208 SemaRef.
Diag(DiagLoc, diag::warn_dangling_variable)
1211 << ExtendingEntity->
getDecl() <<
Init->isGLValue() << DiagRange;
1217 case LK_LifetimeCapture: {
1223 SemaRef.
Diag(DiagLoc, diag::warn_dangling_reference_captured)
1224 << CapEntity->
Entity << DiagRange;
1226 SemaRef.
Diag(DiagLoc, diag::warn_dangling_reference_captured_by_unknown)
1231 case LK_Assignment: {
1234 if (IsGslPtrValueFromGslTempOwner)
1235 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_assignment)
1236 << AEntity->
LHS << DiagRange;
1238 SemaRef.
Diag(DiagLoc, diag::warn_dangling_pointer_assignment)
1243 case LK_MemInitializer: {
1248 if (
auto *ExtendingDecl =
1249 ExtendingEntity ? ExtendingEntity->
getDecl() :
nullptr) {
1250 if (IsGslPtrValueFromGslTempOwner) {
1251 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_member)
1252 << ExtendingDecl << DiagRange;
1253 SemaRef.
Diag(ExtendingDecl->getLocation(),
1254 diag::note_ref_or_ptr_member_declared_here)
1258 bool IsSubobjectMember = ExtendingEntity != InitEntity;
1261 ? diag::err_dangling_member
1262 : diag::warn_dangling_member)
1263 << ExtendingDecl << IsSubobjectMember << RK << DiagRange;
1268 Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {
1269 SemaRef.
Diag(ExtendingDecl->getLocation(),
1270 diag::note_lifetime_extending_member_declared_here)
1271 << RK << IsSubobjectMember;
1289 auto *DRE = dyn_cast<DeclRefExpr>(L);
1296 auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) :
nullptr;
1304 ExtendingEntity ? ExtendingEntity->
getDecl() :
nullptr) {
1305 bool IsPointer = !
Member->getType()->isReferenceType();
1306 SemaRef.
Diag(DiagLoc,
1307 IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
1308 : diag::warn_bind_ref_member_to_parameter)
1311 diag::note_ref_or_ptr_member_declared_here)
1320 if (IsGslPtrValueFromGslTempOwner)
1321 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1324 SemaRef.
Diag(DiagLoc, RK == RK_ReferenceBinding
1325 ? diag::warn_new_dangling_reference
1326 : diag::warn_new_dangling_initializer_list)
1327 << !InitEntity->
getParent() << DiagRange;
1336 case LK_StmtExprResult:
1337 if (
auto *DRE = dyn_cast<DeclRefExpr>(L)) {
1340 if (LK == LK_StmtExprResult)
1342 if (
auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
1345 SemaRef.
Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1350 SemaRef.
Diag(DiagLoc, diag::err_ret_local_block) << DiagRange;
1354 if (LK == LK_StmtExprResult)
1356 SemaRef.
Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange;
1357 }
else if (
auto *CLE = dyn_cast<CompoundLiteralExpr>(L)) {
1358 SemaRef.
Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1360 << 2 << (LK == LK_MustTail) << DiagRange;
1369 SemaRef.
Diag(DiagLoc, diag::err_ret_local_temp_ref)
1371 else if (LK == LK_MustTail)
1372 SemaRef.
Diag(DiagLoc, diag::warn_musttail_local_temp_addr_ref)
1375 SemaRef.
Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
1381 for (
unsigned I = 0; I != Path.size(); ++I) {
1382 auto Elem = Path[I];
1384 switch (Elem.Kind) {
1385 case IndirectLocalPathEntry::AddressOf:
1386 case IndirectLocalPathEntry::LValToRVal:
1387 case IndirectLocalPathEntry::ParenAggInit:
1392 case IndirectLocalPathEntry::LifetimeBoundCall:
1393 case IndirectLocalPathEntry::TemporaryCopy:
1394 case IndirectLocalPathEntry::MemberExpr:
1395 case IndirectLocalPathEntry::GslPointerInit:
1396 case IndirectLocalPathEntry::GslReferenceInit:
1397 case IndirectLocalPathEntry::GslPointerAssignment:
1401 case IndirectLocalPathEntry::DefaultInit: {
1403 SemaRef.
Diag(FD->getLocation(),
1404 diag::note_init_with_default_member_initializer)
1409 case IndirectLocalPathEntry::VarInit: {
1417 case IndirectLocalPathEntry::LambdaCaptureInit: {
1418 if (!Elem.Capture->capturesVariable())
1422 const ValueDecl *VD = Elem.Capture->getCapturedVar();
1423 SemaRef.
Diag(Elem.Capture->getLocation(),
1424 diag::note_lambda_capture_initializer)
1426 << (Elem.Capture->getCaptureKind() ==
LCK_ByRef) << VD
1431 case IndirectLocalPathEntry::DefaultArg: {
1434 SemaRef.
Diag(Param->getDefaultArgRange().getBegin(),
1435 diag::note_init_with_default_argument)
1449 case LK_Assignment: {
1453 ? IndirectLocalPathEntry::LifetimeBoundCall
1454 : IndirectLocalPathEntry::GslPointerAssignment,
1458 case LK_LifetimeCapture: {
1460 Path.push_back({IndirectLocalPathEntry::GslPointerInit,
Init});
1467 if (
Init->isGLValue())
1472 Path,
Init, TemporaryVisitor,
1480 LifetimeKind LK = LTResult.getInt();
1483 nullptr,
nullptr,
Init);
1489 nullptr,
nullptr,
Init);
1496 bool RunAnalysis = (EnableDanglingPointerAssignment &&
1504 nullptr, LK_Assignment, &Entity,
1513 diag::warn_dangling_reference_captured_by_unknown,
SourceLocation()))
1516 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.
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...
Decl - This represents one declaration (or definition), e.g.
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
llvm::iterator_range< specific_attr_iterator< T > > specific_attrs() const
SourceLocation getLocation() const
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
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.
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
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>'.
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 shouldTrackFirstArgument(const FunctionDecl *FD)
bool isAssignmentOperatorLifetimeBound(const CXXMethodDecl *CMD)
bool shouldTrackImplicitObjectArg(const Expr &ImplicitObjectArgument, const CXXMethodDecl *Callee, bool RunningUnderLifetimeSafety)
bool isPointerLikeType(QualType QT)
bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD)
const FunctionDecl * getDeclWithMergedLifetimeBoundAttrs(const FunctionDecl *FD)
bool isGslOwnerType(QualType QT)
bool isInStlNamespace(const Decl *D)
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 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 void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call, LocalVisitor Visit)
void checkCaptureByLifetime(Sema &SemaRef, const CapturingEntity &Entity, Expr *Init)
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)
@ LCK_ByRef
Capturing by reference.
U cast(CodeGen::Address addr)
Describes an entity that is being assigned.
CXXMethodDecl * AssignmentOperator