16#include "llvm/ADT/PointerIntPair.h"
59 llvm::PointerIntPair<const InitializedEntity *, 3, LifetimeKind>;
72 return {Entity, LK_Extended};
97 return {Entity, LK_Extended};
104 return {
nullptr, LK_FullExpression};
109 return {
nullptr, LK_FullExpression};
115 return {
nullptr, LK_Return};
120 return {
nullptr, LK_StmtExprResult};
126 return {
nullptr, LK_New};
134 return {
nullptr, LK_FullExpression};
144 return {InitField, LK_MemInitializer};
151 return {InitField, LK_MemInitializer};
158 return {
nullptr, LK_FullExpression};
162 return {
nullptr, LK_FullExpression};
169 return {
nullptr, LK_FullExpression};
172 llvm_unreachable(
"unknown entity kind");
181 RK_StdInitializerList,
194struct IndirectLocalPathEntry {
205 GslPointerAssignment,
211 const Decl *
D =
nullptr;
214 IndirectLocalPathEntry() {}
215 IndirectLocalPathEntry(EntryKind K, Expr *E) :
Kind(K),
E(
E) {}
216 IndirectLocalPathEntry(EntryKind K, Expr *E,
const Decl *
D)
218 IndirectLocalPathEntry(EntryKind K, Expr *E,
const LambdaCapture *Capture)
224struct RevertToOldSizeRAII {
227 RevertToOldSizeRAII(IndirectLocalPath &Path) :
Path(
Path) {}
228 ~RevertToOldSizeRAII() {
Path.resize(OldSize); }
231using LocalVisitor = llvm::function_ref<
bool(IndirectLocalPath &
Path, Local L,
237 if (
E.Kind == IndirectLocalPathEntry::VarInit &&
E.D == VD)
243 return llvm::any_of(
Path, [=](IndirectLocalPathEntry
E) {
244 return E.Kind == IndirectLocalPathEntry::DefaultInit ||
245 E.Kind == IndirectLocalPathEntry::VarInit;
251 bool RevisitSubinits);
276 bool Result = RD->hasAttr<
T>();
278 if (
auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
279 Result |= CTSD->getSpecializedTemplate()->getTemplatedDecl()->hasAttr<
T>();
285 return isRecordWithAttr<PointerAttr>(QT) || QT->
isPointerType() ||
296 if (
const auto *ND = dyn_cast<NamespaceDecl>(DC))
298 StringRef Name = II->getName();
299 if (Name.size() >= 2 && Name.front() ==
'_' &&
310 if (
const auto *CTSD =
311 dyn_cast_if_present<ClassTemplateSpecializationDecl>(Container)) {
312 if (!CTSD->hasAttr<OwnerAttr>())
314 const auto &TAs = CTSD->getTemplateArgs();
322 dyn_cast_if_present<ClassTemplateSpecializationDecl>(Container);
325 if (!CTSD->hasAttr<OwnerAttr>())
327 const auto &TAs = CTSD->getTemplateArgs();
329 isRecordWithAttr<OwnerAttr>(TAs[0].getAsType());
334 if (
const auto *CTSD =
335 dyn_cast_if_present<ClassTemplateSpecializationDecl>(RD)) {
336 const auto &TAs = CTSD->getTemplateArgs();
338 RD->
getName() ==
"initializer_list" && TAs.size() > 0 &&
346 if (
auto *Conv = dyn_cast_or_null<CXXConversionDecl>(Callee))
347 if (isRecordWithAttr<PointerAttr>(Conv->getConversionType()) &&
348 Callee->getParent()->hasAttr<OwnerAttr>())
352 if (!isRecordWithAttr<PointerAttr>(
353 Callee->getFunctionObjectParameterType()) &&
354 !isRecordWithAttr<OwnerAttr>(Callee->getFunctionObjectParameterType()))
357 if (!Callee->getIdentifier())
359 return llvm::StringSwitch<bool>(Callee->getName())
360 .Cases(
"begin",
"rbegin",
"cbegin",
"crbegin",
true)
361 .Cases(
"end",
"rend",
"cend",
"crend",
true)
362 .Cases(
"c_str",
"data",
"get",
true)
364 .Cases(
"find",
"equal_range",
"lower_bound",
"upper_bound",
true)
367 if (Callee->getReturnType()->isReferenceType()) {
368 if (!Callee->getIdentifier()) {
369 auto OO = Callee->getOverloadedOperator();
370 if (!Callee->getParent()->hasAttr<OwnerAttr>())
372 return OO == OverloadedOperatorKind::OO_Subscript ||
373 OO == OverloadedOperatorKind::OO_Star;
375 return llvm::StringSwitch<bool>(Callee->getName())
376 .Cases(
"front",
"back",
"at",
"top",
"value",
true)
388 if (!RD->hasAttr<PointerAttr>() && !RD->hasAttr<OwnerAttr>())
392 return llvm::StringSwitch<bool>(FD->
getName())
393 .Cases(
"begin",
"rbegin",
"cbegin",
"crbegin",
true)
394 .Cases(
"end",
"rend",
"cend",
"crend",
true)
399 return llvm::StringSwitch<bool>(FD->
getName())
400 .Cases(
"get",
"any_cast",
true)
411 const auto *ParamRefType =
417 if (
const auto *TST =
419 return TST->getTemplateName()
434 if (LHSRecordDecl->hasAttr<PointerAttr>())
463 if (!isRecordWithAttr<OwnerAttr>(RHSArgType))
491 if (
const auto *PrimaryCtorTemplate =
493 PrimaryCtorTemplate &&
495 PrimaryCtorTemplate->getTemplatedDecl()))) {
514 auto *MD = dyn_cast<CXXMethodDecl>(FD);
515 if (MD && MD->isCXXInstanceMember())
546 LocalVisitor Visit) {
550 if (
auto *CE = dyn_cast<CallExpr>(
Call)) {
551 Callee = CE->getDirectCallee();
554 auto *CCE = cast<CXXConstructExpr>(
Call);
555 Callee = CCE->getConstructor();
561 bool EnableGSLAnalysis = !Callee->getASTContext().getDiagnostics().isIgnored(
563 Expr *ObjectArg =
nullptr;
564 if (isa<CXXOperatorCallExpr>(
Call) && Callee->isCXXInstanceMember()) {
566 Args = Args.slice(1);
567 }
else if (
auto *MCE = dyn_cast<CXXMemberCallExpr>(
Call)) {
568 ObjectArg = MCE->getImplicitObjectArgument();
571 auto VisitLifetimeBoundArg = [&](
const Decl *
D,
Expr *Arg) {
572 Path.push_back({IndirectLocalPathEntry::LifetimeBoundCall, Arg,
D});
573 if (Arg->isGLValue())
583 if (isa<MemberExpr>(Arg->IgnoreImpCasts()))
589 if (
const auto *Cond =
590 dyn_cast<AbstractConditionalOperator>(Arg->IgnoreImpCasts());
594 auto ReturnType = Callee->getReturnType();
598 if (ReturnType->isReferenceType() &&
599 !isRecordWithAttr<OwnerAttr>(ReturnType->getPointeeType())) {
600 for (
const IndirectLocalPathEntry &PE : llvm::reverse(
Path)) {
601 if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit ||
602 PE.Kind == IndirectLocalPathEntry::LifetimeBoundCall)
604 if (PE.Kind == IndirectLocalPathEntry::GslPointerInit ||
605 PE.Kind == IndirectLocalPathEntry::GslPointerAssignment)
610 Path.push_back({ReturnType->isReferenceType()
611 ? IndirectLocalPathEntry::GslReferenceInit
612 : IndirectLocalPathEntry::GslPointerInit,
614 if (Arg->isGLValue())
622 bool CheckCoroCall =
false;
623 if (
const auto *RD = Callee->getReturnType()->getAsRecordDecl()) {
624 CheckCoroCall = RD->hasAttr<CoroLifetimeBoundAttr>() &&
625 RD->hasAttr<CoroReturnTypeAttr>() &&
626 !Callee->hasAttr<CoroDisableLifetimeBoundAttr>();
630 bool CheckCoroObjArg = CheckCoroCall;
633 LE && LE->captures().empty())
634 CheckCoroObjArg =
false;
638 CheckCoroObjArg =
false;
640 VisitLifetimeBoundArg(Callee, ObjectArg);
641 else if (EnableGSLAnalysis) {
642 if (
auto *CME = dyn_cast<CXXMethodDecl>(Callee);
644 VisitGSLPointerArg(Callee, ObjectArg);
649 N = std::min<unsigned>(Callee->getNumParams(), Args.size());
652 RevertToOldSizeRAII RAII(
Path);
653 if (
auto *DAE = dyn_cast<CXXDefaultArgExpr>(Arg)) {
655 {IndirectLocalPathEntry::DefaultArg, DAE, DAE->getParam()});
656 Arg = DAE->getExpr();
658 if (CheckCoroCall || Callee->getParamDecl(I)->hasAttr<LifetimeBoundAttr>())
659 VisitLifetimeBoundArg(Callee->getParamDecl(I), Arg);
660 else if (
const auto *CaptureAttr =
661 Callee->getParamDecl(I)->getAttr<LifetimeCaptureByAttr>();
662 CaptureAttr && isa<CXXConstructorDecl>(Callee) &&
663 llvm::any_of(CaptureAttr->params(), [](
int ArgIdx) {
664 return ArgIdx == LifetimeCaptureByAttr::THIS;
679 VisitLifetimeBoundArg(Callee->getParamDecl(I), Arg);
680 else if (EnableGSLAnalysis && I == 0) {
683 VisitGSLPointerArg(Callee, Arg);
684 }
else if (
auto *Ctor = dyn_cast<CXXConstructExpr>(
Call);
686 VisitGSLPointerArg(Ctor->getConstructor(), Arg);
696 LocalVisitor Visit) {
697 RevertToOldSizeRAII RAII(
Path);
704 if (
auto *FE = dyn_cast<FullExpr>(
Init))
705 Init = FE->getSubExpr();
709 if (ILE->isTransparent())
710 Init = ILE->getInit(0);
715 Init =
const_cast<Expr *
>(
Init->skipRValueSubobjectAdjustments());
720 if (CE->getSubExpr()->isGLValue())
721 Init = CE->getSubExpr();
725 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(
Init)) {
726 Init = ASE->getBase();
727 auto *ICE = dyn_cast<ImplicitCastExpr>(
Init);
728 if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay)
729 Init = ICE->getSubExpr();
738 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(
Init)) {
740 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
741 Init = DIE->getExpr();
743 }
while (
Init != Old);
745 if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(
Init)) {
746 if (Visit(
Path, Local(MTE), RK))
750 if (
auto *M = dyn_cast<MemberExpr>(
Init)) {
752 if (
auto *F = dyn_cast<FieldDecl>(M->getMemberDecl());
753 F && !F->getType()->isReferenceType())
757 if (isa<CallExpr>(
Init))
760 switch (
Init->getStmtClass()) {
761 case Stmt::DeclRefExprClass: {
764 auto *DRE = cast<DeclRefExpr>(
Init);
765 auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
766 if (VD && VD->hasLocalStorage() &&
767 !DRE->refersToEnclosingVariableOrCapture()) {
768 if (!VD->getType()->isReferenceType()) {
769 Visit(
Path, Local(DRE), RK);
770 }
else if (isa<ParmVarDecl>(DRE->getDecl())) {
775 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
777 RK_ReferenceBinding, Visit);
783 case Stmt::UnaryOperatorClass: {
788 if (
U->getOpcode() == UO_Deref)
793 case Stmt::ArraySectionExprClass: {
795 Path, cast<ArraySectionExpr>(
Init)->getBase(), Visit,
true);
799 case Stmt::ConditionalOperatorClass:
800 case Stmt::BinaryConditionalOperatorClass: {
801 auto *
C = cast<AbstractConditionalOperator>(
Init);
802 if (!
C->getTrueExpr()->getType()->isVoidType())
804 if (!
C->getFalseExpr()->getType()->isVoidType())
809 case Stmt::CompoundLiteralExprClass: {
810 if (
auto *CLE = dyn_cast<CompoundLiteralExpr>(
Init)) {
811 if (!CLE->isFileScope())
812 Visit(
Path, Local(CLE), RK);
828 bool RevisitSubinits) {
829 RevertToOldSizeRAII RAII(
Path);
837 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(
Init)) {
839 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
840 Init = DIE->getExpr();
843 if (
auto *FE = dyn_cast<FullExpr>(
Init))
844 Init = FE->getSubExpr();
847 Init =
const_cast<Expr *
>(
Init->skipRValueSubobjectAdjustments());
850 Init = BTE->getSubExpr();
855 if (
auto *CE = dyn_cast<CastExpr>(
Init)) {
856 switch (CE->getCastKind()) {
857 case CK_LValueToRValue:
860 Path.push_back({IndirectLocalPathEntry::LValToRVal, CE});
863 [&](IndirectLocalPath &
Path, Local L, ReferenceKind RK) ->
bool {
864 if (
auto *DRE = dyn_cast<DeclRefExpr>(L)) {
865 auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
866 if (VD && VD->getType().isConstQualified() && VD->getInit() &&
868 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
872 }
else if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L)) {
873 if (MTE->getType().isConstQualified())
886 case CK_BaseToDerived:
887 case CK_DerivedToBase:
888 case CK_UncheckedDerivedToBase:
891 case CK_UserDefinedConversion:
892 case CK_ConstructorConversion:
893 case CK_IntegralToPointer:
894 case CK_PointerToIntegral:
896 case CK_IntegralCast:
897 case CK_CPointerToObjCPointerCast:
898 case CK_BlockPointerToObjCPointerCast:
899 case CK_AnyPointerToBlockPointerCast:
900 case CK_AddressSpaceConversion:
903 case CK_ArrayToPointerDecay:
906 Path.push_back({IndirectLocalPathEntry::AddressOf, CE});
908 Path, CE->getSubExpr(), RK_ReferenceBinding, Visit);
914 Init = CE->getSubExpr();
916 }
while (Old !=
Init);
921 if (
auto *ILE = dyn_cast<CXXStdInitializerListExpr>(
Init))
923 RK_StdInitializerList, Visit);
929 if (!RevisitSubinits)
932 if (ILE->isTransparent())
936 if (ILE->getType()->isArrayType()) {
937 for (
unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
943 if (
CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) {
944 assert(RD->isAggregate() &&
"aggregate init on non-aggregate");
949 if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
950 ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
952 RK_ReferenceBinding, Visit);
955 for (; Index < RD->getNumBases() && Index < ILE->getNumInits(); ++Index)
958 for (
const auto *I : RD->fields()) {
959 if (Index >= ILE->getNumInits())
961 if (I->isUnnamedBitField())
963 Expr *SubInit = ILE->getInit(Index);
964 if (I->getType()->isReferenceType())
966 RK_ReferenceBinding, Visit);
982 if (
auto *LE = dyn_cast<LambdaExpr>(
Init)) {
984 for (
Expr *
E : LE->capture_inits()) {
985 assert(CapI != LE->capture_end());
990 Path.push_back({IndirectLocalPathEntry::LambdaCaptureInit,
E, &Cap});
1003 if (
auto *CCE = dyn_cast<CXXConstructExpr>(
Init)) {
1004 if (CCE->getConstructor()->isCopyOrMoveConstructor()) {
1005 if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(CCE->getArg(0))) {
1006 Expr *Arg = MTE->getSubExpr();
1007 Path.push_back({IndirectLocalPathEntry::TemporaryCopy, Arg,
1008 CCE->getConstructor()});
1015 if (isa<CallExpr>(
Init) || isa<CXXConstructExpr>(
Init))
1018 if (
auto *CPE = dyn_cast<CXXParenListInitExpr>(
Init)) {
1019 RevertToOldSizeRAII RAII(
Path);
1020 Path.push_back({IndirectLocalPathEntry::ParenAggInit, CPE});
1021 for (
auto *I : CPE->getInitExprs()) {
1029 switch (
Init->getStmtClass()) {
1030 case Stmt::UnaryOperatorClass: {
1031 auto *UO = cast<UnaryOperator>(
Init);
1034 if (UO->getOpcode() == UO_AddrOf) {
1038 if (isa<MaterializeTemporaryExpr>(UO->getSubExpr()))
1041 Path.push_back({IndirectLocalPathEntry::AddressOf, UO});
1043 RK_ReferenceBinding, Visit);
1048 case Stmt::BinaryOperatorClass: {
1050 auto *BO = cast<BinaryOperator>(
Init);
1052 if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub))
1055 if (BO->getLHS()->getType()->isPointerType())
1057 else if (BO->getRHS()->getType()->isPointerType())
1062 case Stmt::ConditionalOperatorClass:
1063 case Stmt::BinaryConditionalOperatorClass: {
1064 auto *
C = cast<AbstractConditionalOperator>(
Init);
1067 if (!
C->getTrueExpr()->getType()->isVoidType())
1069 if (!
C->getFalseExpr()->getType()->isVoidType())
1074 case Stmt::BlockExprClass:
1075 if (cast<BlockExpr>(
Init)->getBlockDecl()->hasCaptures()) {
1077 Visit(
Path, Local(cast<BlockExpr>(
Init)), RK_ReferenceBinding);
1081 case Stmt::AddrLabelExprClass:
1083 Visit(
Path, Local(cast<AddrLabelExpr>(
Init)), RK_ReferenceBinding);
1103 for (
auto Elem :
Path) {
1104 if (Elem.Kind == IndirectLocalPathEntry::DefaultInit)
1106 if (Elem.Kind != IndirectLocalPathEntry::LambdaCaptureInit)
1115 for (
unsigned N =
Path.size(); I != N; ++I) {
1117 case IndirectLocalPathEntry::AddressOf:
1118 case IndirectLocalPathEntry::LValToRVal:
1119 case IndirectLocalPathEntry::LifetimeBoundCall:
1120 case IndirectLocalPathEntry::TemporaryCopy:
1121 case IndirectLocalPathEntry::GslReferenceInit:
1122 case IndirectLocalPathEntry::GslPointerInit:
1123 case IndirectLocalPathEntry::GslPointerAssignment:
1124 case IndirectLocalPathEntry::ParenAggInit:
1129 case IndirectLocalPathEntry::VarInit:
1130 if (cast<VarDecl>(
Path[I].
D)->isImplicit())
1133 case IndirectLocalPathEntry::DefaultInit:
1134 return Path[I].E->getSourceRange();
1136 case IndirectLocalPathEntry::LambdaCaptureInit:
1139 return Path[I].E->getSourceRange();
1141 case IndirectLocalPathEntry::DefaultArg:
1142 return cast<CXXDefaultArgExpr>(
Path[I].
E)->getUsedLocation();
1145 return E->getSourceRange();
1149 for (
const auto &It : llvm::reverse(
Path)) {
1151 case IndirectLocalPathEntry::VarInit:
1152 case IndirectLocalPathEntry::AddressOf:
1153 case IndirectLocalPathEntry::LifetimeBoundCall:
1155 case IndirectLocalPathEntry::GslPointerInit:
1156 case IndirectLocalPathEntry::GslReferenceInit:
1157 case IndirectLocalPathEntry::GslPointerAssignment:
1194 if (
Path.back().Kind == IndirectLocalPathEntry::LifetimeBoundCall) {
1197 llvm::dyn_cast_or_null<FunctionDecl>(
Path.back().D);
1199 if (
const auto *PD = llvm::dyn_cast<ParmVarDecl>(
Path.back().D))
1200 FD = llvm::dyn_cast<FunctionDecl>(PD->getDeclContext());
1202 if (isa_and_present<CXXConstructorDecl>(FD)) {
1220 if (isa<DeclRefExpr>(L)) {
1232 auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
1234 bool IsGslPtrValueFromGslTempOwner =
1235 MTE && !MTE->getExtendingDecl() &&
1236 isRecordWithAttr<OwnerAttr>(MTE->getType());
1241 if (!IsGslPtrValueFromGslTempOwner)
1254 diag::warn_dangling_lifetime_pointer_assignment,
SourceLocation());
1255 return (EnableGSLAssignmentWarnings &&
1256 (isRecordWithAttr<PointerAttr>(Entity.
LHS->
getType()) ||
1265 assert(!AEntity || LK == LK_Assignment);
1266 assert(!CapEntity || LK == LK_LifetimeCapture);
1267 assert(!InitEntity || (LK != LK_Assignment && LK != LK_LifetimeCapture));
1270 if (LK == LK_FullExpression)
1275 auto TemporaryVisitor = [&](
const IndirectLocalPath &
Path, Local L,
1276 ReferenceKind RK) ->
bool {
1280 auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
1282 bool IsGslPtrValueFromGslTempOwner =
true;
1289 IsGslPtrValueFromGslTempOwner =
false;
1296 case LK_FullExpression:
1297 llvm_unreachable(
"already handled this");
1309 if (IsGslPtrValueFromGslTempOwner && DiagLoc.
isValid()) {
1310 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1319 MTE->setExtendingDecl(ExtendingEntity->
getDecl(),
1331 SemaRef.
Diag(DiagLoc, diag::warn_dangling_variable)
1334 << ExtendingEntity->
getDecl() <<
Init->isGLValue() << DiagRange;
1340 case LK_LifetimeCapture: {
1346 SemaRef.
Diag(DiagLoc, diag::warn_dangling_reference_captured)
1347 << CapEntity->
Entity << DiagRange;
1349 SemaRef.
Diag(DiagLoc, diag::warn_dangling_reference_captured_by_unknown)
1354 case LK_Assignment: {
1357 if (IsGslPtrValueFromGslTempOwner)
1358 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_assignment)
1359 << AEntity->
LHS << DiagRange;
1361 SemaRef.
Diag(DiagLoc, diag::warn_dangling_pointer_assignment)
1366 case LK_MemInitializer: {
1371 if (
auto *ExtendingDecl =
1372 ExtendingEntity ? ExtendingEntity->
getDecl() :
nullptr) {
1373 if (IsGslPtrValueFromGslTempOwner) {
1374 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_member)
1375 << ExtendingDecl << DiagRange;
1376 SemaRef.
Diag(ExtendingDecl->getLocation(),
1377 diag::note_ref_or_ptr_member_declared_here)
1381 bool IsSubobjectMember = ExtendingEntity != InitEntity;
1384 ? diag::err_dangling_member
1385 : diag::warn_dangling_member)
1386 << ExtendingDecl << IsSubobjectMember << RK << DiagRange;
1391 Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {
1392 SemaRef.
Diag(ExtendingDecl->getLocation(),
1393 diag::note_lifetime_extending_member_declared_here)
1394 << RK << IsSubobjectMember;
1412 auto *DRE = dyn_cast<DeclRefExpr>(L);
1415 if (DRE && isRecordWithAttr<OwnerAttr>(DRE->getType()))
1418 auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) :
nullptr;
1426 ExtendingEntity ? ExtendingEntity->
getDecl() :
nullptr) {
1427 bool IsPointer = !
Member->getType()->isReferenceType();
1428 SemaRef.
Diag(DiagLoc,
1429 IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
1430 : diag::warn_bind_ref_member_to_parameter)
1431 << Member << VD << isa<ParmVarDecl>(VD) << DiagRange;
1433 diag::note_ref_or_ptr_member_declared_here)
1441 if (isa<MaterializeTemporaryExpr>(L)) {
1442 if (IsGslPtrValueFromGslTempOwner)
1443 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1446 SemaRef.
Diag(DiagLoc, RK == RK_ReferenceBinding
1447 ? diag::warn_new_dangling_reference
1448 : diag::warn_new_dangling_initializer_list)
1449 << !InitEntity->
getParent() << DiagRange;
1458 case LK_StmtExprResult:
1459 if (
auto *DRE = dyn_cast<DeclRefExpr>(L)) {
1462 if (LK == LK_StmtExprResult)
1464 SemaRef.
Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1466 << isa<ParmVarDecl>(DRE->getDecl()) << (LK == LK_MustTail)
1468 }
else if (isa<BlockExpr>(L)) {
1469 SemaRef.
Diag(DiagLoc, diag::err_ret_local_block) << DiagRange;
1470 }
else if (isa<AddrLabelExpr>(L)) {
1473 if (LK == LK_StmtExprResult)
1475 SemaRef.
Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange;
1476 }
else if (
auto *CLE = dyn_cast<CompoundLiteralExpr>(L)) {
1477 SemaRef.
Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1479 << 2 << (LK == LK_MustTail) << DiagRange;
1488 SemaRef.
Diag(DiagLoc, diag::err_ret_local_temp_ref)
1490 else if (LK == LK_MustTail)
1491 SemaRef.
Diag(DiagLoc, diag::warn_musttail_local_temp_addr_ref)
1494 SemaRef.
Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
1500 for (
unsigned I = 0; I !=
Path.size(); ++I) {
1501 auto Elem =
Path[I];
1503 switch (Elem.Kind) {
1504 case IndirectLocalPathEntry::AddressOf:
1505 case IndirectLocalPathEntry::LValToRVal:
1506 case IndirectLocalPathEntry::ParenAggInit:
1511 case IndirectLocalPathEntry::LifetimeBoundCall:
1512 case IndirectLocalPathEntry::TemporaryCopy:
1513 case IndirectLocalPathEntry::GslPointerInit:
1514 case IndirectLocalPathEntry::GslReferenceInit:
1515 case IndirectLocalPathEntry::GslPointerAssignment:
1519 case IndirectLocalPathEntry::DefaultInit: {
1520 auto *FD = cast<FieldDecl>(Elem.D);
1521 SemaRef.
Diag(FD->getLocation(),
1522 diag::note_init_with_default_member_initializer)
1527 case IndirectLocalPathEntry::VarInit: {
1528 const VarDecl *VD = cast<VarDecl>(Elem.D);
1535 case IndirectLocalPathEntry::LambdaCaptureInit: {
1536 if (!Elem.Capture->capturesVariable())
1540 const ValueDecl *VD = Elem.Capture->getCapturedVar();
1541 SemaRef.
Diag(Elem.Capture->getLocation(),
1542 diag::note_lambda_capture_initializer)
1544 << (Elem.Capture->getCaptureKind() ==
LCK_ByRef) << VD
1549 case IndirectLocalPathEntry::DefaultArg: {
1550 const auto *DAE = cast<CXXDefaultArgExpr>(Elem.E);
1553 diag::note_init_with_default_argument)
1567 case LK_Assignment: {
1571 ? IndirectLocalPathEntry::LifetimeBoundCall
1572 : IndirectLocalPathEntry::GslPointerAssignment,
1576 case LK_LifetimeCapture: {
1578 Path.push_back({IndirectLocalPathEntry::GslPointerInit,
Init});
1585 if (
Init->isGLValue())
1598 LifetimeKind LK = LTResult.getInt();
1601 nullptr,
nullptr, Init);
1607 nullptr,
nullptr, Init);
1614 bool RunAnalysis = (EnableDanglingPointerAssignment &&
1622 nullptr, LK_Assignment, &Entity,
1631 diag::warn_dangling_reference_captured_by_unknown,
SourceLocation()))
1634 nullptr, LK_LifetimeCapture,
const LambdaCapture * Capture
enum clang::sema::@1718::IndirectLocalPathEntry::EntryKind Kind
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
Type source information for an attributed type.
TypeLoc getModifiedLoc() const
The modified type, which is generally canonically different from the attribute type.
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
ASTContext & getASTContext() const LLVM_READONLY
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
SourceLocation getLocation() const
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
TypeSourceInfo * getTypeSourceInfo() 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
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_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.
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.
SourceRange getDefaultArgRange() const
Retrieve the source range that covers the entire default argument.
A (possibly-)qualified type.
Represents a struct/union/class.
Base for LValueReferenceType and RValueReferenceType.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
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
@ Type
The template argument is a type.
Represents a type template specialization; the template must be a class template, a type alias templa...
Base wrapper for a particular "section" of type source info.
T getAsAdjusted() const
Convert to the specified TypeLoc type, returning a null TypeLoc if this TypeLoc is not of the desired...
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool hasAttr(attr::Kind AK) const
Determine whether this type had the specified attribute applied to it (looking through top-level type...
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 isLValueReferenceType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isNullPtrType() const
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
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.
static bool isStdInitializerListOfPointer(const RecordDecl *RD)
bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD)
static void checkExprLifetimeImpl(Sema &SemaRef, const InitializedEntity *InitEntity, const InitializedEntity *ExtendingEntity, LifetimeKind LK, const AssignedEntity *AEntity, const CapturingEntity *CapEntity, Expr *Init)
static bool isAssignmentOperatorLifetimeBound(CXXMethodDecl *CMD)
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 bool isNormalAssignmentOperator(const FunctionDecl *FD)
bool isPointerLikeType(QualType QT)
static bool isInStlNamespace(const Decl *D)
static bool isRecordWithAttr(QualType Type)
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 AnalysisResult analyzePathForGSLPointer(const IndirectLocalPath &Path, Local L)
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 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...
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
bool isCompoundAssignmentOperator(OverloadedOperatorKind Kind)
Determine if this is a compound assignment operator.
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
Describes an entity that is being assigned.
CXXMethodDecl * AssignmentOperator