clang: lib/Sema/SemaCoroutine.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

28

29using namespace clang;

30using namespace sema;

31

36

37

40 return LR;

41}

42

45 bool Res;

47 return Res;

48}

49

50

51

56

59 if (!CoroTraits)

61

62

63

68 };

70

71

72 if (auto *MD = dyn_cast(FD)) {

73 if (MD->isImplicitObjectMemberFunction()) {

74

75

76

77

78

79

80

81 QualType T = MD->getFunctionObjectParameterType();

85 AddArg(T);

86 }

87 }

89 AddArg(T);

90

91

94 if (CoroTrait.isNull())

97 diag::err_coroutine_type_missing_specialization))

99

101 assert(RD && "specialization of class template is not a class?");

102

103

108 if (!Promise) {

109 S.Diag(FuncLoc,

110 diag::err_implied_std_coroutine_traits_promise_type_not_found)

111 << RD;

113 }

114

116

117 auto buildElaboratedType = [&]() {

122 PromiseType);

123 };

124

126 S.Diag(FuncLoc,

127 diag::err_implied_std_coroutine_traits_promise_type_not_class)

128 << buildElaboratedType();

130 }

132 diag::err_coroutine_promise_type_incomplete))

134

135 return PromiseType;

136}

137

138

141 if (PromiseType.isNull())

143

145 assert(CoroNamespace && "Should already be diagnosed");

146

150 S.Diag(Loc, diag::err_implied_coroutine_type_not_found)

151 << "std::coroutine_handle";

153 }

154

156 if (!CoroHandle) {

157 Result.suppressDiagnostics();

158

160 S.Diag(Found->getLocation(), diag::err_malformed_std_coroutine_handle);

162 }

163

164

169

170

173 if (CoroHandleType.isNull())

176 diag::err_coroutine_type_missing_specialization))

178

179 return CoroHandleType;

180}

181

183 StringRef Keyword) {

184

185

186

187

188

189

190 auto *FD = dyn_cast(S.CurContext);

191 if (!FD) {

193 ? diag::err_coroutine_objc_method

194 : diag::err_coroutine_outside_function) << Keyword;

195 return false;

196 }

197

198

199

200 enum InvalidFuncDiag {

201 DiagCtor = 0,

202 DiagDtor,

203 DiagMain,

204 DiagConstexpr,

205 DiagAutoRet,

206 DiagVarargs,

207 DiagConsteval,

208 };

209 bool Diagnosed = false;

210 auto DiagInvalid = [&](InvalidFuncDiag ID) {

211 S.Diag(Loc, diag::err_coroutine_invalid_func_context) << ID << Keyword;

212 Diagnosed = true;

213 return false;

214 };

215

216

217

218 auto *MD = dyn_cast(FD);

219

220 if (MD && isa(MD))

221 return DiagInvalid(DiagCtor);

222

223 else if (MD && isa(MD))

224 return DiagInvalid(DiagDtor);

225

226 else if (FD->isMain())

227 return DiagInvalid(DiagMain);

228

229

230

231

232

233 if (FD->isConstexpr())

234 DiagInvalid(FD->isConsteval() ? DiagConsteval : DiagConstexpr);

235

236

237 if (FD->getReturnType()->isUndeducedType())

238 DiagInvalid(DiagAutoRet);

239

240

241

242 if (FD->isVariadic())

243 DiagInvalid(DiagVarargs);

244

245 return !Diagnosed;

246}

247

248

249

255}

256

263 cast(R.get()));

264}

265

269 if (CoroHandleType.isNull())

271

276 S.Diag(Loc, diag::err_coroutine_handle_missing_member)

277 << "from_address";

279 }

280

281 Expr *FramePtr =

283

289

291}

292

298};

299

303

304

307 Base, Base->getType(), Loc, false, SS,

308 SourceLocation(), nullptr, NameInfo, nullptr,

309 nullptr);

310 if (Result.isInvalid())

312

313

314 if (auto *TE = dyn_cast(Result.get())) {

316 S.Diag(Loc, diag::err_no_member)

317 << NameInfo.getName() << Base->getType()->getAsCXXRecordDecl()

318 << Base->getSourceRange();

320 }

321

322 auto EndLoc = Args.empty() ? Loc : Args.back()->getEndLoc();

324}

325

326

327

328

329

333 return nullptr;

336 return nullptr;

337

338

339

340

341

344 return nullptr;

345

346 Expr *JustAddress = AddressExpr.get();

347

348

350 S.Diag(cast(JustAddress)->getCalleeDecl()->getLocation(),

351 diag::warn_coroutine_handle_address_invalid_return_type)

352 << JustAddress->getType();

353

354

355

357}

358

359

360

361

362

363

364

365

366

367

368

369

370

375

376

377

379

381

382 auto BuildSubExpr = [&](ACT CallType, StringRef Func,

385 if (Result.isInvalid()) {

387 return nullptr;

388 }

391 };

392

394 cast_or_null(BuildSubExpr(ACT::ACT_Ready, "await_ready", {}));

395 if (!AwaitReady)

396 return Calls;

398

399

400

404 diag::note_await_ready_no_bool_conversion);

405 S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)

408 } else

410 }

411

416 return Calls;

417 }

418 Expr *CoroHandle = CoroHandleRes.get();

419 CallExpr *AwaitSuspend = cast_or_null(

420 BuildSubExpr(ACT::ACT_Suspend, "await_suspend", CoroHandle));

421 if (!AwaitSuspend)

422 return Calls;

424

425

426

427

429

430

431 if (Expr *TailCallSuspend =

433

434

435

436

437

438 Calls.Results[ACT::ACT_Suspend] = TailCallSuspend;

439 else {

440

444 diag::err_await_suspend_invalid_return_type)

445 << RetType;

446 S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)

449 } else

450 Calls.Results[ACT::ACT_Suspend] =

452 }

453 }

454

455 BuildSubExpr(ACT::ACT_Resume, "await_resume", {});

456

457

459

460 return Calls;

461}

462

466

467

472

474}

475

477 assert(isa(CurContext) && "not in a function scope");

478 auto *FD = cast(CurContext);

479 bool IsThisDependentType = [&] {

480 if (const auto *MD = dyn_cast_if_present(FD))

481 return MD->isImplicitObjectMemberFunction() &&

482 MD->getThisType()->isDependentType();

483 return false;

484 }();

485

489 if (T.isNull())

490 return nullptr;

491

495 VD->setImplicit();

497 if (VD->isInvalidDecl())

498 return nullptr;

499

501

502

503

505

506

507 if (auto *MD = dyn_cast(FD)) {

511 return nullptr;

514 return nullptr;

515 CtorArgExprs.push_back(ThisExpr.get());

516 }

517 }

518

519

520 auto &Moves = ScopeInfo->CoroutineParameterMoves;

521 for (auto *PD : FD->parameters()) {

522 if (PD->getType()->isDependentType())

523 continue;

524

526 auto Move = Moves.find(PD);

527 assert(Move != Moves.end() &&

528 "Coroutine function parameter not inserted into move map");

529

530

531 auto *MoveDecl =

532 cast(cast(Move->second)->getSingleDecl());

533 RefExpr =

534 BuildDeclRefExpr(MoveDecl, MoveDecl->getType().getNonReferenceType(),

536 if (RefExpr.isInvalid())

537 return nullptr;

538 CtorArgExprs.push_back(RefExpr.get());

539 }

540

541

542

543 if (!CtorArgExprs.empty()) {

544

545

547 CtorArgExprs, FD->getLocation());

550 VD->getLocation(), true, PLE);

552 false,

553 false);

554

555

556

557

558

559

560

561 if (InitSeq) {

563 if (Result.isInvalid()) {

564 VD->setInvalidDecl();

565 } else if (Result.get()) {

569 }

570 } else

572 } else

574

575 FD->addDecl(VD);

576 return VD;

577}

578

579

581 StringRef Keyword,

582 bool IsImplicit = false) {

584 return nullptr;

585

586 assert(isa(S.CurContext) && "not in a function scope");

587

589 assert(ScopeInfo && "missing function scope for function");

590

591 if (ScopeInfo->FirstCoroutineStmtLoc.isInvalid() && !IsImplicit)

592 ScopeInfo->setFirstCoroutineStmt(Loc, Keyword);

593

594 if (ScopeInfo->CoroutinePromise)

595 return ScopeInfo;

596

598 return nullptr;

599

601 if (!ScopeInfo->CoroutinePromise)

602 return nullptr;

603

604 return ScopeInfo;

605}

606

607

608

609

611 llvm::SmallPtrSetImpl<const Decl *> &ThrowingDecls) {

612 auto checkDeclNoexcept = [&](const Decl *D, bool IsDtor = false) {

613

614

616 if (const auto *FD = dyn_cast(D)) {

617

618

619

620

621

622

623

624 if (FD->getBuiltinID() == Builtin::BI__builtin_coro_resume)

625 return;

626 }

627 if (ThrowingDecls.empty()) {

628

629

630

631

632

633 S.Diag(cast(S.CurContext)->getLocation(),

634 diag::err_coroutine_promise_final_suspend_requires_nothrow);

635 }

636 ThrowingDecls.insert(D);

637 }

638 };

639

640 if (auto *CE = dyn_cast(E)) {

642 checkDeclNoexcept(Ctor);

643

645 } else if (auto *CE = dyn_cast(E)) {

646 if (CE->isTypeDependent())

647 return;

648

649 checkDeclNoexcept(CE->getCalleeDecl());

651

654 const auto *T =

656 checkDeclNoexcept(cast(T->getDecl())->getDestructor(),

657 true);

658 }

659 } else

660 for (const auto *Child : E->children()) {

661 if (!Child)

662 continue;

664 }

665}

666

669

670

671

672

673 checkNoThrow(*this, FinalSuspend, ThrowingDecls);

675 ThrowingDecls.end()};

676 sort(SortedDecls, [](const Decl *A, const Decl *B) {

678 });

679 for (const auto *D : SortedDecls) {

680 Diag(D->getEndLoc(), diag::note_coroutine_function_declare_noexcept);

681 }

682 return ThrowingDecls.empty();

683}

684

685

686

688 assert(FSI && "FunctionScopeInfo is null");

690 "first coroutine location not set");

692 return;

696}

697

699 StringRef Keyword) {

700

704 return false;

706 assert(ScopeInfo->CoroutinePromise);

707

708

709 if (ScopeInfo->FirstCoroutineStmtLoc == KWLoc)

711

712

713

714 if (!ScopeInfo->NeedsCoroutineSuspends)

715 return true;

716

717 ScopeInfo->setNeedsCoroutineSuspends(false);

718

719 auto *Fn = cast(CurContext);

721

722 auto buildSuspends = [&](StringRef Name) mutable -> StmtResult {

725 if (Operand.isInvalid())

732 true);

735 Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required)

736 << ((Name == "initial_suspend") ? 0 : 1);

737 Diag(KWLoc, diag::note_declared_coroutine_here) << Keyword;

739 }

740 return cast(Suspend.get());

741 };

742

743 StmtResult InitSuspend = buildSuspends("initial_suspend");

745 return true;

746

747 StmtResult FinalSuspend = buildSuspends("final_suspend");

749 return true;

750

751 ScopeInfo->setCoroutineSuspends(InitSuspend.get(), FinalSuspend.get());

752

753 return true;

754}

755

756

757

759

760

761

762

763

764

765

766

767

768

769

770

771

772

773 while (S && !S->isFunctionScope()) {

774 if (S->isCatchScope())

775 return true;

776 S = S->getParent();

777 }

778 return false;

779}

780

781

782

783

784

785

787 StringRef Keyword) {

788

789

790

792 S.Diag(Loc, diag::err_coroutine_unevaluated_context) << Keyword;

793 return false;

794 }

795

796

798 S.Diag(Loc, diag::err_coroutine_within_handler) << Keyword;

799 return false;

800 }

801

802 return true;

803}

804

808

812 }

813

818 }

819

824 cast(Lookup.get()));

825}

826

833

834 assert(!Operators.isAmbiguous() && "Operator lookup cannot be ambiguous");

839 Functions.end(), false,

840 false);

841 assert(CoawaitOp);

842 return CoawaitOp;

843}

844

848}

849

851 auto *Call = dyn_cast(Operand->IgnoreImplicit());

852 if (Call || Call->isPRValue())

853 return;

854

856 return;

857

858 Call->setCoroElideSafe();

859

860

861 auto *Fn = llvm::dyn_cast_if_present(Call->getCalleeDecl());

862 if (!Fn)

863 return;

864

865 size_t ParmIdx = 0;

866 for (ParmVarDecl *PD : Fn->parameters()) {

867 if (PD->hasAttr())

869

870 ParmIdx++;

871 }

872}

873

874

875

879 if (!FSI)

881

882 if (Operand->hasPlaceholderType()) {

886 Operand = R.get();

887 }

888

889 auto *Promise = FSI->CoroutinePromise;

890 if (Promise->getType()->isDependentType()) {

893 return Res;

894 }

895

897

900

901 if (CurFnAwaitElidable)

903

904 Expr *Transformed = Operand;

910 diag::note_coroutine_promise_implicit_await_transform_required_here)

911 << Operand->getSourceRange();

913 }

914 Transformed = R.get();

915 }

919

921}

922

924 Expr *Awaiter, bool IsImplicit) {

926 if (!Coroutine)

928

932 Awaiter = R.get();

933 }

934

938 return Res;

939 }

940

941

942

945

946

947

948

950

951

953 buildCoawaitCalls(*this, Coroutine->CoroutinePromise, CallLoc, Awaiter);

956

960

961 return Res;

962}

963

967

971 }

972

973

978

979

983

985}

988 if (!Coroutine)

990

995 }

996

997 Expr *Operand = E;

998

1001 return Res;

1002 }

1003

1004

1005

1008

1009

1011 *this, Coroutine->CoroutinePromise, Loc, E);

1014

1018

1019 return Res;

1020}

1021

1026 }

1028}

1029

1031 bool IsImplicit) {

1033 if (!FSI)

1035

1040 E = R.get();

1041 }

1042

1043 VarDecl *Promise = FSI->CoroutinePromise;

1048 } else {

1051 }

1054

1056

1058 return Res;

1059}

1060

1061

1064 assert(Std && "Should already be diagnosed");

1065

1069

1070

1071 S.Diag(Loc, diag::err_implicit_coroutine_std_nothrow_type_not_found);

1072 return nullptr;

1073 }

1074

1076 if (!VD) {

1077 Result.suppressDiagnostics();

1078

1080 S.Diag(Found->getLocation(), diag::err_malformed_std_nothrow);

1081 return nullptr;

1082 }

1083

1086 return nullptr;

1087

1088 return DR.get();

1089}

1090

1096}

1097

1098

1103

1105 assert(PointeeRD && "PromiseType must be a CxxRecordDecl type");

1106

1107 const bool Overaligned = S.getLangOpts().CoroAlignedAllocation;

1108

1109

1110

1111

1112

1114 true, true,

1115 Overaligned))

1116 return false;

1117

1118

1119

1120

1121

1122

1123

1124 if (!OperatorDelete) {

1125

1126

1127 const bool CanProvideSize = true;

1128

1129

1130

1132 Overaligned, DeleteName);

1133

1134 if (!OperatorDelete)

1135 return false;

1136 }

1137

1139 return true;

1140}

1141

1142

1145 assert(Fn && Fn->isCoroutine() && "not a coroutine");

1146 if (!Body) {

1148 "a null body is only allowed for invalid declarations");

1149 return;

1150 }

1151

1152

1153 if (!Fn->CoroutinePromise)

1155

1156 if (isa(Body)) {

1157

1158 return;

1159 }

1160

1161

1162

1163

1164

1165

1166 if (FD->hasAttr())

1167 Diag(FD->getLocation(), diag::warn_always_inline_coroutine);

1168

1169

1170

1171 if (Fn->FirstVLALoc.isValid())

1172 Diag(Fn->FirstVLALoc, diag::err_vla_in_coroutine_unsupported);

1173

1174

1175

1177 Diag(ALE->getBeginLoc(), diag::err_coro_invalid_addr_of_label);

1178

1180 if (Builder.isInvalid() || !Builder.buildStatements())

1182

1183

1185}

1186

1188 if (auto *CS = dyn_cast(Body))

1189 return CS;

1190

1191

1192

1193

1194 assert(isa(Body) && "Unimaged coroutine body type");

1197}

1198

1202 : S(S), FD(FD), Fn(Fn), Loc(FD.getLocation()),

1203 IsPromiseDependentType(

1204 !Fn.CoroutinePromise ||

1205 Fn.CoroutinePromise->getType()->isDependentType()) {

1207

1208 for (auto KV : Fn.CoroutineParameterMoves)

1209 this->ParamMovesVector.push_back(KV.second);

1210 this->ParamMoves = this->ParamMovesVector;

1211

1212 if (!IsPromiseDependentType) {

1213 PromiseRecordDecl = Fn.CoroutinePromise->getType()->getAsCXXRecordDecl();

1214 assert(PromiseRecordDecl && "Type should have already been checked");

1215 }

1216 this->IsValid = makePromiseStmt() && makeInitialAndFinalSuspend();

1217}

1218

1220 assert(this->IsValid && "coroutine already invalid");

1221 this->IsValid = makeReturnObject();

1222 if (this->IsValid && !IsPromiseDependentType)

1224 return this->IsValid;

1225}

1226

1228 assert(this->IsValid && "coroutine already invalid");

1229 assert(!this->IsPromiseDependentType &&

1230 "coroutine cannot have a dependent promise type");

1231 this->IsValid = makeOnException() && makeOnFallthrough() &&

1232 makeGroDeclAndReturnStmt() && makeReturnOnAllocFailure() &&

1233 makeNewAndDeleteExpr();

1234 return this->IsValid;

1235}

1236

1237bool CoroutineStmtBuilder::makePromiseStmt() {

1238

1239

1243 return false;

1244

1246 return true;

1247}

1248

1249bool CoroutineStmtBuilder::makeInitialAndFinalSuspend() {

1251 return false;

1254 return true;

1255}

1256

1261 if (auto *DeclRef = dyn_cast_or_null(E)) {

1262 auto *Decl = DeclRef->getDecl();

1263 if (CXXMethodDecl *Method = dyn_cast_or_null(Decl)) {

1264 if (Method->isStatic())

1265 return true;

1266 else

1268 }

1269 }

1270

1273 diag::err_coroutine_promise_get_return_object_on_allocation_failure)

1274 << PromiseRecordDecl;

1275 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)

1276 << Fn.getFirstCoroutineStmtKeyword();

1277 return false;

1278}

1279

1280bool CoroutineStmtBuilder::makeReturnOnAllocFailure() {

1281 assert(!IsPromiseDependentType &&

1282 "cannot make statement while the promise type is dependent");

1283

1284

1285

1286

1287

1288

1289

1290

1291

1292

1297 return true;

1298

1303 return false;

1304

1306 return false;

1307

1308 ExprResult ReturnObjectOnAllocationFailure =

1310 if (ReturnObjectOnAllocationFailure.isInvalid())

1311 return false;

1312

1316 S.Diag(Found.getFoundDecl()->getLocation(), diag::note_member_declared_here)

1317 << DN;

1320 return false;

1321 }

1322

1324 return true;

1325}

1326

1327

1328

1329

1332 if (auto *MD = dyn_cast(&FD)) {

1336 return false;

1339 return false;

1340 PlacementArgs.push_back(ThisExpr.get());

1341 }

1342 }

1343

1345 if (PD->getType()->isDependentType())

1346 continue;

1347

1348

1349 auto PDLoc = PD->getLocation();

1351 S.BuildDeclRefExpr(PD, PD->getOriginalType().getNonReferenceType(),

1354 return false;

1355

1356 PlacementArgs.push_back(PDRefExpr.get());

1357 }

1358

1359 return true;

1360}

1361

1362bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {

1363

1364 assert(!IsPromiseDependentType &&

1365 "cannot make statement while the promise type is dependent");

1367

1369 return false;

1370

1372

1373

1374

1375

1376

1377

1378

1379

1380

1381

1382

1383

1384

1385

1386

1387

1388

1389

1390

1391

1392

1393

1394

1395

1396

1397

1398

1399

1400

1401

1402

1403

1404

1405

1408

1409 const bool PromiseContainsNew = [this, &PromiseType]() -> bool {

1413

1416

1417 return !R.empty() && !R.isAmbiguous();

1418 }();

1419

1420

1421

1422 bool PassAlignment = S.getLangOpts().CoroAlignedAllocation;

1425 bool WithoutPlacementArgs = false,

1426 bool ForceNonAligned = false) {

1427

1428

1429

1430

1431

1432

1435

1436 PassAlignment = !ForceNonAligned && S.getLangOpts().CoroAlignedAllocation;

1440 false, PassAlignment,

1442 : PlacementArgs,

1443 OperatorNew, UnusedResult, false);

1444 };

1445

1446

1447

1448

1450 return false;

1451

1452 LookupAllocationFunction();

1453

1454 if (PromiseContainsNew && !PlacementArgs.empty()) {

1455

1456

1457

1458

1459

1460

1461

1462

1463

1464

1465

1466

1467 if (!OperatorNew ||

1468 (S.getLangOpts().CoroAlignedAllocation && !PassAlignment))

1470 true);

1471 }

1472

1473

1474

1475

1476

1477

1478

1479

1480

1481

1482

1483

1484

1485

1486

1487

1488

1489

1490

1491 bool FoundNonAlignedInPromise = false;

1492 if (PromiseContainsNew && S.getLangOpts().CoroAlignedAllocation)

1493 if (!OperatorNew || !PassAlignment) {

1494 FoundNonAlignedInPromise = OperatorNew;

1495

1497 false,

1498 true);

1499

1500 if (!OperatorNew && !PlacementArgs.empty())

1502 true,

1503 true);

1504 }

1505

1506 bool IsGlobalOverload =

1507 OperatorNew && !isa(OperatorNew->getDeclContext());

1508

1509

1510

1511 if (RequiresNoThrowAlloc && (!OperatorNew || IsGlobalOverload)) {

1513 if (!StdNoThrow)

1514 return false;

1515 PlacementArgs = {StdNoThrow};

1516 OperatorNew = nullptr;

1518 }

1519

1520

1521

1522

1523 if (FoundNonAlignedInPromise) {

1524 S.Diag(OperatorNew->getLocation(),

1525 diag::warn_non_aligned_allocation_function)

1526 << &FD;

1527 }

1528

1529 if (!OperatorNew) {

1530 if (PromiseContainsNew)

1531 S.Diag(Loc, diag::err_coroutine_unusable_new) << PromiseType << &FD;

1532 else if (RequiresNoThrowAlloc)

1533 S.Diag(Loc, diag::err_coroutine_unfound_nothrow_new)

1534 << &FD << S.getLangOpts().CoroAlignedAllocation;

1535

1536 return false;

1537 }

1538

1539 if (RequiresNoThrowAlloc) {

1540 const auto *FT = OperatorNew->getType()->castAs<FunctionProtoType>();

1541 if (!FT->isNothrow( false)) {

1542 S.Diag(OperatorNew->getLocation(),

1543 diag::err_coroutine_promise_new_requires_nothrow)

1544 << OperatorNew;

1545 S.Diag(Loc, diag::note_coroutine_promise_call_implicitly_required)

1546 << OperatorNew;

1547 return false;

1548 }

1549 }

1550

1553

1554

1555

1556 return false;

1557 }

1558

1559 Expr *FramePtr =

1561

1562 Expr *FrameSize =

1564

1565 Expr *FrameAlignment = nullptr;

1566

1567 if (S.getLangOpts().CoroAlignedAllocation) {

1568 FrameAlignment =

1570

1572 if (!AlignValTy)

1573 return false;

1574

1575 FrameAlignment = S.BuildCXXNamedCast(Loc, tok::kw_static_cast, AlignValTy,

1579 }

1580

1581

1585 return false;

1586

1588 if (S.getLangOpts().CoroAlignedAllocation && PassAlignment)

1589 NewArgs.push_back(FrameAlignment);

1590

1591 if (OperatorNew->getNumParams() > NewArgs.size())

1592 llvm::append_range(NewArgs, PlacementArgs);

1593

1598 return false;

1599

1600

1601

1602 QualType OpDeleteQualType = OperatorDelete->getType();

1603

1607 return false;

1608

1609 Expr *CoroFree =

1611

1613

1614

1615

1616

1617

1618

1619 const auto *OpDeleteType =

1621 if (OpDeleteType->getNumParams() > DeleteArgs.size() &&

1623 OpDeleteType->getParamType(DeleteArgs.size()), FrameSize->getType()))

1624 DeleteArgs.push_back(FrameSize);

1625

1626

1627

1628

1629

1630

1631

1632

1633

1634

1635

1636

1637 if (S.getLangOpts().CoroAlignedAllocation &&

1638 OpDeleteType->getNumParams() > DeleteArgs.size() &&

1640 OpDeleteType->getParamType(DeleteArgs.size()),

1641 FrameAlignment->getType()))

1642 DeleteArgs.push_back(FrameAlignment);

1643

1646 DeleteExpr =

1649 return false;

1650

1653

1654 return true;

1655}

1656

1657bool CoroutineStmtBuilder::makeOnFallthrough() {

1658 assert(!IsPromiseDependentType &&

1659 "cannot make statement while the promise type is dependent");

1660

1661

1662

1663

1664

1665

1666

1667

1668 bool HasRVoid, HasRValue;

1670 lookupMember(S, "return_void", PromiseRecordDecl, Loc, HasRVoid);

1672 lookupMember(S, "return_value", PromiseRecordDecl, Loc, HasRValue);

1673

1675 if (HasRVoid && HasRValue) {

1676

1677 S.Diag(FD.getLocation(),

1678 diag::err_coroutine_promise_incompatible_return_functions)

1679 << PromiseRecordDecl;

1681 diag::note_member_first_declared_here)

1684 diag::note_member_first_declared_here)

1686 return false;

1687 } else if (!HasRVoid && !HasRValue) {

1688

1689

1690

1691

1692

1693

1694

1695

1696

1697

1700 return false;

1701 } else if (HasRVoid) {

1703 true);

1706 return false;

1707 }

1708

1710 return true;

1711}

1712

1713bool CoroutineStmtBuilder::makeOnException() {

1714

1715 assert(!IsPromiseDependentType &&

1716 "cannot make statement while the promise type is dependent");

1717

1718 const bool RequireUnhandledException = S.getLangOpts().CXXExceptions;

1719

1720 if (lookupMember(S, "unhandled_exception", PromiseRecordDecl, Loc)) {

1721 auto DiagID =

1722 RequireUnhandledException

1723 ? diag::err_coroutine_promise_unhandled_exception_required

1724 : diag::

1725 warn_coroutine_promise_unhandled_exception_required_with_exceptions;

1726 S.Diag(Loc, DiagID) << PromiseRecordDecl;

1727 S.Diag(PromiseRecordDecl->getLocation(), diag::note_defined_here)

1728 << PromiseRecordDecl;

1729 return !RequireUnhandledException;

1730 }

1731

1732

1734 return true;

1735

1739 false);

1740 if (UnhandledException.isInvalid())

1741 return false;

1742

1743

1744

1746 S.Diag(Fn.FirstSEHTryLoc, diag::err_seh_in_a_coroutine_with_cxx_exceptions);

1749 return false;

1750 }

1751

1753 return true;

1754}

1755

1756bool CoroutineStmtBuilder::makeReturnObject() {

1757

1758

1759

1763 return false;

1764

1766 return true;

1767}

1768

1770 if (auto *MbrRef = dyn_cast(E)) {

1771 auto *MethodDecl = MbrRef->getMethodDecl();

1772 S.Diag(MethodDecl->getLocation(), diag::note_member_declared_here)

1773 << MethodDecl;

1774 }

1775 S.Diag(Fn.FirstCoroutineStmtLoc, diag::note_declared_coroutine_here)

1776 << Fn.getFirstCoroutineStmtKeyword();

1777}

1778

1779bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() {

1780 assert(!IsPromiseDependentType &&

1781 "cannot make statement while the promise type is dependent");

1782 assert(this->ReturnValue && "ReturnValue must be already formed");

1783

1786 "get_return_object type must no longer be dependent");

1787

1788 QualType const FnRetType = FD.getReturnType();

1790 "get_return_object type must no longer be dependent");

1791

1792

1793

1794

1795

1796

1797

1799

1804 return false;

1805

1806 if (!GroMatchesRetType)

1808 return true;

1809 }

1810

1812

1817 return false;

1818 }

1819

1822 if (GroMatchesRetType) {

1824 } else {

1826 S.Context, &FD, FD.getLocation(), FD.getLocation(),

1830

1833 return false;

1834

1839 return false;

1840

1843 return false;

1844

1846 false);

1847

1849

1850

1851

1855 return false;

1856

1858

1861 return false;

1862

1864 }

1865

1868 return false;

1869 }

1870

1871 if (!GroMatchesRetType &&

1872 castclang::ReturnStmt(ReturnStmt.get())->getNRVOCandidate() == GroDecl)

1874

1875 this->ReturnStmt = ReturnStmt.get();

1876 return true;

1877}

1878

1879

1881 if (T.isNull())

1888

1889 return S

1893}

1894

1895

1902 return Decl;

1903}

1904

1905

1906

1908 assert(isa(CurContext) && "not in a function scope");

1909 auto *FD = cast(CurContext);

1910

1912 if (!ScopeInfo->CoroutineParameterMoves.empty())

1913 return false;

1914

1915

1916

1917

1918

1919

1920

1921 for (auto *PD : FD->parameters()) {

1922 if (PD->getType()->isDependentType())

1923 continue;

1924

1925

1926 bool DeclReferenced = PD->isReferenced();

1927

1931

1932 PD->setReferenced(DeclReferenced);

1933

1935 return false;

1936

1937 Expr *CExpr = nullptr;

1938 if (PD->getType()->getAsCXXRecordDecl() ||

1939 PD->getType()->isRValueReferenceType())

1941 else

1942 CExpr = PDRefExpr.get();

1943

1944

1945

1946 auto *D = buildVarDecl(*this, Loc, PD->getType(), PD->getIdentifier());

1948

1949

1951 if (Stmt.isInvalid())

1952 return false;

1953

1954 ScopeInfo->CoroutineParameterMoves.insert(std::make_pair(PD, Stmt.get()));

1955 }

1956 return true;

1957}

1958

1961 if (!Res)

1963 return Res;

1964}

1965

1970

1973

1977

1979

1980 Diag(KwLoc, diag::err_implied_coroutine_type_not_found)

1981 << "std::coroutine_traits";

1982 return nullptr;

1983 }

1984

1985

1988 Result.suppressDiagnostics();

1990 Diag(Found->getLocation(), diag::err_malformed_std_coroutine_traits);

1991 return nullptr;

1992 }

1993

1995}

This file provides some common utility functions for processing Lambda related AST Constructs.

Defines enum values for all the target-independent builtin functions.

Defines the clang::Expr interface and subclasses for C++ expressions.

llvm::MachO::Record Record

Defines the clang::Preprocessor interface.

static ExprResult buildCoroutineHandle(Sema &S, QualType PromiseType, SourceLocation Loc)

static void noteMemberDeclaredHere(Sema &S, Expr *E, FunctionScopeInfo &Fn)

static void checkReturnStmtInCoroutine(Sema &S, FunctionScopeInfo *FSI)

static bool isValidCoroutineContext(Sema &S, SourceLocation Loc, StringRef Keyword)

static void applySafeElideContext(Expr *Operand)

static Expr * buildStdNoThrowDeclRef(Sema &S, SourceLocation Loc)

Look up the std::nothrow object.

static ExprResult buildOperatorCoawaitCall(Sema &SemaRef, Scope *S, SourceLocation Loc, Expr *E)

static bool diagReturnOnAllocFailure(Sema &S, Expr *E, CXXRecordDecl *PromiseRecordDecl, FunctionScopeInfo &Fn)

static ExprResult buildPromiseCall(Sema &S, VarDecl *Promise, SourceLocation Loc, StringRef Name, MultiExprArg Args)

static Expr * castForMoving(Sema &S, Expr *E, QualType T=QualType())

static Expr * maybeTailCall(Sema &S, QualType RetType, Expr *E, SourceLocation Loc)

static ExprResult buildMemberCall(Sema &S, Expr *Base, SourceLocation Loc, StringRef Name, MultiExprArg Args)

static LookupResult lookupMember(Sema &S, const char *Name, CXXRecordDecl *RD, SourceLocation Loc, bool &Res)

static TypeSourceInfo * getTypeSourceInfoForStdAlignValT(Sema &S, SourceLocation Loc)

static bool isWithinCatchScope(Scope *S)

static bool findDeleteForPromise(Sema &S, SourceLocation Loc, QualType PromiseType, FunctionDecl *&OperatorDelete)

static VarDecl * buildVarDecl(Sema &S, SourceLocation Loc, QualType Type, IdentifierInfo *II)

Build a variable declaration for move parameter.

static void checkNoThrow(Sema &S, const Stmt *E, llvm::SmallPtrSetImpl< const Decl * > &ThrowingDecls)

Recursively check E and all its children to see if any call target (including constructor call) is de...

static ReadySuspendResumeResult buildCoawaitCalls(Sema &S, VarDecl *CoroPromise, SourceLocation Loc, Expr *E)

Build calls to await_ready, await_suspend, and await_resume for a co_await expression.

static bool checkSuspensionContext(Sema &S, SourceLocation Loc, StringRef Keyword)

static QualType lookupCoroutineHandleType(Sema &S, QualType PromiseType, SourceLocation Loc)

Look up the std::coroutine_handle.

static bool collectPlacementArgs(Sema &S, FunctionDecl &FD, SourceLocation Loc, SmallVectorImpl< Expr * > &PlacementArgs)

static CompoundStmt * buildCoroutineBody(Stmt *Body, ASTContext &Context)

static QualType lookupPromiseType(Sema &S, const FunctionDecl *FD, SourceLocation KwLoc)

Look up the std::coroutine_traits<...>::promise_type for the given function type.

static bool isAttributedCoroAwaitElidable(const QualType &QT)

static FunctionScopeInfo * checkCoroutineContext(Sema &S, SourceLocation Loc, StringRef Keyword, bool IsImplicit=false)

Check that this is a context in which a coroutine suspension can appear.

Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...

QualType getRValueReferenceType(QualType T) const

Return the uniqued reference to the type for an rvalue reference to the specified type.

DeclarationNameTable DeclarationNames

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.

QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl=nullptr) const

Return the unique reference to the type for the specified type declaration.

TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc=SourceLocation()) const

Allocate a TypeSourceInfo where all locations have been initialized to a given location,...

QualType getElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, QualType NamedType, TagDecl *OwnedTagDecl=nullptr) const

bool hasSameUnqualifiedType(QualType T1, QualType T2) const

Determine whether the given types are equivalent after cvr-qualifiers have been removed.

AddrLabelExpr - The GNU address of label extension, representing &&label.

SourceLocation getBeginLoc() const LLVM_READONLY

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.

CXXDestructorDecl * getDestructor() const

Returns the destructor decl for this class.

Represents a C++ nested-name-specifier or a global scope specifier.

CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).

FunctionDecl * getDirectCallee()

If the callee is a FunctionDecl, return it. Otherwise return null.

QualType getCallReturnType(const ASTContext &Ctx) const

getCallReturnType - Get the return type of the call expr.

Declaration of a class template.

void setExprNeedsCleanups(bool SideEffects)

Represents a 'co_await' expression.

CompoundStmt - This represents a group of statements like { stmt stmt }.

static CompoundStmt * Create(const ASTContext &C, ArrayRef< Stmt * > Stmts, FPOptionsOverride FPFeatures, SourceLocation LB, SourceLocation RB)

Represents a 'co_return' statement in the C++ Coroutines TS.

Represents the body of a coroutine.

static CoroutineBodyStmt * Create(const ASTContext &C, CtorArgs const &Args)

CoroutineStmtBuilder(Sema &S, FunctionDecl &FD, sema::FunctionScopeInfo &Fn, Stmt *Body)

Construct a CoroutineStmtBuilder and initialize the promise statement and initial/final suspends from...

bool buildDependentStatements()

Build the coroutine body statements that require a non-dependent promise type in order to construct.

bool buildStatements()

Build the coroutine body statements, including the "promise dependent" statements when the promise ty...

Represents a 'co_yield' expression.

DeclContext - This is used only as base class of specific decl types that can act as declaration cont...

Decl - This represents one declaration (or definition), e.g.

SourceLocation getEndLoc() const LLVM_READONLY

void setInvalidDecl(bool Invalid=true)

setInvalidDecl - Indicates the Decl had a semantic error.

bool isInvalidDecl() const

SourceLocation getLocation() const

void setImplicit(bool I=true)

The name of a declaration.

SourceLocation getBeginLoc() const LLVM_READONLY

Represents a 'co_await' expression while the type of the promise is dependent.

RAII object that enters a new expression evaluation context.

This represents one expression.

ExprObjectKind getObjectKind() const

getObjectKind - The object kind that this expression produces.

SourceLocation getExprLoc() const LLVM_READONLY

getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...

bool hasPlaceholderType() const

Returns whether this expression has a placeholder type.

Represents difference between two FPOptions values.

Represents a function declaration or definition.

ArrayRef< ParmVarDecl * > parameters() const

Represents a prototype with parameter type info, e.g.

ArrayRef< QualType > getParamTypes() const

RefQualifierKind getRefQualifier() const

Retrieve the ref-qualifier associated with this function type.

QualType getReturnType() const

One of these records is kept for each identifier that is lexed.

IdentifierInfo & get(StringRef Name)

Return the identifier token info for the specified named identifier.

Describes the kind of initialization being performed, along with location information for tokens rela...

static InitializationKind CreateForInit(SourceLocation Loc, bool DirectInit, Expr *Init)

Create an initialization from an initializer (which, for direct initialization from a parenthesized l...

Describes the sequence of initializations required to initialize a given object or reference with a s...

ExprResult Perform(Sema &S, const InitializedEntity &Entity, const InitializationKind &Kind, MultiExprArg Args, QualType *ResultType=nullptr)

Perform the actual initialization of the given entity based on the computed initialization sequence.

Describes an entity that is being initialized.

static InitializedEntity InitializeResult(SourceLocation ReturnLoc, QualType Type)

Create the initialization entity for the result of a function.

static InitializedEntity InitializeVariable(VarDecl *Var)

Create the initialization entity for a variable.

Represents the results of name lookup.

DeclClass * getAsSingle() const

const UnresolvedSetImpl & asUnresolvedSet() const

NamedDecl * getRepresentativeDecl() const

Fetches a representative decl. Useful for lazy diagnostics.

void suppressDiagnostics()

Suppress the diagnostics that would normally fire because of this lookup.

DeclarationName getLookupName() const

Gets the name to look up.

This represents a decl that may have a name.

Represent a C++ namespace.

A C++ nested-name-specifier augmented with source location information.

static NestedNameSpecifier * Create(const ASTContext &Context, NestedNameSpecifier *Prefix, const IdentifierInfo *II)

Builds a specifier combining a prefix and an identifier.

OpaqueValueExpr - An expression referring to an opaque object of a fixed type and value class.

decls_iterator decls_begin() const

decls_iterator decls_end() const

static ParenListExpr * Create(const ASTContext &Ctx, SourceLocation LParenLoc, ArrayRef< Expr * > Exprs, SourceLocation RParenLoc)

Create a paren list.

Represents a parameter to a function.

IdentifierInfo * getIdentifierInfo(StringRef Name) const

Return information about the specified preprocessor identifier token.

IdentifierTable & getIdentifierTable()

A (possibly-)qualified type.

bool isNull() const

Return true if this QualType doesn't point to a type yet.

const Type * getTypePtr() const

Retrieves a pointer to the underlying (unqualified) type.

QualType getNonReferenceType() const

If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...

QualType getCanonicalType() const

DestructionKind isDestructedType() const

Returns a nonzero value if objects of this type require non-trivial work to clean up after.

ReturnStmt - This represents a return, optionally of an expression: return; return 4;.

Scope - A scope is a transient data structure that is used while parsing the program.

SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)

Emit a diagnostic.

Sema - This implements semantic analysis and AST building for C.

FunctionDecl * FindUsualDeallocationFunction(SourceLocation StartLoc, bool CanProvideSize, bool Overaligned, DeclarationName Name)

ExprResult BuildOperatorCoawaitCall(SourceLocation Loc, Expr *E, UnresolvedLookupExpr *Lookup)

Build a call to 'operator co_await' if there is a suitable operator for the given expression.

Scope * getCurScope() const

Retrieve the parser's current scope.

ExprResult BuildMemberReferenceExpr(Expr *Base, QualType BaseType, SourceLocation OpLoc, bool IsArrow, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierInScope, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs, const Scope *S, ActOnMemberAccessExtraArgs *ExtraArgs=nullptr)

ExprResult CreateBuiltinUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, Expr *InputExpr, bool IsAfterAmp=false)

@ LookupOrdinaryName

Ordinary name lookup, which finds ordinary names (functions, variables, typedefs, etc....

@ LookupOperatorName

Look up of an operator name (e.g., operator+) for use with operator overloading.

@ LookupMemberName

Member name lookup, which finds the names of class/struct/union members.

bool checkFinalSuspendNoThrow(const Stmt *FinalSuspend)

Check that the expression co_await promise.final_suspend() shall not be potentially-throwing.

StmtResult BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs)

ExprResult BuildCoyieldExpr(SourceLocation KwLoc, Expr *E)

void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body)

bool ActOnCoroutineBodyStart(Scope *S, SourceLocation KwLoc, StringRef Keyword)

VarDecl * buildCoroutinePromise(SourceLocation Loc)

StmtResult BuildCoreturnStmt(SourceLocation KwLoc, Expr *E, bool IsImplicit=false)

Expr * BuildBuiltinCallExpr(SourceLocation Loc, Builtin::ID Id, MultiExprArg CallArgs)

BuildBuiltinCallExpr - Create a call to a builtin function specified by Id.

ExprResult BuildResolvedCoawaitExpr(SourceLocation KwLoc, Expr *Operand, Expr *Awaiter, bool IsImplicit=false)

FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const

Returns a pointer to the innermost enclosing function, or nullptr if the current context is not insid...

void FinalizeDeclaration(Decl *D)

FinalizeDeclaration - called by ParseDeclarationAfterDeclarator to perform any semantic actions neces...

ExprResult ActOnCoyieldExpr(Scope *S, SourceLocation KwLoc, Expr *E)

DeclGroupPtrTy ConvertDeclToDeclGroup(Decl *Ptr, Decl *OwnedType=nullptr)

ClassTemplateDecl * StdCoroutineTraitsCache

The C++ "std::coroutine_traits" template, which is defined in <coroutine_traits>

ASTContext & getASTContext() const

DeclRefExpr * BuildDeclRefExpr(ValueDecl *D, QualType Ty, ExprValueKind VK, SourceLocation Loc, const CXXScopeSpec *SS=nullptr)

EnumDecl * getStdAlignValT() const

NamedReturnInfo getNamedReturnInfo(Expr *&E, SimplerImplicitMoveMode Mode=SimplerImplicitMoveMode::Normal)

Determine whether the given expression might be move-eligible or copy-elidable in either a (co_)retur...

StmtResult ActOnCoreturnStmt(Scope *S, SourceLocation KwLoc, Expr *E)

const LangOptions & getLangOpts() const

StmtResult ActOnFinishFullStmt(Stmt *Stmt)

ExprResult BuildCallExpr(Scope *S, Expr *Fn, SourceLocation LParenLoc, MultiExprArg ArgExprs, SourceLocation RParenLoc, Expr *ExecConfig=nullptr, bool IsExecConfig=false, bool AllowRecovery=false)

BuildCallExpr - Handle a call to Fn with the specified array of arguments.

bool FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, AllocationFunctionScope NewScope, AllocationFunctionScope DeleteScope, QualType AllocType, bool IsArray, bool &PassAlignment, MultiExprArg PlaceArgs, FunctionDecl *&OperatorNew, FunctionDecl *&OperatorDelete, bool Diagnose=true)

Finds the overloads of operator new and delete that are appropriate for the allocation.

CleanupInfo Cleanup

Used to control the generation of ExprWithCleanups.

StmtResult ActOnNullStmt(SourceLocation SemiLoc, bool HasLeadingEmptyMacro=false)

ExprResult BuildUnresolvedCoawaitExpr(SourceLocation KwLoc, Expr *Operand, UnresolvedLookupExpr *Lookup)

bool buildCoroutineParameterMoves(SourceLocation Loc)

sema::FunctionScopeInfo * getCurFunction() const

QualType BuildReferenceType(QualType T, bool LValueRef, SourceLocation Loc, DeclarationName Entity)

Build a reference type.

ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc, UnaryOperatorKind Opc, const UnresolvedSetImpl &Fns, Expr *input, bool RequiresADL=true)

Create a unary operation that may resolve to an overloaded operator.

ExprResult ActOnCoawaitExpr(Scope *S, SourceLocation KwLoc, Expr *E)

ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, bool NeedsADL, bool AcceptInvalidDecl=false)

DeclContext * CurContext

CurContext - This is the current declaration context of parsing.

bool FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD, DeclarationName Name, FunctionDecl *&Operator, bool Diagnose=true, bool WantSize=false, bool WantAligned=false)

MaterializeTemporaryExpr * CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary, bool BoundToLvalueReference)

ExprResult PerformContextuallyConvertToBool(Expr *From)

PerformContextuallyConvertToBool - Perform a contextual conversion of the expression From to bool (C+...

bool isUnevaluatedContext() const

Determines whether we are currently in a context that is not evaluated as per C++ [expr] p5.

ExprResult CheckPlaceholderExpr(Expr *E)

Check for operands with placeholder types and complain if found.

ClassTemplateDecl * lookupCoroutineTraits(SourceLocation KwLoc, SourceLocation FuncLoc)

Lookup 'coroutine_traits' in std namespace and std::experimental namespace.

DeclContext * computeDeclContext(QualType T)

Compute the DeclContext that is associated with the given type.

QualType CheckTemplateIdType(TemplateName Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs)

StmtResult BuildReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, bool AllowRecovery=false)

void CheckCompleteVariableDeclaration(VarDecl *VD)

@ PotentiallyEvaluated

The current expression is potentially evaluated at run time, which means that code may be generated t...

ExprResult BuildOperatorCoawaitLookupExpr(Scope *S, SourceLocation Loc)

StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc)

bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)

Ensure that the type T is a complete type.

bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup=false)

Perform qualified name lookup into a given context.

Expr * MaybeCreateExprWithCleanups(Expr *SubExpr)

MaybeCreateExprWithCleanups - If the current full-expression requires any cleanups,...

FullExprArg MakeFullDiscardedValueExpr(Expr *Arg)

NamespaceDecl * getStdNamespace() const

ExprResult PerformCopyInitialization(const InitializedEntity &Entity, SourceLocation EqualLoc, ExprResult Init, bool TopLevelOfInitList=false, bool AllowExplicit=false)

void ActOnUninitializedDecl(Decl *dcl)

void AddInitializerToDecl(Decl *dcl, Expr *init, bool DirectInit)

AddInitializerToDecl - Adds the initializer Init to the declaration dcl.

ExprResult BuildCXXNamedCast(SourceLocation OpLoc, tok::TokenKind Kind, TypeSourceInfo *Ty, Expr *E, SourceRange AngleBrackets, SourceRange Parens)

void MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, bool MightBeOdrUse=true)

Mark a function referenced, and check whether it is odr-used (C++ [basic.def.odr]p2,...

void clearDelayedTypo(TypoExpr *TE)

Clears the state of the given TypoExpr.

void CheckVariableDeclarationType(VarDecl *NewVD)

bool LookupName(LookupResult &R, Scope *S, bool AllowBuiltinCreation=false, bool ForceNoCPlusPlus=false)

Perform unqualified name lookup starting from a given scope.

ExprResult ActOnCXXThis(SourceLocation Loc)

AllocationFunctionScope

The scope in which to find allocation functions.

@ AFS_Both

Look for allocation functions in both the global scope and in the scope of the allocated class.

@ AFS_Class

Only look for allocation functions in the scope of the allocated class.

@ AFS_Global

Only look for allocation functions in the global scope.

ExprResult CorrectDelayedTyposInExpr(Expr *E, VarDecl *InitDecl=nullptr, bool RecoverUncorrectedTypos=false, llvm::function_ref< ExprResult(Expr *)> Filter=[](Expr *E) -> ExprResult { return E;})

Process any TypoExprs in the given Expr and its children, generating diagnostics as appropriate and r...

static CanThrowResult canCalleeThrow(Sema &S, const Expr *E, const Decl *D, SourceLocation Loc=SourceLocation())

Determine whether the callee of a particular function call can throw.

ExprResult ActOnFinishFullExpr(Expr *Expr, bool DiscardedValue)

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.

Stmt - This represents one statement.

SourceRange getSourceRange() const LLVM_READONLY

SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...

SourceLocation getBeginLoc() const LLVM_READONLY

A convenient class for passing around template argument information.

void addArgument(const TemplateArgumentLoc &Loc)

Location wrapper for a TemplateArgument.

Represents a template argument.

Represents a C++ template name within the type system.

Represents a declaration of a type.

A container of type source information.

The base class of the type hierarchy.

bool isStructureType() const

CXXRecordDecl * getAsCXXRecordDecl() const

Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...

bool isBooleanType() const

bool isVoidPointerType() const

const T * castAs() const

Member-template castAs.

bool isReferenceType() const

bool isDependentType() const

Whether this type is a dependent type, meaning that its definition somehow depends on a template para...

bool isRecordType() const

A reference to a name which we were able to look up during parsing but could not resolve to a specifi...

static UnresolvedLookupExpr * Create(const ASTContext &Context, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, bool RequiresADL, UnresolvedSetIterator Begin, UnresolvedSetIterator End, bool KnownDependent, bool KnownInstantiationDependent)

void append(iterator I, iterator E)

A set of unresolved declarations.

Represents a variable declaration or definition.

static VarDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, const IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S)

@ CallInit

Call-style initialization (C++98)

void setNRVOVariable(bool NRVO)

Retains information about a function, method, or block that is currently being parsed.

SourceLocation FirstCoroutineStmtLoc

First coroutine statement in the current function.

std::pair< Stmt *, Stmt * > CoroutineSuspends

The initial and final coroutine suspend points.

VarDecl * CoroutinePromise

The promise object for this coroutine, if any.

bool hasInvalidCoroutineSuspends() const

StringRef getFirstCoroutineStmtKeyword() const

SourceLocation FirstReturnLoc

First 'return' statement in the current function.

SourceLocation FirstSEHTryLoc

First SEH '__try' statement in the current function.

The JSON file list parser is used to communicate input to InstallAPI.

@ RQ_RValue

An rvalue ref-qualifier was provided (&&).

bool isLambdaCallOperator(const CXXMethodDecl *MD)

@ Result

The result type of a method or function.

@ VK_LValue

An l-value expression is a reference to an object with independent storage.

const FunctionProtoType * T

OpaqueValueExpr * OpaqueValue

Stmt * ReturnStmtOnAllocFailure

ArrayRef< Stmt * > ParamMoves

DeclarationNameInfo - A collector data type for bundling together a DeclarationName and the correspon...

DeclarationName getName() const

getName - Returns the embedded declaration name.