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);
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);
505 else if (
const auto *CaptureAttr =
508 llvm::any_of(CaptureAttr->params(), [](
int ArgIdx) {
509 return ArgIdx == LifetimeCaptureByAttr::This;
524 VisitLifetimeBoundArg(CanonCallee->
getParamDecl(I), Arg);
525 else if (EnableGSLAnalysis && I == 0) {
528 VisitGSLPointerArg(CanonCallee, Arg);
529 }
else if (
auto *Ctor = dyn_cast<CXXConstructExpr>(
Call);
531 VisitGSLPointerArg(Ctor->getConstructor(), Arg);
541 LocalVisitor Visit) {
542 RevertToOldSizeRAII RAII(Path);
549 if (
auto *FE = dyn_cast<FullExpr>(
Init))
550 Init = FE->getSubExpr();
554 if (ILE->isTransparent())
555 Init = ILE->getInit(0);
558 if (
MemberExpr *ME = dyn_cast<MemberExpr>(
Init->IgnoreImpCasts()))
560 {IndirectLocalPathEntry::MemberExpr, ME, ME->getMemberDecl()});
563 Init =
const_cast<Expr *
>(
Init->skipRValueSubobjectAdjustments());
568 if (CE->getSubExpr()->isGLValue())
569 Init = CE->getSubExpr();
573 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(
Init)) {
574 Init = ASE->getBase();
575 auto *ICE = dyn_cast<ImplicitCastExpr>(
Init);
576 if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay)
577 Init = ICE->getSubExpr();
586 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(
Init)) {
588 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
589 Init = DIE->getExpr();
591 }
while (
Init != Old);
593 if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(
Init)) {
594 if (Visit(Path, Local(MTE), RK))
598 if (
auto *M = dyn_cast<MemberExpr>(
Init)) {
600 if (
auto *F = dyn_cast<FieldDecl>(M->getMemberDecl());
601 F && !F->getType()->isReferenceType())
608 switch (
Init->getStmtClass()) {
609 case Stmt::DeclRefExprClass: {
613 auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
614 if (VD && VD->hasLocalStorage() &&
615 !DRE->refersToEnclosingVariableOrCapture()) {
616 if (!VD->getType()->isReferenceType()) {
617 Visit(Path, Local(DRE), RK);
622 }
else if (VD->getInit() && !
isVarOnPath(Path, VD)) {
623 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
625 RK_ReferenceBinding, Visit);
631 case Stmt::UnaryOperatorClass: {
636 if (
U->getOpcode() == UO_Deref)
641 case Stmt::ArraySectionExprClass: {
647 case Stmt::ConditionalOperatorClass:
648 case Stmt::BinaryConditionalOperatorClass: {
650 if (!
C->getTrueExpr()->getType()->isVoidType())
652 if (!
C->getFalseExpr()->getType()->isVoidType())
657 case Stmt::CompoundLiteralExprClass: {
658 if (
auto *CLE = dyn_cast<CompoundLiteralExpr>(
Init)) {
659 if (!CLE->isFileScope())
660 Visit(Path, Local(CLE), RK);
676 bool RevisitSubinits) {
677 RevertToOldSizeRAII RAII(Path);
685 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(
Init)) {
687 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
688 Init = DIE->getExpr();
691 if (
auto *FE = dyn_cast<FullExpr>(
Init))
692 Init = FE->getSubExpr();
695 Init =
const_cast<Expr *
>(
Init->skipRValueSubobjectAdjustments());
698 Init = BTE->getSubExpr();
703 if (
auto *CE = dyn_cast<CastExpr>(
Init)) {
704 switch (CE->getCastKind()) {
705 case CK_LValueToRValue:
708 Path.push_back({IndirectLocalPathEntry::LValToRVal, CE});
710 Path,
Init, RK_ReferenceBinding,
711 [&](IndirectLocalPath &Path, Local L, ReferenceKind RK) ->
bool {
712 if (
auto *DRE = dyn_cast<DeclRefExpr>(L)) {
713 auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
714 if (VD && VD->getType().isConstQualified() && VD->getInit() &&
716 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
720 }
else if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L)) {
721 if (MTE->getType().isConstQualified())
734 case CK_BaseToDerived:
735 case CK_DerivedToBase:
736 case CK_UncheckedDerivedToBase:
739 case CK_UserDefinedConversion:
740 case CK_ConstructorConversion:
741 case CK_IntegralToPointer:
742 case CK_PointerToIntegral:
744 case CK_IntegralCast:
745 case CK_CPointerToObjCPointerCast:
746 case CK_BlockPointerToObjCPointerCast:
747 case CK_AnyPointerToBlockPointerCast:
748 case CK_AddressSpaceConversion:
751 case CK_ArrayToPointerDecay:
754 Path.push_back({IndirectLocalPathEntry::AddressOf, CE});
756 Path, CE->getSubExpr(), RK_ReferenceBinding, Visit);
762 Init = CE->getSubExpr();
764 }
while (Old !=
Init);
769 if (
auto *ILE = dyn_cast<CXXStdInitializerListExpr>(
Init))
771 RK_StdInitializerList, Visit);
777 if (!RevisitSubinits)
780 if (ILE->isTransparent())
784 if (ILE->getType()->isArrayType()) {
785 for (
unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
791 if (
CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) {
792 assert(RD->isAggregate() &&
"aggregate init on non-aggregate");
797 if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
798 ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
800 RK_ReferenceBinding, Visit);
803 for (; Index < RD->getNumBases() && Index < ILE->getNumInits(); ++Index)
806 for (
const auto *I : RD->fields()) {
807 if (Index >= ILE->getNumInits())
809 if (I->isUnnamedBitField())
811 Expr *SubInit = ILE->getInit(Index);
812 if (I->getType()->isReferenceType())
814 RK_ReferenceBinding, Visit);
830 if (
auto *LE = dyn_cast<LambdaExpr>(
Init)) {
832 for (
Expr *E : LE->capture_inits()) {
833 assert(CapI != LE->capture_end());
838 Path.push_back({IndirectLocalPathEntry::LambdaCaptureInit, E, &Cap});
851 if (
auto *CCE = dyn_cast<CXXConstructExpr>(
Init)) {
852 if (CCE->getConstructor()->isCopyOrMoveConstructor()) {
853 if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(CCE->getArg(0))) {
854 Expr *Arg = MTE->getSubExpr();
855 Path.push_back({IndirectLocalPathEntry::TemporaryCopy, Arg,
856 CCE->getConstructor()});
866 if (
auto *CPE = dyn_cast<CXXParenListInitExpr>(
Init)) {
867 RevertToOldSizeRAII RAII(Path);
868 Path.push_back({IndirectLocalPathEntry::ParenAggInit, CPE});
869 for (
auto *I : CPE->getInitExprs()) {
877 switch (
Init->getStmtClass()) {
878 case Stmt::UnaryOperatorClass: {
882 if (UO->getOpcode() == UO_AddrOf) {
889 Path.push_back({IndirectLocalPathEntry::AddressOf, UO});
891 RK_ReferenceBinding, Visit);
896 case Stmt::BinaryOperatorClass: {
900 if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub))
903 if (BO->getLHS()->getType()->isPointerType())
905 else if (BO->getRHS()->getType()->isPointerType())
910 case Stmt::ConditionalOperatorClass:
911 case Stmt::BinaryConditionalOperatorClass: {
915 if (!
C->getTrueExpr()->getType()->isVoidType())
917 if (!
C->getFalseExpr()->getType()->isVoidType())
922 case Stmt::BlockExprClass:
929 case Stmt::AddrLabelExprClass:
951 for (
auto Elem : Path) {
952 if (Elem.Kind == IndirectLocalPathEntry::MemberExpr ||
953 Elem.Kind == IndirectLocalPathEntry::LambdaCaptureInit)
955 return Elem.Kind == IndirectLocalPathEntry::DefaultInit
965 for (
unsigned N = Path.size(); I != N; ++I) {
966 switch (Path[I].Kind) {
967 case IndirectLocalPathEntry::AddressOf:
968 case IndirectLocalPathEntry::LValToRVal:
969 case IndirectLocalPathEntry::LifetimeBoundCall:
970 case IndirectLocalPathEntry::TemporaryCopy:
971 case IndirectLocalPathEntry::GslReferenceInit:
972 case IndirectLocalPathEntry::GslPointerInit:
973 case IndirectLocalPathEntry::GslPointerAssignment:
974 case IndirectLocalPathEntry::ParenAggInit:
975 case IndirectLocalPathEntry::MemberExpr:
980 case IndirectLocalPathEntry::VarInit:
984 case IndirectLocalPathEntry::DefaultInit:
985 return Path[I].E->getSourceRange();
987 case IndirectLocalPathEntry::LambdaCaptureInit:
988 if (!Path[I].
Capture->capturesVariable())
990 return Path[I].E->getSourceRange();
992 case IndirectLocalPathEntry::DefaultArg:
1000 for (
const auto &It : llvm::reverse(Path)) {
1002 case IndirectLocalPathEntry::VarInit:
1003 case IndirectLocalPathEntry::AddressOf:
1004 case IndirectLocalPathEntry::LifetimeBoundCall:
1005 case IndirectLocalPathEntry::MemberExpr:
1007 case IndirectLocalPathEntry::GslPointerInit:
1008 case IndirectLocalPathEntry::GslReferenceInit:
1009 case IndirectLocalPathEntry::GslPointerAssignment:
1032 Local L, LifetimeKind LK) {
1040 for (
const auto &E : Path) {
1041 if (E.Kind == IndirectLocalPathEntry::MemberExpr) {
1050 if (
const auto *FD = llvm::dyn_cast_or_null<FieldDecl>(E.D);
1051 FD && !FD->getType()->isReferenceType() &&
1066 if (Path.back().Kind == IndirectLocalPathEntry::LifetimeBoundCall) {
1069 llvm::dyn_cast_or_null<FunctionDecl>(Path.back().D);
1071 if (
const auto *PD = llvm::dyn_cast<ParmVarDecl>(Path.back().D))
1072 FD = llvm::dyn_cast<FunctionDecl>(PD->getDeclContext());
1074 if (isa_and_present<CXXConstructorDecl>(FD)) {
1104 auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
1106 bool IsGslPtrValueFromGslTempOwner =
1107 MTE && !MTE->getExtendingDecl() &&
isGslOwnerType(MTE->getType());
1112 if (!IsGslPtrValueFromGslTempOwner)
1120 diag::warn_dangling_lifetime_pointer_assignment,
SourceLocation());
1121 return (EnableGSLAssignmentWarnings &&
1132 assert(!AEntity || LK == LK_Assignment);
1133 assert(!CapEntity || LK == LK_LifetimeCapture);
1134 assert(!InitEntity || (LK != LK_Assignment && LK != LK_LifetimeCapture));
1137 if (LK == LK_FullExpression)
1142 auto TemporaryVisitor = [&](
const IndirectLocalPath &Path, Local L,
1143 ReferenceKind RK) ->
bool {
1147 auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
1149 bool IsGslPtrValueFromGslTempOwner =
true;
1156 IsGslPtrValueFromGslTempOwner =
false;
1163 case LK_FullExpression:
1164 llvm_unreachable(
"already handled this");
1180 MTE->setExtendingDecl(ExtendingEntity->
getDecl(),
1186 if (SemaRef.
getLangOpts().CPlusPlus23 && InitEntity) {
1188 dyn_cast_if_present<VarDecl>(InitEntity->
getDecl());
1194 if (IsGslPtrValueFromGslTempOwner && DiagLoc.
isValid()) {
1195 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1206 SemaRef.
Diag(DiagLoc, diag::warn_dangling_variable)
1209 << ExtendingEntity->
getDecl() <<
Init->isGLValue() << DiagRange;
1215 case LK_LifetimeCapture: {
1221 SemaRef.
Diag(DiagLoc, diag::warn_dangling_reference_captured)
1222 << CapEntity->
Entity << DiagRange;
1224 SemaRef.
Diag(DiagLoc, diag::warn_dangling_reference_captured_by_unknown)
1229 case LK_Assignment: {
1232 if (IsGslPtrValueFromGslTempOwner)
1233 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_assignment)
1234 << AEntity->
LHS << DiagRange;
1236 SemaRef.
Diag(DiagLoc, diag::warn_dangling_pointer_assignment)
1241 case LK_MemInitializer: {
1246 if (
auto *ExtendingDecl =
1247 ExtendingEntity ? ExtendingEntity->
getDecl() :
nullptr) {
1248 if (IsGslPtrValueFromGslTempOwner) {
1249 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_member)
1250 << ExtendingDecl << DiagRange;
1251 SemaRef.
Diag(ExtendingDecl->getLocation(),
1252 diag::note_ref_or_ptr_member_declared_here)
1256 bool IsSubobjectMember = ExtendingEntity != InitEntity;
1259 ? diag::err_dangling_member
1260 : diag::warn_dangling_member)
1261 << ExtendingDecl << IsSubobjectMember << RK << DiagRange;
1266 Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {
1267 SemaRef.
Diag(ExtendingDecl->getLocation(),
1268 diag::note_lifetime_extending_member_declared_here)
1269 << RK << IsSubobjectMember;
1287 auto *DRE = dyn_cast<DeclRefExpr>(L);
1294 auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) :
nullptr;
1302 ExtendingEntity ? ExtendingEntity->
getDecl() :
nullptr) {
1303 bool IsPointer = !
Member->getType()->isReferenceType();
1304 SemaRef.
Diag(DiagLoc,
1305 IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
1306 : diag::warn_bind_ref_member_to_parameter)
1309 diag::note_ref_or_ptr_member_declared_here)
1318 if (IsGslPtrValueFromGslTempOwner)
1319 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1322 SemaRef.
Diag(DiagLoc, RK == RK_ReferenceBinding
1323 ? diag::warn_new_dangling_reference
1324 : diag::warn_new_dangling_initializer_list)
1325 << !InitEntity->
getParent() << DiagRange;
1334 case LK_StmtExprResult:
1335 if (
auto *DRE = dyn_cast<DeclRefExpr>(L)) {
1338 if (LK == LK_StmtExprResult)
1340 SemaRef.
Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1345 SemaRef.
Diag(DiagLoc, diag::err_ret_local_block) << DiagRange;
1349 if (LK == LK_StmtExprResult)
1351 SemaRef.
Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange;
1352 }
else if (
auto *CLE = dyn_cast<CompoundLiteralExpr>(L)) {
1353 SemaRef.
Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1355 << 2 << (LK == LK_MustTail) << DiagRange;
1364 SemaRef.
Diag(DiagLoc, diag::err_ret_local_temp_ref)
1366 else if (LK == LK_MustTail)
1367 SemaRef.
Diag(DiagLoc, diag::warn_musttail_local_temp_addr_ref)
1370 SemaRef.
Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
1376 for (
unsigned I = 0; I != Path.size(); ++I) {
1377 auto Elem = Path[I];
1379 switch (Elem.Kind) {
1380 case IndirectLocalPathEntry::AddressOf:
1381 case IndirectLocalPathEntry::LValToRVal:
1382 case IndirectLocalPathEntry::ParenAggInit:
1387 case IndirectLocalPathEntry::LifetimeBoundCall:
1388 case IndirectLocalPathEntry::TemporaryCopy:
1389 case IndirectLocalPathEntry::MemberExpr:
1390 case IndirectLocalPathEntry::GslPointerInit:
1391 case IndirectLocalPathEntry::GslReferenceInit:
1392 case IndirectLocalPathEntry::GslPointerAssignment:
1396 case IndirectLocalPathEntry::DefaultInit: {
1398 SemaRef.
Diag(FD->getLocation(),
1399 diag::note_init_with_default_member_initializer)
1404 case IndirectLocalPathEntry::VarInit: {
1412 case IndirectLocalPathEntry::LambdaCaptureInit: {
1413 if (!Elem.Capture->capturesVariable())
1417 const ValueDecl *VD = Elem.Capture->getCapturedVar();
1418 SemaRef.
Diag(Elem.Capture->getLocation(),
1419 diag::note_lambda_capture_initializer)
1421 << (Elem.Capture->getCaptureKind() ==
LCK_ByRef) << VD
1426 case IndirectLocalPathEntry::DefaultArg: {
1429 SemaRef.
Diag(Param->getDefaultArgRange().getBegin(),
1430 diag::note_init_with_default_argument)
1444 case LK_Assignment: {
1448 ? IndirectLocalPathEntry::LifetimeBoundCall
1449 : IndirectLocalPathEntry::GslPointerAssignment,
1453 case LK_LifetimeCapture: {
1455 Path.push_back({IndirectLocalPathEntry::GslPointerInit,
Init});
1462 if (
Init->isGLValue())
1467 Path,
Init, TemporaryVisitor,
1475 LifetimeKind LK = LTResult.getInt();
1478 nullptr,
nullptr,
Init);
1484 nullptr,
nullptr,
Init);
1491 bool RunAnalysis = (EnableDanglingPointerAssignment &&
1499 nullptr, LK_Assignment, &Entity,
1508 diag::warn_dangling_reference_captured_by_unknown,
SourceLocation()))
1511 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.
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 shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee, bool RunningUnderLifetimeSafety)
bool shouldTrackFirstArgument(const FunctionDecl *FD)
bool isAssignmentOperatorLifetimeBound(const CXXMethodDecl *CMD)
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