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()))
585 auto ReturnType = Callee->getReturnType();
589 if (ReturnType->isReferenceType() &&
590 !isRecordWithAttr<OwnerAttr>(ReturnType->getPointeeType())) {
591 for (
const IndirectLocalPathEntry &PE : llvm::reverse(
Path)) {
592 if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit ||
593 PE.Kind == IndirectLocalPathEntry::LifetimeBoundCall)
595 if (PE.Kind == IndirectLocalPathEntry::GslPointerInit ||
596 PE.Kind == IndirectLocalPathEntry::GslPointerAssignment)
601 Path.push_back({ReturnType->isReferenceType()
602 ? IndirectLocalPathEntry::GslReferenceInit
603 : IndirectLocalPathEntry::GslPointerInit,
605 if (Arg->isGLValue())
613 bool CheckCoroCall =
false;
614 if (
const auto *RD = Callee->getReturnType()->getAsRecordDecl()) {
615 CheckCoroCall = RD->hasAttr<CoroLifetimeBoundAttr>() &&
616 RD->hasAttr<CoroReturnTypeAttr>() &&
617 !Callee->hasAttr<CoroDisableLifetimeBoundAttr>();
621 bool CheckCoroObjArg = CheckCoroCall;
624 LE && LE->captures().empty())
625 CheckCoroObjArg =
false;
629 CheckCoroObjArg =
false;
631 VisitLifetimeBoundArg(Callee, ObjectArg);
632 else if (EnableGSLAnalysis) {
633 if (
auto *CME = dyn_cast<CXXMethodDecl>(Callee);
635 VisitGSLPointerArg(Callee, ObjectArg);
640 N = std::min<unsigned>(Callee->getNumParams(), Args.size());
643 RevertToOldSizeRAII RAII(
Path);
644 if (
auto *DAE = dyn_cast<CXXDefaultArgExpr>(Arg)) {
646 {IndirectLocalPathEntry::DefaultArg, DAE, DAE->getParam()});
647 Arg = DAE->getExpr();
649 if (CheckCoroCall || Callee->getParamDecl(I)->hasAttr<LifetimeBoundAttr>())
650 VisitLifetimeBoundArg(Callee->getParamDecl(I), Arg);
651 else if (
const auto *CaptureAttr =
652 Callee->getParamDecl(I)->getAttr<LifetimeCaptureByAttr>();
653 CaptureAttr && isa<CXXConstructorDecl>(Callee) &&
654 llvm::any_of(CaptureAttr->params(), [](
int ArgIdx) {
655 return ArgIdx == LifetimeCaptureByAttr::THIS;
670 VisitLifetimeBoundArg(Callee->getParamDecl(I), Arg);
671 else if (EnableGSLAnalysis && I == 0) {
674 VisitGSLPointerArg(Callee, Arg);
675 }
else if (
auto *Ctor = dyn_cast<CXXConstructExpr>(
Call);
677 VisitGSLPointerArg(Ctor->getConstructor(), Arg);
687 LocalVisitor Visit) {
688 RevertToOldSizeRAII RAII(
Path);
695 if (
auto *FE = dyn_cast<FullExpr>(
Init))
696 Init = FE->getSubExpr();
700 if (ILE->isTransparent())
701 Init = ILE->getInit(0);
706 Init =
const_cast<Expr *
>(
Init->skipRValueSubobjectAdjustments());
711 if (CE->getSubExpr()->isGLValue())
712 Init = CE->getSubExpr();
716 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(
Init)) {
717 Init = ASE->getBase();
718 auto *ICE = dyn_cast<ImplicitCastExpr>(
Init);
719 if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay)
720 Init = ICE->getSubExpr();
729 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(
Init)) {
731 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
732 Init = DIE->getExpr();
734 }
while (
Init != Old);
736 if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(
Init)) {
737 if (Visit(
Path, Local(MTE), RK))
741 if (
auto *M = dyn_cast<MemberExpr>(
Init)) {
743 if (
auto *F = dyn_cast<FieldDecl>(M->getMemberDecl());
744 F && !F->getType()->isReferenceType())
748 if (isa<CallExpr>(
Init))
751 switch (
Init->getStmtClass()) {
752 case Stmt::DeclRefExprClass: {
755 auto *DRE = cast<DeclRefExpr>(
Init);
756 auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
757 if (VD && VD->hasLocalStorage() &&
758 !DRE->refersToEnclosingVariableOrCapture()) {
759 if (!VD->getType()->isReferenceType()) {
760 Visit(
Path, Local(DRE), RK);
761 }
else if (isa<ParmVarDecl>(DRE->getDecl())) {
766 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
768 RK_ReferenceBinding, Visit);
774 case Stmt::UnaryOperatorClass: {
779 if (
U->getOpcode() == UO_Deref)
784 case Stmt::ArraySectionExprClass: {
786 Path, cast<ArraySectionExpr>(
Init)->getBase(), Visit,
true);
790 case Stmt::ConditionalOperatorClass:
791 case Stmt::BinaryConditionalOperatorClass: {
792 auto *
C = cast<AbstractConditionalOperator>(
Init);
793 if (!
C->getTrueExpr()->getType()->isVoidType())
795 if (!
C->getFalseExpr()->getType()->isVoidType())
800 case Stmt::CompoundLiteralExprClass: {
801 if (
auto *CLE = dyn_cast<CompoundLiteralExpr>(
Init)) {
802 if (!CLE->isFileScope())
803 Visit(
Path, Local(CLE), RK);
819 bool RevisitSubinits) {
820 RevertToOldSizeRAII RAII(
Path);
828 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(
Init)) {
830 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
831 Init = DIE->getExpr();
834 if (
auto *FE = dyn_cast<FullExpr>(
Init))
835 Init = FE->getSubExpr();
838 Init =
const_cast<Expr *
>(
Init->skipRValueSubobjectAdjustments());
841 Init = BTE->getSubExpr();
846 if (
auto *CE = dyn_cast<CastExpr>(
Init)) {
847 switch (CE->getCastKind()) {
848 case CK_LValueToRValue:
851 Path.push_back({IndirectLocalPathEntry::LValToRVal, CE});
854 [&](IndirectLocalPath &
Path, Local L, ReferenceKind RK) ->
bool {
855 if (
auto *DRE = dyn_cast<DeclRefExpr>(L)) {
856 auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
857 if (VD && VD->getType().isConstQualified() && VD->getInit() &&
859 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
863 }
else if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L)) {
864 if (MTE->getType().isConstQualified())
877 case CK_BaseToDerived:
878 case CK_DerivedToBase:
879 case CK_UncheckedDerivedToBase:
882 case CK_UserDefinedConversion:
883 case CK_ConstructorConversion:
884 case CK_IntegralToPointer:
885 case CK_PointerToIntegral:
887 case CK_IntegralCast:
888 case CK_CPointerToObjCPointerCast:
889 case CK_BlockPointerToObjCPointerCast:
890 case CK_AnyPointerToBlockPointerCast:
891 case CK_AddressSpaceConversion:
894 case CK_ArrayToPointerDecay:
897 Path.push_back({IndirectLocalPathEntry::AddressOf, CE});
899 Path, CE->getSubExpr(), RK_ReferenceBinding, Visit);
905 Init = CE->getSubExpr();
907 }
while (Old !=
Init);
912 if (
auto *ILE = dyn_cast<CXXStdInitializerListExpr>(
Init))
914 RK_StdInitializerList, Visit);
920 if (!RevisitSubinits)
923 if (ILE->isTransparent())
927 if (ILE->getType()->isArrayType()) {
928 for (
unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
934 if (
CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) {
935 assert(RD->isAggregate() &&
"aggregate init on non-aggregate");
940 if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
941 ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
943 RK_ReferenceBinding, Visit);
946 for (; Index < RD->getNumBases() && Index < ILE->getNumInits(); ++Index)
949 for (
const auto *I : RD->fields()) {
950 if (Index >= ILE->getNumInits())
952 if (I->isUnnamedBitField())
954 Expr *SubInit = ILE->getInit(Index);
955 if (I->getType()->isReferenceType())
957 RK_ReferenceBinding, Visit);
973 if (
auto *LE = dyn_cast<LambdaExpr>(
Init)) {
975 for (
Expr *
E : LE->capture_inits()) {
976 assert(CapI != LE->capture_end());
981 Path.push_back({IndirectLocalPathEntry::LambdaCaptureInit,
E, &Cap});
994 if (
auto *CCE = dyn_cast<CXXConstructExpr>(
Init)) {
995 if (CCE->getConstructor()->isCopyOrMoveConstructor()) {
996 if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(CCE->getArg(0))) {
997 Expr *Arg = MTE->getSubExpr();
998 Path.push_back({IndirectLocalPathEntry::TemporaryCopy, Arg,
999 CCE->getConstructor()});
1006 if (isa<CallExpr>(
Init) || isa<CXXConstructExpr>(
Init))
1009 if (
auto *CPE = dyn_cast<CXXParenListInitExpr>(
Init)) {
1010 RevertToOldSizeRAII RAII(
Path);
1011 Path.push_back({IndirectLocalPathEntry::ParenAggInit, CPE});
1012 for (
auto *I : CPE->getInitExprs()) {
1020 switch (
Init->getStmtClass()) {
1021 case Stmt::UnaryOperatorClass: {
1022 auto *UO = cast<UnaryOperator>(
Init);
1025 if (UO->getOpcode() == UO_AddrOf) {
1029 if (isa<MaterializeTemporaryExpr>(UO->getSubExpr()))
1032 Path.push_back({IndirectLocalPathEntry::AddressOf, UO});
1034 RK_ReferenceBinding, Visit);
1039 case Stmt::BinaryOperatorClass: {
1041 auto *BO = cast<BinaryOperator>(
Init);
1043 if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub))
1046 if (BO->getLHS()->getType()->isPointerType())
1048 else if (BO->getRHS()->getType()->isPointerType())
1053 case Stmt::ConditionalOperatorClass:
1054 case Stmt::BinaryConditionalOperatorClass: {
1055 auto *
C = cast<AbstractConditionalOperator>(
Init);
1058 if (!
C->getTrueExpr()->getType()->isVoidType())
1060 if (!
C->getFalseExpr()->getType()->isVoidType())
1065 case Stmt::BlockExprClass:
1066 if (cast<BlockExpr>(
Init)->getBlockDecl()->hasCaptures()) {
1068 Visit(
Path, Local(cast<BlockExpr>(
Init)), RK_ReferenceBinding);
1072 case Stmt::AddrLabelExprClass:
1074 Visit(
Path, Local(cast<AddrLabelExpr>(
Init)), RK_ReferenceBinding);
1094 for (
auto Elem :
Path) {
1095 if (Elem.Kind == IndirectLocalPathEntry::DefaultInit)
1097 if (Elem.Kind != IndirectLocalPathEntry::LambdaCaptureInit)
1106 for (
unsigned N =
Path.size(); I != N; ++I) {
1108 case IndirectLocalPathEntry::AddressOf:
1109 case IndirectLocalPathEntry::LValToRVal:
1110 case IndirectLocalPathEntry::LifetimeBoundCall:
1111 case IndirectLocalPathEntry::TemporaryCopy:
1112 case IndirectLocalPathEntry::GslReferenceInit:
1113 case IndirectLocalPathEntry::GslPointerInit:
1114 case IndirectLocalPathEntry::GslPointerAssignment:
1115 case IndirectLocalPathEntry::ParenAggInit:
1120 case IndirectLocalPathEntry::VarInit:
1121 if (cast<VarDecl>(
Path[I].
D)->isImplicit())
1124 case IndirectLocalPathEntry::DefaultInit:
1125 return Path[I].E->getSourceRange();
1127 case IndirectLocalPathEntry::LambdaCaptureInit:
1130 return Path[I].E->getSourceRange();
1132 case IndirectLocalPathEntry::DefaultArg:
1133 return cast<CXXDefaultArgExpr>(
Path[I].
E)->getUsedLocation();
1136 return E->getSourceRange();
1140 for (
const auto &It : llvm::reverse(
Path)) {
1142 case IndirectLocalPathEntry::VarInit:
1143 case IndirectLocalPathEntry::AddressOf:
1144 case IndirectLocalPathEntry::LifetimeBoundCall:
1146 case IndirectLocalPathEntry::GslPointerInit:
1147 case IndirectLocalPathEntry::GslReferenceInit:
1148 case IndirectLocalPathEntry::GslPointerAssignment:
1185 if (
Path.back().Kind == IndirectLocalPathEntry::LifetimeBoundCall) {
1188 llvm::dyn_cast_or_null<FunctionDecl>(
Path.back().D);
1190 if (
const auto *PD = llvm::dyn_cast<ParmVarDecl>(
Path.back().D))
1191 FD = llvm::dyn_cast<FunctionDecl>(PD->getDeclContext());
1193 if (isa_and_present<CXXConstructorDecl>(FD)) {
1211 if (isa<DeclRefExpr>(L)) {
1223 auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
1225 bool IsGslPtrValueFromGslTempOwner =
1226 MTE && !MTE->getExtendingDecl() &&
1227 isRecordWithAttr<OwnerAttr>(MTE->getType());
1232 if (!IsGslPtrValueFromGslTempOwner)
1245 diag::warn_dangling_lifetime_pointer_assignment,
SourceLocation());
1246 return (EnableGSLAssignmentWarnings &&
1247 (isRecordWithAttr<PointerAttr>(Entity.
LHS->
getType()) ||
1256 assert(!AEntity || LK == LK_Assignment);
1257 assert(!CapEntity || LK == LK_LifetimeCapture);
1258 assert(!InitEntity || (LK != LK_Assignment && LK != LK_LifetimeCapture));
1261 if (LK == LK_FullExpression)
1266 auto TemporaryVisitor = [&](
const IndirectLocalPath &
Path, Local L,
1267 ReferenceKind RK) ->
bool {
1271 auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
1273 bool IsGslPtrValueFromGslTempOwner =
true;
1280 IsGslPtrValueFromGslTempOwner =
false;
1287 case LK_FullExpression:
1288 llvm_unreachable(
"already handled this");
1300 if (IsGslPtrValueFromGslTempOwner && DiagLoc.
isValid()) {
1301 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1310 MTE->setExtendingDecl(ExtendingEntity->
getDecl(),
1322 SemaRef.
Diag(DiagLoc, diag::warn_dangling_variable)
1325 << ExtendingEntity->
getDecl() <<
Init->isGLValue() << DiagRange;
1331 case LK_LifetimeCapture: {
1337 SemaRef.
Diag(DiagLoc, diag::warn_dangling_reference_captured)
1338 << CapEntity->
Entity << DiagRange;
1340 SemaRef.
Diag(DiagLoc, diag::warn_dangling_reference_captured_by_unknown)
1345 case LK_Assignment: {
1348 if (IsGslPtrValueFromGslTempOwner)
1349 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_assignment)
1350 << AEntity->
LHS << DiagRange;
1352 SemaRef.
Diag(DiagLoc, diag::warn_dangling_pointer_assignment)
1357 case LK_MemInitializer: {
1362 if (
auto *ExtendingDecl =
1363 ExtendingEntity ? ExtendingEntity->
getDecl() :
nullptr) {
1364 if (IsGslPtrValueFromGslTempOwner) {
1365 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_member)
1366 << ExtendingDecl << DiagRange;
1367 SemaRef.
Diag(ExtendingDecl->getLocation(),
1368 diag::note_ref_or_ptr_member_declared_here)
1372 bool IsSubobjectMember = ExtendingEntity != InitEntity;
1375 ? diag::err_dangling_member
1376 : diag::warn_dangling_member)
1377 << ExtendingDecl << IsSubobjectMember << RK << DiagRange;
1382 Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {
1383 SemaRef.
Diag(ExtendingDecl->getLocation(),
1384 diag::note_lifetime_extending_member_declared_here)
1385 << RK << IsSubobjectMember;
1403 auto *DRE = dyn_cast<DeclRefExpr>(L);
1406 if (DRE && isRecordWithAttr<OwnerAttr>(DRE->getType()))
1409 auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) :
nullptr;
1417 ExtendingEntity ? ExtendingEntity->
getDecl() :
nullptr) {
1418 bool IsPointer = !
Member->getType()->isReferenceType();
1419 SemaRef.
Diag(DiagLoc,
1420 IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
1421 : diag::warn_bind_ref_member_to_parameter)
1422 << Member << VD << isa<ParmVarDecl>(VD) << DiagRange;
1424 diag::note_ref_or_ptr_member_declared_here)
1432 if (isa<MaterializeTemporaryExpr>(L)) {
1433 if (IsGslPtrValueFromGslTempOwner)
1434 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1437 SemaRef.
Diag(DiagLoc, RK == RK_ReferenceBinding
1438 ? diag::warn_new_dangling_reference
1439 : diag::warn_new_dangling_initializer_list)
1440 << !InitEntity->
getParent() << DiagRange;
1449 case LK_StmtExprResult:
1450 if (
auto *DRE = dyn_cast<DeclRefExpr>(L)) {
1453 if (LK == LK_StmtExprResult)
1455 SemaRef.
Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1457 << isa<ParmVarDecl>(DRE->getDecl()) << (LK == LK_MustTail)
1459 }
else if (isa<BlockExpr>(L)) {
1460 SemaRef.
Diag(DiagLoc, diag::err_ret_local_block) << DiagRange;
1461 }
else if (isa<AddrLabelExpr>(L)) {
1464 if (LK == LK_StmtExprResult)
1466 SemaRef.
Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange;
1467 }
else if (
auto *CLE = dyn_cast<CompoundLiteralExpr>(L)) {
1468 SemaRef.
Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1470 << 2 << (LK == LK_MustTail) << DiagRange;
1479 SemaRef.
Diag(DiagLoc, diag::err_ret_local_temp_ref)
1481 else if (LK == LK_MustTail)
1482 SemaRef.
Diag(DiagLoc, diag::warn_musttail_local_temp_addr_ref)
1485 SemaRef.
Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
1491 for (
unsigned I = 0; I !=
Path.size(); ++I) {
1492 auto Elem =
Path[I];
1494 switch (Elem.Kind) {
1495 case IndirectLocalPathEntry::AddressOf:
1496 case IndirectLocalPathEntry::LValToRVal:
1497 case IndirectLocalPathEntry::ParenAggInit:
1502 case IndirectLocalPathEntry::LifetimeBoundCall:
1503 case IndirectLocalPathEntry::TemporaryCopy:
1504 case IndirectLocalPathEntry::GslPointerInit:
1505 case IndirectLocalPathEntry::GslReferenceInit:
1506 case IndirectLocalPathEntry::GslPointerAssignment:
1510 case IndirectLocalPathEntry::DefaultInit: {
1511 auto *FD = cast<FieldDecl>(Elem.D);
1512 SemaRef.
Diag(FD->getLocation(),
1513 diag::note_init_with_default_member_initializer)
1518 case IndirectLocalPathEntry::VarInit: {
1519 const VarDecl *VD = cast<VarDecl>(Elem.D);
1526 case IndirectLocalPathEntry::LambdaCaptureInit: {
1527 if (!Elem.Capture->capturesVariable())
1531 const ValueDecl *VD = Elem.Capture->getCapturedVar();
1532 SemaRef.
Diag(Elem.Capture->getLocation(),
1533 diag::note_lambda_capture_initializer)
1535 << (Elem.Capture->getCaptureKind() ==
LCK_ByRef) << VD
1540 case IndirectLocalPathEntry::DefaultArg: {
1541 const auto *DAE = cast<CXXDefaultArgExpr>(Elem.E);
1544 diag::note_init_with_default_argument)
1558 case LK_Assignment: {
1562 ? IndirectLocalPathEntry::LifetimeBoundCall
1563 : IndirectLocalPathEntry::GslPointerAssignment,
1567 case LK_LifetimeCapture: {
1569 Path.push_back({IndirectLocalPathEntry::GslPointerInit,
Init});
1576 if (
Init->isGLValue())
1589 LifetimeKind LK = LTResult.getInt();
1592 nullptr,
nullptr, Init);
1598 nullptr,
nullptr, Init);
1605 bool RunAnalysis = (EnableDanglingPointerAssignment &&
1613 nullptr, LK_Assignment, &Entity,
1622 diag::warn_dangling_reference_captured_by_unknown,
SourceLocation()))
1625 nullptr, LK_LifetimeCapture,
const LambdaCapture * Capture
enum clang::sema::@1712::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