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>();
298 if (
const auto *ND = dyn_cast<NamespaceDecl>(DC))
300 StringRef Name = II->getName();
301 if (Name.size() >= 2 && Name.front() ==
'_' &&
312 if (
const auto *CTSD =
313 dyn_cast_if_present<ClassTemplateSpecializationDecl>(Container)) {
314 if (!CTSD->hasAttr<OwnerAttr>())
316 const auto &TAs = CTSD->getTemplateArgs();
324 dyn_cast_if_present<ClassTemplateSpecializationDecl>(Container);
327 if (!CTSD->hasAttr<OwnerAttr>())
329 const auto &TAs = CTSD->getTemplateArgs();
331 isRecordWithAttr<OwnerAttr>(TAs[0].getAsType());
336 if (
const auto *CTSD =
337 dyn_cast_if_present<ClassTemplateSpecializationDecl>(RD)) {
338 const auto &TAs = CTSD->getTemplateArgs();
340 RD->
getName() ==
"initializer_list" && TAs.size() > 0 &&
348 if (
auto *Conv = dyn_cast_or_null<CXXConversionDecl>(Callee))
349 if (isRecordWithAttr<PointerAttr>(Conv->getConversionType()) &&
350 Callee->getParent()->hasAttr<OwnerAttr>())
354 if (!isRecordWithAttr<PointerAttr>(
355 Callee->getFunctionObjectParameterType()) &&
356 !isRecordWithAttr<OwnerAttr>(Callee->getFunctionObjectParameterType()))
359 if (!Callee->getIdentifier())
361 return llvm::StringSwitch<bool>(Callee->getName())
362 .Cases(
"begin",
"rbegin",
"cbegin",
"crbegin",
true)
363 .Cases(
"end",
"rend",
"cend",
"crend",
true)
364 .Cases(
"c_str",
"data",
"get",
true)
366 .Cases(
"find",
"equal_range",
"lower_bound",
"upper_bound",
true)
369 if (Callee->getReturnType()->isReferenceType()) {
370 if (!Callee->getIdentifier()) {
371 auto OO = Callee->getOverloadedOperator();
372 if (!Callee->getParent()->hasAttr<OwnerAttr>())
374 return OO == OverloadedOperatorKind::OO_Subscript ||
375 OO == OverloadedOperatorKind::OO_Star;
377 return llvm::StringSwitch<bool>(Callee->getName())
378 .Cases(
"front",
"back",
"at",
"top",
"value",
true)
390 if (!RD->hasAttr<PointerAttr>() && !RD->hasAttr<OwnerAttr>())
394 return llvm::StringSwitch<bool>(FD->
getName())
395 .Cases(
"begin",
"rbegin",
"cbegin",
"crbegin",
true)
396 .Cases(
"end",
"rend",
"cend",
"crend",
true)
401 return llvm::StringSwitch<bool>(FD->
getName())
402 .Cases(
"get",
"any_cast",
true)
413 const auto *ParamRefType =
419 if (
const auto *TST =
421 return TST->getTemplateName()
436 if (LHSRecordDecl->hasAttr<PointerAttr>())
465 if (!isRecordWithAttr<OwnerAttr>(RHSArgType))
493 if (
const auto *PrimaryCtorTemplate =
495 PrimaryCtorTemplate &&
497 PrimaryCtorTemplate->getTemplatedDecl()))) {
516 auto *MD = dyn_cast<CXXMethodDecl>(FD);
517 if (MD && MD->isCXXInstanceMember())
536 return cast_if_present<CXXMethodDecl>(
561 LocalVisitor Visit) {
565 if (
auto *CE = dyn_cast<CallExpr>(
Call)) {
566 Callee = CE->getDirectCallee();
569 auto *CCE = cast<CXXConstructExpr>(
Call);
570 Callee = CCE->getConstructor();
576 bool EnableGSLAnalysis = !Callee->getASTContext().getDiagnostics().isIgnored(
578 Expr *ObjectArg =
nullptr;
579 if (isa<CXXOperatorCallExpr>(
Call) && Callee->isCXXInstanceMember()) {
581 Args = Args.slice(1);
582 }
else if (
auto *MCE = dyn_cast<CXXMemberCallExpr>(
Call)) {
583 ObjectArg = MCE->getImplicitObjectArgument();
586 auto VisitLifetimeBoundArg = [&](
const Decl *
D,
Expr *Arg) {
587 Path.push_back({IndirectLocalPathEntry::LifetimeBoundCall, Arg,
D});
588 if (Arg->isGLValue())
598 if (isa<MemberExpr>(Arg->IgnoreImpCasts()))
604 if (
const auto *Cond =
605 dyn_cast<AbstractConditionalOperator>(Arg->IgnoreImpCasts());
609 auto ReturnType = Callee->getReturnType();
613 if (ReturnType->isReferenceType() &&
614 !isRecordWithAttr<OwnerAttr>(ReturnType->getPointeeType())) {
615 for (
const IndirectLocalPathEntry &PE : llvm::reverse(
Path)) {
616 if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit ||
617 PE.Kind == IndirectLocalPathEntry::LifetimeBoundCall)
619 if (PE.Kind == IndirectLocalPathEntry::GslPointerInit ||
620 PE.Kind == IndirectLocalPathEntry::GslPointerAssignment)
625 Path.push_back({ReturnType->isReferenceType()
626 ? IndirectLocalPathEntry::GslReferenceInit
627 : IndirectLocalPathEntry::GslPointerInit,
629 if (Arg->isGLValue())
637 bool CheckCoroCall =
false;
638 if (
const auto *RD = Callee->getReturnType()->getAsRecordDecl()) {
639 CheckCoroCall = RD->hasAttr<CoroLifetimeBoundAttr>() &&
640 RD->hasAttr<CoroReturnTypeAttr>() &&
641 !Callee->hasAttr<CoroDisableLifetimeBoundAttr>();
645 bool CheckCoroObjArg = CheckCoroCall;
648 LE && LE->captures().empty())
649 CheckCoroObjArg =
false;
653 CheckCoroObjArg =
false;
655 VisitLifetimeBoundArg(Callee, ObjectArg);
656 else if (EnableGSLAnalysis) {
657 if (
auto *CME = dyn_cast<CXXMethodDecl>(Callee);
659 VisitGSLPointerArg(Callee, ObjectArg);
664 unsigned NP = std::min(Callee->getNumParams(), CanonCallee->
getNumParams());
665 for (
unsigned I = 0, N = std::min<unsigned>(NP, Args.size()); I != N; ++I) {
667 RevertToOldSizeRAII RAII(
Path);
668 if (
auto *DAE = dyn_cast<CXXDefaultArgExpr>(Arg)) {
670 {IndirectLocalPathEntry::DefaultArg, DAE, DAE->getParam()});
671 Arg = DAE->getExpr();
675 VisitLifetimeBoundArg(CanonCallee->
getParamDecl(I), Arg);
676 else if (
const auto *CaptureAttr =
678 CaptureAttr && isa<CXXConstructorDecl>(CanonCallee) &&
679 llvm::any_of(CaptureAttr->params(), [](
int ArgIdx) {
680 return ArgIdx == LifetimeCaptureByAttr::THIS;
695 VisitLifetimeBoundArg(CanonCallee->
getParamDecl(I), Arg);
696 else if (EnableGSLAnalysis && I == 0) {
699 VisitGSLPointerArg(CanonCallee, Arg);
700 }
else if (
auto *Ctor = dyn_cast<CXXConstructExpr>(
Call);
702 VisitGSLPointerArg(Ctor->getConstructor(), Arg);
712 LocalVisitor Visit) {
713 RevertToOldSizeRAII RAII(
Path);
720 if (
auto *FE = dyn_cast<FullExpr>(
Init))
721 Init = FE->getSubExpr();
725 if (ILE->isTransparent())
726 Init = ILE->getInit(0);
731 Init =
const_cast<Expr *
>(
Init->skipRValueSubobjectAdjustments());
736 if (CE->getSubExpr()->isGLValue())
737 Init = CE->getSubExpr();
741 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(
Init)) {
742 Init = ASE->getBase();
743 auto *ICE = dyn_cast<ImplicitCastExpr>(
Init);
744 if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay)
745 Init = ICE->getSubExpr();
754 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(
Init)) {
756 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
757 Init = DIE->getExpr();
759 }
while (
Init != Old);
761 if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(
Init)) {
762 if (Visit(
Path, Local(MTE), RK))
766 if (
auto *M = dyn_cast<MemberExpr>(
Init)) {
768 if (
auto *F = dyn_cast<FieldDecl>(M->getMemberDecl());
769 F && !F->getType()->isReferenceType())
773 if (isa<CallExpr>(
Init))
776 switch (
Init->getStmtClass()) {
777 case Stmt::DeclRefExprClass: {
780 auto *DRE = cast<DeclRefExpr>(
Init);
781 auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
782 if (VD && VD->hasLocalStorage() &&
783 !DRE->refersToEnclosingVariableOrCapture()) {
784 if (!VD->getType()->isReferenceType()) {
785 Visit(
Path, Local(DRE), RK);
786 }
else if (isa<ParmVarDecl>(DRE->getDecl())) {
791 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
793 RK_ReferenceBinding, Visit);
799 case Stmt::UnaryOperatorClass: {
804 if (
U->getOpcode() == UO_Deref)
809 case Stmt::ArraySectionExprClass: {
811 Path, cast<ArraySectionExpr>(
Init)->getBase(), Visit,
true);
815 case Stmt::ConditionalOperatorClass:
816 case Stmt::BinaryConditionalOperatorClass: {
817 auto *
C = cast<AbstractConditionalOperator>(
Init);
818 if (!
C->getTrueExpr()->getType()->isVoidType())
820 if (!
C->getFalseExpr()->getType()->isVoidType())
825 case Stmt::CompoundLiteralExprClass: {
826 if (
auto *CLE = dyn_cast<CompoundLiteralExpr>(
Init)) {
827 if (!CLE->isFileScope())
828 Visit(
Path, Local(CLE), RK);
844 bool RevisitSubinits) {
845 RevertToOldSizeRAII RAII(
Path);
853 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(
Init)) {
855 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
856 Init = DIE->getExpr();
859 if (
auto *FE = dyn_cast<FullExpr>(
Init))
860 Init = FE->getSubExpr();
863 Init =
const_cast<Expr *
>(
Init->skipRValueSubobjectAdjustments());
866 Init = BTE->getSubExpr();
871 if (
auto *CE = dyn_cast<CastExpr>(
Init)) {
872 switch (CE->getCastKind()) {
873 case CK_LValueToRValue:
876 Path.push_back({IndirectLocalPathEntry::LValToRVal, CE});
879 [&](IndirectLocalPath &
Path, Local L, ReferenceKind RK) ->
bool {
880 if (
auto *DRE = dyn_cast<DeclRefExpr>(L)) {
881 auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
882 if (VD && VD->getType().isConstQualified() && VD->getInit() &&
884 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
888 }
else if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L)) {
889 if (MTE->getType().isConstQualified())
902 case CK_BaseToDerived:
903 case CK_DerivedToBase:
904 case CK_UncheckedDerivedToBase:
907 case CK_UserDefinedConversion:
908 case CK_ConstructorConversion:
909 case CK_IntegralToPointer:
910 case CK_PointerToIntegral:
912 case CK_IntegralCast:
913 case CK_CPointerToObjCPointerCast:
914 case CK_BlockPointerToObjCPointerCast:
915 case CK_AnyPointerToBlockPointerCast:
916 case CK_AddressSpaceConversion:
919 case CK_ArrayToPointerDecay:
922 Path.push_back({IndirectLocalPathEntry::AddressOf, CE});
924 Path, CE->getSubExpr(), RK_ReferenceBinding, Visit);
930 Init = CE->getSubExpr();
932 }
while (Old !=
Init);
937 if (
auto *ILE = dyn_cast<CXXStdInitializerListExpr>(
Init))
939 RK_StdInitializerList, Visit);
945 if (!RevisitSubinits)
948 if (ILE->isTransparent())
952 if (ILE->getType()->isArrayType()) {
953 for (
unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
959 if (
CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) {
960 assert(RD->isAggregate() &&
"aggregate init on non-aggregate");
965 if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
966 ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
968 RK_ReferenceBinding, Visit);
971 for (; Index < RD->getNumBases() && Index < ILE->getNumInits(); ++Index)
974 for (
const auto *I : RD->fields()) {
975 if (Index >= ILE->getNumInits())
977 if (I->isUnnamedBitField())
979 Expr *SubInit = ILE->getInit(Index);
980 if (I->getType()->isReferenceType())
982 RK_ReferenceBinding, Visit);
998 if (
auto *LE = dyn_cast<LambdaExpr>(
Init)) {
1000 for (
Expr *
E : LE->capture_inits()) {
1001 assert(CapI != LE->capture_end());
1006 Path.push_back({IndirectLocalPathEntry::LambdaCaptureInit,
E, &Cap});
1019 if (
auto *CCE = dyn_cast<CXXConstructExpr>(
Init)) {
1020 if (CCE->getConstructor()->isCopyOrMoveConstructor()) {
1021 if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(CCE->getArg(0))) {
1022 Expr *Arg = MTE->getSubExpr();
1023 Path.push_back({IndirectLocalPathEntry::TemporaryCopy, Arg,
1024 CCE->getConstructor()});
1031 if (isa<CallExpr>(
Init) || isa<CXXConstructExpr>(
Init))
1034 if (
auto *CPE = dyn_cast<CXXParenListInitExpr>(
Init)) {
1035 RevertToOldSizeRAII RAII(
Path);
1036 Path.push_back({IndirectLocalPathEntry::ParenAggInit, CPE});
1037 for (
auto *I : CPE->getInitExprs()) {
1045 switch (
Init->getStmtClass()) {
1046 case Stmt::UnaryOperatorClass: {
1047 auto *UO = cast<UnaryOperator>(
Init);
1050 if (UO->getOpcode() == UO_AddrOf) {
1054 if (isa<MaterializeTemporaryExpr>(UO->getSubExpr()))
1057 Path.push_back({IndirectLocalPathEntry::AddressOf, UO});
1059 RK_ReferenceBinding, Visit);
1064 case Stmt::BinaryOperatorClass: {
1066 auto *BO = cast<BinaryOperator>(
Init);
1068 if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub))
1071 if (BO->getLHS()->getType()->isPointerType())
1073 else if (BO->getRHS()->getType()->isPointerType())
1078 case Stmt::ConditionalOperatorClass:
1079 case Stmt::BinaryConditionalOperatorClass: {
1080 auto *
C = cast<AbstractConditionalOperator>(
Init);
1083 if (!
C->getTrueExpr()->getType()->isVoidType())
1085 if (!
C->getFalseExpr()->getType()->isVoidType())
1090 case Stmt::BlockExprClass:
1091 if (cast<BlockExpr>(
Init)->getBlockDecl()->hasCaptures()) {
1093 Visit(
Path, Local(cast<BlockExpr>(
Init)), RK_ReferenceBinding);
1097 case Stmt::AddrLabelExprClass:
1099 Visit(
Path, Local(cast<AddrLabelExpr>(
Init)), RK_ReferenceBinding);
1119 for (
auto Elem :
Path) {
1120 if (Elem.Kind == IndirectLocalPathEntry::DefaultInit)
1122 if (Elem.Kind != IndirectLocalPathEntry::LambdaCaptureInit)
1131 for (
unsigned N =
Path.size(); I != N; ++I) {
1133 case IndirectLocalPathEntry::AddressOf:
1134 case IndirectLocalPathEntry::LValToRVal:
1135 case IndirectLocalPathEntry::LifetimeBoundCall:
1136 case IndirectLocalPathEntry::TemporaryCopy:
1137 case IndirectLocalPathEntry::GslReferenceInit:
1138 case IndirectLocalPathEntry::GslPointerInit:
1139 case IndirectLocalPathEntry::GslPointerAssignment:
1140 case IndirectLocalPathEntry::ParenAggInit:
1145 case IndirectLocalPathEntry::VarInit:
1146 if (cast<VarDecl>(
Path[I].
D)->isImplicit())
1149 case IndirectLocalPathEntry::DefaultInit:
1150 return Path[I].E->getSourceRange();
1152 case IndirectLocalPathEntry::LambdaCaptureInit:
1155 return Path[I].E->getSourceRange();
1157 case IndirectLocalPathEntry::DefaultArg:
1158 return cast<CXXDefaultArgExpr>(
Path[I].
E)->getUsedLocation();
1161 return E->getSourceRange();
1165 for (
const auto &It : llvm::reverse(
Path)) {
1167 case IndirectLocalPathEntry::VarInit:
1168 case IndirectLocalPathEntry::AddressOf:
1169 case IndirectLocalPathEntry::LifetimeBoundCall:
1171 case IndirectLocalPathEntry::GslPointerInit:
1172 case IndirectLocalPathEntry::GslReferenceInit:
1173 case IndirectLocalPathEntry::GslPointerAssignment:
1210 if (
Path.back().Kind == IndirectLocalPathEntry::LifetimeBoundCall) {
1213 llvm::dyn_cast_or_null<FunctionDecl>(
Path.back().D);
1215 if (
const auto *PD = llvm::dyn_cast<ParmVarDecl>(
Path.back().D))
1216 FD = llvm::dyn_cast<FunctionDecl>(PD->getDeclContext());
1218 if (isa_and_present<CXXConstructorDecl>(FD)) {
1236 if (isa<DeclRefExpr>(L)) {
1248 auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
1250 bool IsGslPtrValueFromGslTempOwner =
1251 MTE && !MTE->getExtendingDecl() &&
1252 isRecordWithAttr<OwnerAttr>(MTE->getType());
1257 if (!IsGslPtrValueFromGslTempOwner)
1271 diag::warn_dangling_lifetime_pointer_assignment,
SourceLocation());
1272 return (EnableGSLAssignmentWarnings &&
1273 (isRecordWithAttr<PointerAttr>(Entity.
LHS->
getType()) ||
1282 assert(!AEntity || LK == LK_Assignment);
1283 assert(!CapEntity || LK == LK_LifetimeCapture);
1284 assert(!InitEntity || (LK != LK_Assignment && LK != LK_LifetimeCapture));
1287 if (LK == LK_FullExpression)
1292 auto TemporaryVisitor = [&](
const IndirectLocalPath &
Path, Local L,
1293 ReferenceKind RK) ->
bool {
1297 auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
1299 bool IsGslPtrValueFromGslTempOwner =
true;
1306 IsGslPtrValueFromGslTempOwner =
false;
1313 case LK_FullExpression:
1314 llvm_unreachable(
"already handled this");
1326 if (IsGslPtrValueFromGslTempOwner && DiagLoc.
isValid()) {
1327 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1336 MTE->setExtendingDecl(ExtendingEntity->
getDecl(),
1348 SemaRef.
Diag(DiagLoc, diag::warn_dangling_variable)
1351 << ExtendingEntity->
getDecl() <<
Init->isGLValue() << DiagRange;
1357 case LK_LifetimeCapture: {
1363 SemaRef.
Diag(DiagLoc, diag::warn_dangling_reference_captured)
1364 << CapEntity->
Entity << DiagRange;
1366 SemaRef.
Diag(DiagLoc, diag::warn_dangling_reference_captured_by_unknown)
1371 case LK_Assignment: {
1374 if (IsGslPtrValueFromGslTempOwner)
1375 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_assignment)
1376 << AEntity->
LHS << DiagRange;
1378 SemaRef.
Diag(DiagLoc, diag::warn_dangling_pointer_assignment)
1383 case LK_MemInitializer: {
1388 if (
auto *ExtendingDecl =
1389 ExtendingEntity ? ExtendingEntity->
getDecl() :
nullptr) {
1390 if (IsGslPtrValueFromGslTempOwner) {
1391 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_member)
1392 << ExtendingDecl << DiagRange;
1393 SemaRef.
Diag(ExtendingDecl->getLocation(),
1394 diag::note_ref_or_ptr_member_declared_here)
1398 bool IsSubobjectMember = ExtendingEntity != InitEntity;
1401 ? diag::err_dangling_member
1402 : diag::warn_dangling_member)
1403 << ExtendingDecl << IsSubobjectMember << RK << DiagRange;
1408 Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {
1409 SemaRef.
Diag(ExtendingDecl->getLocation(),
1410 diag::note_lifetime_extending_member_declared_here)
1411 << RK << IsSubobjectMember;
1429 auto *DRE = dyn_cast<DeclRefExpr>(L);
1432 if (DRE && isRecordWithAttr<OwnerAttr>(DRE->getType()))
1435 auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) :
nullptr;
1443 ExtendingEntity ? ExtendingEntity->
getDecl() :
nullptr) {
1444 bool IsPointer = !
Member->getType()->isReferenceType();
1445 SemaRef.
Diag(DiagLoc,
1446 IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
1447 : diag::warn_bind_ref_member_to_parameter)
1448 << Member << VD << isa<ParmVarDecl>(VD) << DiagRange;
1450 diag::note_ref_or_ptr_member_declared_here)
1458 if (isa<MaterializeTemporaryExpr>(L)) {
1459 if (IsGslPtrValueFromGslTempOwner)
1460 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1463 SemaRef.
Diag(DiagLoc, RK == RK_ReferenceBinding
1464 ? diag::warn_new_dangling_reference
1465 : diag::warn_new_dangling_initializer_list)
1466 << !InitEntity->
getParent() << DiagRange;
1475 case LK_StmtExprResult:
1476 if (
auto *DRE = dyn_cast<DeclRefExpr>(L)) {
1479 if (LK == LK_StmtExprResult)
1481 SemaRef.
Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1483 << isa<ParmVarDecl>(DRE->getDecl()) << (LK == LK_MustTail)
1485 }
else if (isa<BlockExpr>(L)) {
1486 SemaRef.
Diag(DiagLoc, diag::err_ret_local_block) << DiagRange;
1487 }
else if (isa<AddrLabelExpr>(L)) {
1490 if (LK == LK_StmtExprResult)
1492 SemaRef.
Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange;
1493 }
else if (
auto *CLE = dyn_cast<CompoundLiteralExpr>(L)) {
1494 SemaRef.
Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1496 << 2 << (LK == LK_MustTail) << DiagRange;
1505 SemaRef.
Diag(DiagLoc, diag::err_ret_local_temp_ref)
1507 else if (LK == LK_MustTail)
1508 SemaRef.
Diag(DiagLoc, diag::warn_musttail_local_temp_addr_ref)
1511 SemaRef.
Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
1517 for (
unsigned I = 0; I !=
Path.size(); ++I) {
1518 auto Elem =
Path[I];
1520 switch (Elem.Kind) {
1521 case IndirectLocalPathEntry::AddressOf:
1522 case IndirectLocalPathEntry::LValToRVal:
1523 case IndirectLocalPathEntry::ParenAggInit:
1528 case IndirectLocalPathEntry::LifetimeBoundCall:
1529 case IndirectLocalPathEntry::TemporaryCopy:
1530 case IndirectLocalPathEntry::GslPointerInit:
1531 case IndirectLocalPathEntry::GslReferenceInit:
1532 case IndirectLocalPathEntry::GslPointerAssignment:
1536 case IndirectLocalPathEntry::DefaultInit: {
1537 auto *FD = cast<FieldDecl>(Elem.D);
1538 SemaRef.
Diag(FD->getLocation(),
1539 diag::note_init_with_default_member_initializer)
1544 case IndirectLocalPathEntry::VarInit: {
1545 const VarDecl *VD = cast<VarDecl>(Elem.D);
1552 case IndirectLocalPathEntry::LambdaCaptureInit: {
1553 if (!Elem.Capture->capturesVariable())
1557 const ValueDecl *VD = Elem.Capture->getCapturedVar();
1558 SemaRef.
Diag(Elem.Capture->getLocation(),
1559 diag::note_lambda_capture_initializer)
1561 << (Elem.Capture->getCaptureKind() ==
LCK_ByRef) << VD
1566 case IndirectLocalPathEntry::DefaultArg: {
1567 const auto *DAE = cast<CXXDefaultArgExpr>(Elem.E);
1570 diag::note_init_with_default_argument)
1584 case LK_Assignment: {
1588 ? IndirectLocalPathEntry::LifetimeBoundCall
1589 : IndirectLocalPathEntry::GslPointerAssignment,
1593 case LK_LifetimeCapture: {
1595 Path.push_back({IndirectLocalPathEntry::GslPointerInit,
Init});
1602 if (
Init->isGLValue())
1615 LifetimeKind LK = LTResult.getInt();
1618 nullptr,
nullptr, Init);
1624 nullptr,
nullptr, Init);
1631 bool RunAnalysis = (EnableDanglingPointerAssignment &&
1639 nullptr, LK_Assignment, &Entity,
1648 diag::warn_dangling_reference_captured_by_unknown,
SourceLocation()))
1651 nullptr, LK_LifetimeCapture,
enum clang::sema::@1724::IndirectLocalPathEntry::EntryKind Kind
const LambdaCapture * Capture
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.
decl_type * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
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 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)
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 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 const FunctionDecl * getDeclWithMergedLifetimeBoundAttrs(const FunctionDecl *FD)
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 bool isAssignmentOperatorLifetimeBound(const CXXMethodDecl *CMD)
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