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 {
206 GslPointerAssignment,
212 const Decl *
D =
nullptr;
215 IndirectLocalPathEntry() {}
216 IndirectLocalPathEntry(EntryKind K, Expr *E) :
Kind(K),
E(
E) {}
217 IndirectLocalPathEntry(EntryKind K, Expr *E,
const Decl *
D)
219 IndirectLocalPathEntry(EntryKind K, Expr *E,
const LambdaCapture *Capture)
225struct RevertToOldSizeRAII {
228 RevertToOldSizeRAII(IndirectLocalPath &Path) :
Path(
Path) {}
229 ~RevertToOldSizeRAII() {
Path.resize(OldSize); }
232using LocalVisitor = llvm::function_ref<
bool(IndirectLocalPath &
Path, Local L,
238 if (
E.Kind == IndirectLocalPathEntry::VarInit &&
E.D == VD)
244 return llvm::any_of(
Path, [=](IndirectLocalPathEntry
E) {
245 return E.Kind == IndirectLocalPathEntry::DefaultInit ||
246 E.Kind == IndirectLocalPathEntry::VarInit;
252 bool RevisitSubinits);
277 bool Result = RD->hasAttr<
T>();
279 if (
auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
280 Result |= CTSD->getSpecializedTemplate()->getTemplatedDecl()->hasAttr<
T>();
299 if (
const auto *ND = dyn_cast<NamespaceDecl>(DC))
301 StringRef Name = II->getName();
302 if (Name.size() >= 2 && Name.front() ==
'_' &&
313 if (
const auto *CTSD =
314 dyn_cast_if_present<ClassTemplateSpecializationDecl>(Container)) {
315 if (!CTSD->hasAttr<OwnerAttr>())
317 const auto &TAs = CTSD->getTemplateArgs();
325 dyn_cast_if_present<ClassTemplateSpecializationDecl>(Container);
328 if (!CTSD->hasAttr<OwnerAttr>())
330 const auto &TAs = CTSD->getTemplateArgs();
332 isRecordWithAttr<OwnerAttr>(TAs[0].getAsType());
337 if (
const auto *CTSD =
338 dyn_cast_if_present<ClassTemplateSpecializationDecl>(RD)) {
339 const auto &TAs = CTSD->getTemplateArgs();
341 RD->
getName() ==
"initializer_list" && TAs.size() > 0 &&
349 if (
auto *Conv = dyn_cast_or_null<CXXConversionDecl>(Callee))
350 if (isRecordWithAttr<PointerAttr>(Conv->getConversionType()) &&
351 Callee->getParent()->hasAttr<OwnerAttr>())
355 if (!isRecordWithAttr<PointerAttr>(
356 Callee->getFunctionObjectParameterType()) &&
357 !isRecordWithAttr<OwnerAttr>(Callee->getFunctionObjectParameterType()))
360 if (!Callee->getIdentifier())
362 return llvm::StringSwitch<bool>(Callee->getName())
363 .Cases(
"begin",
"rbegin",
"cbegin",
"crbegin",
true)
364 .Cases(
"end",
"rend",
"cend",
"crend",
true)
365 .Cases(
"c_str",
"data",
"get",
true)
367 .Cases(
"find",
"equal_range",
"lower_bound",
"upper_bound",
true)
370 if (Callee->getReturnType()->isReferenceType()) {
371 if (!Callee->getIdentifier()) {
372 auto OO = Callee->getOverloadedOperator();
373 if (!Callee->getParent()->hasAttr<OwnerAttr>())
375 return OO == OverloadedOperatorKind::OO_Subscript ||
376 OO == OverloadedOperatorKind::OO_Star;
378 return llvm::StringSwitch<bool>(Callee->getName())
379 .Cases(
"front",
"back",
"at",
"top",
"value",
true)
391 if (!RD->hasAttr<PointerAttr>() && !RD->hasAttr<OwnerAttr>())
395 return llvm::StringSwitch<bool>(FD->
getName())
396 .Cases(
"begin",
"rbegin",
"cbegin",
"crbegin",
true)
397 .Cases(
"end",
"rend",
"cend",
"crend",
true)
402 return llvm::StringSwitch<bool>(FD->
getName())
403 .Cases(
"get",
"any_cast",
true)
414 const auto *ParamRefType =
420 if (
const auto *TST =
422 return TST->getTemplateName()
437 if (LHSRecordDecl->hasAttr<PointerAttr>())
466 if (!isRecordWithAttr<OwnerAttr>(RHSArgType))
494 if (
const auto *PrimaryCtorTemplate =
496 PrimaryCtorTemplate &&
498 PrimaryCtorTemplate->getTemplatedDecl()))) {
517 auto *MD = dyn_cast<CXXMethodDecl>(FD);
518 if (MD && MD->isCXXInstanceMember())
519 LHST = Ctx.getLValueReferenceType(MD->getFunctionObjectParameterType());
522 if (Ctx.hasSameType(RetT, LHST))
537 return cast_if_present<CXXMethodDecl>(
562 LocalVisitor Visit) {
566 if (
auto *CE = dyn_cast<CallExpr>(
Call)) {
567 Callee = CE->getDirectCallee();
570 auto *CCE = cast<CXXConstructExpr>(
Call);
571 Callee = CCE->getConstructor();
577 bool EnableGSLAnalysis = !Callee->getASTContext().getDiagnostics().isIgnored(
579 Expr *ObjectArg =
nullptr;
580 if (isa<CXXOperatorCallExpr>(
Call) && Callee->isCXXInstanceMember()) {
582 Args = Args.slice(1);
583 }
else if (
auto *MCE = dyn_cast<CXXMemberCallExpr>(
Call)) {
584 ObjectArg = MCE->getImplicitObjectArgument();
587 auto VisitLifetimeBoundArg = [&](
const Decl *
D,
Expr *Arg) {
588 Path.push_back({IndirectLocalPathEntry::LifetimeBoundCall, Arg,
D});
589 if (Arg->isGLValue())
597 auto ReturnType = Callee->getReturnType();
601 if (ReturnType->isReferenceType() &&
602 !isRecordWithAttr<OwnerAttr>(ReturnType->getPointeeType())) {
603 for (
const IndirectLocalPathEntry &PE : llvm::reverse(
Path)) {
604 if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit ||
605 PE.Kind == IndirectLocalPathEntry::LifetimeBoundCall)
607 if (PE.Kind == IndirectLocalPathEntry::GslPointerInit ||
608 PE.Kind == IndirectLocalPathEntry::GslPointerAssignment)
613 Path.push_back({ReturnType->isReferenceType()
614 ? IndirectLocalPathEntry::GslReferenceInit
615 : IndirectLocalPathEntry::GslPointerInit,
617 if (Arg->isGLValue())
625 bool CheckCoroCall =
false;
626 if (
const auto *RD = Callee->getReturnType()->getAsRecordDecl()) {
627 CheckCoroCall = RD->hasAttr<CoroLifetimeBoundAttr>() &&
628 RD->hasAttr<CoroReturnTypeAttr>() &&
629 !Callee->hasAttr<CoroDisableLifetimeBoundAttr>();
633 bool CheckCoroObjArg = CheckCoroCall;
636 LE && LE->captures().empty())
637 CheckCoroObjArg =
false;
641 CheckCoroObjArg =
false;
643 VisitLifetimeBoundArg(Callee, ObjectArg);
644 else if (EnableGSLAnalysis) {
645 if (
auto *CME = dyn_cast<CXXMethodDecl>(Callee);
647 VisitGSLPointerArg(Callee, ObjectArg);
652 unsigned NP = std::min(Callee->getNumParams(), CanonCallee->
getNumParams());
653 for (
unsigned I = 0, N = std::min<unsigned>(NP, Args.size()); I != N; ++I) {
655 RevertToOldSizeRAII RAII(
Path);
656 if (
auto *DAE = dyn_cast<CXXDefaultArgExpr>(Arg)) {
658 {IndirectLocalPathEntry::DefaultArg, DAE, DAE->getParam()});
659 Arg = DAE->getExpr();
663 VisitLifetimeBoundArg(CanonCallee->
getParamDecl(I), Arg);
664 else if (
const auto *CaptureAttr =
666 CaptureAttr && isa<CXXConstructorDecl>(CanonCallee) &&
667 llvm::any_of(CaptureAttr->params(), [](
int ArgIdx) {
668 return ArgIdx == LifetimeCaptureByAttr::THIS;
683 VisitLifetimeBoundArg(CanonCallee->
getParamDecl(I), Arg);
684 else if (EnableGSLAnalysis && I == 0) {
687 VisitGSLPointerArg(CanonCallee, Arg);
688 }
else if (
auto *Ctor = dyn_cast<CXXConstructExpr>(
Call);
690 VisitGSLPointerArg(Ctor->getConstructor(), Arg);
700 LocalVisitor Visit) {
701 RevertToOldSizeRAII RAII(
Path);
708 if (
auto *FE = dyn_cast<FullExpr>(
Init))
709 Init = FE->getSubExpr();
713 if (ILE->isTransparent())
714 Init = ILE->getInit(0);
717 if (
MemberExpr *ME = dyn_cast<MemberExpr>(
Init->IgnoreImpCasts()))
719 {IndirectLocalPathEntry::MemberExpr, ME, ME->getMemberDecl()});
722 Init =
const_cast<Expr *
>(
Init->skipRValueSubobjectAdjustments());
727 if (CE->getSubExpr()->isGLValue())
728 Init = CE->getSubExpr();
732 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(
Init)) {
733 Init = ASE->getBase();
734 auto *ICE = dyn_cast<ImplicitCastExpr>(
Init);
735 if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay)
736 Init = ICE->getSubExpr();
745 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(
Init)) {
747 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
748 Init = DIE->getExpr();
750 }
while (
Init != Old);
752 if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(
Init)) {
753 if (Visit(
Path, Local(MTE), RK))
757 if (
auto *M = dyn_cast<MemberExpr>(
Init)) {
759 if (
auto *F = dyn_cast<FieldDecl>(M->getMemberDecl());
760 F && !F->getType()->isReferenceType())
764 if (isa<CallExpr>(
Init))
767 switch (
Init->getStmtClass()) {
768 case Stmt::DeclRefExprClass: {
771 auto *DRE = cast<DeclRefExpr>(
Init);
772 auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
773 if (VD && VD->hasLocalStorage() &&
774 !DRE->refersToEnclosingVariableOrCapture()) {
775 if (!VD->getType()->isReferenceType()) {
776 Visit(
Path, Local(DRE), RK);
777 }
else if (isa<ParmVarDecl>(DRE->getDecl())) {
782 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
784 RK_ReferenceBinding, Visit);
790 case Stmt::UnaryOperatorClass: {
795 if (
U->getOpcode() == UO_Deref)
800 case Stmt::ArraySectionExprClass: {
802 Path, cast<ArraySectionExpr>(
Init)->getBase(), Visit,
true);
806 case Stmt::ConditionalOperatorClass:
807 case Stmt::BinaryConditionalOperatorClass: {
808 auto *
C = cast<AbstractConditionalOperator>(
Init);
809 if (!
C->getTrueExpr()->getType()->isVoidType())
811 if (!
C->getFalseExpr()->getType()->isVoidType())
816 case Stmt::CompoundLiteralExprClass: {
817 if (
auto *CLE = dyn_cast<CompoundLiteralExpr>(
Init)) {
818 if (!CLE->isFileScope())
819 Visit(
Path, Local(CLE), RK);
835 bool RevisitSubinits) {
836 RevertToOldSizeRAII RAII(
Path);
844 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(
Init)) {
846 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
847 Init = DIE->getExpr();
850 if (
auto *FE = dyn_cast<FullExpr>(
Init))
851 Init = FE->getSubExpr();
854 Init =
const_cast<Expr *
>(
Init->skipRValueSubobjectAdjustments());
857 Init = BTE->getSubExpr();
862 if (
auto *CE = dyn_cast<CastExpr>(
Init)) {
863 switch (CE->getCastKind()) {
864 case CK_LValueToRValue:
867 Path.push_back({IndirectLocalPathEntry::LValToRVal, CE});
870 [&](IndirectLocalPath &
Path, Local L, ReferenceKind RK) ->
bool {
871 if (
auto *DRE = dyn_cast<DeclRefExpr>(L)) {
872 auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
873 if (VD && VD->getType().isConstQualified() && VD->getInit() &&
875 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
879 }
else if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L)) {
880 if (MTE->getType().isConstQualified())
893 case CK_BaseToDerived:
894 case CK_DerivedToBase:
895 case CK_UncheckedDerivedToBase:
898 case CK_UserDefinedConversion:
899 case CK_ConstructorConversion:
900 case CK_IntegralToPointer:
901 case CK_PointerToIntegral:
903 case CK_IntegralCast:
904 case CK_CPointerToObjCPointerCast:
905 case CK_BlockPointerToObjCPointerCast:
906 case CK_AnyPointerToBlockPointerCast:
907 case CK_AddressSpaceConversion:
910 case CK_ArrayToPointerDecay:
913 Path.push_back({IndirectLocalPathEntry::AddressOf, CE});
915 Path, CE->getSubExpr(), RK_ReferenceBinding, Visit);
921 Init = CE->getSubExpr();
923 }
while (Old !=
Init);
928 if (
auto *ILE = dyn_cast<CXXStdInitializerListExpr>(
Init))
930 RK_StdInitializerList, Visit);
936 if (!RevisitSubinits)
939 if (ILE->isTransparent())
943 if (ILE->getType()->isArrayType()) {
944 for (
unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
950 if (
CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) {
951 assert(RD->isAggregate() &&
"aggregate init on non-aggregate");
956 if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
957 ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
959 RK_ReferenceBinding, Visit);
962 for (; Index < RD->getNumBases() && Index < ILE->getNumInits(); ++Index)
965 for (
const auto *I : RD->fields()) {
966 if (Index >= ILE->getNumInits())
968 if (I->isUnnamedBitField())
970 Expr *SubInit = ILE->getInit(Index);
971 if (I->getType()->isReferenceType())
973 RK_ReferenceBinding, Visit);
989 if (
auto *LE = dyn_cast<LambdaExpr>(
Init)) {
991 for (
Expr *
E : LE->capture_inits()) {
992 assert(CapI != LE->capture_end());
997 Path.push_back({IndirectLocalPathEntry::LambdaCaptureInit,
E, &Cap});
1010 if (
auto *CCE = dyn_cast<CXXConstructExpr>(
Init)) {
1011 if (CCE->getConstructor()->isCopyOrMoveConstructor()) {
1012 if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(CCE->getArg(0))) {
1013 Expr *Arg = MTE->getSubExpr();
1014 Path.push_back({IndirectLocalPathEntry::TemporaryCopy, Arg,
1015 CCE->getConstructor()});
1022 if (isa<CallExpr>(
Init) || isa<CXXConstructExpr>(
Init))
1025 if (
auto *CPE = dyn_cast<CXXParenListInitExpr>(
Init)) {
1026 RevertToOldSizeRAII RAII(
Path);
1027 Path.push_back({IndirectLocalPathEntry::ParenAggInit, CPE});
1028 for (
auto *I : CPE->getInitExprs()) {
1036 switch (
Init->getStmtClass()) {
1037 case Stmt::UnaryOperatorClass: {
1038 auto *UO = cast<UnaryOperator>(
Init);
1041 if (UO->getOpcode() == UO_AddrOf) {
1045 if (isa<MaterializeTemporaryExpr>(UO->getSubExpr()))
1048 Path.push_back({IndirectLocalPathEntry::AddressOf, UO});
1050 RK_ReferenceBinding, Visit);
1055 case Stmt::BinaryOperatorClass: {
1057 auto *BO = cast<BinaryOperator>(
Init);
1059 if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub))
1062 if (BO->getLHS()->getType()->isPointerType())
1064 else if (BO->getRHS()->getType()->isPointerType())
1069 case Stmt::ConditionalOperatorClass:
1070 case Stmt::BinaryConditionalOperatorClass: {
1071 auto *
C = cast<AbstractConditionalOperator>(
Init);
1074 if (!
C->getTrueExpr()->getType()->isVoidType())
1076 if (!
C->getFalseExpr()->getType()->isVoidType())
1081 case Stmt::BlockExprClass:
1082 if (cast<BlockExpr>(
Init)->getBlockDecl()->hasCaptures()) {
1084 Visit(
Path, Local(cast<BlockExpr>(
Init)), RK_ReferenceBinding);
1088 case Stmt::AddrLabelExprClass:
1090 Visit(
Path, Local(cast<AddrLabelExpr>(
Init)), RK_ReferenceBinding);
1110 for (
auto Elem :
Path) {
1111 if (Elem.Kind == IndirectLocalPathEntry::MemberExpr ||
1112 Elem.Kind == IndirectLocalPathEntry::LambdaCaptureInit)
1114 return Elem.Kind == IndirectLocalPathEntry::DefaultInit
1124 for (
unsigned N =
Path.size(); I != N; ++I) {
1126 case IndirectLocalPathEntry::AddressOf:
1127 case IndirectLocalPathEntry::LValToRVal:
1128 case IndirectLocalPathEntry::LifetimeBoundCall:
1129 case IndirectLocalPathEntry::TemporaryCopy:
1130 case IndirectLocalPathEntry::GslReferenceInit:
1131 case IndirectLocalPathEntry::GslPointerInit:
1132 case IndirectLocalPathEntry::GslPointerAssignment:
1133 case IndirectLocalPathEntry::ParenAggInit:
1134 case IndirectLocalPathEntry::MemberExpr:
1139 case IndirectLocalPathEntry::VarInit:
1140 if (cast<VarDecl>(
Path[I].
D)->isImplicit())
1143 case IndirectLocalPathEntry::DefaultInit:
1144 return Path[I].E->getSourceRange();
1146 case IndirectLocalPathEntry::LambdaCaptureInit:
1149 return Path[I].E->getSourceRange();
1151 case IndirectLocalPathEntry::DefaultArg:
1152 return cast<CXXDefaultArgExpr>(
Path[I].
E)->getUsedLocation();
1155 return E->getSourceRange();
1159 for (
const auto &It : llvm::reverse(
Path)) {
1161 case IndirectLocalPathEntry::VarInit:
1162 case IndirectLocalPathEntry::AddressOf:
1163 case IndirectLocalPathEntry::LifetimeBoundCall:
1164 case IndirectLocalPathEntry::MemberExpr:
1166 case IndirectLocalPathEntry::GslPointerInit:
1167 case IndirectLocalPathEntry::GslReferenceInit:
1168 case IndirectLocalPathEntry::GslPointerAssignment:
1191 Local L, LifetimeKind LK) {
1199 for (
const auto &
E :
Path) {
1200 if (
E.Kind == IndirectLocalPathEntry::MemberExpr) {
1209 if (
const auto *FD = llvm::dyn_cast_or_null<FieldDecl>(
E.D);
1210 FD && !FD->getType()->isReferenceType() &&
1211 isRecordWithAttr<OwnerAttr>(FD->getType()) &&
1212 LK != LK_MemInitializer) {
1226 if (
Path.back().Kind == IndirectLocalPathEntry::LifetimeBoundCall) {
1229 llvm::dyn_cast_or_null<FunctionDecl>(
Path.back().D);
1231 if (
const auto *PD = llvm::dyn_cast<ParmVarDecl>(
Path.back().D))
1232 FD = llvm::dyn_cast<FunctionDecl>(PD->getDeclContext());
1234 if (isa_and_present<CXXConstructorDecl>(FD)) {
1252 if (isa<DeclRefExpr>(L)) {
1264 auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
1266 bool IsGslPtrValueFromGslTempOwner =
1267 MTE && !MTE->getExtendingDecl() &&
1268 isRecordWithAttr<OwnerAttr>(MTE->getType());
1273 if (!IsGslPtrValueFromGslTempOwner)
1287 diag::warn_dangling_lifetime_pointer_assignment,
SourceLocation());
1288 return (EnableGSLAssignmentWarnings &&
1289 (isRecordWithAttr<PointerAttr>(Entity.
LHS->
getType()) ||
1298 assert(!AEntity || LK == LK_Assignment);
1299 assert(!CapEntity || LK == LK_LifetimeCapture);
1300 assert(!InitEntity || (LK != LK_Assignment && LK != LK_LifetimeCapture));
1303 if (LK == LK_FullExpression)
1308 auto TemporaryVisitor = [&](
const IndirectLocalPath &
Path, Local L,
1309 ReferenceKind RK) ->
bool {
1313 auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
1315 bool IsGslPtrValueFromGslTempOwner =
true;
1322 IsGslPtrValueFromGslTempOwner =
false;
1329 case LK_FullExpression:
1330 llvm_unreachable(
"already handled this");
1342 if (IsGslPtrValueFromGslTempOwner && DiagLoc.
isValid()) {
1343 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1352 MTE->setExtendingDecl(ExtendingEntity->
getDecl(),
1364 SemaRef.
Diag(DiagLoc, diag::warn_dangling_variable)
1367 << ExtendingEntity->
getDecl() <<
Init->isGLValue() << DiagRange;
1373 case LK_LifetimeCapture: {
1379 SemaRef.
Diag(DiagLoc, diag::warn_dangling_reference_captured)
1380 << CapEntity->
Entity << DiagRange;
1382 SemaRef.
Diag(DiagLoc, diag::warn_dangling_reference_captured_by_unknown)
1387 case LK_Assignment: {
1390 if (IsGslPtrValueFromGslTempOwner)
1391 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_assignment)
1392 << AEntity->
LHS << DiagRange;
1394 SemaRef.
Diag(DiagLoc, diag::warn_dangling_pointer_assignment)
1399 case LK_MemInitializer: {
1404 if (
auto *ExtendingDecl =
1405 ExtendingEntity ? ExtendingEntity->
getDecl() :
nullptr) {
1406 if (IsGslPtrValueFromGslTempOwner) {
1407 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_member)
1408 << ExtendingDecl << DiagRange;
1409 SemaRef.
Diag(ExtendingDecl->getLocation(),
1410 diag::note_ref_or_ptr_member_declared_here)
1414 bool IsSubobjectMember = ExtendingEntity != InitEntity;
1417 ? diag::err_dangling_member
1418 : diag::warn_dangling_member)
1419 << ExtendingDecl << IsSubobjectMember << RK << DiagRange;
1424 Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {
1425 SemaRef.
Diag(ExtendingDecl->getLocation(),
1426 diag::note_lifetime_extending_member_declared_here)
1427 << RK << IsSubobjectMember;
1445 auto *DRE = dyn_cast<DeclRefExpr>(L);
1449 if (DRE && isRecordWithAttr<OwnerAttr>(DRE->getType()))
1452 auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) :
nullptr;
1460 ExtendingEntity ? ExtendingEntity->
getDecl() :
nullptr) {
1461 bool IsPointer = !
Member->getType()->isReferenceType();
1462 SemaRef.
Diag(DiagLoc,
1463 IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
1464 : diag::warn_bind_ref_member_to_parameter)
1465 << Member << VD << isa<ParmVarDecl>(VD) << DiagRange;
1467 diag::note_ref_or_ptr_member_declared_here)
1475 if (isa<MaterializeTemporaryExpr>(L)) {
1476 if (IsGslPtrValueFromGslTempOwner)
1477 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1480 SemaRef.
Diag(DiagLoc, RK == RK_ReferenceBinding
1481 ? diag::warn_new_dangling_reference
1482 : diag::warn_new_dangling_initializer_list)
1483 << !InitEntity->
getParent() << DiagRange;
1492 case LK_StmtExprResult:
1493 if (
auto *DRE = dyn_cast<DeclRefExpr>(L)) {
1496 if (LK == LK_StmtExprResult)
1498 SemaRef.
Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1500 << isa<ParmVarDecl>(DRE->getDecl()) << (LK == LK_MustTail)
1502 }
else if (isa<BlockExpr>(L)) {
1503 SemaRef.
Diag(DiagLoc, diag::err_ret_local_block) << DiagRange;
1504 }
else if (isa<AddrLabelExpr>(L)) {
1507 if (LK == LK_StmtExprResult)
1509 SemaRef.
Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange;
1510 }
else if (
auto *CLE = dyn_cast<CompoundLiteralExpr>(L)) {
1511 SemaRef.
Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1513 << 2 << (LK == LK_MustTail) << DiagRange;
1522 SemaRef.
Diag(DiagLoc, diag::err_ret_local_temp_ref)
1524 else if (LK == LK_MustTail)
1525 SemaRef.
Diag(DiagLoc, diag::warn_musttail_local_temp_addr_ref)
1528 SemaRef.
Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
1534 for (
unsigned I = 0; I !=
Path.size(); ++I) {
1535 auto Elem =
Path[I];
1537 switch (Elem.Kind) {
1538 case IndirectLocalPathEntry::AddressOf:
1539 case IndirectLocalPathEntry::LValToRVal:
1540 case IndirectLocalPathEntry::ParenAggInit:
1545 case IndirectLocalPathEntry::LifetimeBoundCall:
1546 case IndirectLocalPathEntry::TemporaryCopy:
1547 case IndirectLocalPathEntry::MemberExpr:
1548 case IndirectLocalPathEntry::GslPointerInit:
1549 case IndirectLocalPathEntry::GslReferenceInit:
1550 case IndirectLocalPathEntry::GslPointerAssignment:
1554 case IndirectLocalPathEntry::DefaultInit: {
1555 auto *FD = cast<FieldDecl>(Elem.D);
1556 SemaRef.
Diag(FD->getLocation(),
1557 diag::note_init_with_default_member_initializer)
1562 case IndirectLocalPathEntry::VarInit: {
1563 const VarDecl *VD = cast<VarDecl>(Elem.D);
1570 case IndirectLocalPathEntry::LambdaCaptureInit: {
1571 if (!Elem.Capture->capturesVariable())
1575 const ValueDecl *VD = Elem.Capture->getCapturedVar();
1576 SemaRef.
Diag(Elem.Capture->getLocation(),
1577 diag::note_lambda_capture_initializer)
1579 << (Elem.Capture->getCaptureKind() ==
LCK_ByRef) << VD
1584 case IndirectLocalPathEntry::DefaultArg: {
1585 const auto *DAE = cast<CXXDefaultArgExpr>(Elem.E);
1588 diag::note_init_with_default_argument)
1602 case LK_Assignment: {
1606 ? IndirectLocalPathEntry::LifetimeBoundCall
1607 : IndirectLocalPathEntry::GslPointerAssignment,
1611 case LK_LifetimeCapture: {
1613 Path.push_back({IndirectLocalPathEntry::GslPointerInit,
Init});
1620 if (
Init->isGLValue())
1633 LifetimeKind LK = LTResult.getInt();
1636 nullptr,
nullptr, Init);
1642 nullptr,
nullptr, Init);
1649 bool RunAnalysis = (EnableDanglingPointerAssignment &&
1657 nullptr, LK_Assignment, &Entity,
1666 diag::warn_dangling_reference_captured_by_unknown,
SourceLocation()))
1669 nullptr, LK_LifetimeCapture,
const LambdaCapture * Capture
enum clang::sema::@1727::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 ...
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.
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.
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 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 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