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

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 nullptr, false);

95 if (CoroTrait.isNull())

98 diag::err_coroutine_type_missing_specialization))

100

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

103

104

109 if (!Promise) {

110 S.Diag(FuncLoc,

111 diag::err_implied_std_coroutine_traits_promise_type_not_found)

112 << RD;

114 }

115

118 Qualifier, Promise);

119

121 S.Diag(FuncLoc,

122 diag::err_implied_std_coroutine_traits_promise_type_not_class)

123 << PromiseType;

125 }

127 diag::err_coroutine_promise_type_incomplete))

129

130 return PromiseType;

131}

132

133

136 if (PromiseType.isNull())

138

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

141

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

146 << "std::coroutine_handle";

148 }

149

151 if (!CoroHandle) {

152 Result.suppressDiagnostics();

153

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

157 }

158

159

164

165

168 nullptr, false);

169 if (CoroHandleType.isNull())

172 diag::err_coroutine_type_missing_specialization))

174

175 return CoroHandleType;

176}

177

180

181

182

183

184

185

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

187 if (!FD) {

189 ? diag::err_coroutine_objc_method

190 : diag::err_coroutine_outside_function) << Keyword;

191 return false;

192 }

193

194

195

196 enum InvalidFuncDiag {

197 DiagCtor = 0,

198 DiagDtor,

199 DiagMain,

200 DiagConstexpr,

201 DiagAutoRet,

202 DiagVarargs,

203 DiagConsteval,

204 };

205 bool Diagnosed = false;

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

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

208 Diagnosed = true;

209 return false;

210 };

211

212

213

214 auto *MD = dyn_cast(FD);

215

217 return DiagInvalid(DiagCtor);

218

220 return DiagInvalid(DiagDtor);

221

222 else if (FD->isMain())

223 return DiagInvalid(DiagMain);

224

225

226

227

228

229 if (FD->isConstexpr())

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

231

232

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

234 DiagInvalid(DiagAutoRet);

235

236

237

238 if (FD->isVariadic())

239 DiagInvalid(DiagVarargs);

240

241 return !Diagnosed;

242}

243

244

245

252

261

265 if (CoroHandleType.isNull())

267

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

273 << "from_address";

275 }

276

277 Expr *FramePtr =

279

285

286 return S.BuildCallExpr(nullptr, FromAddr.get(), Loc, FramePtr, Loc);

287}

288

295

299

300

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

304 SourceLocation(), nullptr, NameInfo, nullptr,

305 nullptr);

306 if (Result.isInvalid())

308

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

310 return S.BuildCallExpr(nullptr, Result.get(), Loc, Args, EndLoc, nullptr);

311}

312

313

314

315

316

320 return nullptr;

322 if (T->isClassType() && T->isStructureType())

323 return nullptr;

324

325

326

327

328

331 return nullptr;

332

333 Expr *JustAddress = AddressExpr.get();

334

335

338 diag::warn_coroutine_handle_address_invalid_return_type)

339 << JustAddress->getType();

340

341

342

344}

345

346

347

348

349

350

351

352

353

354

355

356

357

362

363

364

366

368

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

372 if (Result.isInvalid()) {

374 return nullptr;

375 }

376 Calls.Results[CallType] = Result.get();

377 return Result.get();

378 };

379

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

382 if (!AwaitReady)

383 return Calls;

385

386

387

391 diag::note_await_ready_no_bool_conversion);

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

395 } else

397 }

398

403 return Calls;

404 }

405 Expr *CoroHandle = CoroHandleRes.get();

406 CallExpr *AwaitSuspend = cast_or_null(

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

408 if (!AwaitSuspend)

409 return Calls;

411

412

413

414

416

417

418 if (Expr *TailCallSuspend =

420

421

422

423

424

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

426 else {

427

431 diag::err_await_suspend_invalid_return_type)

432 << RetType;

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

436 } else

437 Calls.Results[ACT::ACT_Suspend] =

439 }

440 }

441

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

443

444

446

447 return Calls;

448}

449

462

466 bool IsThisDependentType = [&] {

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

468 return MD->isImplicitObjectMemberFunction() &&

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

470 return false;

471 }();

472

473 QualType T = FD->getType()->isDependentType() || IsThisDependentType

476 if (T.isNull())

477 return nullptr;

478

480 &PP.getIdentifierTable().get("__promise"), T,

482 VD->setImplicit();

484 if (VD->isInvalidDecl())

485 return nullptr;

486

488

489

490

492

493

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

498 return nullptr;

501 return nullptr;

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

503 }

504 }

505

506

507 auto &Moves = ScopeInfo->CoroutineParameterMoves;

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

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

510 continue;

511

513 auto Move = Moves.find(PD);

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

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

516

517

518 auto *MoveDecl =

520 RefExpr =

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

523 if (RefExpr.isInvalid())

524 return nullptr;

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

526 }

527

528

529

530 if (!CtorArgExprs.empty()) {

531

532

534 CtorArgExprs, FD->getLocation());

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

539 false,

540 false);

541

542

543

544

545

546

547

548 if (InitSeq) {

550 if (Result.isInvalid()) {

551 VD->setInvalidDecl();

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

556 }

557 } else

559 } else

561

562 FD->addDecl(VD);

563 return VD;

564}

565

566

569 bool IsImplicit = false) {

571 return nullptr;

572

574

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

577

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

579 ScopeInfo->setFirstCoroutineStmt(Loc, Keyword);

580

581 if (ScopeInfo->CoroutinePromise)

582 return ScopeInfo;

583

585 return nullptr;

586

588 if (!ScopeInfo->CoroutinePromise)

589 return nullptr;

590

591 return ScopeInfo;

592}

593

594

595

596

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

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

600

601

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

604

605

606

607

608

609

610

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

612 return;

613 }

614 if (ThrowingDecls.empty()) {

615

616

617

618

619

621 diag::err_coroutine_promise_final_suspend_requires_nothrow);

622 }

623 ThrowingDecls.insert(D);

624 }

625 };

626

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

629 checkDeclNoexcept(Ctor);

630

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

633 if (CE->isTypeDependent())

634 return;

635

636 checkDeclNoexcept(CE->getCalleeDecl());

638

641 const auto *T =

643 checkDeclNoexcept(

645 true);

646 }

647 } else

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

649 if (!Child)

650 continue;

652 }

653}

654

657

658

659

660

661 checkNoThrow(*this, FinalSuspend, ThrowingDecls);

663 ThrowingDecls.end()};

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

666 });

667 for (const auto *D : SortedDecls) {

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

669 }

670 return ThrowingDecls.empty();

671}

672

673

674

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

678 "first coroutine location not set");

680 return;

684}

685

688

691 dyn_cast_or_null(CurContext));

692

694 return false;

696 assert(ScopeInfo->CoroutinePromise);

697

698

699 if (ScopeInfo->FirstCoroutineStmtLoc == KWLoc)

701

702

703

704 if (!ScopeInfo->NeedsCoroutineSuspends)

705 return true;

706

707 ScopeInfo->setNeedsCoroutineSuspends(false);

708

711

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

714 buildPromiseCall(*this, ScopeInfo->CoroutinePromise, Loc, Name, {});

715 if (Operand.isInvalid())

722 true);

725 Diag(Loc, diag::note_coroutine_promise_suspend_implicitly_required)

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

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

729 }

731 };

732

733 StmtResult InitSuspend = buildSuspends("initial_suspend");

735 return true;

736

737 StmtResult FinalSuspend = buildSuspends("final_suspend");

739 return true;

740

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

742

743 return true;

744}

745

746

747

749

750

751

752

753

754

755

756

757

758

759

760

761

762

765 return true;

767 }

768 return false;

769}

770

771

772

773

774

775

778

779

780

782 const bool BadContext =

786 if (BadContext) {

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

788 return false;

789 }

790

791

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

794 return false;

795 }

796 return true;

797}

798

802

805 }

806

810 E = R.get();

811 }

812

818}

819

822 Context.DeclarationNames.getCXXOperatorName(OO_Coawait);

826

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

831 DeclarationNameInfo(OpName, Loc), true, Functions.begin(),

832 Functions.end(), false,

833 false);

834 assert(CoawaitOp);

835 return CoawaitOp;

836}

837

840 return Record && Record->hasAttr();

841}

842

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

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

846 return;

847

849 return;

850

851 Call->setCoroElideSafe();

852

853

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

855 if (!Fn)

856 return;

857

858 size_t ParmIdx = 0;

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

860 if (PD->hasAttr())

862

863 ParmIdx++;

864 }

865}

866

867

868

872 if (!FSI)

874

875 if (Operand->hasPlaceholderType()) {

879 Operand = R.get();

880 }

881

882 auto *Promise = FSI->CoroutinePromise;

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

886 return Res;

887 }

888

889 auto *RD = Promise->getType()->getAsCXXRecordDecl();

890

893

894 if (CurFnAwaitElidable)

896

897 Expr *Transformed = Operand;

898 if (lookupMember(*this, "await_transform", RD, Loc)) {

900 buildPromiseCall(*this, Promise, Loc, "await_transform", Operand);

903 diag::note_coroutine_promise_implicit_await_transform_required_here)

904 << Operand->getSourceRange();

906 }

907 Transformed = R.get();

908 }

912

914}

915

917 Expr *Awaiter, bool IsImplicit) {

919 if (!Coroutine)

921

925 Awaiter = R.get();

926 }

927

931 return Res;

932 }

933

934

935

938

939

940

941

943

944

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

949

953

954 return Res;

955}

956

960

963 }

964

965

967 *this, getCurFunction()->CoroutinePromise, Loc, "yield_value", E);

970

971

975

977}

980 if (!Coroutine)

982

986 E = R.get();

987 }

988

989 Expr *Operand = E;

990

993 return Res;

994 }

995

996

997

1000

1001

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

1006

1010

1011 return Res;

1012}

1013

1020

1022 bool IsImplicit) {

1024 if (!FSI)

1026

1031 E = R.get();

1032 }

1033

1034 VarDecl *Promise = FSI->CoroutinePromise;

1038 PC = buildPromiseCall(*this, Promise, Loc, "return_value", E);

1039 } else {

1041 PC = buildPromiseCall(*this, Promise, Loc, "return_void", {});

1042 }

1045

1047

1049 return Res;

1050}

1051

1052

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

1056

1060

1061

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

1063 return nullptr;

1064 }

1065

1066 auto *VD = Result.getAsSingle<VarDecl>();

1067 if (!VD) {

1068 Result.suppressDiagnostics();

1069

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

1072 return nullptr;

1073 }

1074

1077 return nullptr;

1078

1079 return DR.get();

1080}

1081

1088

1089

1090

1092 unsigned DiagnosticID,

1096

1099 bool HaveIssuedWarning = false;

1100 for (auto Decl : R) {

1102 continue;

1103 if (!HaveIssuedWarning) {

1104 S.Diag(Loc, DiagnosticID) << Name;

1105 HaveIssuedWarning = true;

1106 }

1109 }

1111 return HaveIssuedWarning;

1112}

1113

1114

1120 diag::warn_coroutine_type_aware_allocator_ignored,

1121 DeleteName, PromiseType);

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

1124

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

1126

1127

1128

1129

1130

1134 IDP, true))

1135 return false;

1136

1137

1138

1139

1140

1141

1142

1143 if (!OperatorDelete) {

1144

1145

1146

1147

1148

1151

1152 if (!OperatorDelete)

1153 return false;

1154 }

1155

1156 assert(!OperatorDelete->isTypeAwareOperatorNewOrDelete());

1158 return true;

1159}

1160

1161

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

1165 if (!Body) {

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

1168 return;

1169 }

1170

1171

1172 if (!Fn->CoroutinePromise)

1174

1176

1177 return;

1178 }

1179

1180

1181

1182

1183

1184

1185 if (FD->hasAttr())

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

1187

1188

1189

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

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

1192

1193

1194

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

1197

1198

1200 Diag(FD->getLocation(), diag::warn_noreturn_coroutine) << FD;

1201

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

1205

1206

1208}

1209

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

1212 return CS;

1213

1214

1215

1216

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

1220}

1221

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

1226 IsPromiseDependentType(

1227 !Fn.CoroutinePromise ||

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

1230

1231 for (auto KV : Fn.CoroutineParameterMoves)

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

1233 this->ParamMoves = this->ParamMovesVector;

1234

1235 if (!IsPromiseDependentType) {

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

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

1238 }

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

1240}

1241

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

1244 this->IsValid = makeReturnObject();

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

1247 return this->IsValid;

1248}

1249

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

1252 assert(!this->IsPromiseDependentType &&

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

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

1255 makeGroDeclAndReturnStmt() && makeReturnOnAllocFailure() &&

1256 makeNewAndDeleteExpr();

1257 return this->IsValid;

1258}

1259

1260bool CoroutineStmtBuilder::makePromiseStmt() {

1261

1262

1266 return false;

1267

1269 return true;

1270}

1271

1272bool CoroutineStmtBuilder::makeInitialAndFinalSuspend() {

1274 return false;

1277 return true;

1278}

1279

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

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

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

1287 if (Method->isStatic())

1288 return true;

1289 else

1291 }

1292 }

1293

1295 Loc,

1296 diag::err_coroutine_promise_get_return_object_on_allocation_failure)

1297 << PromiseRecordDecl;

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

1299 << Fn.getFirstCoroutineStmtKeyword();

1300 return false;

1301}

1302

1303bool CoroutineStmtBuilder::makeReturnOnAllocFailure() {

1304 assert(!IsPromiseDependentType &&

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

1306

1307

1308

1309

1310

1311

1312

1313

1314

1315

1316 DeclarationName DN =

1317 S.PP.getIdentifierInfo("get_return_object_on_allocation_failure");

1319 if (!S.LookupQualifiedName(Found, PromiseRecordDecl))

1320 return true;

1321

1322 CXXScopeSpec SS;

1324 S.BuildDeclarationNameExpr(SS, Found, false);

1326 return false;

1327

1329 return false;

1330

1331 ExprResult ReturnObjectOnAllocationFailure =

1332 S.BuildCallExpr(nullptr, DeclNameExpr.get(), Loc, {}, Loc);

1333 if (ReturnObjectOnAllocationFailure.isInvalid())

1334 return false;

1335

1337 S.BuildReturnStmt(Loc, ReturnObjectOnAllocationFailure.get());

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

1340 << DN;

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

1342 << Fn.getFirstCoroutineStmtKeyword();

1343 return false;

1344 }

1345

1347 return true;

1348}

1349

1350

1351

1352

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

1359 return false;

1362 return false;

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

1364 }

1365 }

1366

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

1369 continue;

1370

1371

1372 auto PDLoc = PD->getLocation();

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

1377 return false;

1378

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

1380 }

1381

1382 return true;

1383}

1384

1385bool CoroutineStmtBuilder::makeNewAndDeleteExpr() {

1386

1387 assert(!IsPromiseDependentType &&

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

1389 QualType PromiseType = Fn.CoroutinePromise->getType();

1390

1391 if (S.RequireCompleteType(Loc, PromiseType, diag::err_incomplete_type))

1392 return false;

1393

1395

1396

1397

1398

1399

1400

1401

1402

1403

1404

1405

1406

1407

1408

1409

1410

1411

1412

1413

1414

1415

1416

1417

1418

1419

1420

1421

1422

1423

1424

1425

1426

1427

1428

1429 FunctionDecl *OperatorNew = nullptr;

1430 SmallVector<Expr *, 1> PlacementArgs;

1431 DeclarationName NewName =

1432 S.getASTContext().DeclarationNames.getCXXOperatorName(OO_New);

1433

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

1436

1439

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

1441 }();

1442

1443

1444

1445 ImplicitAllocationParameters IAP(

1449 bool WithoutPlacementArgs = false,

1450 bool ForceNonAligned = false) {

1451

1452

1453

1454

1455

1456

1460

1461 bool ShouldUseAlignedAlloc =

1462 !ForceNonAligned && S.getLangOpts().CoroAlignedAllocation;

1463 IAP = ImplicitAllocationParameters(

1465

1466 FunctionDecl *UnusedResult = nullptr;

1467 S.FindAllocationFunctions(

1468 Loc, SourceRange(), NewScope,

1470 false, IAP,

1471 WithoutPlacementArgs ? MultiExprArg{} : PlacementArgs, OperatorNew,

1472 UnusedResult, false);

1473 assert(!OperatorNew || !OperatorNew->isTypeAwareOperatorNewOrDelete());

1474 };

1475

1476

1477

1478

1480 return false;

1481

1482 LookupAllocationFunction();

1483

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

1485

1486

1487

1488

1489

1490

1491

1492

1493

1494

1495

1496

1497 if (!OperatorNew || (S.getLangOpts().CoroAlignedAllocation &&

1500 true);

1501 }

1502

1503

1504

1505

1506

1507

1508

1509

1510

1511

1512

1513

1514

1515

1516

1517

1518

1519

1520

1521 bool FoundNonAlignedInPromise = false;

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

1524 FoundNonAlignedInPromise = OperatorNew;

1525

1527 false,

1528 true);

1529

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

1532 true,

1533 true);

1534 }

1535

1536 bool IsGlobalOverload =

1538

1539

1540

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

1543 if (!StdNoThrow)

1544 return false;

1545 PlacementArgs = {StdNoThrow};

1546 OperatorNew = nullptr;

1548 }

1549

1550

1551

1552

1553 if (FoundNonAlignedInPromise) {

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

1555 diag::warn_non_aligned_allocation_function)

1556 << &FD;

1557 }

1558

1559 if (!OperatorNew) {

1560 if (PromiseContainsNew) {

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

1563 S, Loc, diag::note_coroutine_unusable_type_aware_allocators, NewName,

1564 PromiseType);

1565 } else if (RequiresNoThrowAlloc)

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

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

1568

1569 return false;

1570 }

1571 assert(!OperatorNew->isTypeAwareOperatorNewOrDelete());

1572

1574 diag::warn_coroutine_type_aware_allocator_ignored,

1575 NewName, PromiseType);

1576

1577 if (RequiresNoThrowAlloc) {

1578 const auto *FT = OperatorNew->getType()->castAs();

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

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

1581 diag::err_coroutine_promise_new_requires_nothrow)

1582 << OperatorNew;

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

1584 << OperatorNew;

1585 return false;

1586 }

1587 }

1588

1589 FunctionDecl *OperatorDelete = nullptr;

1591

1592

1593

1594 return false;

1595 }

1596

1597 assert(!OperatorDelete->isTypeAwareOperatorNewOrDelete());

1598

1599 Expr *FramePtr =

1600 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_frame, {});

1601

1602 Expr *FrameSize =

1603 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_size, {});

1604

1605 Expr *FrameAlignment = nullptr;

1606

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

1608 FrameAlignment =

1609 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_align, {});

1610

1612 if (!AlignValTy)

1613 return false;

1614

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

1616 FrameAlignment, SourceRange(Loc, Loc),

1617 SourceRange(Loc, Loc))

1618 .get();

1619 }

1620

1621

1623 S.BuildDeclRefExpr(OperatorNew, OperatorNew->getType(), VK_LValue, Loc);

1625 return false;

1626

1627 SmallVector<Expr *, 2> NewArgs(1, FrameSize);

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

1630 NewArgs.push_back(FrameAlignment);

1631

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

1633 llvm::append_range(NewArgs, PlacementArgs);

1634

1636 S.BuildCallExpr(S.getCurScope(), NewRef.get(), Loc, NewArgs, Loc);

1637 NewExpr = S.ActOnFinishFullExpr(NewExpr.get(), false);

1639 return false;

1640

1641

1642

1643 QualType OpDeleteQualType = OperatorDelete->getType();

1644

1646 S.BuildDeclRefExpr(OperatorDelete, OpDeleteQualType, VK_LValue, Loc);

1648 return false;

1649

1650 Expr *CoroFree =

1651 S.BuildBuiltinCallExpr(Loc, Builtin::BI__builtin_coro_free, {FramePtr});

1652

1653 SmallVector<Expr *, 2> DeleteArgs{CoroFree};

1654

1655

1656

1657

1658

1659

1660 const auto *OpDeleteType =

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

1663 S.getASTContext().hasSameUnqualifiedType(

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

1665 DeleteArgs.push_back(FrameSize);

1666

1667

1668

1669

1670

1671

1672

1673

1674

1675

1676

1677

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

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

1680 S.getASTContext().hasSameUnqualifiedType(

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

1682 FrameAlignment->getType()))

1683 DeleteArgs.push_back(FrameAlignment);

1684

1686 S.BuildCallExpr(S.getCurScope(), DeleteRef.get(), Loc, DeleteArgs, Loc);

1687 DeleteExpr =

1688 S.ActOnFinishFullExpr(DeleteExpr.get(), false);

1690 return false;

1691

1694

1695 return true;

1696}

1697

1698bool CoroutineStmtBuilder::makeOnFallthrough() {

1699 assert(!IsPromiseDependentType &&

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

1701

1702

1703

1704

1705

1706

1707

1708

1709 bool HasRVoid, HasRValue;

1710 LookupResult LRVoid =

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

1712 LookupResult LRValue =

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

1714

1716 if (HasRVoid && HasRValue) {

1717

1718 S.Diag(FD.getLocation(),

1719 diag::err_coroutine_promise_incompatible_return_functions)

1720 << PromiseRecordDecl;

1722 diag::note_member_first_declared_here)

1725 diag::note_member_first_declared_here)

1727 return false;

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

1729

1730

1731

1732

1733

1734

1735

1736

1737

1738

1739 Fallthrough = S.ActOnNullStmt(PromiseRecordDecl->getLocation());

1740 if (Fallthrough.isInvalid())

1741 return false;

1742 } else if (HasRVoid) {

1743 Fallthrough = S.BuildCoreturnStmt(FD.getLocation(), nullptr,

1744 true);

1745 Fallthrough = S.ActOnFinishFullStmt(Fallthrough.get());

1746 if (Fallthrough.isInvalid())

1747 return false;

1748 }

1749

1751 return true;

1752}

1753

1754bool CoroutineStmtBuilder::makeOnException() {

1755

1756 assert(!IsPromiseDependentType &&

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

1758

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

1760

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

1762 auto DiagID =

1763 RequireUnhandledException

1764 ? diag::err_coroutine_promise_unhandled_exception_required

1765 : diag::

1766 warn_coroutine_promise_unhandled_exception_required_with_exceptions;

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

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

1769 << PromiseRecordDecl;

1770 return !RequireUnhandledException;

1771 }

1772

1773

1774 if (!S.getLangOpts().CXXExceptions)

1775 return true;

1776

1778 buildPromiseCall(S, Fn.CoroutinePromise, Loc, "unhandled_exception", {});

1779 UnhandledException = S.ActOnFinishFullExpr(UnhandledException.get(), Loc,

1780 false);

1781 if (UnhandledException.isInvalid())

1782 return false;

1783

1784

1785

1786 if (!S.getLangOpts().Borland && Fn.FirstSEHTryLoc.isValid()) {

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

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

1789 << Fn.getFirstCoroutineStmtKeyword();

1790 return false;

1791 }

1792

1794 return true;

1795}

1796

1797bool CoroutineStmtBuilder::makeReturnObject() {

1798

1799

1800

1802 buildPromiseCall(S, Fn.CoroutinePromise, Loc, "get_return_object", {});

1804 return false;

1805

1807 return true;

1808}

1809

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

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

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

1814 << MethodDecl;

1815 }

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

1817 << Fn.getFirstCoroutineStmtKeyword();

1818}

1819

1820bool CoroutineStmtBuilder::makeGroDeclAndReturnStmt() {

1821 assert(!IsPromiseDependentType &&

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

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

1824

1825 QualType const GroType = this->ReturnValue->getType();

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

1828

1829 QualType const FnRetType = FD.getReturnType();

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

1832

1833

1834

1835

1836

1837

1838

1839 bool GroMatchesRetType = S.getASTContext().hasSameType(GroType, FnRetType);

1840

1843 S.ActOnFinishFullExpr(this->ReturnValue, Loc, false);

1845 return false;

1846

1847 if (!GroMatchesRetType)

1849 return true;

1850 }

1851

1853

1854 InitializedEntity Entity =

1856 S.PerformCopyInitialization(Entity, SourceLocation(), ReturnValue);

1858 return false;

1859 }

1860

1862 clang::VarDecl *GroDecl = nullptr;

1863 if (GroMatchesRetType) {

1865 } else {

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

1868 &S.PP.getIdentifierTable().get("__coro_gro"), GroType,

1869 S.Context.getTrivialTypeSourceInfo(GroType, Loc), SC_None);

1871

1872 S.CheckVariableDeclarationType(GroDecl);

1874 return false;

1875

1878 S.PerformCopyInitialization(Entity, SourceLocation(), ReturnValue);

1880 return false;

1881

1882 Res = S.ActOnFinishFullExpr(Res.get(), false);

1884 return false;

1885

1886 S.AddInitializerToDecl(GroDecl, Res.get(),

1887 false);

1888

1889 S.FinalizeDeclaration(GroDecl);

1890

1891

1892

1894 S.ActOnDeclStmt(S.ConvertDeclToDeclGroup(GroDecl), Loc, Loc);

1895 if (GroDeclStmt.isInvalid())

1896 return false;

1897

1898 this->ResultDecl = GroDeclStmt.get();

1899

1900 ExprResult declRef = S.BuildDeclRefExpr(GroDecl, GroType, VK_LValue, Loc);

1902 return false;

1903

1904 ReturnStmt = S.BuildReturnStmt(Loc, declRef.get());

1905 }

1906

1909 return false;

1910 }

1911

1912 if (!GroMatchesRetType &&

1915

1917 return true;

1918}

1919

1920

1922 if (T.isNull())

1929

1930 return S

1934}

1935

1936

1945

1946

1947

1951

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

1954 return false;

1955

1956

1957

1958

1959

1960

1961

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

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

1964 continue;

1965

1966

1967 bool DeclReferenced = PD->isReferenced();

1968

1972

1973 PD->setReferenced(DeclReferenced);

1974

1976 return false;

1977

1978 Expr *CExpr = nullptr;

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

1980 PD->getType()->isRValueReferenceType())

1982 else

1983 CExpr = PDRefExpr.get();

1984

1985

1986

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

1989

1990

1992 if (Stmt.isInvalid())

1993 return false;

1994

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

1996 }

1997 return true;

1998}

1999

2002 if (!Res)

2004 return Res;

2005}

2006

2011

2013 PP.getIdentifierTable().get("coroutine_traits");

2014

2018

2020

2021 Diag(KwLoc, diag::err_implied_coroutine_type_not_found)

2022 << "std::coroutine_traits";

2023 return nullptr;

2024 }

2025

2026

2029 Result.suppressDiagnostics();

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

2032 return nullptr;

2033 }

2034

2036}

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.

TokenType getType() const

Returns the token's type, e.g.

llvm::MachO::Record Record

Defines the clang::Preprocessor interface.

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

Definition SemaCoroutine.cpp:262

static bool DiagnoseTypeAwareAllocators(Sema &S, SourceLocation Loc, unsigned DiagnosticID, DeclarationName Name, QualType PromiseType)

Definition SemaCoroutine.cpp:1091

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

Definition SemaCoroutine.cpp:1810

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

Definition SemaCoroutine.cpp:675

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

Definition SemaCoroutine.cpp:178

static void applySafeElideContext(Expr *Operand)

Definition SemaCoroutine.cpp:843

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

Look up the std::nothrow object.

Definition SemaCoroutine.cpp:1053

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

Definition SemaCoroutine.cpp:253

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

Definition SemaCoroutine.cpp:1280

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

Definition SemaCoroutine.cpp:450

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

Definition SemaCoroutine.cpp:1921

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

Definition SemaCoroutine.cpp:317

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

Definition SemaCoroutine.cpp:296

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

Definition SemaCoroutine.cpp:32

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

Definition SemaCoroutine.cpp:1082

static bool isWithinCatchScope(Scope *S)

Definition SemaCoroutine.cpp:748

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

Definition SemaCoroutine.cpp:1115

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

Build a variable declaration for move parameter.

Definition SemaCoroutine.cpp:1937

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...

Definition SemaCoroutine.cpp:597

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.

Definition SemaCoroutine.cpp:358

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

Definition SemaCoroutine.cpp:776

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

Look up the std::coroutine_handle.

Definition SemaCoroutine.cpp:134

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

Definition SemaCoroutine.cpp:1353

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

Definition SemaCoroutine.cpp:1210

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

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

Definition SemaCoroutine.cpp:52

static bool isAttributedCoroAwaitElidable(const QualType &QT)

Definition SemaCoroutine.cpp:838

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.

Definition SemaCoroutine.cpp:567

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

QualType getLValueReferenceType(QualType T, bool SpelledAsLValue=true) const

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

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

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

QualType getTypeDeclType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier Qualifier, const TypeDecl *Decl) const

CanQualType getCanonicalTagType(const TagDecl *TD) const

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...

Definition SemaCoroutine.cpp:1222

bool buildDependentStatements()

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

Definition SemaCoroutine.cpp:1250

bool buildStatements()

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

Definition SemaCoroutine.cpp:1242

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.

FunctionDecl * getAsFunction() LLVM_READONLY

Returns the function itself, or the templated function if this is a function template.

bool isInvalidDecl() const

SourceLocation getLocation() const

void setImplicit(bool I=true)

DeclContext * getDeclContext()

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 function 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.

bool isNoReturn() const

Determines whether this function is known to be 'noreturn', through an attribute on its declaration o...

ArrayRef< ParmVarDecl * > parameters() const

bool isTypeAwareOperatorNewOrDelete() const

Determine whether this is a type aware operator new or delete.

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...

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.

Represents a C++ nested name specifier, such as "\::std::vector::".

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.

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

bool isCatchScope() const

isCatchScope - Return true if this scope is a C++ catch statement.

const Scope * getParent() const

getParent - Return the scope that this is nested in.

bool isFunctionScope() const

isFunctionScope() - Return true if this scope is a function scope.

SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)

Emit a diagnostic.

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

FunctionDecl * FindUsualDeallocationFunction(SourceLocation StartLoc, ImplicitDeallocationParameters, DeclarationName Name, bool Diagnose=true)

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.

Definition SemaCoroutine.cpp:246

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.

Definition SemaCoroutine.cpp:655

StmtResult BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs)

Definition SemaCoroutine.cpp:2000

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

ExprResult BuildCoyieldExpr(SourceLocation KwLoc, Expr *E)

Definition SemaCoroutine.cpp:978

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

Definition SemaCoroutine.cpp:1162

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

Definition SemaCoroutine.cpp:686

VarDecl * buildCoroutinePromise(SourceLocation Loc)

Definition SemaCoroutine.cpp:463

const ExpressionEvaluationContextRecord & currentEvaluationContext() const

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

Definition SemaCoroutine.cpp:1021

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)

Definition SemaCoroutine.cpp:916

FunctionDecl * getCurFunctionDecl(bool AllowLambda=false) const

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

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

Definition SemaCoroutine.cpp:957

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)

Definition SemaCoroutine.cpp:1014

const LangOptions & getLangOpts() const

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.

CleanupInfo Cleanup

Used to control the generation of ExprWithCleanups.

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

Definition SemaCoroutine.cpp:869

bool buildCoroutineParameterMoves(SourceLocation Loc)

Definition SemaCoroutine.cpp:1948

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)

Definition SemaCoroutine.cpp:799

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

DeclContext * CurContext

CurContext - This is the current declaration context of parsing.

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.

Definition SemaCoroutine.cpp:2007

DeclContext * computeDeclContext(QualType T)

Compute the DeclContext that is associated with the given type.

void CheckCompleteVariableDeclaration(VarDecl *VD)

QualType CheckTemplateIdType(ElaboratedTypeKeyword Keyword, TemplateName Template, SourceLocation TemplateLoc, TemplateArgumentListInfo &TemplateArgs, Scope *Scope, bool ForNestedNameSpecifier)

@ PotentiallyEvaluated

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

ExprResult BuildOperatorCoawaitLookupExpr(Scope *S, SourceLocation Loc)

Definition SemaCoroutine.cpp:820

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

friend class InitializationSequence

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 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)

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 declaration of a type.

A container of type source information.

The base class of the type hierarchy.

bool isBooleanType() const

CXXRecordDecl * getAsCXXRecordDecl() const

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

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.

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

CanQual< Type > CanQualType

Represents a canonical, potentially-qualified type.

bool isa(CodeGen::Address addr)

AllocationFunctionScope

The scope in which to find allocation functions.

@ Both

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

@ Global

Only look for allocation functions in the global scope.

@ Class

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

AlignedAllocationMode alignedAllocationModeFromBool(bool IsAligned)

@ RQ_RValue

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

@ TemplateName

The identifier is a template name. FIXME: Add an annotation for that.

bool isAlignedAllocation(AlignedAllocationMode Mode)

MutableArrayRef< Expr * > MultiExprArg

bool isLambdaCallOperator(const CXXMethodDecl *MD)

@ Result

The result type of a method or function.

const FunctionProtoType * T

@ Keyword

The name has been typo-corrected to a keyword.

@ VK_LValue

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

U cast(CodeGen::Address addr)

@ None

No keyword precedes the qualified type name.

ActionResult< Expr * > ExprResult

ActionResult< Stmt * > StmtResult

Definition SemaCoroutine.cpp:289

OpaqueValueExpr * OpaqueValue

Definition SemaCoroutine.cpp:292

Expr * Results[3]

Definition SemaCoroutine.cpp:291

AwaitCallType

Definition SemaCoroutine.cpp:290

@ ACT_Resume

Definition SemaCoroutine.cpp:290

@ ACT_Suspend

Definition SemaCoroutine.cpp:290

@ ACT_Ready

Definition SemaCoroutine.cpp:290

bool IsInvalid

Definition SemaCoroutine.cpp:293

Stmt * ReturnStmtOnAllocFailure

ArrayRef< Stmt * > ParamMoves

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

SizedDeallocationMode PassSize

enum clang::Sema::ExpressionEvaluationContextRecord::ExpressionKind ExprContext