15#include "llvm/ADT/PointerIntPair.h"
50 llvm::PointerIntPair<const InitializedEntity *, 3, LifetimeKind>;
63 return {Entity, LK_Extended};
88 return {Entity, LK_Extended};
95 return {
nullptr, LK_FullExpression};
100 return {
nullptr, LK_FullExpression};
106 return {
nullptr, LK_Return};
111 return {
nullptr, LK_StmtExprResult};
117 return {
nullptr, LK_New};
125 return {
nullptr, LK_FullExpression};
135 return {InitField, LK_MemInitializer};
142 return {InitField, LK_MemInitializer};
149 return {
nullptr, LK_FullExpression};
153 return {
nullptr, LK_FullExpression};
160 return {
nullptr, LK_FullExpression};
163 llvm_unreachable(
"unknown entity kind");
172 RK_StdInitializerList,
185struct IndirectLocalPathEntry {
196 GslPointerAssignment,
200 const Decl *
D =
nullptr;
203 IndirectLocalPathEntry() {}
204 IndirectLocalPathEntry(EntryKind K, Expr *E) :
Kind(K),
E(
E) {}
205 IndirectLocalPathEntry(EntryKind K, Expr *E,
const Decl *
D)
207 IndirectLocalPathEntry(EntryKind K, Expr *E,
const LambdaCapture *Capture)
213struct RevertToOldSizeRAII {
216 RevertToOldSizeRAII(IndirectLocalPath &Path) :
Path(
Path) {}
217 ~RevertToOldSizeRAII() {
Path.resize(OldSize); }
220using LocalVisitor = llvm::function_ref<
bool(IndirectLocalPath &
Path, Local L,
226 if (
E.Kind == IndirectLocalPathEntry::VarInit &&
E.D == VD)
232 return llvm::any_of(
Path, [=](IndirectLocalPathEntry
E) {
233 return E.Kind == IndirectLocalPathEntry::DefaultInit ||
234 E.Kind == IndirectLocalPathEntry::VarInit;
240 bool RevisitSubinits,
241 bool EnableLifetimeWarnings);
246 bool EnableLifetimeWarnings);
250 return RD->hasAttr<
T>();
261 if (
const auto *ND = dyn_cast<NamespaceDecl>(DC))
263 StringRef Name = II->getName();
264 if (Name.size() >= 2 && Name.front() ==
'_' &&
273 if (
auto *Conv = dyn_cast_or_null<CXXConversionDecl>(Callee))
274 if (isRecordWithAttr<PointerAttr>(Conv->getConversionType()))
278 if (!isRecordWithAttr<PointerAttr>(
279 Callee->getFunctionObjectParameterType()) &&
280 !isRecordWithAttr<OwnerAttr>(Callee->getFunctionObjectParameterType()))
282 if (Callee->getReturnType()->isPointerType() ||
283 isRecordWithAttr<PointerAttr>(Callee->getReturnType())) {
284 if (!Callee->getIdentifier())
286 return llvm::StringSwitch<bool>(Callee->getName())
287 .Cases(
"begin",
"rbegin",
"cbegin",
"crbegin",
true)
288 .Cases(
"end",
"rend",
"cend",
"crend",
true)
289 .Cases(
"c_str",
"data",
"get",
true)
291 .Cases(
"find",
"equal_range",
"lower_bound",
"upper_bound",
true)
293 }
else if (Callee->getReturnType()->isReferenceType()) {
294 if (!Callee->getIdentifier()) {
295 auto OO = Callee->getOverloadedOperator();
296 return OO == OverloadedOperatorKind::OO_Subscript ||
297 OO == OverloadedOperatorKind::OO_Star;
299 return llvm::StringSwitch<bool>(Callee->getName())
300 .Cases(
"front",
"back",
"at",
"top",
"value",
true)
312 if (!RD->hasAttr<PointerAttr>() && !RD->hasAttr<OwnerAttr>())
316 return llvm::StringSwitch<bool>(FD->
getName())
317 .Cases(
"begin",
"rbegin",
"cbegin",
"crbegin",
true)
318 .Cases(
"end",
"rend",
"cend",
"crend",
true)
322 return llvm::StringSwitch<bool>(FD->
getName())
323 .Cases(
"get",
"any_cast",
true)
330 LocalVisitor Visit) {
331 auto VisitPointerArg = [&](
const Decl *
D,
Expr *Arg,
bool Value) {
334 if (isa<MemberExpr>(Arg->IgnoreImpCasts()))
338 for (
const IndirectLocalPathEntry &PE : llvm::reverse(
Path)) {
339 if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit)
341 if (PE.Kind == IndirectLocalPathEntry::GslPointerInit ||
342 PE.Kind == IndirectLocalPathEntry::GslPointerAssignment)
347 Path.push_back({
Value ? IndirectLocalPathEntry::GslPointerInit
348 : IndirectLocalPathEntry::GslReferenceInit,
350 if (Arg->isGLValue())
360 if (
auto *MCE = dyn_cast<CXXMemberCallExpr>(
Call)) {
361 const auto *MD = cast_or_null<CXXMethodDecl>(MCE->getDirectCallee());
363 VisitPointerArg(MD, MCE->getImplicitObjectArgument(),
364 !MD->getReturnType()->isReferenceType());
366 }
else if (
auto *OCE = dyn_cast<CXXOperatorCallExpr>(
Call)) {
368 if (Callee && Callee->isCXXInstanceMember() &&
370 VisitPointerArg(Callee, OCE->getArg(0),
371 !Callee->getReturnType()->isReferenceType());
373 }
else if (
auto *CE = dyn_cast<CallExpr>(
Call)) {
376 VisitPointerArg(Callee, CE->getArg(0),
377 !Callee->getReturnType()->isReferenceType());
381 if (
auto *CCE = dyn_cast<CXXConstructExpr>(
Call)) {
382 const auto *Ctor = CCE->getConstructor();
384 if (CCE->getNumArgs() > 0 && RD->
hasAttr<PointerAttr>())
385 VisitPointerArg(Ctor->getParamDecl(0), CCE->getArgs()[0],
true);
413 auto *MD = dyn_cast<CXXMethodDecl>(FD);
414 if (MD && MD->isCXXInstanceMember())
417 LHST = MD->getParamDecl(0)->getType();
427 LocalVisitor Visit) {
431 if (
auto *CE = dyn_cast<CallExpr>(
Call)) {
432 Callee = CE->getDirectCallee();
435 auto *CCE = cast<CXXConstructExpr>(
Call);
436 Callee = CCE->getConstructor();
442 Expr *ObjectArg =
nullptr;
443 if (isa<CXXOperatorCallExpr>(
Call) && Callee->isCXXInstanceMember()) {
445 Args = Args.slice(1);
446 }
else if (
auto *MCE = dyn_cast<CXXMemberCallExpr>(
Call)) {
447 ObjectArg = MCE->getImplicitObjectArgument();
450 auto VisitLifetimeBoundArg = [&](
const Decl *
D,
Expr *Arg) {
451 Path.push_back({IndirectLocalPathEntry::LifetimeBoundCall, Arg,
D});
452 if (Arg->isGLValue())
462 bool CheckCoroCall =
false;
463 if (
const auto *RD = Callee->getReturnType()->getAsRecordDecl()) {
464 CheckCoroCall = RD->hasAttr<CoroLifetimeBoundAttr>() &&
465 RD->hasAttr<CoroReturnTypeAttr>() &&
466 !Callee->hasAttr<CoroDisableLifetimeBoundAttr>();
470 bool CheckCoroObjArg = CheckCoroCall;
473 LE && LE->captures().empty())
474 CheckCoroObjArg =
false;
478 CheckCoroObjArg =
false;
480 VisitLifetimeBoundArg(Callee, ObjectArg);
484 N = std::min<unsigned>(Callee->getNumParams(), Args.size());
486 if (CheckCoroCall || Callee->getParamDecl(I)->hasAttr<LifetimeBoundAttr>())
487 VisitLifetimeBoundArg(Callee->getParamDecl(I), Args[I]);
496 bool EnableLifetimeWarnings) {
497 RevertToOldSizeRAII RAII(
Path);
504 if (
auto *FE = dyn_cast<FullExpr>(
Init))
505 Init = FE->getSubExpr();
509 if (ILE->isTransparent())
510 Init = ILE->getInit(0);
515 Init =
const_cast<Expr *
>(
Init->skipRValueSubobjectAdjustments());
520 if (CE->getSubExpr()->isGLValue())
521 Init = CE->getSubExpr();
525 if (
auto *ASE = dyn_cast<ArraySubscriptExpr>(
Init)) {
526 Init = ASE->getBase();
527 auto *ICE = dyn_cast<ImplicitCastExpr>(
Init);
528 if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay)
529 Init = ICE->getSubExpr();
534 EnableLifetimeWarnings);
539 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(
Init)) {
541 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
542 Init = DIE->getExpr();
544 }
while (
Init != Old);
546 if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(
Init)) {
547 if (Visit(
Path, Local(MTE), RK))
549 EnableLifetimeWarnings);
552 if (
auto *M = dyn_cast<MemberExpr>(
Init)) {
554 if (
auto *F = dyn_cast<FieldDecl>(M->getMemberDecl());
555 F && !F->getType()->isReferenceType())
557 EnableLifetimeWarnings);
560 if (isa<CallExpr>(
Init)) {
561 if (EnableLifetimeWarnings)
566 switch (
Init->getStmtClass()) {
567 case Stmt::DeclRefExprClass: {
570 auto *DRE = cast<DeclRefExpr>(
Init);
571 auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
572 if (VD && VD->hasLocalStorage() &&
573 !DRE->refersToEnclosingVariableOrCapture()) {
574 if (!VD->getType()->isReferenceType()) {
575 Visit(
Path, Local(DRE), RK);
576 }
else if (isa<ParmVarDecl>(DRE->getDecl())) {
581 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
583 RK_ReferenceBinding, Visit,
584 EnableLifetimeWarnings);
590 case Stmt::UnaryOperatorClass: {
595 if (
U->getOpcode() == UO_Deref)
597 EnableLifetimeWarnings);
601 case Stmt::ArraySectionExprClass: {
603 cast<ArraySectionExpr>(
Init)->getBase(),
604 Visit,
true, EnableLifetimeWarnings);
608 case Stmt::ConditionalOperatorClass:
609 case Stmt::BinaryConditionalOperatorClass: {
610 auto *
C = cast<AbstractConditionalOperator>(
Init);
611 if (!
C->getTrueExpr()->getType()->isVoidType())
613 EnableLifetimeWarnings);
614 if (!
C->getFalseExpr()->getType()->isVoidType())
616 EnableLifetimeWarnings);
620 case Stmt::CompoundLiteralExprClass: {
621 if (
auto *CLE = dyn_cast<CompoundLiteralExpr>(
Init)) {
622 if (!CLE->isFileScope())
623 Visit(
Path, Local(CLE), RK);
639 bool RevisitSubinits,
640 bool EnableLifetimeWarnings) {
641 RevertToOldSizeRAII RAII(
Path);
649 if (
auto *DIE = dyn_cast<CXXDefaultInitExpr>(
Init)) {
651 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
652 Init = DIE->getExpr();
655 if (
auto *FE = dyn_cast<FullExpr>(
Init))
656 Init = FE->getSubExpr();
659 Init =
const_cast<Expr *
>(
Init->skipRValueSubobjectAdjustments());
662 Init = BTE->getSubExpr();
667 if (
auto *CE = dyn_cast<CastExpr>(
Init)) {
668 switch (CE->getCastKind()) {
669 case CK_LValueToRValue:
672 Path.push_back({IndirectLocalPathEntry::LValToRVal, CE});
675 [&](IndirectLocalPath &
Path, Local L, ReferenceKind RK) ->
bool {
676 if (
auto *DRE = dyn_cast<DeclRefExpr>(L)) {
677 auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
678 if (VD && VD->getType().isConstQualified() && VD->getInit() &&
680 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
682 Path, VD->getInit(), Visit,
true, EnableLifetimeWarnings);
684 }
else if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L)) {
685 if (MTE->getType().isConstQualified())
688 EnableLifetimeWarnings);
692 EnableLifetimeWarnings);
700 case CK_BaseToDerived:
701 case CK_DerivedToBase:
702 case CK_UncheckedDerivedToBase:
705 case CK_UserDefinedConversion:
706 case CK_ConstructorConversion:
707 case CK_IntegralToPointer:
708 case CK_PointerToIntegral:
710 case CK_IntegralCast:
711 case CK_CPointerToObjCPointerCast:
712 case CK_BlockPointerToObjCPointerCast:
713 case CK_AnyPointerToBlockPointerCast:
714 case CK_AddressSpaceConversion:
717 case CK_ArrayToPointerDecay:
720 Path.push_back({IndirectLocalPathEntry::AddressOf, CE});
722 RK_ReferenceBinding, Visit,
723 EnableLifetimeWarnings);
729 Init = CE->getSubExpr();
731 }
while (Old !=
Init);
736 if (
auto *ILE = dyn_cast<CXXStdInitializerListExpr>(
Init))
738 RK_StdInitializerList, Visit,
739 EnableLifetimeWarnings);
745 if (!RevisitSubinits)
748 if (ILE->isTransparent())
751 EnableLifetimeWarnings);
753 if (ILE->getType()->isArrayType()) {
754 for (
unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
757 EnableLifetimeWarnings);
761 if (
CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) {
762 assert(RD->isAggregate() &&
"aggregate init on non-aggregate");
767 if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
768 ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
770 RK_ReferenceBinding, Visit,
771 EnableLifetimeWarnings);
774 for (; Index < RD->getNumBases() && Index < ILE->getNumInits(); ++Index)
777 EnableLifetimeWarnings);
778 for (
const auto *I : RD->fields()) {
779 if (Index >= ILE->getNumInits())
781 if (I->isUnnamedBitField())
783 Expr *SubInit = ILE->getInit(Index);
784 if (I->getType()->isReferenceType())
786 RK_ReferenceBinding, Visit,
787 EnableLifetimeWarnings);
793 Path, SubInit, Visit, RevisitSubinits, EnableLifetimeWarnings);
803 if (
auto *LE = dyn_cast<LambdaExpr>(
Init)) {
805 for (
Expr *
E : LE->capture_inits()) {
806 assert(CapI != LE->capture_end());
811 Path.push_back({IndirectLocalPathEntry::LambdaCaptureInit,
E, &Cap});
814 Visit, EnableLifetimeWarnings);
817 EnableLifetimeWarnings);
825 if (
auto *CCE = dyn_cast<CXXConstructExpr>(
Init)) {
826 if (CCE->getConstructor()->isCopyOrMoveConstructor()) {
827 if (
auto *MTE = dyn_cast<MaterializeTemporaryExpr>(CCE->getArg(0))) {
828 Expr *Arg = MTE->getSubExpr();
829 Path.push_back({IndirectLocalPathEntry::TemporaryCopy, Arg,
830 CCE->getConstructor()});
838 if (isa<CallExpr>(
Init) || isa<CXXConstructExpr>(
Init)) {
839 if (EnableLifetimeWarnings)
844 switch (
Init->getStmtClass()) {
845 case Stmt::UnaryOperatorClass: {
846 auto *UO = cast<UnaryOperator>(
Init);
849 if (UO->getOpcode() == UO_AddrOf) {
853 if (isa<MaterializeTemporaryExpr>(UO->getSubExpr()))
856 Path.push_back({IndirectLocalPathEntry::AddressOf, UO});
858 RK_ReferenceBinding, Visit,
859 EnableLifetimeWarnings);
864 case Stmt::BinaryOperatorClass: {
866 auto *BO = cast<BinaryOperator>(
Init);
868 if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub))
871 if (BO->getLHS()->getType()->isPointerType())
873 EnableLifetimeWarnings);
874 else if (BO->getRHS()->getType()->isPointerType())
876 EnableLifetimeWarnings);
880 case Stmt::ConditionalOperatorClass:
881 case Stmt::BinaryConditionalOperatorClass: {
882 auto *
C = cast<AbstractConditionalOperator>(
Init);
885 if (!
C->getTrueExpr()->getType()->isVoidType())
887 EnableLifetimeWarnings);
888 if (!
C->getFalseExpr()->getType()->isVoidType())
890 EnableLifetimeWarnings);
894 case Stmt::BlockExprClass:
895 if (cast<BlockExpr>(
Init)->getBlockDecl()->hasCaptures()) {
897 Visit(
Path, Local(cast<BlockExpr>(
Init)), RK_ReferenceBinding);
901 case Stmt::AddrLabelExprClass:
903 Visit(
Path, Local(cast<AddrLabelExpr>(
Init)), RK_ReferenceBinding);
929 for (
auto Elem :
Path) {
930 if (Elem.Kind == IndirectLocalPathEntry::DefaultInit)
932 else if (Elem.Kind != IndirectLocalPathEntry::LambdaCaptureInit)
941 for (
unsigned N =
Path.size(); I != N; ++I) {
943 case IndirectLocalPathEntry::AddressOf:
944 case IndirectLocalPathEntry::LValToRVal:
945 case IndirectLocalPathEntry::LifetimeBoundCall:
946 case IndirectLocalPathEntry::TemporaryCopy:
947 case IndirectLocalPathEntry::GslReferenceInit:
948 case IndirectLocalPathEntry::GslPointerInit:
949 case IndirectLocalPathEntry::GslPointerAssignment:
954 case IndirectLocalPathEntry::VarInit:
955 if (cast<VarDecl>(
Path[I].
D)->isImplicit())
958 case IndirectLocalPathEntry::DefaultInit:
959 return Path[I].E->getSourceRange();
961 case IndirectLocalPathEntry::LambdaCaptureInit:
964 return Path[I].E->getSourceRange();
967 return E->getSourceRange();
971 for (
const auto &It : llvm::reverse(
Path)) {
973 case IndirectLocalPathEntry::VarInit:
974 case IndirectLocalPathEntry::AddressOf:
975 case IndirectLocalPathEntry::LifetimeBoundCall:
977 case IndirectLocalPathEntry::GslPointerInit:
978 case IndirectLocalPathEntry::GslReferenceInit:
979 case IndirectLocalPathEntry::GslPointerAssignment:
993 bool EnableLifetimeWarnings) {
994 assert((AEntity && LK == LK_Assignment) ||
995 (InitEntity && LK != LK_Assignment));
998 if (LK == LK_FullExpression)
1003 auto TemporaryVisitor = [&](IndirectLocalPath &
Path, Local L,
1004 ReferenceKind RK) ->
bool {
1008 auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
1010 bool IsGslPtrValueFromGslTempOwner =
false;
1011 bool IsLocalGslOwner =
false;
1013 if (isa<DeclRefExpr>(L)) {
1019 IsLocalGslOwner = isRecordWithAttr<OwnerAttr>(L->getType());
1023 IsGslPtrValueFromGslTempOwner =
1024 MTE && !MTE->getExtendingDecl() &&
1025 isRecordWithAttr<OwnerAttr>(MTE->getType());
1029 if (!IsGslPtrValueFromGslTempOwner)
1035 case LK_FullExpression:
1036 llvm_unreachable(
"already handled this");
1048 if (IsGslPtrValueFromGslTempOwner && DiagLoc.
isValid()) {
1049 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1058 MTE->setExtendingDecl(ExtendingEntity->
getDecl(),
1070 SemaRef.
Diag(DiagLoc, diag::warn_unsupported_lifetime_extension)
1081 SemaRef.
Diag(DiagLoc, diag::warn_dangling_variable)
1084 << ExtendingEntity->
getDecl() <<
Init->isGLValue() << DiagRange;
1090 case LK_Assignment: {
1095 "No lifetime extension for assignments");
1096 SemaRef.
Diag(DiagLoc,
1097 IsGslPtrValueFromGslTempOwner
1098 ? diag::warn_dangling_lifetime_pointer_assignment
1099 : diag::warn_dangling_pointer_assignment)
1100 << AEntity->
LHS << DiagRange;
1103 case LK_MemInitializer: {
1108 if (
auto *ExtendingDecl =
1109 ExtendingEntity ? ExtendingEntity->
getDecl() :
nullptr) {
1110 if (IsGslPtrValueFromGslTempOwner) {
1111 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_member)
1112 << ExtendingDecl << DiagRange;
1113 SemaRef.
Diag(ExtendingDecl->getLocation(),
1114 diag::note_ref_or_ptr_member_declared_here)
1118 bool IsSubobjectMember = ExtendingEntity != InitEntity;
1121 ? diag::err_dangling_member
1122 : diag::warn_dangling_member)
1123 << ExtendingDecl << IsSubobjectMember << RK << DiagRange;
1128 Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {
1129 SemaRef.
Diag(ExtendingDecl->getLocation(),
1130 diag::note_lifetime_extending_member_declared_here)
1131 << RK << IsSubobjectMember;
1154 auto *DRE = dyn_cast<DeclRefExpr>(L);
1155 auto *VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) :
nullptr;
1163 ExtendingEntity ? ExtendingEntity->
getDecl() :
nullptr) {
1164 bool IsPointer = !
Member->getType()->isReferenceType();
1165 SemaRef.
Diag(DiagLoc,
1166 IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
1167 : diag::warn_bind_ref_member_to_parameter)
1168 << Member << VD << isa<ParmVarDecl>(VD) << DiagRange;
1170 diag::note_ref_or_ptr_member_declared_here)
1178 if (isa<MaterializeTemporaryExpr>(L)) {
1179 if (IsGslPtrValueFromGslTempOwner)
1180 SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1183 SemaRef.
Diag(DiagLoc, RK == RK_ReferenceBinding
1184 ? diag::warn_new_dangling_reference
1185 : diag::warn_new_dangling_initializer_list)
1186 << !InitEntity->
getParent() << DiagRange;
1194 case LK_StmtExprResult:
1195 if (
auto *DRE = dyn_cast<DeclRefExpr>(L)) {
1198 if (LK == LK_StmtExprResult)
1200 SemaRef.
Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1202 << isa<ParmVarDecl>(DRE->getDecl()) << DiagRange;
1203 }
else if (isa<BlockExpr>(L)) {
1204 SemaRef.
Diag(DiagLoc, diag::err_ret_local_block) << DiagRange;
1205 }
else if (isa<AddrLabelExpr>(L)) {
1208 if (LK == LK_StmtExprResult)
1210 SemaRef.
Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange;
1211 }
else if (
auto *CLE = dyn_cast<CompoundLiteralExpr>(L)) {
1212 SemaRef.
Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1223 SemaRef.
Diag(DiagLoc, diag::err_ret_local_temp_ref)
1226 SemaRef.
Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
1232 for (
unsigned I = 0; I !=
Path.size(); ++I) {
1233 auto Elem =
Path[I];
1235 switch (Elem.Kind) {
1236 case IndirectLocalPathEntry::AddressOf:
1237 case IndirectLocalPathEntry::LValToRVal:
1242 case IndirectLocalPathEntry::LifetimeBoundCall:
1243 case IndirectLocalPathEntry::TemporaryCopy:
1244 case IndirectLocalPathEntry::GslPointerInit:
1245 case IndirectLocalPathEntry::GslReferenceInit:
1246 case IndirectLocalPathEntry::GslPointerAssignment:
1250 case IndirectLocalPathEntry::DefaultInit: {
1251 auto *FD = cast<FieldDecl>(Elem.D);
1252 SemaRef.
Diag(FD->getLocation(),
1253 diag::note_init_with_default_member_initializer)
1258 case IndirectLocalPathEntry::VarInit: {
1259 const VarDecl *VD = cast<VarDecl>(Elem.D);
1266 case IndirectLocalPathEntry::LambdaCaptureInit:
1267 if (!Elem.Capture->capturesVariable())
1271 const ValueDecl *VD = Elem.Capture->getCapturedVar();
1272 SemaRef.
Diag(Elem.Capture->getLocation(),
1273 diag::note_lambda_capture_initializer)
1275 << (Elem.Capture->getCaptureKind() ==
LCK_ByRef) << VD
1287 if (EnableLifetimeWarnings && LK == LK_Assignment &&
1288 isRecordWithAttr<PointerAttr>(AEntity->
LHS->
getType()))
1289 Path.push_back({IndirectLocalPathEntry::GslPointerAssignment,
Init});
1291 if (
Init->isGLValue())
1294 EnableLifetimeWarnings);
1299 !InitEntity, EnableLifetimeWarnings);
1305 LifetimeKind LK = LTResult.getInt();
1310 nullptr, Init, EnableLifetimeWarnings);
1318 (EnableLifetimeWarnings &&
1319 isRecordWithAttr<PointerAttr>(Entity.
LHS->
getType()));
1325 nullptr, LK_Assignment, &Entity,
1326 Init, EnableLifetimeWarnings);
const LambdaCapture * Capture
enum clang::sema::@1658::IndirectLocalPathEntry::EntryKind Kind
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 static or instance method of a struct/union/class.
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...
DeclContext * getParent()
getParent - Returns the containing DeclContext.
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
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
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.
A (possibly-)qualified type.
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
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 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.
bool isLValueReferenceType() const
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
bool isInitCapture() const
Whether this variable is the implicit variable for a lambda init-capture.
Represents a variable declaration or definition.
static bool pathContainsInit(IndirectLocalPath &Path)
static void checkExprLifetimeImpl(Sema &SemaRef, const InitializedEntity *InitEntity, const InitializedEntity *ExtendingEntity, LifetimeKind LK, const AssignedEntity *AEntity, Expr *Init, bool EnableLifetimeWarnings)
static bool isVarOnPath(IndirectLocalPath &Path, VarDecl *VD)
void checkExprLifetime(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 isInStlNamespace(const Decl *D)
static void handleGslAnnotatedTypes(IndirectLocalPath &Path, Expr *Call, LocalVisitor Visit)
static bool isRecordWithAttr(QualType Type)
static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, Expr *Init, LocalVisitor Visit, bool RevisitSubinits, bool EnableLifetimeWarnings)
Visit the locals that would be reachable through an object initialized by the prvalue expression Init...
static bool shouldTrackFirstArgument(const FunctionDecl *FD)
static bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD)
static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, Expr *Init, ReferenceKind RK, LocalVisitor Visit, bool EnableLifetimeWarnings)
Visit the locals that would be reachable through a reference bound to the glvalue expression Init.
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...
PathLifetimeKind
Whether a path to an object supports lifetime extension.
@ NoExtend
Do not lifetime extend along this path.
@ ShouldExtend
We should lifetime-extend, but we don't because (due to technical limitations) we can't.
@ Extend
Lifetime-extend along this path.
static bool pathOnlyHandlesGslPointer(IndirectLocalPath &Path)
static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee)
static void visitLifetimeBoundArguments(IndirectLocalPath &Path, Expr *Call, LocalVisitor Visit)
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.
const FunctionProtoType * T
Describes an entity that is being assigned.