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