diff options
author | Marek Polacek <polacek@redhat.com> | 2019-06-22 15:14:30 +0000 |
---|---|---|
committer | Marek Polacek <mpolacek@gcc.gnu.org> | 2019-06-22 15:14:30 +0000 |
commit | 78f7607db4c53f8cfe4653a6c91c0328bc2854c3 (patch) | |
tree | d8c288e122322c16f7c0c600df65e9b34feaf7c2 /gcc/cp/search.c | |
parent | 7f3db013dc8264e39339ee4b83900ef25d0d32aa (diff) | |
download | gcc-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.c | 51 |
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. */ |