<div dir="ltr">LGTM</div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Sep 28, 2016 at 10:09 PM, Eric Fiselier <span dir="ltr"><<a href="mailto:eric@efcs.ca" target="_blank">eric@efcs.ca</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">EricWF created this revision.<br>
EricWF added reviewers: rsmith, GorNishanov.<br>
EricWF added a subscriber: cfe-commits.<br>
Herald added a subscriber: mehdi_amini.<br>
<br>
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()`.<br>
<br>
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.<br>
<br>
<a href="https://reviews.llvm.org/D25060" rel="noreferrer" target="_blank">https://reviews.llvm.org/<wbr>D25060</a><br>
<br>
Files:<br>
  lib/Sema/SemaCoroutine.cpp<br>
  test/SemaCXX/coroutines.cpp<br>
<br>
Index: test/SemaCXX/coroutines.cpp<br>
==============================<wbr>==============================<wbr>=======<br>
--- test/SemaCXX/coroutines.cpp<br>
+++ test/SemaCXX/coroutines.cpp<br>
@@ -1,5 +1,22 @@<br>
 // RUN: %clang_cc1 -std=c++14 -fcoroutines -verify %s<br>
<br>
+void no_coroutine_traits_bad_arg_<wbr>await() {<br>
+  co_await a; // expected-error {{include <coroutine>}}<br>
+  // expected-error@-1 {{use of undeclared identifier 'a'}}<br>
+}<br>
+<br>
+void no_coroutine_traits_bad_arg_<wbr>yield() {<br>
+  co_yield a; // expected-error {{include <coroutine>}}<br>
+  // expected-error@-1 {{use of undeclared identifier 'a'}}<br>
+}<br>
+<br>
+<br>
+void no_coroutine_traits_bad_arg_<wbr>return() {<br>
+  co_return a; // expected-error {{include <coroutine>}}<br>
+  // expected-error@-1 {{use of undeclared identifier 'a'}}<br>
+}<br>
+<br>
+<br>
 struct awaitable {<br>
   bool await_ready();<br>
   void await_suspend(); // FIXME: coroutine_handle<br>
Index: lib/Sema/SemaCoroutine.cpp<br>
==============================<wbr>==============================<wbr>=======<br>
--- lib/Sema/SemaCoroutine.cpp<br>
+++ lib/Sema/SemaCoroutine.cpp<br>
@@ -213,6 +213,11 @@<br>
 }<br>
<br>
 ExprResult Sema::ActOnCoawaitExpr(Scope *S, SourceLocation Loc, Expr *E) {<br>
+  auto *Coroutine = checkCoroutineContext(*this, Loc, "co_await");<br>
+  if (!Coroutine) {<br>
+    CorrectDelayedTyposInExpr(E);<br>
+    return ExprError();<br>
+  }<br>
   if (E->getType()-><wbr>isPlaceholderType()) {<br>
     ExprResult R = CheckPlaceholderExpr(E);<br>
     if (R.isInvalid()) return ExprError();<br>
@@ -222,6 +227,7 @@<br>
   ExprResult Awaitable = buildOperatorCoawaitCall(*<wbr>this, S, Loc, E);<br>
   if (Awaitable.isInvalid())<br>
     return ExprError();<br>
+<br>
   return BuildCoawaitExpr(Loc, Awaitable.get());<br>
 }<br>
 ExprResult Sema::BuildCoawaitExpr(<wbr>SourceLocation Loc, Expr *E) {<br>
@@ -275,8 +281,10 @@<br>
<br>
 ExprResult Sema::ActOnCoyieldExpr(Scope *S, SourceLocation Loc, Expr *E) {<br>
   auto *Coroutine = checkCoroutineContext(*this, Loc, "co_yield");<br>
-  if (!Coroutine)<br>
+  if (!Coroutine) {<br>
+    CorrectDelayedTyposInExpr(E);<br>
     return ExprError();<br>
+  }<br>
<br>
   // Build yield_value call.<br>
   ExprResult Awaitable =<br>
@@ -325,6 +333,11 @@<br>
 }<br>
<br>
 StmtResult Sema::ActOnCoreturnStmt(<wbr>SourceLocation Loc, Expr *E) {<br>
+  auto *Coroutine = checkCoroutineContext(*this, Loc, "co_return");<br>
+  if (!Coroutine) {<br>
+    CorrectDelayedTyposInExpr(E);<br>
+    return StmtError();<br>
+  }<br>
   return BuildCoreturnStmt(Loc, E);<br>
 }<br>
 StmtResult Sema::BuildCoreturnStmt(<wbr>SourceLocation Loc, Expr *E) {<br>
<br>
<br>
</blockquote></div><br></div>