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 MemberExpr,
204 GslReferenceInit,
205 GslPointerInit,
206 GslPointerAssignment,
207 DefaultArg,
208 ParenAggInit,
211 union {
214 };
215 IndirectLocalPathEntry() {}
216 IndirectLocalPathEntry(EntryKind K, Expr *E) : Kind(K), E(E) {}
217 IndirectLocalPathEntry(EntryKind K, Expr *E, const Decl *D)
219 IndirectLocalPathEntry(EntryKind K, Expr *E, const LambdaCapture *Capture)
221};
222
224
225struct RevertToOldSizeRAII {
228 RevertToOldSizeRAII(IndirectLocalPath &Path) : Path(Path) {}
229 ~RevertToOldSizeRAII() { Path.resize(OldSize); }
230};
231
232using LocalVisitor = llvm::function_ref<bool(IndirectLocalPath &Path, Local L,
233 ReferenceKind RK)>;
234}
235
238 if (E.Kind == IndirectLocalPathEntry::VarInit && E.D == VD)
239 return true;
240 return false;
241}
242
244 return llvm::any_of(Path, [=](IndirectLocalPathEntry E) {
245 return E.Kind == IndirectLocalPathEntry::DefaultInit ||
246 E.Kind == IndirectLocalPathEntry::VarInit;
247 });
248}
249
251 Expr *Init, LocalVisitor Visit,
252 bool RevisitSubinits);
253
255 Expr *Init, ReferenceKind RK,
256 LocalVisitor Visit);
257
260 if (!RD)
261 return false;
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277 bool Result = RD->hasAttr<T>();
278
279 if (auto *CTSD = dyn_cast(RD))
280 Result |= CTSD->getSpecializedTemplate()->getTemplatedDecl()->hasAttr<T>();
281
283}
284
285
287
290}
291
292
293
294
297 if (!DC)
298 return false;
299 if (const auto *ND = dyn_cast(DC))
300 if (const IdentifierInfo *II = ND->getIdentifier()) {
301 StringRef Name = II->getName();
302 if (Name.size() >= 2 && Name.front() == '_' &&
303 (Name[1] == '_' || isUppercase(Name[1])))
304 return true;
305 }
306
308}
309
310
311
313 if (const auto *CTSD =
314 dyn_cast_if_present(Container)) {
315 if (!CTSD->hasAttr())
316 return false;
317 const auto &TAs = CTSD->getTemplateArgs();
320 }
321 return false;
322}
324 const auto *CTSD =
325 dyn_cast_if_present(Container);
326 if (!CTSD)
327 return false;
328 if (!CTSD->hasAttr())
329 return false;
330 const auto &TAs = CTSD->getTemplateArgs();
332 isRecordWithAttr(TAs[0].getAsType());
333}
334
335
337 if (const auto *CTSD =
338 dyn_cast_if_present(RD)) {
339 const auto &TAs = CTSD->getTemplateArgs();
341 RD->getName() == "initializer_list" && TAs.size() > 0 &&
344 }
345 return false;
346}
347
349 if (auto *Conv = dyn_cast_or_null(Callee))
350 if (isRecordWithAttr(Conv->getConversionType()) &&
351 Callee->getParent()->hasAttr())
352 return true;
354 return false;
355 if (!isRecordWithAttr(
356 Callee->getFunctionObjectParameterType()) &&
357 !isRecordWithAttr(Callee->getFunctionObjectParameterType()))
358 return false;
360 if (!Callee->getIdentifier())
361 return false;
362 return llvm::StringSwitch(Callee->getName())
363 .Cases("begin", "rbegin", "cbegin", "crbegin", true)
364 .Cases("end", "rend", "cend", "crend", true)
365 .Cases("c_str", "data", "get", true)
366
367 .Cases("find", "equal_range", "lower_bound", "upper_bound", true)
368 .Default(false);
369 }
370 if (Callee->getReturnType()->isReferenceType()) {
371 if (!Callee->getIdentifier()) {
372 auto OO = Callee->getOverloadedOperator();
373 if (!Callee->getParent()->hasAttr())
374 return false;
375 return OO == OverloadedOperatorKind::OO_Subscript ||
376 OO == OverloadedOperatorKind::OO_Star;
377 }
378 return llvm::StringSwitch(Callee->getName())
379 .Cases("front", "back", "at", "top", "value", true)
380 .Default(false);
381 }
382 return false;
383}
384
387 return false;
389 if (!FD->isInStdNamespace() || !RD || !RD->isInStdNamespace())
390 return false;
391 if (!RD->hasAttr() && !RD->hasAttr())
392 return false;
394 isRecordWithAttr(FD->getReturnType())) {
395 return llvm::StringSwitch(FD->getName())
396 .Cases("begin", "rbegin", "cbegin", "crbegin", true)
397 .Cases("end", "rend", "cend", "crend", true)
398 .Case("data", true)
399 .Default(false);
400 }
402 return llvm::StringSwitch(FD->getName())
403 .Cases("get", "any_cast", true)
404 .Default(false);
405 }
406 return false;
407}
408
409
410
412 if (!Ctor || Ctor->param_size() != 1)
413 return false;
414 const auto *ParamRefType =
416 if (!ParamRefType)
417 return false;
418
419
420 if (const auto *TST =
422 return TST->getTemplateName()
423 .getAsTemplateDecl()
424 ->getTemplatedDecl()
426 return false;
427}
428
429
430
431static bool
434
435
436
437 if (LHSRecordDecl->hasAttr())
438 return true;
439
442 return false;
443
444
445
446
447
448
449
450
451
452
453
456
457
458
459
460
461
463 return true;
464
465
466 if (!isRecordWithAttr(RHSArgType))
467 return false;
468
469
470
471
472
473
474
475
476
477
479 return false;
480
481
482
484 return true;
485
486
487
488
489
490
491
492
493
494 if (const auto *PrimaryCtorTemplate =
496 PrimaryCtorTemplate &&
498 PrimaryCtorTemplate->getTemplatedDecl()))) {
499 return false;
500 }
501
502
503 return true;
504}
505
506
507
508
509
517 auto *MD = dyn_cast(FD);
518 if (MD && MD->isCXXInstanceMember())
519 LHST = Ctx.getLValueReferenceType(MD->getFunctionObjectParameterType());
520 else
522 if (Ctx.hasSameType(RetT, LHST))
523 return true;
524 }
525 }
526 return false;
527}
528
532}
533
537 return cast_if_present(
539}
540
544 if (!TSI)
545 return false;
546
547
548
553 if (ATL.getAttrAs())
554 return true;
555 }
556
558}
559
560
562 LocalVisitor Visit) {
565
566 if (auto *CE = dyn_cast(Call)) {
567 Callee = CE->getDirectCallee();
568 Args = llvm::ArrayRef(CE->getArgs(), CE->getNumArgs());
569 } else {
570 auto *CCE = cast(Call);
571 Callee = CCE->getConstructor();
572 Args = llvm::ArrayRef(CCE->getArgs(), CCE->getNumArgs());
573 }
574 if (!Callee)
575 return;
576
577 bool EnableGSLAnalysis = !Callee->getASTContext().getDiagnostics().isIgnored(
578 diag::warn_dangling_lifetime_pointer, SourceLocation());
579 Expr *ObjectArg = nullptr;
580 if (isa(Call) && Callee->isCXXInstanceMember()) {
581 ObjectArg = Args[0];
582 Args = Args.slice(1);
583 } else if (auto *MCE = dyn_cast(Call)) {
584 ObjectArg = MCE->getImplicitObjectArgument();
585 }
586
587 auto VisitLifetimeBoundArg = [&](const Decl *D, Expr *Arg) {
588 Path.push_back({IndirectLocalPathEntry::LifetimeBoundCall, Arg, D});
589 if (Arg->isGLValue())
591 Visit);
592 else
594 Path.pop_back();
595 };
596 auto VisitGSLPointerArg = [&](const FunctionDecl *Callee, Expr *Arg) {
597 auto ReturnType = Callee->getReturnType();
598
599
600
601 if (ReturnType->isReferenceType() &&
602 !isRecordWithAttr(ReturnType->getPointeeType())) {
603 for (const IndirectLocalPathEntry &PE : llvm::reverse(Path)) {
604 if (PE.Kind == IndirectLocalPathEntry::GslReferenceInit ||
605 PE.Kind == IndirectLocalPathEntry::LifetimeBoundCall)
606 continue;
607 if (PE.Kind == IndirectLocalPathEntry::GslPointerInit ||
608 PE.Kind == IndirectLocalPathEntry::GslPointerAssignment)
609 return;
610 break;
611 }
612 }
613 Path.push_back({ReturnType->isReferenceType()
614 ? IndirectLocalPathEntry::GslReferenceInit
615 : IndirectLocalPathEntry::GslPointerInit,
616 Arg, Callee});
617 if (Arg->isGLValue())
619 Visit);
620 else
622 Path.pop_back();
623 };
624
625 bool CheckCoroCall = false;
626 if (const auto *RD = Callee->getReturnType()->getAsRecordDecl()) {
627 CheckCoroCall = RD->hasAttr() &&
628 RD->hasAttr() &&
629 !Callee->hasAttr();
630 }
631
632 if (ObjectArg) {
633 bool CheckCoroObjArg = CheckCoroCall;
634
635 if (auto *LE = dyn_cast(ObjectArg->IgnoreImplicit());
636 LE && LE->captures().empty())
637 CheckCoroObjArg = false;
638
639
641 CheckCoroObjArg = false;
643 VisitLifetimeBoundArg(Callee, ObjectArg);
644 else if (EnableGSLAnalysis) {
645 if (auto *CME = dyn_cast(Callee);
647 VisitGSLPointerArg(Callee, ObjectArg);
648 }
649 }
650
652 unsigned NP = std::min(Callee->getNumParams(), CanonCallee->getNumParams());
653 for (unsigned I = 0, N = std::min(NP, Args.size()); I != N; ++I) {
654 Expr *Arg = Args[I];
655 RevertToOldSizeRAII RAII(Path);
656 if (auto *DAE = dyn_cast(Arg)) {
657 Path.push_back(
658 {IndirectLocalPathEntry::DefaultArg, DAE, DAE->getParam()});
659 Arg = DAE->getExpr();
660 }
661 if (CheckCoroCall ||
663 VisitLifetimeBoundArg(CanonCallee->getParamDecl(I), Arg);
664 else if (const auto *CaptureAttr =
666 CaptureAttr && isa(CanonCallee) &&
667 llvm::any_of(CaptureAttr->params(), [](int ArgIdx) {
668 return ArgIdx == LifetimeCaptureByAttr::THIS;
669 }))
670
671
672
673
674
675
676
677
678
679
680
681
682
683 VisitLifetimeBoundArg(CanonCallee->getParamDecl(I), Arg);
684 else if (EnableGSLAnalysis && I == 0) {
685
687 VisitGSLPointerArg(CanonCallee, Arg);
688 } else if (auto *Ctor = dyn_cast(Call);
690 VisitGSLPointerArg(Ctor->getConstructor(), Arg);
691 }
692 }
693 }
694}
695
696
697
699 Expr *Init, ReferenceKind RK,
700 LocalVisitor Visit) {
701 RevertToOldSizeRAII RAII(Path);
702
703
705 do {
707
708 if (auto *FE = dyn_cast(Init))
709 Init = FE->getSubExpr();
710
712
713 if (ILE->isTransparent())
714 Init = ILE->getInit(0);
715 }
716
717 if (MemberExpr *ME = dyn_cast(Init->IgnoreImpCasts()))
718 Path.push_back(
719 {IndirectLocalPathEntry::MemberExpr, ME, ME->getMemberDecl()});
720
721
722 Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
723
724
725
727 if (CE->getSubExpr()->isGLValue())
728 Init = CE->getSubExpr();
729
730
731
732 if (auto *ASE = dyn_cast(Init)) {
733 Init = ASE->getBase();
734 auto *ICE = dyn_cast(Init);
735 if (ICE && ICE->getCastKind() == CK_ArrayToPointerDecay)
736 Init = ICE->getSubExpr();
737 else
738
739
741 }
742
743
744
745 if (auto *DIE = dyn_cast(Init)) {
746 Path.push_back(
747 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
748 Init = DIE->getExpr();
749 }
750 } while (Init != Old);
751
752 if (auto *MTE = dyn_cast(Init)) {
753 if (Visit(Path, Local(MTE), RK))
755 }
756
757 if (auto *M = dyn_cast(Init)) {
758
759 if (auto *F = dyn_cast(M->getMemberDecl());
760 F && !F->getType()->isReferenceType())
762 }
763
764 if (isa(Init))
766
767 switch (Init->getStmtClass()) {
768 case Stmt::DeclRefExprClass: {
769
770
771 auto *DRE = cast(Init);
772 auto *VD = dyn_cast(DRE->getDecl());
773 if (VD && VD->hasLocalStorage() &&
774 !DRE->refersToEnclosingVariableOrCapture()) {
775 if (!VD->getType()->isReferenceType()) {
776 Visit(Path, Local(DRE), RK);
777 } else if (isa(DRE->getDecl())) {
778
779
780 break;
782 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
784 RK_ReferenceBinding, Visit);
785 }
786 }
787 break;
788 }
789
790 case Stmt::UnaryOperatorClass: {
791
792
793
795 if (U->getOpcode() == UO_Deref)
797 break;
798 }
799
800 case Stmt::ArraySectionExprClass: {
802 Path, cast(Init)->getBase(), Visit, true);
803 break;
804 }
805
806 case Stmt::ConditionalOperatorClass:
807 case Stmt::BinaryConditionalOperatorClass: {
809 if (->getTrueExpr()->getType()->isVoidType())
811 if (->getFalseExpr()->getType()->isVoidType())
813 break;
814 }
815
816 case Stmt::CompoundLiteralExprClass: {
817 if (auto *CLE = dyn_cast(Init)) {
818 if (!CLE->isFileScope())
819 Visit(Path, Local(CLE), RK);
820 }
821 break;
822 }
823
824
825
826 default:
827 break;
828 }
829}
830
831
832
834 Expr *Init, LocalVisitor Visit,
835 bool RevisitSubinits) {
836 RevertToOldSizeRAII RAII(Path);
837
839 do {
841
842
843
844 if (auto *DIE = dyn_cast(Init)) {
845 Path.push_back(
846 {IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
847 Init = DIE->getExpr();
848 }
849
850 if (auto *FE = dyn_cast(Init))
851 Init = FE->getSubExpr();
852
853
854 Init = const_cast<Expr *>(Init->skipRValueSubobjectAdjustments());
855
857 Init = BTE->getSubExpr();
858
860
861
862 if (auto *CE = dyn_cast(Init)) {
863 switch (CE->getCastKind()) {
864 case CK_LValueToRValue:
865
866
867 Path.push_back({IndirectLocalPathEntry::LValToRVal, CE});
869 Path, Init, RK_ReferenceBinding,
870 [&](IndirectLocalPath &Path, Local L, ReferenceKind RK) -> bool {
871 if (auto *DRE = dyn_cast(L)) {
872 auto *VD = dyn_cast(DRE->getDecl());
873 if (VD && VD->getType().isConstQualified() && VD->getInit() &&
875 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
877 true);
878 }
879 } else if (auto *MTE = dyn_cast(L)) {
880 if (MTE->getType().isConstQualified())
882 Visit, true);
883 }
884 return false;
885 });
886
887
888
889
890
891 case CK_NoOp:
892 case CK_BitCast:
893 case CK_BaseToDerived:
894 case CK_DerivedToBase:
895 case CK_UncheckedDerivedToBase:
896 case CK_Dynamic:
897 case CK_ToUnion:
898 case CK_UserDefinedConversion:
899 case CK_ConstructorConversion:
900 case CK_IntegralToPointer:
901 case CK_PointerToIntegral:
902 case CK_VectorSplat:
903 case CK_IntegralCast:
904 case CK_CPointerToObjCPointerCast:
905 case CK_BlockPointerToObjCPointerCast:
906 case CK_AnyPointerToBlockPointerCast:
907 case CK_AddressSpaceConversion:
908 break;
909
910 case CK_ArrayToPointerDecay:
911
912
913 Path.push_back({IndirectLocalPathEntry::AddressOf, CE});
915 Path, CE->getSubExpr(), RK_ReferenceBinding, Visit);
916
917 default:
918 return;
919 }
920
921 Init = CE->getSubExpr();
922 }
923 } while (Old != Init);
924
925
926
927
928 if (auto *ILE = dyn_cast(Init))
930 RK_StdInitializerList, Visit);
931
933
934
935
936 if (!RevisitSubinits)
937 return;
938
939 if (ILE->isTransparent())
941 RevisitSubinits);
942
943 if (ILE->getType()->isArrayType()) {
944 for (unsigned I = 0, N = ILE->getNumInits(); I != N; ++I)
946 RevisitSubinits);
947 return;
948 }
949
950 if (CXXRecordDecl *RD = ILE->getType()->getAsCXXRecordDecl()) {
951 assert(RD->isAggregate() && "aggregate init on non-aggregate");
952
953
954
955
956 if (RD->isUnion() && ILE->getInitializedFieldInUnion() &&
957 ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
959 RK_ReferenceBinding, Visit);
960 else {
961 unsigned Index = 0;
962 for (; Index < RD->getNumBases() && Index < ILE->getNumInits(); ++Index)
964 RevisitSubinits);
965 for (const auto *I : RD->fields()) {
966 if (Index >= ILE->getNumInits())
967 break;
968 if (I->isUnnamedBitField())
969 continue;
970 Expr *SubInit = ILE->getInit(Index);
971 if (I->getType()->isReferenceType())
973 RK_ReferenceBinding, Visit);
974 else
975
976
977
979 RevisitSubinits);
980 ++Index;
981 }
982 }
983 }
984 return;
985 }
986
987
988
989 if (auto *LE = dyn_cast(Init)) {
991 for (Expr *E : LE->capture_inits()) {
992 assert(CapI != LE->capture_end());
994 if ()
995 continue;
997 Path.push_back({IndirectLocalPathEntry::LambdaCaptureInit, E, &Cap});
998 if (E->isGLValue())
1000 Visit);
1001 else
1004 Path.pop_back();
1005 }
1006 }
1007
1008
1009
1010 if (auto *CCE = dyn_cast(Init)) {
1011 if (CCE->getConstructor()->isCopyOrMoveConstructor()) {
1012 if (auto *MTE = dyn_cast(CCE->getArg(0))) {
1013 Expr *Arg = MTE->getSubExpr();
1014 Path.push_back({IndirectLocalPathEntry::TemporaryCopy, Arg,
1015 CCE->getConstructor()});
1017 Path.pop_back();
1018 }
1019 }
1020 }
1021
1022 if (isa(Init) || isa(Init))
1024
1025 if (auto *CPE = dyn_cast(Init)) {
1026 RevertToOldSizeRAII RAII(Path);
1027 Path.push_back({IndirectLocalPathEntry::ParenAggInit, CPE});
1028 for (auto *I : CPE->getInitExprs()) {
1029 if (I->isGLValue())
1031 Visit);
1032 else
1034 }
1035 }
1036 switch (Init->getStmtClass()) {
1037 case Stmt::UnaryOperatorClass: {
1038 auto *UO = cast(Init);
1039
1040
1041 if (UO->getOpcode() == UO_AddrOf) {
1042
1043
1044
1045 if (isa(UO->getSubExpr()))
1046 return;
1047
1048 Path.push_back({IndirectLocalPathEntry::AddressOf, UO});
1050 RK_ReferenceBinding, Visit);
1051 }
1052 break;
1053 }
1054
1055 case Stmt::BinaryOperatorClass: {
1056
1057 auto *BO = cast(Init);
1059 if (!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub))
1060 break;
1061
1062 if (BO->getLHS()->getType()->isPointerType())
1064 else if (BO->getRHS()->getType()->isPointerType())
1066 break;
1067 }
1068
1069 case Stmt::ConditionalOperatorClass:
1070 case Stmt::BinaryConditionalOperatorClass: {
1072
1073
1074 if (->getTrueExpr()->getType()->isVoidType())
1076 if (->getFalseExpr()->getType()->isVoidType())
1078 break;
1079 }
1080
1081 case Stmt::BlockExprClass:
1082 if (cast(Init)->getBlockDecl()->hasCaptures()) {
1083
1084 Visit(Path, Local(cast(Init)), RK_ReferenceBinding);
1085 }
1086 break;
1087
1088 case Stmt::AddrLabelExprClass:
1089
1090 Visit(Path, Local(cast(Init)), RK_ReferenceBinding);
1091 break;
1092
1093 default:
1094 break;
1095 }
1096}
1097
1098
1100
1102
1105
1106
1107
1110 for (auto Elem : Path) {
1111 if (Elem.Kind == IndirectLocalPathEntry::MemberExpr ||
1112 Elem.Kind == IndirectLocalPathEntry::LambdaCaptureInit)
1113 continue;
1114 return Elem.Kind == IndirectLocalPathEntry::DefaultInit
1117 }
1119}
1120
1121
1124 for (unsigned N = Path.size(); I != N; ++I) {
1126 case IndirectLocalPathEntry::AddressOf:
1127 case IndirectLocalPathEntry::LValToRVal:
1128 case IndirectLocalPathEntry::LifetimeBoundCall:
1129 case IndirectLocalPathEntry::TemporaryCopy:
1130 case IndirectLocalPathEntry::GslReferenceInit:
1131 case IndirectLocalPathEntry::GslPointerInit:
1132 case IndirectLocalPathEntry::GslPointerAssignment:
1133 case IndirectLocalPathEntry::ParenAggInit:
1134 case IndirectLocalPathEntry::MemberExpr:
1135
1136
1137 break;
1138
1139 case IndirectLocalPathEntry::VarInit:
1140 if (cast(Path[I].D)->isImplicit())
1142 [[fallthrough]];
1143 case IndirectLocalPathEntry::DefaultInit:
1144 return Path[I].E->getSourceRange();
1145
1146 case IndirectLocalPathEntry::LambdaCaptureInit:
1147 if ([I].Capture->capturesVariable())
1148 continue;
1149 return Path[I].E->getSourceRange();
1150
1151 case IndirectLocalPathEntry::DefaultArg:
1152 return cast(Path[I].E)->getUsedLocation();
1153 }
1154 }
1155 return E->getSourceRange();
1156}
1157
1159 for (const auto &It : llvm::reverse(Path)) {
1160 switch (It.Kind) {
1161 case IndirectLocalPathEntry::VarInit:
1162 case IndirectLocalPathEntry::AddressOf:
1163 case IndirectLocalPathEntry::LifetimeBoundCall:
1164 case IndirectLocalPathEntry::MemberExpr:
1165 continue;
1166 case IndirectLocalPathEntry::GslPointerInit:
1167 case IndirectLocalPathEntry::GslReferenceInit:
1168 case IndirectLocalPathEntry::GslPointerAssignment:
1169 return true;
1170 default:
1171 return false;
1172 }
1173 }
1174 return false;
1175}
1176
1178
1180
1181
1183
1185
1187};
1188
1189
1191 Local L, LifetimeKind LK) {
1194
1195
1196
1197
1198
1199 for (const auto &E : Path) {
1200 if (E.Kind == IndirectLocalPathEntry::MemberExpr) {
1201
1204
1205
1206
1207
1208
1209 if (const auto *FD = llvm::dyn_cast_or_null(E.D);
1210 FD && !FD->getType()->isReferenceType() &&
1211 isRecordWithAttr(FD->getType()) &&
1212 LK != LK_MemInitializer) {
1214 }
1216 }
1217 }
1218
1219
1220
1221
1222
1223
1224
1225
1226 if (Path.back().Kind == IndirectLocalPathEntry::LifetimeBoundCall) {
1227
1229 llvm::dyn_cast_or_null(Path.back().D);
1230
1231 if (const auto *PD = llvm::dyn_cast(Path.back().D))
1232 FD = llvm::dyn_cast(PD->getDeclContext());
1233
1234 if (isa_and_present(FD)) {
1235
1236
1237
1239 }
1240
1241
1242
1243 if (FD &&
1248
1250 }
1251
1252 if (isa(L)) {
1253
1254
1255
1256
1257
1261 }
1262
1263
1264 auto *MTE = dyn_cast(L);
1265
1266 bool IsGslPtrValueFromGslTempOwner =
1267 MTE && !MTE->getExtendingDecl() &&
1268 isRecordWithAttr(MTE->getType());
1269
1270
1271
1272
1273 if (!IsGslPtrValueFromGslTempOwner)
1274 return Skip;
1276}
1277
1282}
1283
1287 diag::warn_dangling_lifetime_pointer_assignment, SourceLocation());
1288 return (EnableGSLAssignmentWarnings &&
1289 (isRecordWithAttr(Entity.LHS->getType()) ||
1291}
1292
1293static void
1298 assert(!AEntity || LK == LK_Assignment);
1299 assert(!CapEntity || LK == LK_LifetimeCapture);
1300 assert(!InitEntity || (LK != LK_Assignment && LK != LK_LifetimeCapture));
1301
1302
1303 if (LK == LK_FullExpression)
1304 return;
1305
1306
1307
1308 auto TemporaryVisitor = [&](const IndirectLocalPath &Path, Local L,
1309 ReferenceKind RK) -> bool {
1312
1313 auto *MTE = dyn_cast(L);
1314
1315 bool IsGslPtrValueFromGslTempOwner = true;
1318 return false;
1320 return true;
1322 IsGslPtrValueFromGslTempOwner = false;
1323 LLVM_FALLTHROUGH;
1325 break;
1326 }
1327
1328 switch (LK) {
1329 case LK_FullExpression:
1330 llvm_unreachable("already handled this");
1331
1332 case LK_Extended: {
1333 if (!MTE) {
1334
1335
1336
1337
1338
1339 return false;
1340 }
1341
1342 if (IsGslPtrValueFromGslTempOwner && DiagLoc.isValid()) {
1343 SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1344 << DiagRange;
1345 return false;
1346 }
1347
1350
1351
1352 MTE->setExtendingDecl(ExtendingEntity->getDecl(),
1354
1355 return true;
1356
1358
1359
1360
1362 return false;
1363
1364 SemaRef.Diag(DiagLoc, diag::warn_dangling_variable)
1365 << RK << !InitEntity->getParent()
1367 << ExtendingEntity->getDecl() << Init->isGLValue() << DiagRange;
1368 break;
1369 }
1370 break;
1371 }
1372
1373 case LK_LifetimeCapture: {
1374
1375
1376 if (!MTE)
1377 return false;
1378 if (CapEntity->Entity)
1379 SemaRef.Diag(DiagLoc, diag::warn_dangling_reference_captured)
1380 << CapEntity->Entity << DiagRange;
1381 else
1382 SemaRef.Diag(DiagLoc, diag::warn_dangling_reference_captured_by_unknown)
1383 << DiagRange;
1384 return false;
1385 }
1386
1387 case LK_Assignment: {
1389 return false;
1390 if (IsGslPtrValueFromGslTempOwner)
1391 SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_assignment)
1392 << AEntity->LHS << DiagRange;
1393 else
1394 SemaRef.Diag(DiagLoc, diag::warn_dangling_pointer_assignment)
1396 << DiagRange;
1397 return false;
1398 }
1399 case LK_MemInitializer: {
1400 if (MTE) {
1401
1402
1403
1404 if (auto *ExtendingDecl =
1405 ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
1406 if (IsGslPtrValueFromGslTempOwner) {
1407 SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_member)
1408 << ExtendingDecl << DiagRange;
1409 SemaRef.Diag(ExtendingDecl->getLocation(),
1410 diag::note_ref_or_ptr_member_declared_here)
1411 << true;
1412 return false;
1413 }
1414 bool IsSubobjectMember = ExtendingEntity != InitEntity;
1417 ? diag::err_dangling_member
1418 : diag::warn_dangling_member)
1419 << ExtendingDecl << IsSubobjectMember << RK << DiagRange;
1420
1421
1422
1423 if (Path.empty() ||
1424 Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {
1425 SemaRef.Diag(ExtendingDecl->getLocation(),
1426 diag::note_lifetime_extending_member_declared_here)
1427 << RK << IsSubobjectMember;
1428 }
1429 } else {
1430
1431
1432
1433
1434
1435
1436 return false;
1437 }
1438 } else {
1439
1440
1441
1443 return false;
1444
1445 auto *DRE = dyn_cast(L);
1446
1447
1448
1449 if (DRE && isRecordWithAttr(DRE->getType()))
1450 return false;
1451
1452 auto *VD = DRE ? dyn_cast(DRE->getDecl()) : nullptr;
1453 if (!VD) {
1454
1455
1456 return false;
1457 }
1458
1460 ExtendingEntity ? ExtendingEntity->getDecl() : nullptr) {
1461 bool IsPointer = ->getType()->isReferenceType();
1462 SemaRef.Diag(DiagLoc,
1463 IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
1464 : diag::warn_bind_ref_member_to_parameter)
1465 << Member << VD << isa(VD) << DiagRange;
1467 diag::note_ref_or_ptr_member_declared_here)
1469 }
1470 }
1471 break;
1472 }
1473
1474 case LK_New:
1475 if (isa(L)) {
1476 if (IsGslPtrValueFromGslTempOwner)
1477 SemaRef.Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1478 << DiagRange;
1479 else
1480 SemaRef.Diag(DiagLoc, RK == RK_ReferenceBinding
1481 ? diag::warn_new_dangling_reference
1482 : diag::warn_new_dangling_initializer_list)
1483 << !InitEntity->getParent() << DiagRange;
1484 } else {
1485
1486 return false;
1487 }
1488 break;
1489
1490 case LK_Return:
1491 case LK_MustTail:
1492 case LK_StmtExprResult:
1493 if (auto *DRE = dyn_cast(L)) {
1494
1495
1496 if (LK == LK_StmtExprResult)
1497 return false;
1498 SemaRef.Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1500 << isa(DRE->getDecl()) << (LK == LK_MustTail)
1501 << DiagRange;
1502 } else if (isa(L)) {
1503 SemaRef.Diag(DiagLoc, diag::err_ret_local_block) << DiagRange;
1504 } else if (isa(L)) {
1505
1506
1507 if (LK == LK_StmtExprResult)
1508 return false;
1509 SemaRef.Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange;
1510 } else if (auto *CLE = dyn_cast(L)) {
1511 SemaRef.Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1513 << 2 << (LK == LK_MustTail) << DiagRange;
1514 } else {
1515
1516
1517
1518
1519
1520 if (SemaRef.getLangOpts().CPlusPlus26 &&
1522 SemaRef.Diag(DiagLoc, diag::err_ret_local_temp_ref)
1524 else if (LK == LK_MustTail)
1525 SemaRef.Diag(DiagLoc, diag::warn_musttail_local_temp_addr_ref)
1527 else
1528 SemaRef.Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
1530 }
1531 break;
1532 }
1533
1534 for (unsigned I = 0; I != Path.size(); ++I) {
1535 auto Elem = Path[I];
1536
1537 switch (Elem.Kind) {
1538 case IndirectLocalPathEntry::AddressOf:
1539 case IndirectLocalPathEntry::LValToRVal:
1540 case IndirectLocalPathEntry::ParenAggInit:
1541
1542
1543 break;
1544
1545 case IndirectLocalPathEntry::LifetimeBoundCall:
1546 case IndirectLocalPathEntry::TemporaryCopy:
1547 case IndirectLocalPathEntry::MemberExpr:
1548 case IndirectLocalPathEntry::GslPointerInit:
1549 case IndirectLocalPathEntry::GslReferenceInit:
1550 case IndirectLocalPathEntry::GslPointerAssignment:
1551
1552 break;
1553
1554 case IndirectLocalPathEntry::DefaultInit: {
1555 auto *FD = cast(Elem.D);
1556 SemaRef.Diag(FD->getLocation(),
1557 diag::note_init_with_default_member_initializer)
1559 break;
1560 }
1561
1562 case IndirectLocalPathEntry::VarInit: {
1563 const VarDecl *VD = cast(Elem.D);
1564 SemaRef.Diag(VD->getLocation(), diag::note_local_var_initializer)
1567 break;
1568 }
1569
1570 case IndirectLocalPathEntry::LambdaCaptureInit: {
1571 if (!Elem.Capture->capturesVariable())
1572 break;
1573
1574
1575 const ValueDecl *VD = Elem.Capture->getCapturedVar();
1576 SemaRef.Diag(Elem.Capture->getLocation(),
1577 diag::note_lambda_capture_initializer)
1578 << VD << VD->isInitCapture() << Elem.Capture->isExplicit()
1579 << (Elem.Capture->getCaptureKind() == LCK_ByRef) << VD
1581 break;
1582 }
1583
1584 case IndirectLocalPathEntry::DefaultArg: {
1585 const auto *DAE = cast(Elem.E);
1586 const ParmVarDecl *Param = DAE->getParam();
1588 diag::note_init_with_default_argument)
1590 break;
1591 }
1592 }
1593 }
1594
1595
1596
1597 return false;
1598 };
1599
1601 switch (LK) {
1602 case LK_Assignment: {
1604 Path.push_back(
1606 ? IndirectLocalPathEntry::LifetimeBoundCall
1607 : IndirectLocalPathEntry::GslPointerAssignment,
1609 break;
1610 }
1611 case LK_LifetimeCapture: {
1613 Path.push_back({IndirectLocalPathEntry::GslPointerInit, Init});
1614 break;
1615 }
1616 default:
1617 break;
1618 }
1619
1620 if (Init->isGLValue())
1622 TemporaryVisitor);
1623 else
1625 Path, Init, TemporaryVisitor,
1626
1627 !InitEntity);
1628}
1629
1631 Expr *Init) {
1633 LifetimeKind LK = LTResult.getInt();
1634 const InitializedEntity *ExtendingEntity = LTResult.getPointer();
1636 nullptr, nullptr, Init);
1637}
1638
1642 nullptr, nullptr, Init);
1643}
1644
1646 Expr *Init) {
1648 diag::warn_dangling_pointer_assignment, SourceLocation());
1649 bool RunAnalysis = (EnableDanglingPointerAssignment &&
1652
1653 if (!RunAnalysis)
1654 return;
1655
1657 nullptr, LK_Assignment, &Entity,
1658 nullptr, Init);
1659}
1660
1662 Expr *Init) {
1666 diag::warn_dangling_reference_captured_by_unknown, SourceLocation()))
1667 return;
1669 nullptr, LK_LifetimeCapture,
1670 nullptr,
1671 &Entity, Init);
1672}
1673
1674}
const LambdaCapture * Capture
enum clang::sema::@1727::IndirectLocalPathEntry::EntryKind Kind
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Type source information for an attributed type.
TypeLoc getModifiedLoc() const
The modified type, which is generally canonically different from the attribute type.
Represents binding an expression to a temporary.
Represents a call to a C++ constructor.
Expr * getArg(unsigned Arg)
Return the specified argument.
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
Represents a C++ constructor within a class.
Represents a static or instance method of a struct/union/class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Represents a C++ struct/union/class.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
bool isStdNamespace() const
Decl - This represents one declaration (or definition), e.g.
bool isInStdNamespace() const
ASTContext & getASTContext() const LLVM_READONLY
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
SourceLocation getLocation() const
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
TypeSourceInfo * getTypeSourceInfo() const
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
This represents one expression.
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
QualType getReturnType() const
FunctionTemplateDecl * getPrimaryTemplate() const
Retrieve the primary template that this function template specialization either specializes or was in...
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
size_t param_size() const
One of these records is kept for each identifier that is lexed.
Describes an C or C++ initializer list.
Describes an entity that is being initialized.
EntityKind getKind() const
Determine the kind of initialization.
unsigned allocateManglingNumber() const
QualType getType() const
Retrieve type being initialized.
ValueDecl * getDecl() const
Retrieve the variable, parameter, or field being initialized.
const InitializedEntity * getParent() const
Retrieve the parent of the entity being initialized, when the initialization itself is occurring with...
@ EK_Variable
The entity being initialized is a variable.
@ EK_Temporary
The entity being initialized is a temporary object.
@ EK_Binding
The entity being initialized is a structured binding of a decomposition declaration.
@ EK_BlockElement
The entity being initialized is a field of block descriptor for the copied-in c++ object.
@ EK_Parameter_CF_Audited
The entity being initialized is a function parameter; function is member of group of audited CF APIs.
@ EK_LambdaToBlockConversionBlockElement
The entity being initialized is a field of block descriptor for the copied-in lambda object that's us...
@ EK_Member
The entity being initialized is a non-static data member subobject.
@ EK_Base
The entity being initialized is a base member subobject.
@ EK_Result
The entity being initialized is the result of a function call.
@ EK_TemplateParameter
The entity being initialized is a non-type template parameter.
@ EK_StmtExprResult
The entity being initialized is the result of a statement expression.
@ EK_ParenAggInitMember
The entity being initialized is a non-static data member subobject of an object initialized via paren...
@ EK_VectorElement
The entity being initialized is an element of a vector.
@ EK_New
The entity being initialized is an object (or array of objects) allocated via new.
@ EK_CompoundLiteralInit
The entity being initialized is the initializer for a compound literal.
@ EK_Parameter
The entity being initialized is a function parameter.
@ EK_Delegating
The initialization is being done by a delegating constructor.
@ EK_ComplexElement
The entity being initialized is the real or imaginary part of a complex number.
@ EK_ArrayElement
The entity being initialized is an element of an array.
@ EK_LambdaCapture
The entity being initialized is the field that captures a variable in a lambda.
@ EK_Exception
The entity being initialized is an exception object that is being thrown.
@ EK_RelatedResult
The entity being implicitly initialized back to the formal result type.
bool isDefaultMemberInitializer() const
Is this the default member initializer of a member (specified inside the class definition)?
Describes the capture of a variable or of this, or of a C++1y init-capture.
bool capturesVariable() const
Determine whether this capture handles a variable.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Represents a parameter to a function.
SourceRange getDefaultArgRange() const
Retrieve the source range that covers the entire default argument.
A (possibly-)qualified type.
Represents a struct/union/class.
decl_type * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
Base for LValueReferenceType and RValueReferenceType.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Sema - This implements semantic analysis and AST building for C.
DiagnosticsEngine & getDiagnostics() const
const LangOptions & getLangOpts() const
static bool CanBeGetReturnObject(const FunctionDecl *FD)
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
@ Type
The template argument is a type.
Represents a type template specialization; the template must be a class template, a type alias templa...
Base wrapper for a particular "section" of type source info.
T getAsAdjusted() const
Convert to the specified TypeLoc type, returning a null TypeLoc if this TypeLoc is not of the desired...
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool hasAttr(attr::Kind AK) const
Determine whether this type had the specified attribute applied to it (looking through top-level type...
bool isPointerType() const
bool isReferenceType() const
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isLValueReferenceType() const
const T * getAs() const
Member-template getAs'.
bool isNullPtrType() const
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
bool isInitCapture() const
Whether this variable is the implicit variable for a lambda init-capture.
Represents a variable declaration or definition.
static bool isStdInitializerListOfPointer(const RecordDecl *RD)
bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD)
static void checkExprLifetimeImpl(Sema &SemaRef, const InitializedEntity *InitEntity, const InitializedEntity *ExtendingEntity, LifetimeKind LK, const AssignedEntity *AEntity, const CapturingEntity *CapEntity, Expr *Init)
static bool shouldRunGSLAssignmentAnalysis(const Sema &SemaRef, const AssignedEntity &Entity)
static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, Expr *Init, ReferenceKind RK, LocalVisitor Visit)
Visit the locals that would be reachable through a reference bound to the glvalue expression Init.
void checkExprLifetimeMustTailArg(Sema &SemaRef, const InitializedEntity &Entity, Expr *Init)
Check that the lifetime of the given expr (and its subobjects) is sufficient, assuming that it is pas...
static bool pathOnlyHandlesGslPointer(const IndirectLocalPath &Path)
static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, Expr *Init, LocalVisitor Visit, bool RevisitSubinits)
Visit the locals that would be reachable through an object initialized by the prvalue expression Init...
static bool isNormalAssignmentOperator(const FunctionDecl *FD)
static AnalysisResult analyzePathForGSLPointer(const IndirectLocalPath &Path, Local L, LifetimeKind LK)
static bool isInStlNamespace(const Decl *D)
static bool isRecordWithAttr(QualType Type)
bool isGLSPointerType(QualType QT)
static bool shouldTrackFirstArgument(const FunctionDecl *FD)
static bool isContainerOfOwner(const RecordDecl *Container)
static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I, Expr *E)
Find the range for the first interesting entry in the path at or after I.
static LifetimeResult getEntityLifetime(const InitializedEntity *Entity, const InitializedEntity *InitField=nullptr)
Determine the declaration which an initialized entity ultimately refers to, for the purpose of lifeti...
static const FunctionDecl * getDeclWithMergedLifetimeBoundAttrs(const FunctionDecl *FD)
static bool isContainerOfPointer(const RecordDecl *Container)
void checkInitLifetime(Sema &SemaRef, const InitializedEntity &Entity, Expr *Init)
Check that the lifetime of the given expr (and its subobjects) is sufficient for initializing the ent...
static bool isCopyLikeConstructor(const CXXConstructorDecl *Ctor)
void checkAssignmentLifetime(Sema &SemaRef, const AssignedEntity &Entity, Expr *Init)
Check that the lifetime of the given expr (and its subobjects) is sufficient for assigning to the ent...
static bool shouldTrackFirstArgumentForConstructor(const CXXConstructExpr *Ctor)
PathLifetimeKind
Whether a path to an object supports lifetime extension.
@ NoExtend
Do not lifetime extend along this path.
@ Extend
Lifetime-extend along this path.
static bool isVarOnPath(const IndirectLocalPath &Path, VarDecl *VD)
static bool pathContainsInit(const IndirectLocalPath &Path)
static bool isPointerLikeType(QualType QT)
static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call, LocalVisitor Visit)
void checkCaptureByLifetime(Sema &SemaRef, const CapturingEntity &Entity, Expr *Init)
static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee)
static bool isAssignmentOperatorLifetimeBound(const CXXMethodDecl *CMD)
static PathLifetimeKind shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path)
Determine whether this is an indirect path to a temporary that we are supposed to lifetime-extend alo...
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
bool isCompoundAssignmentOperator(OverloadedOperatorKind Kind)
Determine if this is a compound assignment operator.
LLVM_READONLY bool isUppercase(unsigned char c)
Return true if this character is an uppercase ASCII letter: [A-Z].
@ LCK_ByRef
Capturing by reference.
@ Result
The result type of a method or function.
const FunctionProtoType * T
Describes an entity that is being assigned.
CXXMethodDecl * AssignmentOperator