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 (->isClassType() &&
->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 ( ||
->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 ((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