On 1/28/20 11:14 AM, Iain Sandoe wrote:
Hi,

Since coroutine-ness is discovered lazily, we encounter the diagnostics
during each keyword parse.  We were not handling the case where a user code
failed to include fundamental information (e.g. the traits) in a graceful
manner (nor tolerating that level of fail for subsequent diagnostics).

Once we've emitted an error for this level of fail, then we suppress
additional copies (otherwise the same thing will be reported for every
coroutine keyword seen).

tested on x86_64-darwin16,
OK for trunk?
thanks
iain

gcc/cp/ChangeLog:

2020-01-28  Iain Sandoe  <i...@sandoe.co.uk>

        * coroutines.cc (get_coroutine_info): Tolerate fatal errors that might
        leave the info unset.
        (find_coro_traits_template_decl): Note we emitted the error and
        suppress duplicates.
        (coro_promise_type_found_p): Reorder initialization so that we check
        for the traits and their usability before allocation of the info
        table.  Check for a suitable return type and emit a diagnostic for
        here instead of relying on the lookup machinery.  This allows the
        error to have a better location, and means we can suppress multiple
        copies.
        (coro_function_valid_p): Re-check for a valid promise (and thus the
        traits) before proceeding.  Tolerate missing info as a fatal error.


    coroutine_info **slot = coroutine_info_table->find_slot_with_hash
      (fn_decl, coroutine_info_hasher::hash (fn_decl), NO_INSERT);
@@ -255,11 +256,16 @@ static GTY(()) tree void_coro_handle_type;
  static tree
  find_coro_traits_template_decl (location_t kw)
  {
+  static bool error_emitted = false;
    tree traits_decl = lookup_qualified_name (std_node, coro_traits_identifier,
                                            0, true);
-  if (traits_decl == NULL_TREE || traits_decl == error_mark_node)
+  /* If we are missing fundmental information, such as the traits, then don't
+     emit this for every keyword in a TU.  */
+  if (!error_emitted &&
+      (traits_decl == NULL_TREE || traits_decl == error_mark_node))
      {
        error_at (kw, "cannot find %<coroutine traits%> template");
+      error_emitted = true;
        return NULL_TREE;
      }

don't you just want to protect the error_at call with error_emitted? Then I think the logic in the else branch will be simpler. You might want to pick a canonical 'error' value -- either NULL_TREE or error_mark_node, but not both?

nathan

--
Nathan Sidwell

Reply via email to