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 {

212 const Decl *D = nullptr;

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

237 for (auto E : Path)

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

808 auto *C = cast(Init);

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

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

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

1071 auto *C = cast(Init);

1072

1073

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

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