On 12/19/18 3:27 PM, Marek Polacek wrote:
Prompted by Jon's observation in 52869, I noticed that we don't treat
a noexcept-specifier as a complete-class context of a class ([class.mem]/6).
As with member function bodies, default arguments, and NSDMIs, names used in
a noexcept-specifier of a member-function can be declared later in the class
body, so we need to wait and parse them at the end of the class.
For that, I've made use of DEFAULT_ARG (now best to be renamed to UNPARSED_ARG).

Or DEFERRED_PARSE, yes.

+  /* We can't compare unparsed noexcept-specifiers.  Save the old decl
+     and check this again after we've parsed the noexcept-specifiers
+     for real.  */
+  if (UNPARSED_NOEXCEPT_SPEC_P (new_exceptions))
+    {
+      vec_safe_push (DEFARG_INSTANTIATIONS (TREE_PURPOSE (new_exceptions)),
+                    copy_decl (old_decl));
+      return;
+    }

Why copy_decl?

It seems wasteful to allocate a vec to hold this single decl; let's make the last field of tree_default_arg a union instead. And add a new macro for the single decl case.

I notice that default_arg currently uses tree_common for some reason, and we ought to be able to save two words by switching to tree_base

@@ -1245,6 +1245,7 @@ nothrow_spec_p (const_tree spec)
              || TREE_VALUE (spec)
              || spec == noexcept_false_spec
              || TREE_PURPOSE (spec) == error_mark_node
+             || TREE_CODE (TREE_PURPOSE (spec)) == DEFAULT_ARG

Maybe use UNPARSED_NOEXCEPT_SPEC_P here?

+/* Make sure that any member-function parameters are in scope.
+   For instance, a function's noexcept-specifier can use the function's
+   parameters:
+
+   struct S {
+     void fn (int p) noexcept(noexcept(p));
+   };
+
+   so we need to make sure name lookup can find them.  This is used
+   when we delay parsing of the noexcept-specifier.  */
+
+static void
+maybe_begin_member_function_processing (tree decl)

This name is pretty misleading. How about inject_parm_decls, to go with inject_this_parameter?

+/* Undo the effects of maybe_begin_member_function_processing.  */
+
+static void
+maybe_end_member_function_processing (void)

And then perhaps pop_injected_parms.

+/* Check throw specifier of OVERRIDER is at least as strict as
+   the one of BASEFN.  */
+
+bool
+maybe_check_throw_specifier (tree overrider, tree basefn)
+{
+  maybe_instantiate_noexcept (basefn);
+  maybe_instantiate_noexcept (overrider);
+  tree base_throw = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (basefn));
+  tree over_throw = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (overrider));
+
+  if (DECL_INVALID_OVERRIDER_P (overrider))
+    return true;
+
+  /* Can't check this yet.  Pretend this is fine and let
+     noexcept_override_late_checks check this later.  */
+  if (UNPARSED_NOEXCEPT_SPEC_P (base_throw)
+      || UNPARSED_NOEXCEPT_SPEC_P (over_throw))
+    return true;
+
+  if (!comp_except_specs (base_throw, over_throw, ce_derived))
+    {
+      auto_diagnostic_group d;
+      error ("looser throw specifier for %q+#F", overrider);

Since we're touching this diagnostic, let's correct it now to "exception specification". And add "on overriding virtual function".

Jason

Reply via email to