On 1/29/20 10:39 AM, Iain Sandoe wrote:
Hi Nathan,

Nathan Sidwell <nat...@acm.org> wrote:

Made the function type error recorded per function too.

OK now?

Still some things to address ...

diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc
index e8a6a4033f6..3ad80699ca0 100644
--- a/gcc/cp/coroutines.cc
+++ b/gcc/cp/coroutines.cc

@@ -257,9 +260,15 @@ find_coro_traits_template_decl (location_t kw)
  {
    tree traits_decl = lookup_qualified_name (std_node, coro_traits_identifier,
                                            0, true);
-  if (traits_decl == NULL_TREE || traits_decl == error_mark_node)
-    {
-      error_at (kw, "cannot find %<coroutine traits%> template");
+  /* If we are missing fundmental information, such as the traits, then don't
+     emit this for every keyword in a TU.  This particular error is per TU
+     so we don't need to keep the indicator per function.  */
+  static bool traits_error_emitted = false;

You can of course move this into the if's block scope.

+  if (traits_decl == error_mark_node)
+    {
+      if (!traits_error_emitted)
+       error_at (kw, "cannot find %<coroutine traits%> template");

Give the name you were looking for:
   "%<%E::%E%> ...", std_node, coro_traits_identifier
also, what if you find something, but it's not a type template?

        /* Coroutine traits template.  */
        coro_traits_templ = find_coro_traits_template_decl (loc);
-      gcc_checking_assert (coro_traits_templ != NULL);
+      if (coro_traits_templ == NULL_TREE
+         || coro_traits_templ == error_mark_node)
+       return false;

ISTM that find_coro_traits_template_decl should be returning exactly one of NULL_TREE of error_mark_node on failure. Its users don't particularly care why it failed (not found vs found ambiguous/not template).

 +  /* Save the coroutine data on the side to avoid the overhead on every
+     function decl tree.  */
+
    coroutine_info *coro_info = get_or_insert_coroutine_info (fndecl);
    /* Without this, we cannot really proceed.  */
    gcc_checking_assert (coro_info);
@@ -407,6 +427,18 @@ coro_promise_type_found_p (tree fndecl, location_t loc)
      {
        /* Get the coroutine traits template class instance for the function
         signature we have - coroutine_traits <R, ...>  */
+      if (!CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))))
+       {
+         /* It makes more sense to show the function header for this, even
+            though we will have encountered it when processing a keyword.
+            Only emit the error once, not for every keyword we encounter.  */
+         if (!coro_info->coro_ret_type_error_emitted)
+           error_at (DECL_SOURCE_LOCATION (fndecl), "a coroutine must have a"
+                     " class or struct return type");

Perhaps something like "coroutine return type %qT is not a class"? I.e. show them the type.
(structs are classes, there's no need to say 'class or struct')


+         coro_info->coro_ret_type_error_emitted = true;
+         return false;
+       }
+
        tree templ_class = instantiate_coro_traits (fndecl, loc);
/* Find the promise type for that. */
@@ -422,7 +454,7 @@ coro_promise_type_found_p (tree fndecl, location_t loc)
        /* Try to find the handle type for the promise.  */
        tree handle_type =
        instantiate_coro_handle_for_promise_type (loc, coro_info->promise_type);
-      if (handle_type == NULL_TREE)
+      if (handle_type == NULL_TREE || handle_type == error_mark_node)

similar to coro_traits_template_decl.


--
Nathan Sidwell

Reply via email to