aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/search.c
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2019-06-22 15:14:30 +0000
committerMarek Polacek <mpolacek@gcc.gnu.org>2019-06-22 15:14:30 +0000
commit78f7607db4c53f8cfe4653a6c91c0328bc2854c3 (patch)
treed8c288e122322c16f7c0c600df65e9b34feaf7c2 /gcc/cp/search.c
parent7f3db013dc8264e39339ee4b83900ef25d0d32aa (diff)
downloadgcc-78f7607db4c53f8cfe4653a6c91c0328bc2854c3.zip
gcc-78f7607db4c53f8cfe4653a6c91c0328bc2854c3.tar.gz
gcc-78f7607db4c53f8cfe4653a6c91c0328bc2854c3.tar.bz2
PR c++/86476 - noexcept-specifier is a complete-class context.
PR c++/52869 * cp-tree.def (DEFAULT_ARG): Update commentary. * cp-tree.h (UNPARSED_NOEXCEPT_SPEC_P): New macro. (tree_default_arg): Use tree_base instead of tree_common. (do_push_parm_decls, maybe_check_overriding_exception_spec): Declare. * decl.c (do_push_parm_decls): New function, broken out of... (store_parm_decls): ...here. Call it. * except.c (nothrow_spec_p): Accept DEFAULT_ARG in the assert. * parser.c (cp_parser_noexcept_specification_opt, cp_parser_late_noexcept_specifier, noexcept_override_late_checks): Forward-declare. (unparsed_noexcepts): New macro. (push_unparsed_function_queues): Update initializer. (cp_parser_direct_declarator): Pass FRIEND_P to cp_parser_exception_specification_opt. (inject_parm_decls): New. (pop_injected_parms): New. (cp_parser_class_specifier_1): Implement delayed parsing of noexcept-specifiers. (cp_parser_save_noexcept): New. (cp_parser_late_noexcept_specifier): New. (noexcept_override_late_checks): New. (cp_parser_noexcept_specification_opt): Add FRIEND_P parameter. Call cp_parser_save_noexcept instead of the normal processing if needed. (cp_parser_exception_specification_opt): Add FRIEND_P parameter and pass it to cp_parser_noexcept_specification_opt. (cp_parser_save_member_function_body): Fix comment. (cp_parser_save_default_args): Maybe save the noexcept-specifier to post process. (cp_parser_transaction): Update call to cp_parser_noexcept_specification_opt. (cp_parser_transaction_expression): Likewise. * parser.h (cp_unparsed_functions_entry): Add new field to carry a noexcept-specifier. * pt.c (dependent_type_p_r): Handle unparsed noexcept expression. * search.c (maybe_check_overriding_exception_spec): New function, broken out of... (check_final_overrider): ...here. Call maybe_check_overriding_exception_spec. * tree.c (canonical_eh_spec): Handle UNPARSED_NOEXCEPT_SPEC_P. (cp_tree_equal): Handle DEFAULT_ARG. * g++.dg/cpp0x/noexcept45.C: New test. * g++.dg/cpp0x/noexcept46.C: New test. * g++.dg/cpp0x/noexcept47.C: New test. * g++.dg/cpp0x/noexcept48.C: New test. * g++.dg/cpp0x/noexcept49.C: New test. * g++.dg/cpp0x/noexcept50.C: New test. * g++.dg/cpp0x/noexcept51.C: New test. * g++.dg/cpp0x/noexcept52.C: New test. * g++.dg/cpp0x/noexcept53.C: New test. * g++.dg/eh/shadow1.C: Adjust dg-error. From-SVN: r272586
Diffstat (limited to 'gcc/cp/search.c')
-rw-r--r--gcc/cp/search.c51
1 files changed, 35 insertions, 16 deletions
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index dac08d4..372c442 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -1860,6 +1860,39 @@ locate_field_accessor (tree basetype_path, tree field_decl, bool const_p)
NULL, &lfd);
}
+/* Check throw specifier of OVERRIDER is at least as strict as
+ the one of BASEFN. */
+
+bool
+maybe_check_overriding_exception_spec (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 exception specification on overriding virtual function "
+ "%q+#F", overrider);
+ inform (DECL_SOURCE_LOCATION (basefn),
+ "overridden function is %q#F", basefn);
+ DECL_INVALID_OVERRIDER_P (overrider) = 1;
+ return false;
+ }
+ return true;
+}
+
/* Check that virtual overrider OVERRIDER is acceptable for base function
BASEFN. Issue diagnostic, and return zero, if unacceptable. */
@@ -1870,7 +1903,6 @@ check_final_overrider (tree overrider, tree basefn)
tree base_type = TREE_TYPE (basefn);
tree over_return = fndecl_declared_return_type (overrider);
tree base_return = fndecl_declared_return_type (basefn);
- tree over_throw, base_throw;
int fail = 0;
@@ -1954,21 +1986,8 @@ check_final_overrider (tree overrider, tree basefn)
return 0;
}
- /* Check throw specifier is at least as strict. */
- maybe_instantiate_noexcept (basefn);
- maybe_instantiate_noexcept (overrider);
- base_throw = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (basefn));
- over_throw = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (overrider));
-
- if (!comp_except_specs (base_throw, over_throw, ce_derived))
- {
- auto_diagnostic_group d;
- error ("looser throw specifier for %q+#F", overrider);
- inform (DECL_SOURCE_LOCATION (basefn),
- "overridden function is %q#F", basefn);
- DECL_INVALID_OVERRIDER_P (overrider) = 1;
- return 0;
- }
+ if (!maybe_check_overriding_exception_spec (overrider, basefn))
+ return 0;
/* Check for conflicting type attributes. But leave transaction_safe for
set_one_vmethod_tm_attributes. */