clang: lib/Sema/CheckExprLifetime.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
16#include "llvm/ADT/PointerIntPair.h"
17
19namespace {
20enum LifetimeKind {
21
22
23 LK_FullExpression,
24
25
26
27 LK_Extended,
28
29
30
31 LK_New,
32
33
34
35 LK_Return,
36
37
38
39 LK_MustTail,
40
41
42
43 LK_StmtExprResult,
44
45
46
47 LK_MemInitializer,
48
49
50
51
52 LK_Assignment,
53
54
55
56 LK_LifetimeCapture,
57};
58using LifetimeResult =
59 llvm::PointerIntPair<const InitializedEntity *, 3, LifetimeKind>;
60}
61
62
63
64
65static LifetimeResult
68
69 switch (Entity->getKind()) {
71
72 return {Entity, LK_Extended};
73
75
78
79
80
81
82
83
84
85
86
87
88
89
90
92 : LK_MemInitializer};
93
95
96
97 return {Entity, LK_Extended};
98
101
102
103
104 return {nullptr, LK_FullExpression};
105
107
108
109 return {nullptr, LK_FullExpression};
110
112
113
114
115 return {nullptr, LK_Return};
116
118
119
120 return {nullptr, LK_StmtExprResult};
121
123
124
125
126 return {nullptr, LK_New};
127
131
132
133
134 return {nullptr, LK_FullExpression};
135
137
139
141
144 return {InitField, LK_MemInitializer};
145
147
148
149
150
151 return {InitField, LK_MemInitializer};
152
158 return {nullptr, LK_FullExpression};
159
161
162 return {nullptr, LK_FullExpression};
163
165
166
167
168
169 return {nullptr, LK_FullExpression};
170 }
171
172 llvm_unreachable("unknown entity kind");
173}
174
175namespace {
176enum ReferenceKind {
177
178 RK_ReferenceBinding,
179
180
181 RK_StdInitializerList,
182};
183
184
185
186
187
188
189using Local = Expr *;
190
191
192
193
194struct IndirectLocalPathEntry {
195 enum EntryKind {
196 DefaultInit,
197 AddressOf,
198 VarInit,
199 LValToRVal,
200 LifetimeBoundCall,
201 TemporaryCopy,
202 LambdaCaptureInit,
203 GslReferenceInit,
204 GslPointerInit,
205 GslPointerAssignment,
206 DefaultArg,
207 ParenAggInit,
210 union {
213 };
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)
220};
221
223
224struct RevertToOldSizeRAII {
227 RevertToOldSizeRAII(IndirectLocalPath &Path) : Path(Path) {}
228 ~RevertToOldSizeRAII() { Path.resize(OldSize); }
229};
230
231using LocalVisitor = llvm::function_ref<bool(IndirectLocalPath &Path, Local L,
232 ReferenceKind RK)>;
233}
234
237 if (E.Kind == IndirectLocalPathEntry::VarInit && E.D == VD)
238 return true;
239 return false;
240}
241
243 return llvm::any_of(Path, [=](IndirectLocalPathEntry E) {
244 return E.Kind == IndirectLocalPathEntry::DefaultInit ||
245 E.Kind == IndirectLocalPathEntry::VarInit;
246 });
247}
248
250 Expr *Init, LocalVisitor Visit,
251 bool RevisitSubinits);
252
254 Expr *Init, ReferenceKind RK,
255 LocalVisitor Visit);
256
259 if (!RD)
260 return false;
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276 bool Result = RD->hasAttr<T>();
277
278 if (auto *CTSD = dyn_cast(RD))
279 Result |= CTSD->getSpecializedTemplate()->getTemplatedDecl()->hasAttr<T>();
280
282}
283
284
286
289}
290
291
292
293
296 if (!DC)
297 return false;
298 if (const auto *ND = dyn_cast(DC))
299 if (const IdentifierInfo *II = ND->getIdentifier()) {
300 StringRef Name = II->getName();
301 if (Name.size() >= 2 && Name.front() == '_' &&
302 (Name[1] == '_' || isUppercase(Name[1])))
303 return true;
304 }
305
307}
308
309
310
312 if (const auto *CTSD =
313 dyn_cast_if_present(Container)) {
314 if (!CTSD->hasAttr())
315 return false;
316 const auto &TAs = CTSD->getTemplateArgs();
319 }
320 return false;
321}
323 const auto *CTSD =
324 dyn_cast_if_present(Container);
325 if (!CTSD)
326 return false;
327 if (!CTSD->hasAttr())
328 return false;
329 const auto &TAs = CTSD->getTemplateArgs();
331 isRecordWithAttr(TAs[0].getAsType());
332}
333
334
336 if (const auto *CTSD =
337 dyn_cast_if_present(RD)) {
338 const auto &TAs = CTSD->getTemplateArgs();
340 RD->getName() == "initializer_list" && TAs.size() > 0 &&
343 }
344 return false;
345}
346
348 if (auto *Conv = dyn_cast_or_null(Callee))
349 if (isRecordWithAttr(Conv->getConversionType()) &&
350 Callee->getParent()->hasAttr())
351 return true;
353 return false;
354 if (!isRecordWithAttr(
355 Callee->getFunctionObjectParameterType()) &&
356 !isRecordWithAttr(Callee->getFunctionObjectParameterType()))
357 return false;
359 if (!Callee->getIdentifier())
360 return false;
361 return llvm::StringSwitch(Callee->getName())
362 .Cases("begin", "rbegin", "cbegin", "crbegin", true)
363 .Cases("end", "rend", "cend", "crend", true)
364 .Cases("c_str", "data", "get", true)
365
366 .Cases("find", "equal_range", "lower_bound", "upper_bound", true)
367 .Default(false);
368 }
369 if (Callee->getReturnType()->isReferenceType()) {
370 if (!Callee->getIdentifier()) {
371 auto OO = Callee->getOverloadedOperator();
372 if (!Callee->getParent()->hasAttr())
373 return false;
374 return OO == OverloadedOperatorKind::OO_Subscript ||
375 OO == OverloadedOperatorKind::OO_Star;
376 }
377 return llvm::StringSwitch(Callee->getName())
378 .Cases("front", "back", "at", "top", "value", true)
379 .Default(false);
380 }
381 return false;
382}
383
386 return false;
388 if (!FD->isInStdNamespace() || !RD || !RD->isInStdNamespace())
389 return false;
390 if (!RD->hasAttr() && !RD->hasAttr())
391 return false;
393 isRecordWithAttr(FD->getReturnType())) {
394 return llvm::StringSwitch(FD->getName())
395 .Cases("begin", "rbegin", "cbegin", "crbegin", true)
396 .Cases("end", "rend", "cend", "crend", true)
397 .Case("data", true)
398 .Default(false);
399 }
401 return llvm::StringSwitch(FD->getName())
402 .Cases("get", "any_cast", true)
403 .Default(false);
404 }
405 return false;
406}
407
408
409
411 if (!Ctor || Ctor->param_size() != 1)
412 return false;
413 const auto *ParamRefType =
415 if (!ParamRefType)
416 return false;
417
418
419 if (const auto *TST =
421 return TST->getTemplateName()
422 .getAsTemplateDecl()
423 ->getTemplatedDecl()
425 return false;
426}
427
428
429
430static bool
433
434
435
436 if (LHSRecordDecl->hasAttr())
437 return true;
438
441 return false;
442
443
444
445
446
447
448
449
450
451
452
455
456
457
458
459
460
462 return true;
463
464
465 if (!isRecordWithAttr(RHSArgType))
466 return false;
467
468
469
470
471
472
473
474
475
476
478 return false;
479
480
481
483 return true;
484
485
486
487
488
489
490
491
492
493 if (const auto *PrimaryCtorTemplate =
495 PrimaryCtorTemplate &&
497 PrimaryCtorTemplate->getTemplatedDecl()))) {
498 return false;
499 }
500
501
502 return true;
503}
504
505
506
507
508
516 auto *MD = dyn_cast(FD);
517 if (MD && MD->isCXXInstanceMember())
519 else
522 return true;
523 }
524 }
525 return false;
526}
527
531}
532
536 return cast_if_present(
538}
539
543 if (!TSI)
544 return false;
545
546
547
552 if (ATL.getAttrAs())
553 return true;
554 }
555
557}
558
559
561 LocalVisitor Visit) {
564
565 if (auto *CE = dyn_cast(Call)) {
566 Callee = CE->getDirectCallee();
567 Args = llvm::ArrayRef(CE->getArgs(), CE->getNumArgs());
568 } else {
569 auto *CCE = cast(Call);
570 Callee = CCE->getConstructor();
571 Args = llvm::ArrayRef(CCE->getArgs(), CCE->getNumArgs());
572 }
573 if (!Callee)
574 return;
575
576 bool EnableGSLAnalysis = !Callee->getASTContext().getDiagnostics().isIgnored(
577 diag::warn_dangling_lifetime_pointer, SourceLocation());
578 Expr *ObjectArg = nullptr;
579 if (isa(Call) && Callee->isCXXInstanceMember()) {
580 ObjectArg = Args[0];
581 Args = Args.slice(1);
582 } else if (auto *MCE = dyn_cast(Call)) {
583 ObjectArg = MCE->getImplicitObjectArgument();
584 }
585
586 auto VisitLifetimeBoundArg = [&](const Decl *D, Expr *Arg) {
587 Path.push_back({IndirectLocalPathEntry::LifetimeBoundCall, Arg, D});
588 if (Arg->isGLValue())
590 Visit);
591 else
593 Path.pop_back();
594 };
595 auto VisitGSLPointerArg = [&](const FunctionDecl *Callee, Expr *Arg) {
596
597
598 if (isa(Arg->IgnoreImpCasts()))
599 return;
600
601
602
603
604 if (const auto *Cond =
605 dyn_cast(Arg->IgnoreImpCasts());
607 return;
608
609 auto ReturnType = Callee->getReturnType();
610
611
612
613 if (ReturnType->isReferenceType() &&
614 !isRecordWithAttr(ReturnType->getPointeeType())) {
615 for (const IndirectLocalPathEntry &PE : llvm::reverse(Path)) {
616 if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit ||
617 PE.Kind == IndirectLocalPathEntry::LifetimeBoundCall)
618 continue;
619 if (PE.Kind == IndirectLocalPathEntry::GslPointerInit ||
620 PE.Kind == IndirectLocalPathEntry::GslPointerAssignment)
621 return;
622 break;
623 }
624 }
625 Path.push_back({ReturnType->isReferenceType()
626 ? IndirectLocalPathEntry::GslReferenceInit
627 : IndirectLocalPathEntry::GslPointerInit,
628 Arg, Callee});
629 if (Arg->isGLValue())
631 Visit);
632 else
634 Path.pop_back();
635 };
636
637 bool CheckCoroCall = false;
638 if (const auto *RD = Callee->getReturnType()->getAsRecordDecl()) {
639 CheckCoroCall = RD->hasAttr() &&
640 RD->hasAttr() &&
641 !Callee->hasAttr();
642 }
643
644 if (ObjectArg) {
645 bool CheckCoroObjArg = CheckCoroCall;
646
647 if (auto *LE = dyn_cast(ObjectArg->IgnoreImplicit());
648 LE && LE->captures().empty())
649 CheckCoroObjArg = false;
650
651
653 CheckCoroObjArg = false;
655 VisitLifetimeBoundArg(Callee, ObjectArg);
656 else if (EnableGSLAnalysis) {
657 if (auto *CME = dyn_cast(Callee);
659 VisitGSLPointerArg(Callee, ObjectArg);
660 }
661 }
662
664 unsigned NP = std::min(Callee->getNumParams(), CanonCallee->getNumParams());
665 for (unsigned I = 0, N = std::min(NP, Args.size()); I != N; ++I) {
666 Expr *Arg = Args[I];
667 RevertToOldSizeRAII RAII(Path);
668 if (auto *DAE = dyn_cast(Arg)) {
669 Path.push_back(
670 {IndirectLocalPathEntry::DefaultArg, DAE, DAE->getParam()});
671 Arg = DAE->getExpr();
672 }
673 if (CheckCoroCall ||
675 VisitLifetimeBoundArg(CanonCallee->getParamDecl(I), Arg);
676 else if (const auto *CaptureAttr =
678 CaptureAttr && isa(CanonCallee) &&
679 llvm::any_of(CaptureAttr->params(), [](int ArgIdx) {
680 return ArgIdx == LifetimeCaptureByAttr::THIS;
681 }))
682
683
684
685
686
687
688
689
690
691
692
693
694
695 VisitLifetimeBoundArg(CanonCallee->getParamDecl(I), Arg);
696 else if (EnableGSLAnalysis && I == 0) {
697
699 VisitGSLPointerArg(CanonCallee, Arg);
700 } else if (auto *Ctor = dyn_cast(Call);
702 VisitGSLPointerArg(Ctor->getConstructor(), Arg);
703 }
704 }
705 }
706}
707
708
709
711 Expr *Init, ReferenceKind RK,
712 LocalVisitor Visit) {
713 RevertToOldSizeRAII RAII(Path);
714
715
717 do {
719
720 if (auto *FE = dyn_cast(Init))
721 Init = FE->getSubExpr();
722
724
725 if (ILE->isTransparent())
726 Init = ILE->getInit(0);
727 }
728
729
730
731 Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
732
733
734
736 if (CE->getSubExpr()->isGLValue())
737 Init = CE->getSubExpr();
738
739
740
741 if (auto *ASE = dyn_cast(Init)) {
742 Init = ASE->getBase();
743 auto *ICE = dyn_cast(Init);
744 if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay)
745 Init = ICE->getSubExpr();
746 else
747
748
750 }
751
752
753
754 if (auto *DIE = dyn_cast(Init)) {
755 Path.push_back(
756 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
757 Init = DIE->getExpr();
758 }
759 } while (Init != Old);
760
761 if (auto *MTE = dyn_cast(Init)) {
762 if (Visit(Path, Local(MTE), RK))
764 }
765
766 if (auto *M = dyn_cast(Init)) {
767
768 if (auto *F = dyn_cast(M->getMemberDecl());
769 F && !F->getType()->isReferenceType())
771 }
772
773 if (isa(Init))
775
776 switch (Init->getStmtClass()) {
777 case Stmt::DeclRefExprClass: {
778
779
780 auto *DRE = cast(Init);
781 auto *VD = dyn_cast(DRE->getDecl());
782 if (VD && VD->hasLocalStorage() &&
783 !DRE->refersToEnclosingVariableOrCapture()) {
784 if (!VD->getType()->isReferenceType()) {
785 Visit(Path, Local(DRE), RK);
786 } else if (isa(DRE->getDecl())) {
787
788
789 break;
791 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
793 RK_ReferenceBinding, Visit);
794 }
795 }
796 break;
797 }
798
799 case Stmt::UnaryOperatorClass: {
800
801
802
804 if (U->getOpcode() == UO_Deref)
806 break;
807 }
808
809 case Stmt::ArraySectionExprClass: {
811 Path, cast(Init)->getBase(), Visit, true);
812 break;
813 }
814
815 case Stmt::ConditionalOperatorClass:
816 case Stmt::BinaryConditionalOperatorClass: {
818 if (->getTrueExpr()->getType()->isVoidType())
820 if (->getFalseExpr()->getType()->isVoidType())
822 break;
823 }
824
825 case Stmt::CompoundLiteralExprClass: {
826 if (auto *CLE = dyn_cast(Init)) {
827 if (!CLE->isFileScope())
828 Visit(Path, Local(CLE), RK);
829 }
830 break;
831 }
832
833
834
835 default:
836 break;
837 }
838}
839
840
841
843 Expr *Init, LocalVisitor Visit,
844 bool RevisitSubinits) {
845 RevertToOldSizeRAII RAII(Path);
846
848 do {
850
851
852
853 if (auto *DIE = dyn_cast(Init)) {
854 Path.push_back(
855 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
856 Init = DIE->getExpr();
857 }
858
859 if (auto *FE = dyn_cast(Init))
860 Init = FE->getSubExpr();
861
862
863 Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
864
866 Init = BTE->getSubExpr();
867
869
870
871 if (auto *CE = dyn_cast(Init)) {
872 switch (CE->getCastKind()) {
873 case CK_LValueToRValue:
874
875
876 Path.push_back({IndirectLocalPathEntry::LValToRVal, CE});
878 Path, Init, RK_ReferenceBinding,
879 [&](IndirectLocalPath &Path, Local L, ReferenceKind RK) -> bool {
880 if (auto *DRE = dyn_cast(L)) {
881 auto *VD = dyn_cast(DRE->getDecl());
882 if (VD && VD->getType().isConstQualified() && VD->getInit() &&
884 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
886 true);
887 }
888 } else if (auto *MTE = dyn_cast(L)) {
889 if (MTE->getType().isConstQualified())
891 Visit, true);
892 }
893 return false;
894 });
895
896
897
898
899
900 case CK_NoOp:
901 case CK_BitCast:
902 case CK_BaseToDerived:
903 case CK_DerivedToBase:
904 case CK_UncheckedDerivedToBase:
905 case CK_Dynamic:
906 case CK_ToUnion:
907 case CK_UserDefinedConversion:
908 case CK_ConstructorConversion:
909 case CK_IntegralToPointer:
910 case CK_PointerToIntegral:
911 case CK_VectorSplat:
912 case CK_IntegralCast:
913 case CK_CPointerToObjCPointerCast:
914 case CK_BlockPointerToObjCPointerCast:
915 case CK_AnyPointerToBlockPointerCast:
916 case CK_AddressSpaceConversion:
917 break;
918
919 case CK_ArrayToPointerDecay:
920
921
922 Path.push_back({IndirectLocalPathEntry::AddressOf, CE});
924 Path, CE->getSubExpr(), RK_ReferenceBinding, Visit);
925
926 default:
927 return;
928 }
929
930 Init = CE->getSubExpr();
931 }
932 } while (Old != Init);
933
934
935
936
937 if (auto *ILE = dyn_cast(Init))
939 RK_StdInitializerList, Visit);
940
942
943
944
945 if (!RevisitSubinits)
946 return;
947
948 if (ILE->isTransparent())
950 RevisitSubinits);
951
952 if (ILE->getType()->isArrayType()) {
953 for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
955 RevisitSubinits);
956 return;
957 }
958
959 if (CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) {
960 assert(RD->isAggregate() && "aggregate init on non-aggregate");
961
962
963
964
965 if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
966 ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
968 RK_ReferenceBinding, Visit);
969 else {
970 unsigned Index = 0;
971 for (; Index < RD->getNumBases() && Index < ILE->getNumInits(); ++Index)
973 RevisitSubinits);
974 for (const auto *I : RD->fields()) {
975 if (Index >= ILE->getNumInits())
976 break;
977 if (I->isUnnamedBitField())
978 continue;
979 Expr *SubInit = ILE->getInit(Index);
980 if (I->getType()->isReferenceType())
982 RK_ReferenceBinding, Visit);
983 else
984
985
986
988 RevisitSubinits);
989 ++Index;
990 }
991 }
992 }
993 return;
994 }
995
996
997
998 if (auto *LE = dyn_cast(Init)) {
1000 for (Expr *E : LE->capture_inits()) {
1001 assert(CapI != LE->capture_end());
1003 if ()
1004 continue;
1006 Path.push_back({IndirectLocalPathEntry::LambdaCaptureInit, E, &Cap});
1007 if (E->isGLValue())
1009 Visit);
1010 else
1013 Path.pop_back();
1014 }
1015 }
1016
1017
1018
1019 if (auto *CCE = dyn_cast(Init)) {
1020 if (CCE->getConstructor()->isCopyOrMoveConstructor()) {
1021 if (auto *MTE = dyn_cast(CCE->getArg(0))) {
1022 Expr *Arg = MTE->getSubExpr();
1023 Path.push_back({IndirectLocalPathEntry::TemporaryCopy, Arg,
1024 CCE->getConstructor()});
1026 Path.pop_back();
1027 }
1028 }
1029 }
1030
1031 if (isa(Init) || isa(Init))
1033
1034 if (auto *CPE = dyn_cast(Init)) {
1035 RevertToOldSizeRAII RAII(Path);
1036 Path.push_back({IndirectLocalPathEntry::ParenAggInit, CPE});
1037 for (auto *I : CPE->getInitExprs()) {
1038 if (I->isGLValue())
1040 Visit);
1041 else
1043 }
1044 }
1045 switch (Init->getStmtClass()) {
1046 case Stmt::UnaryOperatorClass: {
1047 auto *UO = cast(Init);
1048
1049
1050 if (UO->getOpcode() == UO_AddrOf) {
1051
1052
1053
1054 if (isa(UO->getSubExpr()))
1055 return;
1056
1057 Path.push_back({IndirectLocalPathEntry::AddressOf, UO});
1059 RK_ReferenceBinding, Visit);
1060 }
1061 break;
1062 }
1063
1064 case Stmt::BinaryOperatorClass: {
1065
1066 auto *BO = cast(Init);
1068 if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub))
1069 break;
1070
1071 if (BO->getLHS()->getType()->isPointerType())
1073 else if (BO->getRHS()->getType()->isPointerType())
1075 break;
1076 }
1077
1078 case Stmt::ConditionalOperatorClass:
1079 case Stmt::BinaryConditionalOperatorClass: {
1081
1082
1083 if (->getTrueExpr()->getType()->isVoidType())
1085 if (->getFalseExpr()->getType()->isVoidType())
1087 break;
1088 }
1089
1090 case Stmt::BlockExprClass:
1091 if (cast(Init)->getBlockDecl()->hasCaptures()) {
1092
1093 Visit(Path, Local(cast(Init)), RK_ReferenceBinding);
1094 }
1095 break;
1096
1097 case Stmt::AddrLabelExprClass:
1098
1099 Visit(Path, Local(cast(Init)), RK_ReferenceBinding);
1100 break;
1101
1102 default:
1103 break;
1104 }
1105}
1106
1107
1109
1111
1114
1115
1116
1119 for (auto Elem : Path) {
1120 if (Elem.Kind == IndirectLocalPathEntry::DefaultInit)
1122 if (Elem.Kind != IndirectLocalPathEntry::LambdaCaptureInit)
1124 }
1126}
1127
1128
1131 for (unsigned N = Path.size(); I != N; ++I) {
1133 case IndirectLocalPathEntry::AddressOf:
1134 case IndirectLocalPathEntry::LValToRVal:
1135 case IndirectLocalPathEntry::LifetimeBoundCall:
1136 case IndirectLocalPathEntry::TemporaryCopy:
1137 case IndirectLocalPathEntry::GslReferenceInit:
1138 case IndirectLocalPathEntry::GslPointerInit:
1139 case IndirectLocalPathEntry::GslPointerAssignment:
1140 case IndirectLocalPathEntry::ParenAggInit:
1141
1142
1143 break;
1144
1145 case IndirectLocalPathEntry::VarInit:
1146 if (cast(Path[I].D)->isImplicit())
1148 [[fallthrough]];
1149 case IndirectLocalPathEntry::DefaultInit:
1150 return Path[I].E->getSourceRange();
1151
1152 case IndirectLocalPathEntry::LambdaCaptureInit:
1153 if ([I].Capture->capturesVariable())
1154 continue;
1155 return Path[I].E->getSourceRange();
1156
1157 case IndirectLocalPathEntry::DefaultArg:
1158 return cast(Path[I].E)->getUsedLocation();
1159 }
1160 }
1161 return E->getSourceRange();
1162}
1163
1165 for (const auto &It : llvm::reverse(Path)) {
1166 switch (It.Kind) {
1167 case IndirectLocalPathEntry::VarInit:
1168 case IndirectLocalPathEntry::AddressOf:
1169 case IndirectLocalPathEntry::LifetimeBoundCall:
1170 continue;
1171 case IndirectLocalPathEntry::GslPointerInit:
1172 case IndirectLocalPathEntry::GslReferenceInit:
1173 case IndirectLocalPathEntry::GslPointerAssignment:
1174 return true;
1175 default:
1176 return false;
1177 }
1178 }
1179 return false;
1180}
1181
1183
1185
1186
1188
1190
1192};
1193
1194
1196 Local L) {
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210 if (Path.back().Kind == IndirectLocalPathEntry::LifetimeBoundCall) {
1211
1213 llvm::dyn_cast_or_null(Path.back().D);
1214
1215 if (const auto *PD = llvm::dyn_cast(Path.back().D))
1216 FD = llvm::dyn_cast(PD->getDeclContext());
1217
1218 if (isa_and_present(FD)) {
1219
1220
1221
1223 }
1224
1225
1226
1227 if (FD &&
1232
1234 }
1235
1236 if (isa(L)) {
1237
1238
1239
1240
1241
1245 }
1246
1247
1248 auto *MTE = dyn_cast(L);
1249
1250 bool IsGslPtrValueFromGslTempOwner =
1251 MTE && !MTE->getExtendingDecl() &&
1252 isRecordWithAttr(MTE->getType());
1253
1254
1255
1256
1257 if (!IsGslPtrValueFromGslTempOwner)
1258 return Skip;
1260}
1261
1266}
1267
1271 diag::warn_dangling_lifetime_pointer_assignment, SourceLocation());
1272 return (EnableGSLAssignmentWarnings &&
1273 (isRecordWithAttr(Entity.LHS->getType()) ||
1275}
1276
1277static void
1282 assert(!AEntity || LK == LK_Assignment);
1283 assert(!CapEntity || LK == LK_LifetimeCapture);
1284 assert(!InitEntity || (LK != LK_Assignment && LK != LK_LifetimeCapture));
1285
1286
1287 if (LK == LK_FullExpression)
1288 return;
1289
1290
1291
1292 auto TemporaryVisitor = [&](const IndirectLocalPath &Path, Local L,
1293 ReferenceKind RK) -> bool {
1296
1297 auto *MTE = dyn_cast(L);
1298
1299 bool IsGslPtrValueFromGslTempOwner = true;
1302 return false;
1304 return true;
1306 IsGslPtrValueFromGslTempOwner = false;
1307 LLVM_FALLTHROUGH;
1309 break;
1310 }
1311
1312 switch (LK) {
1313 case LK_FullExpression:
1314 llvm_unreachable("already handled this");
1315
1316 case LK_Extended: {
1317 if (!MTE) {
1318
1319
1320
1321
1322
1323 return false;
1324 }
1325
1326 if (IsGslPtrValueFromGslTempOwner && DiagLoc.isValid()) {
1327 SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1328 << DiagRange;
1329 return false;
1330 }
1331
1334
1335
1336 MTE->setExtendingDecl(ExtendingEntity->getDecl(),
1338
1339 return true;
1340
1342
1343
1344
1346 return false;
1347
1348 SemaRef.Diag(DiagLoc, diag::warn_dangling_variable)
1349 << RK << !InitEntity->getParent()
1351 << ExtendingEntity->getDecl() << Init->isGLValue() << DiagRange;
1352 break;
1353 }
1354 break;
1355 }
1356
1357 case LK_LifetimeCapture: {
1358
1359
1360 if (!MTE)
1361 return false;
1362 if (CapEntity->Entity)
1363 SemaRef.Diag(DiagLoc, diag::warn_dangling_reference_captured)
1364 << CapEntity->Entity << DiagRange;
1365 else
1366 SemaRef.Diag(DiagLoc, diag::warn_dangling_reference_captured_by_unknown)
1367 << DiagRange;
1368 return false;
1369 }
1370
1371 case LK_Assignment: {
1373 return false;
1374 if (IsGslPtrValueFromGslTempOwner)
1375 SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_assignment)
1376 << AEntity->LHS << DiagRange;
1377 else
1378 SemaRef.Diag(DiagLoc, diag::warn_dangling_pointer_assignment)
1380 << DiagRange;
1381 return false;
1382 }
1383 case LK_MemInitializer: {
1384 if (MTE) {
1385
1386
1387
1388 if (auto *ExtendingDecl =
1389 ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
1390 if (IsGslPtrValueFromGslTempOwner) {
1391 SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_member)
1392 << ExtendingDecl << DiagRange;
1393 SemaRef.Diag(ExtendingDecl->getLocation(),
1394 diag::note_ref_or_ptr_member_declared_here)
1395 << true;
1396 return false;
1397 }
1398 bool IsSubobjectMember = ExtendingEntity != InitEntity;
1401 ? diag::err_dangling_member
1402 : diag::warn_dangling_member)
1403 << ExtendingDecl << IsSubobjectMember << RK << DiagRange;
1404
1405
1406
1407 if (Path.empty() ||
1408 Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {
1409 SemaRef.Diag(ExtendingDecl->getLocation(),
1410 diag::note_lifetime_extending_member_declared_here)
1411 << RK << IsSubobjectMember;
1412 }
1413 } else {
1414
1415
1416
1417
1418
1419
1420 return false;
1421 }
1422 } else {
1423
1424
1425
1427 return false;
1428
1429 auto *DRE = dyn_cast(L);
1430
1431
1432 if (DRE && isRecordWithAttr(DRE->getType()))
1433 return false;
1434
1435 auto *VD = DRE ? dyn_cast(DRE->getDecl()) : nullptr;
1436 if (!VD) {
1437
1438
1439 return false;
1440 }
1441
1443 ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
1444 bool IsPointer = ->getType()->isReferenceType();
1445 SemaRef.Diag(DiagLoc,
1446 IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
1447 : diag::warn_bind_ref_member_to_parameter)
1448 << Member << VD << isa(VD) << DiagRange;
1450 diag::note_ref_or_ptr_member_declared_here)
1452 }
1453 }
1454 break;
1455 }
1456
1457 case LK_New:
1458 if (isa(L)) {
1459 if (IsGslPtrValueFromGslTempOwner)
1460 SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1461 << DiagRange;
1462 else
1463 SemaRef.Diag(DiagLoc, RK == RK_ReferenceBinding
1464 ? diag::warn_new_dangling_reference
1465 : diag::warn_new_dangling_initializer_list)
1466 << !InitEntity->getParent() << DiagRange;
1467 } else {
1468
1469 return false;
1470 }
1471 break;
1472
1473 case LK_Return:
1474 case LK_MustTail:
1475 case LK_StmtExprResult:
1476 if (auto *DRE = dyn_cast(L)) {
1477
1478
1479 if (LK == LK_StmtExprResult)
1480 return false;
1481 SemaRef.Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1483 << isa(DRE->getDecl()) << (LK == LK_MustTail)
1484 << DiagRange;
1485 } else if (isa(L)) {
1486 SemaRef.Diag(DiagLoc, diag::err_ret_local_block) << DiagRange;
1487 } else if (isa(L)) {
1488
1489
1490 if (LK == LK_StmtExprResult)
1491 return false;
1492 SemaRef.Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange;
1493 } else if (auto *CLE = dyn_cast(L)) {
1494 SemaRef.Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1496 << 2 << (LK == LK_MustTail) << DiagRange;
1497 } else {
1498
1499
1500
1501
1502
1503 if (SemaRef.getLangOpts().CPlusPlus26 &&
1505 SemaRef.Diag(DiagLoc, diag::err_ret_local_temp_ref)
1507 else if (LK == LK_MustTail)
1508 SemaRef.Diag(DiagLoc, diag::warn_musttail_local_temp_addr_ref)
1510 else
1511 SemaRef.Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
1513 }
1514 break;
1515 }
1516
1517 for (unsigned I = 0; I != Path.size(); ++I) {
1518 auto Elem = Path[I];
1519
1520 switch (Elem.Kind) {
1521 case IndirectLocalPathEntry::AddressOf:
1522 case IndirectLocalPathEntry::LValToRVal:
1523 case IndirectLocalPathEntry::ParenAggInit:
1524
1525
1526 break;
1527
1528 case IndirectLocalPathEntry::LifetimeBoundCall:
1529 case IndirectLocalPathEntry::TemporaryCopy:
1530 case IndirectLocalPathEntry::GslPointerInit:
1531 case IndirectLocalPathEntry::GslReferenceInit:
1532 case IndirectLocalPathEntry::GslPointerAssignment:
1533
1534 break;
1535
1536 case IndirectLocalPathEntry::DefaultInit: {
1537 auto *FD = cast(Elem.D);
1538 SemaRef.Diag(FD->getLocation(),
1539 diag::note_init_with_default_member_initializer)
1541 break;
1542 }
1543
1544 case IndirectLocalPathEntry::VarInit: {
1545 const VarDecl *VD = cast(Elem.D);
1546 SemaRef.Diag(VD->getLocation(), diag::note_local_var_initializer)
1549 break;
1550 }
1551
1552 case IndirectLocalPathEntry::LambdaCaptureInit: {
1553 if (!Elem.Capture->capturesVariable())
1554 break;
1555
1556
1557 const ValueDecl *VD = Elem.Capture->getCapturedVar();
1558 SemaRef.Diag(Elem.Capture->getLocation(),
1559 diag::note_lambda_capture_initializer)
1560 << VD << VD->isInitCapture() << Elem.Capture->isExplicit()
1561 << (Elem.Capture->getCaptureKind() == LCK_ByRef) << VD
1563 break;
1564 }
1565
1566 case IndirectLocalPathEntry::DefaultArg: {
1567 const auto *DAE = cast(Elem.E);
1568 const ParmVarDecl *Param = DAE->getParam();
1570 diag::note_init_with_default_argument)
1572 break;
1573 }
1574 }
1575 }
1576
1577
1578
1579 return false;
1580 };
1581
1583 switch (LK) {
1584 case LK_Assignment: {
1586 Path.push_back(
1588 ? IndirectLocalPathEntry::LifetimeBoundCall
1589 : IndirectLocalPathEntry::GslPointerAssignment,
1591 break;
1592 }
1593 case LK_LifetimeCapture: {
1595 Path.push_back({IndirectLocalPathEntry::GslPointerInit, Init});
1596 break;
1597 }
1598 default:
1599 break;
1600 }
1601
1602 if (Init->isGLValue())
1604 TemporaryVisitor);
1605 else
1607 Path, Init, TemporaryVisitor,
1608
1609 !InitEntity);
1610}
1611
1613 Expr *Init) {
1615 LifetimeKind LK = LTResult.getInt();
1616 const InitializedEntity *ExtendingEntity = LTResult.getPointer();
1618 nullptr, nullptr, Init);
1619}
1620
1624 nullptr, nullptr, Init);
1625}
1626
1628 Expr *Init) {
1630 diag::warn_dangling_pointer_assignment, SourceLocation());
1631 bool RunAnalysis = (EnableDanglingPointerAssignment &&
1634
1635 if (!RunAnalysis)
1636 return;
1637
1639 nullptr, LK_Assignment, &Entity,
1640 nullptr, Init);
1641}
1642
1644 Expr *Init) {
1648 diag::warn_dangling_reference_captured_by_unknown, SourceLocation()))
1649 return;
1651 nullptr, LK_LifetimeCapture,
1652 nullptr,
1653 &Entity, Init);
1654}
1655
1656}
enum clang::sema::@1725::IndirectLocalPathEntry::EntryKind Kind
const LambdaCapture * Capture
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
bool hasSameType(QualType T1, QualType T2) const
Determine whether the given types T1 and T2 are equivalent.
QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const
Return the uniqued reference to the type for an lvalue reference to the specified type.
Type source information for an attributed type.
TypeLoc getModifiedLoc() const
The modified type, which is generally canonically different from the attribute type.
Represents binding an expression to a temporary.
Represents a call to a C++ constructor.
Expr * getArg(unsigned Arg)
Return the specified argument.
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
Represents a C++ constructor within a class.
Represents a static or instance method of a struct/union/class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Represents a C++ struct/union/class.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
bool isStdNamespace() const
Decl - This represents one declaration (or definition), e.g.
bool isInStdNamespace() const
ASTContext & getASTContext() const LLVM_READONLY
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
SourceLocation getLocation() const
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
TypeSourceInfo * getTypeSourceInfo() const
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
This represents one expression.
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
QualType getReturnType() const
FunctionTemplateDecl * getPrimaryTemplate() const
Retrieve the primary template that this function template specialization either specializes or was in...
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
size_t param_size() const
One of these records is kept for each identifier that is lexed.
Describes an C or C++ initializer list.
Describes an entity that is being initialized.
EntityKind getKind() const
Determine the kind of initialization.
unsigned allocateManglingNumber() const
QualType getType() const
Retrieve type being initialized.
ValueDecl * getDecl() const
Retrieve the variable, parameter, or field being initialized.
const InitializedEntity * getParent() const
Retrieve the parent of the entity being initialized, when the initialization itself is occurring with...
@ EK_Variable
The entity being initialized is a variable.
@ EK_Temporary
The entity being initialized is a temporary object.
@ EK_Binding
The entity being initialized is a structured binding of a decomposition declaration.
@ EK_BlockElement
The entity being initialized is a field of block descriptor for the copied-in c++ object.
@ EK_Parameter_CF_Audited
The entity being initialized is a function parameter; function is member of group of audited CF APIs.
@ EK_LambdaToBlockConversionBlockElement
The entity being initialized is a field of block descriptor for the copied-in lambda object that's us...
@ EK_Member
The entity being initialized is a non-static data member subobject.
@ EK_Base
The entity being initialized is a base member subobject.
@ EK_Result
The entity being initialized is the result of a function call.
@ EK_TemplateParameter
The entity being initialized is a non-type template parameter.
@ EK_StmtExprResult
The entity being initialized is the result of a statement expression.
@ EK_ParenAggInitMember
The entity being initialized is a non-static data member subobject of an object initialized via paren...
@ EK_VectorElement
The entity being initialized is an element of a vector.
@ EK_New
The entity being initialized is an object (or array of objects) allocated via new.
@ EK_CompoundLiteralInit
The entity being initialized is the initializer for a compound literal.
@ EK_Parameter
The entity being initialized is a function parameter.
@ EK_Delegating
The initialization is being done by a delegating constructor.
@ EK_ComplexElement
The entity being initialized is the real or imaginary part of a complex number.
@ EK_ArrayElement
The entity being initialized is an element of an array.
@ EK_LambdaCapture
The entity being initialized is the field that captures a variable in a lambda.
@ EK_Exception
The entity being initialized is an exception object that is being thrown.
@ EK_RelatedResult
The entity being implicitly initialized back to the formal result type.
bool isDefaultMemberInitializer() const
Is this the default member initializer of a member (specified inside the class definition)?
Describes the capture of a variable or of this, or of a C++1y init-capture.
bool capturesVariable() const
Determine whether this capture handles a variable.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Represents a parameter to a function.
SourceRange getDefaultArgRange() const
Retrieve the source range that covers the entire default argument.
A (possibly-)qualified type.
Represents a struct/union/class.
decl_type * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
Base for LValueReferenceType and RValueReferenceType.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Sema - This implements semantic analysis and AST building for C.
DiagnosticsEngine & getDiagnostics() const
const LangOptions & getLangOpts() const
static bool CanBeGetReturnObject(const FunctionDecl *FD)
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
@ Type
The template argument is a type.
Represents a type template specialization; the template must be a class template, a type alias templa...
Base wrapper for a particular "section" of type source info.
T getAsAdjusted() const
Convert to the specified TypeLoc type, returning a null TypeLoc if this TypeLoc is not of the desired...
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool hasAttr(attr::Kind AK) const
Determine whether this type had the specified attribute applied to it (looking through top-level type...
bool isPointerType() const
bool isReferenceType() const
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isLValueReferenceType() const
const T * getAs() const
Member-template getAs'.
bool isNullPtrType() const
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
bool isInitCapture() const
Whether this variable is the implicit variable for a lambda init-capture.
Represents a variable declaration or definition.
static bool isStdInitializerListOfPointer(const RecordDecl *RD)
bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD)
static void checkExprLifetimeImpl(Sema &SemaRef, const InitializedEntity *InitEntity, const InitializedEntity *ExtendingEntity, LifetimeKind LK, const AssignedEntity *AEntity, const CapturingEntity *CapEntity, Expr *Init)
static bool shouldRunGSLAssignmentAnalysis(const Sema &SemaRef, const AssignedEntity &Entity)
static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, Expr *Init, ReferenceKind RK, LocalVisitor Visit)
Visit the locals that would be reachable through a reference bound to the glvalue expression Init.
void checkExprLifetimeMustTailArg(Sema &SemaRef, const InitializedEntity &Entity, Expr *Init)
Check that the lifetime of the given expr (and its subobjects) is sufficient, assuming that it is pas...
static bool pathOnlyHandlesGslPointer(const IndirectLocalPath &Path)
static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, Expr *Init, LocalVisitor Visit, bool RevisitSubinits)
Visit the locals that would be reachable through an object initialized by the prvalue expression Init...
static bool isNormalAssignmentOperator(const FunctionDecl *FD)
static bool isInStlNamespace(const Decl *D)
static bool isRecordWithAttr(QualType Type)
bool isGLSPointerType(QualType QT)
static bool shouldTrackFirstArgument(const FunctionDecl *FD)
static bool isContainerOfOwner(const RecordDecl *Container)
static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I, Expr *E)
Find the range for the first interesting entry in the path at or after I.
static AnalysisResult analyzePathForGSLPointer(const IndirectLocalPath &Path, Local L)
static LifetimeResult getEntityLifetime(const InitializedEntity *Entity, const InitializedEntity *InitField=nullptr)
Determine the declaration which an initialized entity ultimately refers to, for the purpose of lifeti...
static const FunctionDecl * getDeclWithMergedLifetimeBoundAttrs(const FunctionDecl *FD)
static bool isContainerOfPointer(const RecordDecl *Container)
void checkInitLifetime(Sema &SemaRef, const InitializedEntity &Entity, Expr *Init)
Check that the lifetime of the given expr (and its subobjects) is sufficient for initializing the ent...
static bool isCopyLikeConstructor(const CXXConstructorDecl *Ctor)
void checkAssignmentLifetime(Sema &SemaRef, const AssignedEntity &Entity, Expr *Init)
Check that the lifetime of the given expr (and its subobjects) is sufficient for assigning to the ent...
static bool shouldTrackFirstArgumentForConstructor(const CXXConstructExpr *Ctor)
PathLifetimeKind
Whether a path to an object supports lifetime extension.
@ NoExtend
Do not lifetime extend along this path.
@ Extend
Lifetime-extend along this path.
static bool isVarOnPath(const IndirectLocalPath &Path, VarDecl *VD)
static bool pathContainsInit(const IndirectLocalPath &Path)
static bool isPointerLikeType(QualType QT)
static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call, LocalVisitor Visit)
void checkCaptureByLifetime(Sema &SemaRef, const CapturingEntity &Entity, Expr *Init)
static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee)
static bool isAssignmentOperatorLifetimeBound(const CXXMethodDecl *CMD)
static PathLifetimeKind shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path)
Determine whether this is an indirect path to a temporary that we are supposed to lifetime-extend alo...
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
bool isCompoundAssignmentOperator(OverloadedOperatorKind Kind)
Determine if this is a compound assignment operator.
LLVM_READONLY bool isUppercase(unsigned char c)
Return true if this character is an uppercase ASCII letter: [A-Z].
@ LCK_ByRef
Capturing by reference.
@ Result
The result type of a method or function.
const FunctionProtoType * T
Describes an entity that is being assigned.
CXXMethodDecl * AssignmentOperator