EricWF created this revision.
EricWF added reviewers: rsmith, GorNishanov.
EricWF added a subscriber: cfe-commits.
Herald added a subscriber: mehdi_amini.

If there is an error finding the `coroutine_traits` template when building a 
coroutine AST nodes we throw away the remainder of the assignment expression. 
If the expression has uncorrected typo's this will trigger an assertion in 
`~Sema()`.

This patch attempts to preemptively correct those typo's when we encounter an 
error building the coroutine nodes, at least for the case where the 
`coroutine_traits` template is invalid.

https://reviews.llvm.org/D25060

Files:
  lib/Sema/SemaCoroutine.cpp
  test/SemaCXX/coroutines.cpp

Index: test/SemaCXX/coroutines.cpp
===================================================================
--- test/SemaCXX/coroutines.cpp
+++ test/SemaCXX/coroutines.cpp
@@ -1,5 +1,22 @@
 // RUN: %clang_cc1 -std=c++14 -fcoroutines -verify %s
 
+void no_coroutine_traits_bad_arg_await() {
+  co_await a; // expected-error {{include <coroutine>}}
+  // expected-error@-1 {{use of undeclared identifier 'a'}}
+}
+
+void no_coroutine_traits_bad_arg_yield() {
+  co_yield a; // expected-error {{include <coroutine>}}
+  // expected-error@-1 {{use of undeclared identifier 'a'}}
+}
+
+
+void no_coroutine_traits_bad_arg_return() {
+  co_return a; // expected-error {{include <coroutine>}}
+  // expected-error@-1 {{use of undeclared identifier 'a'}}
+}
+
+
 struct awaitable {
   bool await_ready();
   void await_suspend(); // FIXME: coroutine_handle
Index: lib/Sema/SemaCoroutine.cpp
===================================================================
--- lib/Sema/SemaCoroutine.cpp
+++ lib/Sema/SemaCoroutine.cpp
@@ -213,6 +213,11 @@
 }
 
 ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) {
+  auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await");
+  if (!Coroutine) {
+    CorrectDelayedTyposInExpr(E);
+    return ExprError();
+  }
   if (E->getType()->isPlaceholderType()) {
     ExprResult R = CheckPlaceholderExpr(E);
     if (R.isInvalid()) return ExprError();
@@ -222,6 +227,7 @@
   ExprResult Awaitable = buildOperatorCoawaitCall(*this, S, Loc, E);
   if (Awaitable.isInvalid())
     return ExprError();
+
   return BuildCoawaitExpr(Loc, Awaitable.get());
 }
 ExprResult Sema::BuildCoawaitExpr(SourceLocation Loc, Expr *E) {
@@ -275,8 +281,10 @@
 
 ExprResult Sema::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr *E) {
   auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
-  if (!Coroutine)
+  if (!Coroutine) {
+    CorrectDelayedTyposInExpr(E);
     return ExprError();
+  }
 
   // Build yield_value call.
   ExprResult Awaitable =
@@ -325,6 +333,11 @@
 }
 
 StmtResult Sema::ActOnCoreturnStmt(SourceLocation Loc, Expr *E) {
+  auto *Coroutine = checkCoroutineContext(*this, Loc, "co_return");
+  if (!Coroutine) {
+    CorrectDelayedTyposInExpr(E);
+    return StmtError();
+  }
   return BuildCoreturnStmt(Loc, E);
 }
 StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E) {


Index: test/SemaCXX/coroutines.cpp
===================================================================
--- test/SemaCXX/coroutines.cpp
+++ test/SemaCXX/coroutines.cpp
@@ -1,5 +1,22 @@
 // RUN: %clang_cc1 -std=c++14 -fcoroutines -verify %s
 
+void no_coroutine_traits_bad_arg_await() {
+  co_await a; // expected-error {{include <coroutine>}}
+  // expected-error@-1 {{use of undeclared identifier 'a'}}
+}
+
+void no_coroutine_traits_bad_arg_yield() {
+  co_yield a; // expected-error {{include <coroutine>}}
+  // expected-error@-1 {{use of undeclared identifier 'a'}}
+}
+
+
+void no_coroutine_traits_bad_arg_return() {
+  co_return a; // expected-error {{include <coroutine>}}
+  // expected-error@-1 {{use of undeclared identifier 'a'}}
+}
+
+
 struct awaitable {
   bool await_ready();
   void await_suspend(); // FIXME: coroutine_handle
Index: lib/Sema/SemaCoroutine.cpp
===================================================================
--- lib/Sema/SemaCoroutine.cpp
+++ lib/Sema/SemaCoroutine.cpp
@@ -213,6 +213,11 @@
 }
 
 ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) {
+  auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await");
+  if (!Coroutine) {
+    CorrectDelayedTyposInExpr(E);
+    return ExprError();
+  }
   if (E->getType()->isPlaceholderType()) {
     ExprResult R = CheckPlaceholderExpr(E);
     if (R.isInvalid()) return ExprError();
@@ -222,6 +227,7 @@
   ExprResult Awaitable = buildOperatorCoawaitCall(*this, S, Loc, E);
   if (Awaitable.isInvalid())
     return ExprError();
+
   return BuildCoawaitExpr(Loc, Awaitable.get());
 }
 ExprResult Sema::BuildCoawaitExpr(SourceLocation Loc, Expr *E) {
@@ -275,8 +281,10 @@
 
 ExprResult Sema::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr *E) {
   auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");
-  if (!Coroutine)
+  if (!Coroutine) {
+    CorrectDelayedTyposInExpr(E);
     return ExprError();
+  }
 
   // Build yield_value call.
   ExprResult Awaitable =
@@ -325,6 +333,11 @@
 }
 
 StmtResult Sema::ActOnCoreturnStmt(SourceLocation Loc, Expr *E) {
+  auto *Coroutine = checkCoroutineContext(*this, Loc, "co_return");
+  if (!Coroutine) {
+    CorrectDelayedTyposInExpr(E);
+    return StmtError();
+  }
   return BuildCoreturnStmt(Loc, E);
 }
 StmtResult Sema::BuildCoreturnStmt(SourceLocation Loc, Expr *E) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to