diff options
author | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-04-29 18:04:50 +0000 |
---|---|---|
committer | jason <jason@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-04-29 18:04:50 +0000 |
commit | f2c1aabc34bf9104f92557b39920ccb896a3f551 (patch) | |
tree | 2f6939ee0e72751f47ab06c75051dd73d1f3d903 /gcc/cp/method.c | |
parent | e1506184f16d3ea8b5f199c6c93c277bafaec9e2 (diff) | |
download | gcc-f2c1aabc34bf9104f92557b39920ccb896a3f551.tar.gz |
DR 1351
Represent the unevaluated exception specification of an implicitly
declared or deleted function with a simple placeholder, not a list
of functions.
* cp-tree.h (UNEVALUATED_NOEXCEPT_SPEC_P): New.
* except.c (unevaluated_noexcept_spec): New.
* class.c (deduce_noexcept_on_destructor): Use it.
* decl.c (check_redeclaration_exception_specification): Call
maybe_instantiate_noexcept.
(duplicate_decls): Call it before merge_types.
(start_preparsed_function): Call maybe_instantiate_noexcept.
* decl2.c (mark_used): Call maybe_instantiate_noexcept earlier.
* init.c (get_nsdmi): Factor out of perform_member_init.
* method.c (process_subob_fn): Call maybe_instantiate_noexcept.
(walk_field_subobs): Consider NSDMI for EH spec.
(get_defaulted_eh_spec): New.
(implicitly_declare_fn): Use unevaluated_noexcept_spec.
(defaulted_late_check): Defer EH checking in non-template classes.
(after_nsdmi_defaulted_late_checks): New.
* parser.c (cp_parser_class_specifier_1): Use it.
(unparsed_classes): New macro.
* parser.h (cp_unparsed_functions_entry_d): Add classes field.
* pt.c (maybe_instantiate_noexcept): Use get_defaulted_eh_spec.
Remove list-of-functions handling.
* typeck2.c (merge_exception_specifiers): Remove list-of-functions
handling and FN parameter.
* typeck.c (merge_types): Adjust.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@209907 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp/method.c')
-rw-r--r-- | gcc/cp/method.c | 101 |
1 files changed, 79 insertions, 22 deletions
diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 11bff7f4587..f8fc01ff531 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -1003,8 +1003,9 @@ process_subob_fn (tree fn, tree *spec_p, bool *trivial_p, if (spec_p) { + maybe_instantiate_noexcept (fn); tree raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)); - *spec_p = merge_exception_specifiers (*spec_p, raises, fn); + *spec_p = merge_exception_specifiers (*spec_p, raises); } if (!trivial_fn_p (fn)) @@ -1090,17 +1091,14 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk, inform (0, "initializer for %q+#D is invalid", field); if (trivial_p) *trivial_p = false; -#if 0 /* Core 1351: If the field has an NSDMI that could throw, the - default constructor is noexcept(false). FIXME this is - broken by deferred parsing and 1360 saying we can't lazily - declare a non-trivial default constructor. Also this - needs to do deferred instantiation. Disable until the - conflict between 1351 and 1360 is resolved. */ - if (spec_p && !expr_noexcept_p (DECL_INITIAL (field), complain)) - *spec_p = noexcept_false_spec; -#endif - + default constructor is noexcept(false). */ + if (spec_p) + { + tree nsdmi = get_nsdmi (field, /*ctor*/false); + if (!expr_noexcept_p (nsdmi, complain)) + *spec_p = noexcept_false_spec; + } /* Don't do the normal processing. */ continue; } @@ -1438,6 +1436,26 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, --c_inhibit_evaluation_warnings; } +/* DECL is a defaulted function whose exception specification is now + needed. Return what it should be. */ + +tree +get_defaulted_eh_spec (tree decl) +{ + if (DECL_CLONED_FUNCTION_P (decl)) + decl = DECL_CLONED_FUNCTION (decl); + special_function_kind sfk = special_function_p (decl); + tree ctype = DECL_CONTEXT (decl); + tree parms = FUNCTION_FIRST_USER_PARMTYPE (decl); + tree parm_type = TREE_VALUE (parms); + bool const_p = CP_TYPE_CONST_P (non_reference (parm_type)); + tree spec = empty_except_spec; + synthesized_method_walk (ctype, sfk, const_p, &spec, NULL, NULL, + NULL, false, DECL_INHERITED_CTOR_BASE (decl), + parms); + return spec; +} + /* DECL is a deleted function. If it's implicitly deleted, explain why and return true; else return false. */ @@ -1675,6 +1693,13 @@ implicitly_declare_fn (special_function_kind kind, tree type, deleted_p = DECL_DELETED_FN (inherited_ctor); constexpr_p = DECL_DECLARED_CONSTEXPR_P (inherited_ctor); } + else if (cxx_dialect >= cxx11) + { + raises = unevaluated_noexcept_spec (); + synthesized_method_walk (type, kind, const_p, NULL, &trivial_p, + &deleted_p, &constexpr_p, false, + inherited_base, inherited_parms); + } else synthesized_method_walk (type, kind, const_p, &raises, &trivial_p, &deleted_p, &constexpr_p, false, @@ -1826,25 +1851,33 @@ defaulted_late_check (tree fn) is explicitly defaulted on its first declaration, (...) it is implicitly considered to have the same exception-specification as if it had been implicitly declared. */ - if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))) + tree fn_spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)); + if (!fn_spec) { - maybe_instantiate_noexcept (fn); - if (!comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)), - eh_spec, ce_normal)) + if (DECL_DEFAULTED_IN_CLASS_P (fn)) + TREE_TYPE (fn) = build_exception_variant (TREE_TYPE (fn), eh_spec); + } + else if (UNEVALUATED_NOEXCEPT_SPEC_P (fn_spec)) + /* Equivalent to the implicit spec. */; + else if (DECL_DEFAULTED_IN_CLASS_P (fn) + && !CLASSTYPE_TEMPLATE_INSTANTIATION (ctx)) + /* We can't compare an explicit exception-specification on a + constructor defaulted in the class body to the implicit + exception-specification until after we've parsed any NSDMI; see + after_nsdmi_defaulted_late_checks. */; + else + { + tree eh_spec = get_defaulted_eh_spec (fn); + if (!comp_except_specs (fn_spec, eh_spec, ce_normal)) { if (DECL_DEFAULTED_IN_CLASS_P (fn)) - { - DECL_DELETED_FN (fn) = true; - eh_spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)); - } + DECL_DELETED_FN (fn) = true; else error ("function %q+D defaulted on its redeclaration " "with an exception-specification that differs from " - "the implicit declaration %q#D", fn, implicit_fn); + "the implicit exception-specification %qX", fn, eh_spec); } } - if (DECL_DEFAULTED_IN_CLASS_P (fn)) - TREE_TYPE (fn) = build_exception_variant (TREE_TYPE (fn), eh_spec); if (DECL_DEFAULTED_IN_CLASS_P (fn) && DECL_DECLARED_CONSTEXPR_P (implicit_fn)) @@ -1874,6 +1907,30 @@ defaulted_late_check (tree fn) DECL_DELETED_FN (fn) = 1; } +/* OK, we've parsed the NSDMI for class T, now we can check any explicit + exception-specifications on functions defaulted in the class body. */ + +void +after_nsdmi_defaulted_late_checks (tree t) +{ + if (uses_template_parms (t)) + return; + if (t == error_mark_node) + return; + for (tree fn = TYPE_METHODS (t); fn; fn = DECL_CHAIN (fn)) + if (!DECL_ARTIFICIAL (fn) && DECL_DEFAULTED_IN_CLASS_P (fn)) + { + tree fn_spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)); + if (UNEVALUATED_NOEXCEPT_SPEC_P (fn_spec)) + continue; + + tree eh_spec = get_defaulted_eh_spec (fn); + if (!comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)), + eh_spec, ce_normal)) + DECL_DELETED_FN (fn) = true; + } +} + /* Returns true iff FN can be explicitly defaulted, and gives any errors if defaulting FN is ill-formed. */ |