17#include "llvm/ADT/PointerIntPair.h"
60 llvm::PointerIntPair<const InitializedEntity *, 3, LifetimeKind>;
73 return {Entity, LK_Extended};
98 return {Entity, LK_Extended};
105 return {
nullptr, LK_FullExpression};
110 return {
nullptr, LK_FullExpression};
116 return {
nullptr, LK_Return};
121 return {
nullptr, LK_StmtExprResult};
127 return {
nullptr, LK_New};
135 return {
nullptr, LK_FullExpression};
145 return {InitField, LK_MemInitializer};
152 return {InitField, LK_MemInitializer};
160 return {
nullptr, LK_FullExpression};
164 return {
nullptr, LK_FullExpression};
171 return {
nullptr, LK_FullExpression};
174 llvm_unreachable(
"unknown entity kind");
183 RK_StdInitializerList,
196struct IndirectLocalPathEntry {
208 GslPointerAssignment,
214 const Decl *D =
nullptr;
217 IndirectLocalPathEntry() {}
218 IndirectLocalPathEntry(EntryKind K, Expr *E) : Kind(K), E(E) {}
219 IndirectLocalPathEntry(EntryKind K, Expr *E,
const Decl *D)
220 : Kind(K), E(E), D(D) {}
221 IndirectLocalPathEntry(EntryKind K, Expr *E,
const LambdaCapture *
Capture)
225using IndirectLocalPath = llvm::SmallVectorImpl<IndirectLocalPathEntry>;
227struct RevertToOldSizeRAII {
228 IndirectLocalPath &Path;
229 unsigned OldSize = Path.size();
230 RevertToOldSizeRAII(IndirectLocalPath &Path) : Path(Path) {}
231 ~RevertToOldSizeRAII() { Path.resize(OldSize); }
234using LocalVisitor = llvm::function_ref<
bool(IndirectLocalPath &Path, Local L,
240 if (E.Kind == IndirectLocalPathEntry::VarInit && E.D == VD)
246 return llvm::any_of(Path, [=](IndirectLocalPathEntry E) {
247 return E.Kind == IndirectLocalPathEntry::DefaultInit ||
248 E.Kind == IndirectLocalPathEntry::VarInit;
254 bool RevisitSubinits);
279 bool Result = RD->hasAttr<
T>();
281 if (
auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
282 Result |= CTSD->getSpecializedTemplate()->getTemplatedDecl()->hasAttr<
T>();
301 if (
const auto *ND = dyn_cast<NamespaceDecl>(DC))
303 StringRef Name = II->getName();
304 if (Name.size() >= 2 && Name.front() ==
'_' &&
315 if (
const auto *CTSD =
316 dyn_cast_if_present<ClassTemplateSpecializationDecl>(Container)) {
317 if (!CTSD->hasAttr<OwnerAttr>())
319 const auto &TAs = CTSD->getTemplateArgs();
327 dyn_cast_if_present<ClassTemplateSpecializationDecl>(Container);
330 if (!CTSD->hasAttr<OwnerAttr>())
332 const auto &TAs = CTSD->getTemplateArgs();
339 if (
const auto *CTSD =
340 dyn_cast_if_present<ClassTemplateSpecializationDecl>(RD)) {
341 const auto &TAs = CTSD->getTemplateArgs();
343 RD->
getName() ==
"initializer_list" && TAs.size() > 0 &&
351 if (
auto *Conv = dyn_cast_or_null<CXXConversionDecl>(Callee))
353 Callee->getParent()->hasAttr<OwnerAttr>())
358 Callee->getFunctionObjectParameterType()) &&
362 if (!Callee->getIdentifier())
364 return llvm::StringSwitch<bool>(Callee->getName())
365 .Cases({
"begin",
"rbegin",
"cbegin",
"crbegin"},
true)
366 .Cases({
"end",
"rend",
"cend",
"crend"},
true)
367 .Cases({
"c_str",
"data",
"get"},
true)
369 .Cases({
"find",
"equal_range",
"lower_bound",
"upper_bound"},
true)
372 if (Callee->getReturnType()->isReferenceType()) {
373 if (!Callee->getIdentifier()) {
374 auto OO = Callee->getOverloadedOperator();
375 if (!Callee->getParent()->hasAttr<OwnerAttr>())
377 return OO == OverloadedOperatorKind::OO_Subscript ||
378 OO == OverloadedOperatorKind::OO_Star;
380 return llvm::StringSwitch<bool>(Callee->getName())
381 .Cases({
"front",
"back",
"at",
"top",
"value"},
true)
393 if (!RD->hasAttr<PointerAttr>() && !RD->hasAttr<OwnerAttr>())
397 return llvm::StringSwitch<bool>(FD->
getName())
398 .Cases({
"begin",
"rbegin",
"cbegin",
"crbegin"},
true)
399 .Cases({
"end",
"rend",
"cend",
"crend"},
true)
404 return llvm::StringSwitch<bool>(FD->
getName())
405 .Cases({
"get",
"any_cast"},
true)
416 const auto *ParamRefType =
422 if (
const auto *TST =
423 ParamRefType->getPointeeType()->getAs<TemplateSpecializationType>())
424 return TST->getTemplateName()
439 if (LHSRecordDecl->hasAttr<PointerAttr>())
496 if (
const auto *PrimaryCtorTemplate =
498 PrimaryCtorTemplate &&
500 PrimaryCtorTemplate->getTemplatedDecl()))) {
510 LocalVisitor Visit) {
514 if (
auto *CE = dyn_cast<CallExpr>(
Call)) {
515 Callee = CE->getDirectCallee();
519 Callee = CCE->getConstructor();
525 bool EnableGSLAnalysis = !Callee->getASTContext().getDiagnostics().isIgnored(
527 Expr *ObjectArg =
nullptr;
530 Args = Args.slice(1);
531 }
else if (
auto *MCE = dyn_cast<CXXMemberCallExpr>(
Call)) {
532 ObjectArg = MCE->getImplicitObjectArgument();
535 auto VisitLifetimeBoundArg = [&](
const Decl *D,
Expr *Arg) {
536 Path.push_back({IndirectLocalPathEntry::LifetimeBoundCall, Arg, D});
537 if (Arg->isGLValue())
545 auto ReturnType = Callee->getReturnType();
549 if (ReturnType->isReferenceType() &&
551 for (
const IndirectLocalPathEntry &PE : llvm::reverse(Path)) {
552 if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit ||
553 PE.Kind == IndirectLocalPathEntry::LifetimeBoundCall)
555 if (PE.Kind == IndirectLocalPathEntry::GslPointerInit ||
556 PE.Kind == IndirectLocalPathEntry::GslPointerAssignment)
561 Path.push_back({ReturnType->isReferenceType()
562 ? IndirectLocalPathEntry::GslReferenceInit
563 : IndirectLocalPathEntry::GslPointerInit,
565 if (Arg->isGLValue())
573 bool CheckCoroCall =
false;
574 if (
const auto *RD = Callee->getReturnType()->getAsRecordDecl()) {
575 CheckCoroCall = RD->hasAttr<CoroLifetimeBoundAttr>() &&
576 RD->hasAttr<CoroReturnTypeAttr>() &&
577 !Callee->hasAttr<CoroDisableLifetimeBoundAttr>();
581 bool CheckCoroObjArg = CheckCoroCall;
584 LE && LE->captures().empty())
585 CheckCoroObjArg =
false;
589 CheckCoroObjArg =
false;
592 VisitLifetimeBoundArg(Callee, ObjectArg);
593 else if (EnableGSLAnalysis) {
594 if (
auto *CME = dyn_cast<CXXMethodDecl>(Callee);
596 VisitGSLPointerArg(Callee, ObjectArg);
602 unsigned NP = std::min(Callee->getNumParams(), CanonCallee->
getNumParams());
603 for (
unsigned I = 0, N = std::min<unsigned>(NP, Args.size()); I != N; ++I) {
605 RevertToOldSizeRAII RAII(Path);
606 if (
auto *DAE = dyn_cast<CXXDefaultArgExpr>(Arg)) {
608 {IndirectLocalPathEntry::DefaultArg, DAE, DAE->getParam()});
609 Arg = DAE->getExpr();
613 VisitLifetimeBoundArg(CanonCallee->
getParamDecl(I), Arg);
614 else if (
const auto *CaptureAttr =
617 llvm::any_of(CaptureAttr->params(), [](
int ArgIdx) {
618 return ArgIdx == LifetimeCaptureByAttr::This;
633 VisitLifetimeBoundArg(CanonCallee->
getParamDecl(I), Arg);
634 else if (EnableGSLAnalysis && I == 0) {
637 VisitGSLPointerArg(CanonCallee, Arg);
638 }
else if (
auto *Ctor = dyn_cast<CXXConstructExpr>(
Call);
640 VisitGSLPointerArg(Ctor->getConstructor(), Arg);
650 LocalVisitor Visit) {
651 RevertToOldSizeRAII RAII(Path);
658 if (
auto *FE = dyn_cast<FullExpr>(
Init))
659 Init = FE->getSubExpr();
663 if (ILE->isTransparent())
664 Init = ILE->getInit(0);
667 if (
MemberExpr *ME = dyn_cast<MemberExpr>(
Init->IgnoreImpCasts()))
669 {IndirectLocalPathEntry::MemberExpr, ME, ME->getMemberDecl()});
672 Init =
const_cast<Expr *
>(
Init->skipRValueSubobjectAdjustments());
677 if (CE->getSubExpr()->isGLValue())
678 Init = CE->getSubExpr();
682 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(
Init)) {
683 Init = ASE->getBase();
684 auto *ICE = dyn_cast<ImplicitCastExpr>(
Init);
685 if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay)
686 Init = ICE->getSubExpr();
695 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(
Init)) {
697 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
698 Init = DIE->getExpr();
700 }
while (
Init != Old);
702 if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(
Init)) {
703 if (Visit(Path, Local(MTE), RK))
707 if (
auto *M = dyn_cast<MemberExpr>(
Init)) {
709 if (
auto *F = dyn_cast<FieldDecl>(M->getMemberDecl());
710 F && !F->getType()->isReferenceType())
717 switch (
Init->getStmtClass()) {
718 case Stmt::DeclRefExprClass: {
722 auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
723 if (VD && VD->hasLocalStorage() &&
724 !DRE->refersToEnclosingVariableOrCapture()) {
725 if (!VD->getType()->isReferenceType()) {
726 Visit(Path, Local(DRE), RK);
731 }
else if (VD->getInit() && !
isVarOnPath(Path, VD)) {
732 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
734 RK_ReferenceBinding, Visit);
740 case Stmt::UnaryOperatorClass: {
745 if (
U->getOpcode() == UO_Deref)
750 case Stmt::ArraySectionExprClass: {
756 case Stmt::ConditionalOperatorClass:
757 case Stmt::BinaryConditionalOperatorClass: {
759 if (!
C->getTrueExpr()->getType()->isVoidType())
761 if (!
C->getFalseExpr()->getType()->isVoidType())
766 case Stmt::CompoundLiteralExprClass: {
767 if (
auto *CLE = dyn_cast<CompoundLiteralExpr>(
Init)) {
768 if (!CLE->isFileScope())
769 Visit(Path, Local(CLE), RK);
785 bool RevisitSubinits) {
786 RevertToOldSizeRAII RAII(Path);
794 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(
Init)) {
796 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
797 Init = DIE->getExpr();
800 if (
auto *FE = dyn_cast<FullExpr>(
Init))
801 Init = FE->getSubExpr();
804 Init =
const_cast<Expr *
>(
Init->skipRValueSubobjectAdjustments());
807 Init = BTE->getSubExpr();
812 if (
auto *CE = dyn_cast<CastExpr>(
Init)) {
813 switch (CE->getCastKind()) {
814 case CK_LValueToRValue:
817 Path.push_back({IndirectLocalPathEntry::LValToRVal, CE});
819 Path,
Init, RK_ReferenceBinding,
820 [&](IndirectLocalPath &Path, Local L, ReferenceKind RK) ->
bool {
821 if (
auto *DRE = dyn_cast<DeclRefExpr>(L)) {
822 auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
823 if (VD && VD->getType().isConstQualified() && VD->getInit() &&
825 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
829 }
else if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L)) {
830 if (MTE->getType().isConstQualified())
843 case CK_BaseToDerived:
844 case CK_DerivedToBase:
845 case CK_UncheckedDerivedToBase:
848 case CK_UserDefinedConversion:
849 case CK_ConstructorConversion:
850 case CK_IntegralToPointer:
851 case CK_PointerToIntegral:
853 case CK_IntegralCast:
854 case CK_CPointerToObjCPointerCast:
855 case CK_BlockPointerToObjCPointerCast:
856 case CK_AnyPointerToBlockPointerCast:
857 case CK_AddressSpaceConversion:
860 case CK_ArrayToPointerDecay:
863 Path.push_back({IndirectLocalPathEntry::AddressOf, CE});
865 Path, CE->getSubExpr(), RK_ReferenceBinding, Visit);
871 Init = CE->getSubExpr();
873 }
while (Old !=
Init);
878 if (
auto *ILE = dyn_cast<CXXStdInitializerListExpr>(
Init))
880 RK_StdInitializerList, Visit);
886 if (!RevisitSubinits)
889 if (ILE->isTransparent())
893 if (ILE->getType()->isArrayType()) {
894 for (
unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
900 if (
CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) {
901 assert(RD->isAggregate() &&
"aggregate init on non-aggregate");
906 if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
907 ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
909 RK_ReferenceBinding, Visit);
912 for (; Index < RD->getNumBases() && Index < ILE->getNumInits(); ++Index)
915 for (
const auto *I : RD->fields()) {
916 if (Index >= ILE->getNumInits())
918 if (I->isUnnamedBitField())
920 Expr *SubInit = ILE->getInit(Index);
921 if (I->getType()->isReferenceType())
923 RK_ReferenceBinding, Visit);
939 if (
auto *LE = dyn_cast<LambdaExpr>(
Init)) {
941 for (
Expr *E : LE->capture_inits()) {
942 assert(CapI != LE->capture_end());
947 Path.push_back({IndirectLocalPathEntry::LambdaCaptureInit, E, &Cap});
960 if (
auto *CCE = dyn_cast<CXXConstructExpr>(
Init)) {
961 if (CCE->getConstructor()->isCopyOrMoveConstructor()) {
962 if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(CCE->getArg(0))) {
963 Expr *Arg = MTE->getSubExpr();
964 Path.push_back({IndirectLocalPathEntry::TemporaryCopy, Arg,
965 CCE->getConstructor()});
975 if (
auto *CPE = dyn_cast<CXXParenListInitExpr>(
Init)) {
976 RevertToOldSizeRAII RAII(Path);
977 Path.push_back({IndirectLocalPathEntry::ParenAggInit, CPE});
978 for (
auto *I : CPE->getInitExprs()) {
986 switch (
Init->getStmtClass()) {
987 case Stmt::UnaryOperatorClass: {
991 if (UO->getOpcode() == UO_AddrOf) {
998 Path.push_back({IndirectLocalPathEntry::AddressOf, UO});
1000 RK_ReferenceBinding, Visit);
1005 case Stmt::BinaryOperatorClass: {
1009 if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub))
1012 if (BO->getLHS()->getType()->isPointerType())
1014 else if (BO->getRHS()->getType()->isPointerType())
1019 case Stmt::ConditionalOperatorClass:
1020 case Stmt::BinaryConditionalOperatorClass: {
1024 if (!
C->getTrueExpr()->getType()->isVoidType())
1026 if (!
C->getFalseExpr()->getType()->isVoidType())
1031 case Stmt::BlockExprClass:
1038 case Stmt::AddrLabelExprClass:
1060 for (
auto Elem : Path) {
1061 if (Elem.Kind == IndirectLocalPathEntry::MemberExpr ||
1062 Elem.Kind == IndirectLocalPathEntry::LambdaCaptureInit)
1064 return Elem.Kind == IndirectLocalPathEntry::DefaultInit
1074 for (
unsigned N = Path.size(); I != N; ++I) {
1075 switch (Path[I].Kind) {
1076 case IndirectLocalPathEntry::AddressOf:
1077 case IndirectLocalPathEntry::LValToRVal:
1078 case IndirectLocalPathEntry::LifetimeBoundCall:
1079 case IndirectLocalPathEntry::TemporaryCopy:
1080 case IndirectLocalPathEntry::GslReferenceInit:
1081 case IndirectLocalPathEntry::GslPointerInit:
1082 case IndirectLocalPathEntry::GslPointerAssignment:
1083 case IndirectLocalPathEntry::ParenAggInit:
1084 case IndirectLocalPathEntry::MemberExpr:
1089 case IndirectLocalPathEntry::VarInit:
1093 case IndirectLocalPathEntry::DefaultInit:
1094 return Path[I].E->getSourceRange();
1096 case IndirectLocalPathEntry::LambdaCaptureInit:
1097 if (!Path[I].
Capture->capturesVariable())
1099 return Path[I].E->getSourceRange();
1101 case IndirectLocalPathEntry::DefaultArg:
1109 for (
const auto &It : llvm::reverse(Path)) {
1111 case IndirectLocalPathEntry::VarInit:
1112 case IndirectLocalPathEntry::AddressOf:
1113 case IndirectLocalPathEntry::LifetimeBoundCall:
1114 case IndirectLocalPathEntry::MemberExpr:
1116 case IndirectLocalPathEntry::GslPointerInit:
1117 case IndirectLocalPathEntry::GslReferenceInit:
1118 case IndirectLocalPathEntry::GslPointerAssignment:
1141 Local L, LifetimeKind LK) {
1149 for (
const auto &E : Path) {
1150 if (E.Kind == IndirectLocalPathEntry::MemberExpr) {
1159 if (
const auto *FD = llvm::dyn_cast_or_null<FieldDecl>(E.D);
1160 FD && !FD->getType()->isReferenceType() &&
1162 LK != LK_MemInitializer) {
1176 if (Path.back().Kind == IndirectLocalPathEntry::LifetimeBoundCall) {
1179 llvm::dyn_cast_or_null<FunctionDecl>(Path.back().D);
1181 if (
const auto *PD = llvm::dyn_cast<ParmVarDecl>(Path.back().D))
1182 FD = llvm::dyn_cast<FunctionDecl>(PD->getDeclContext());
1184 if (isa_and_present<CXXConstructorDecl>(FD)) {
1215 auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
1217 bool IsGslPtrValueFromGslTempOwner =
1218 MTE && !MTE->getExtendingDecl() &&
1224 if (!IsGslPtrValueFromGslTempOwner)
1232 diag::warn_dangling_lifetime_pointer_assignment,
SourceLocation());
1233 return (EnableGSLAssignmentWarnings &&
1244 assert(!AEntity || LK == LK_Assignment);
1245 assert(!CapEntity || LK == LK_LifetimeCapture);
1246 assert(!InitEntity || (LK != LK_Assignment && LK != LK_LifetimeCapture));
1249 if (LK == LK_FullExpression)
1254 auto TemporaryVisitor = [&](
const IndirectLocalPath &Path, Local L,
1255 ReferenceKind RK) ->
bool {
1259 auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
1261 bool IsGslPtrValueFromGslTempOwner =
true;
1268 IsGslPtrValueFromGslTempOwner =
false;
1275 case LK_FullExpression:
1276 llvm_unreachable(
"already handled this");
1292 MTE->setExtendingDecl(ExtendingEntity->
getDecl(),
1298 if (SemaRef.
getLangOpts().CPlusPlus23 && InitEntity) {
1300 dyn_cast_if_present<VarDecl>(InitEntity->
getDecl());
1306 if (IsGslPtrValueFromGslTempOwner && DiagLoc.
isValid()) {
1307 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1318 SemaRef.
Diag(DiagLoc, diag::warn_dangling_variable)
1321 << ExtendingEntity->
getDecl() <<
Init->isGLValue() << DiagRange;
1327 case LK_LifetimeCapture: {
1333 SemaRef.
Diag(DiagLoc, diag::warn_dangling_reference_captured)
1334 << CapEntity->
Entity << DiagRange;
1336 SemaRef.
Diag(DiagLoc, diag::warn_dangling_reference_captured_by_unknown)
1341 case LK_Assignment: {
1344 if (IsGslPtrValueFromGslTempOwner)
1345 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_assignment)
1346 << AEntity->
LHS << DiagRange;
1348 SemaRef.
Diag(DiagLoc, diag::warn_dangling_pointer_assignment)
1353 case LK_MemInitializer: {
1358 if (
auto *ExtendingDecl =
1359 ExtendingEntity ? ExtendingEntity->
getDecl() :
nullptr) {
1360 if (IsGslPtrValueFromGslTempOwner) {
1361 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_member)
1362 << ExtendingDecl << DiagRange;
1363 SemaRef.
Diag(ExtendingDecl->getLocation(),
1364 diag::note_ref_or_ptr_member_declared_here)
1368 bool IsSubobjectMember = ExtendingEntity != InitEntity;
1371 ? diag::err_dangling_member
1372 : diag::warn_dangling_member)
1373 << ExtendingDecl << IsSubobjectMember << RK << DiagRange;
1378 Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {
1379 SemaRef.
Diag(ExtendingDecl->getLocation(),
1380 diag::note_lifetime_extending_member_declared_here)
1381 << RK << IsSubobjectMember;
1399 auto *DRE = dyn_cast<DeclRefExpr>(L);
1406 auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) :
nullptr;
1414 ExtendingEntity ? ExtendingEntity->
getDecl() :
nullptr) {
1415 bool IsPointer = !
Member->getType()->isReferenceType();
1416 SemaRef.
Diag(DiagLoc,
1417 IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
1418 : diag::warn_bind_ref_member_to_parameter)
1421 diag::note_ref_or_ptr_member_declared_here)
1430 if (IsGslPtrValueFromGslTempOwner)
1431 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1434 SemaRef.
Diag(DiagLoc, RK == RK_ReferenceBinding
1435 ? diag::warn_new_dangling_reference
1436 : diag::warn_new_dangling_initializer_list)
1437 << !InitEntity->
getParent() << DiagRange;
1446 case LK_StmtExprResult:
1447 if (
auto *DRE = dyn_cast<DeclRefExpr>(L)) {
1450 if (LK == LK_StmtExprResult)
1452 SemaRef.
Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1457 SemaRef.
Diag(DiagLoc, diag::err_ret_local_block) << DiagRange;
1461 if (LK == LK_StmtExprResult)
1463 SemaRef.
Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange;
1464 }
else if (
auto *CLE = dyn_cast<CompoundLiteralExpr>(L)) {
1465 SemaRef.
Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1467 << 2 << (LK == LK_MustTail) << DiagRange;
1476 SemaRef.
Diag(DiagLoc, diag::err_ret_local_temp_ref)
1478 else if (LK == LK_MustTail)
1479 SemaRef.
Diag(DiagLoc, diag::warn_musttail_local_temp_addr_ref)
1482 SemaRef.
Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
1488 for (
unsigned I = 0; I != Path.size(); ++I) {
1489 auto Elem = Path[I];
1491 switch (Elem.Kind) {
1492 case IndirectLocalPathEntry::AddressOf:
1493 case IndirectLocalPathEntry::LValToRVal:
1494 case IndirectLocalPathEntry::ParenAggInit:
1499 case IndirectLocalPathEntry::LifetimeBoundCall:
1500 case IndirectLocalPathEntry::TemporaryCopy:
1501 case IndirectLocalPathEntry::MemberExpr:
1502 case IndirectLocalPathEntry::GslPointerInit:
1503 case IndirectLocalPathEntry::GslReferenceInit:
1504 case IndirectLocalPathEntry::GslPointerAssignment:
1508 case IndirectLocalPathEntry::DefaultInit: {
1510 SemaRef.
Diag(FD->getLocation(),
1511 diag::note_init_with_default_member_initializer)
1516 case IndirectLocalPathEntry::VarInit: {
1524 case IndirectLocalPathEntry::LambdaCaptureInit: {
1525 if (!Elem.Capture->capturesVariable())
1529 const ValueDecl *VD = Elem.Capture->getCapturedVar();
1530 SemaRef.
Diag(Elem.Capture->getLocation(),
1531 diag::note_lambda_capture_initializer)
1533 << (Elem.Capture->getCaptureKind() ==
LCK_ByRef) << VD
1538 case IndirectLocalPathEntry::DefaultArg: {
1541 SemaRef.
Diag(Param->getDefaultArgRange().getBegin(),
1542 diag::note_init_with_default_argument)
1556 case LK_Assignment: {
1560 ? IndirectLocalPathEntry::LifetimeBoundCall
1561 : IndirectLocalPathEntry::GslPointerAssignment,
1565 case LK_LifetimeCapture: {
1567 Path.push_back({IndirectLocalPathEntry::GslPointerInit,
Init});
1574 if (
Init->isGLValue())
1579 Path,
Init, TemporaryVisitor,
1587 LifetimeKind LK = LTResult.getInt();
1590 nullptr,
nullptr,
Init);
1596 nullptr,
nullptr,
Init);
1603 bool RunAnalysis = (EnableDanglingPointerAssignment &&
1611 nullptr, LK_Assignment, &Entity,
1620 diag::warn_dangling_reference_captured_by_unknown,
SourceLocation()))
1623 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.
The base class of the type hierarchy.
bool hasAttr(attr::Kind AK) const
Determine whether this type had the specified attribute applied to it (looking through top-level type...
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
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 isAssignmentOperatorLifetimeBound(const CXXMethodDecl *CMD)
bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD)
const FunctionDecl * getDeclWithMergedLifetimeBoundAttrs(const FunctionDecl *FD)
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)
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 isRecordWithAttr(QualType Type)
bool isGLSPointerType(QualType QT)
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)
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.
@ Result
The result type of a method or function.
const FunctionProtoType * T
U cast(CodeGen::Address addr)
Describes an entity that is being assigned.
CXXMethodDecl * AssignmentOperator