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 {

211 const Decl *D = nullptr;

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

236 for (auto E : Path)

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: {

817 auto *C = cast(Init);

818 if (C->getTrueExpr()->getType()->isVoidType())

820 if (C->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 (E)

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: {

1080 auto *C = cast(Init);

1081

1082

1083 if (C->getTrueExpr()->getType()->isVoidType())

1085 if (C->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 (Path[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 = Member->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