summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaCoroutine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaCoroutine.cpp')
-rw-r--r--clang/lib/Sema/SemaCoroutine.cpp106
1 files changed, 106 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp
new file mode 100644
index 00000000000..6545b6709a2
--- /dev/null
+++ b/clang/lib/Sema/SemaCoroutine.cpp
@@ -0,0 +1,106 @@
+//===--- SemaCoroutines.cpp - Semantic Analysis for Coroutines ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements semantic analysis for C++ Coroutines.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Sema/SemaInternal.h"
+using namespace clang;
+using namespace sema;
+
+static FunctionScopeInfo *
+checkCoroutineContext(Sema &S, SourceLocation Loc, StringRef Keyword) {
+ // 'co_await' and 'co_yield' are permitted in unevaluated operands.
+ if (S.isUnevaluatedContext())
+ return nullptr;
+
+ // Any other usage must be within a function.
+ auto *FD = dyn_cast<FunctionDecl>(S.CurContext);
+ if (!FD) {
+ S.Diag(Loc, isa<ObjCMethodDecl>(S.CurContext)
+ ? diag::err_coroutine_objc_method
+ : diag::err_coroutine_outside_function) << Keyword;
+ } else if (isa<CXXConstructorDecl>(FD) || isa<CXXDestructorDecl>(FD)) {
+ // Coroutines TS [special]/6:
+ // A special member function shall not be a coroutine.
+ //
+ // FIXME: We assume that this really means that a coroutine cannot
+ // be a constructor or destructor.
+ S.Diag(Loc, diag::err_coroutine_ctor_dtor)
+ << isa<CXXDestructorDecl>(FD) << Keyword;
+ } else if (FD->isConstexpr()) {
+ S.Diag(Loc, diag::err_coroutine_constexpr) << Keyword;
+ } else if (FD->isVariadic()) {
+ S.Diag(Loc, diag::err_coroutine_varargs) << Keyword;
+ } else {
+ auto *ScopeInfo = S.getCurFunction();
+ assert(ScopeInfo && "missing function scope for function");
+ return ScopeInfo;
+ }
+
+ return nullptr;
+}
+
+ExprResult Sema::ActOnCoawaitExpr(SourceLocation Loc, Expr *E) {
+ auto *Context = checkCoroutineContext(*this, Loc, "co_await");
+ ExprResult Res = ExprError();
+
+ if (Context && !Res.isInvalid())
+ Context->CoroutineStmts.push_back(Res.get());
+ return Res;
+}
+
+ExprResult Sema::ActOnCoyieldExpr(SourceLocation Loc, Expr *E) {
+ auto *Context = checkCoroutineContext(*this, Loc, "co_yield");
+ ExprResult Res = ExprError();
+
+ if (Context && !Res.isInvalid())
+ Context->CoroutineStmts.push_back(Res.get());
+ return Res;
+}
+
+StmtResult Sema::ActOnCoreturnStmt(SourceLocation Loc, Expr *E) {
+ auto *Context = checkCoroutineContext(*this, Loc, "co_return");
+ StmtResult Res = StmtError();
+
+ if (Context && !Res.isInvalid())
+ Context->CoroutineStmts.push_back(Res.get());
+ return Res;
+}
+
+void Sema::CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *Body) {
+ FunctionScopeInfo *Fn = getCurFunction();
+ assert(Fn && !Fn->CoroutineStmts.empty() && "not a coroutine");
+
+ // Coroutines [stmt.return]p1:
+ // A return statement shall not appear in a coroutine.
+ if (!Fn->Returns.empty()) {
+ Diag(Fn->Returns.front()->getLocStart(), diag::err_return_in_coroutine);
+ auto *First = Fn->CoroutineStmts[0];
+ Diag(First->getLocStart(), diag::note_declared_coroutine_here)
+ << 0; // FIXME: Indicate the kind here
+ }
+
+ bool AnyCoawaits = false;
+ bool AnyCoyields = false;
+ for (auto *CoroutineStmt : Fn->CoroutineStmts) {
+ (void)CoroutineStmt;
+ AnyCoawaits = AnyCoyields = true; // FIXME
+ }
+
+ if (!AnyCoawaits && !AnyCoyields)
+ Diag(Fn->CoroutineStmts.front()->getLocStart(),
+ diag::ext_coroutine_without_coawait_coyield);
+
+ // FIXME: If we have a deduced return type, resolve it now.
+ // FIXME: Compute the promise type.
+ // FIXME: Perform analysis of initial and final suspend, and set_exception call.
+ // FIXME: Complete the semantic analysis of the CoroutineStmts.
+}
OpenPOWER on IntegriCloud