From c526171d734653ebde26fc8a29191247add7bf3e Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Thu, 28 Mar 2019 20:24:48 +0000 Subject: [PATCH] PR c++/89612 - ICE with member friend template with noexcept. * pt.c (maybe_instantiate_noexcept): For function templates, use their template result (function decl). Don't set up local specializations. Temporarily turn on processing_template_decl. Update the template type too. * g++.dg/cpp0x/noexcept38.C: New test. * g++.dg/cpp0x/noexcept39.C: New test. * g++.dg/cpp1z/noexcept-type21.C: New test. From-SVN: r270005 --- gcc/cp/ChangeLog | 6 ++ gcc/cp/pt.c | 75 ++++++++++++-------- gcc/testsuite/ChangeLog | 7 ++ gcc/testsuite/g++.dg/cpp0x/noexcept38.C | 19 +++++ gcc/testsuite/g++.dg/cpp0x/noexcept39.C | 19 +++++ gcc/testsuite/g++.dg/cpp1z/noexcept-type21.C | 16 +++++ 6 files changed, 113 insertions(+), 29 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept38.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept39.C create mode 100644 gcc/testsuite/g++.dg/cpp1z/noexcept-type21.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 075e977b70b..eb35f9ec798 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2019-03-28 Marek Polacek + PR c++/89612 - ICE with member friend template with noexcept. + * pt.c (maybe_instantiate_noexcept): For function templates, use their + template result (function decl). Don't set up local specializations. + Temporarily turn on processing_template_decl. Update the template type + too. + PR c++/89836 - bool constant expression and explicit conversions. * call.c (build_converted_constant_expr_internal): New function, renamed from... diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 229b34a197e..91c341589be 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -24193,6 +24193,17 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain) if (DECL_CLONED_FUNCTION_P (fn)) fn = DECL_CLONED_FUNCTION (fn); + + tree orig_fn = NULL_TREE; + /* For a member friend template we can get a TEMPLATE_DECL. Let's use + its FUNCTION_DECL for the rest of this function -- push_access_scope + doesn't accept TEMPLATE_DECLs. */ + if (DECL_FUNCTION_TEMPLATE_P (fn)) + { + orig_fn = fn; + fn = DECL_TEMPLATE_RESULT (fn); + } + fntype = TREE_TYPE (fn); spec = TYPE_RAISES_EXCEPTIONS (fntype); @@ -24229,37 +24240,41 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain) push_deferring_access_checks (dk_no_deferred); input_location = DECL_SOURCE_LOCATION (fn); - /* A new stack interferes with pop_access_scope. */ - { - /* Set up the list of local specializations. */ - local_specialization_stack lss (lss_copy); - - tree save_ccp = current_class_ptr; - tree save_ccr = current_class_ref; - /* If needed, set current_class_ptr for the benefit of - tsubst_copy/PARM_DECL. */ - tree tdecl = DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (fn)); - if (DECL_NONSTATIC_MEMBER_FUNCTION_P (tdecl)) - { - tree this_parm = DECL_ARGUMENTS (tdecl); - current_class_ptr = NULL_TREE; - current_class_ref = cp_build_fold_indirect_ref (this_parm); - current_class_ptr = this_parm; - } + tree save_ccp = current_class_ptr; + tree save_ccr = current_class_ref; + /* If needed, set current_class_ptr for the benefit of + tsubst_copy/PARM_DECL. */ + tree tdecl = DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (fn)); + if (DECL_NONSTATIC_MEMBER_FUNCTION_P (tdecl)) + { + tree this_parm = DECL_ARGUMENTS (tdecl); + current_class_ptr = NULL_TREE; + current_class_ref = cp_build_fold_indirect_ref (this_parm); + current_class_ptr = this_parm; + } - /* Create substitution entries for the parameters. */ - register_parameter_specializations (tdecl, fn); + /* If this function is represented by a TEMPLATE_DECL, then + the deferred noexcept-specification might still contain + dependent types, even after substitution. And we need the + dependency check functions to work in build_noexcept_spec. */ + if (orig_fn) + ++processing_template_decl; - /* Do deferred instantiation of the noexcept-specifier. */ - noex = tsubst_copy_and_build (DEFERRED_NOEXCEPT_PATTERN (noex), - DEFERRED_NOEXCEPT_ARGS (noex), - tf_warning_or_error, fn, - /*function_p=*/false, - /*i_c_e_p=*/true); - current_class_ptr = save_ccp; - current_class_ref = save_ccr; - spec = build_noexcept_spec (noex, tf_warning_or_error); - } + /* Do deferred instantiation of the noexcept-specifier. */ + noex = tsubst_copy_and_build (DEFERRED_NOEXCEPT_PATTERN (noex), + DEFERRED_NOEXCEPT_ARGS (noex), + tf_warning_or_error, fn, + /*function_p=*/false, + /*i_c_e_p=*/true); + + current_class_ptr = save_ccp; + current_class_ref = save_ccr; + + /* Build up the noexcept-specification. */ + spec = build_noexcept_spec (noex, tf_warning_or_error); + + if (orig_fn) + --processing_template_decl; pop_deferring_access_checks (); pop_access_scope (fn); @@ -24279,6 +24294,8 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain) } TREE_TYPE (fn) = build_exception_variant (fntype, spec); + if (orig_fn) + TREE_TYPE (orig_fn) = TREE_TYPE (fn); } FOR_EACH_CLONE (clone, fn) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index cf9ed5cda8f..9a496ec58f4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2019-03-28 Marek Polacek + + PR c++/89612 - ICE with member friend template with noexcept. + * g++.dg/cpp0x/noexcept38.C: New test. + * g++.dg/cpp0x/noexcept39.C: New test. + * g++.dg/cpp1z/noexcept-type21.C: New test. + 2019-03-28 Uroš Bizjak PR target/89848 diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept38.C b/gcc/testsuite/g++.dg/cpp0x/noexcept38.C new file mode 100644 index 00000000000..ecab59df694 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept38.C @@ -0,0 +1,19 @@ +// PR c++/89612 +// { dg-do compile { target c++11 } } + +template +struct C { + template + friend int foo() noexcept(N); + + template + friend int foo2() noexcept(N); // { dg-error "different exception" } +}; + +template +int foo() noexcept(N); + +template +int foo2() noexcept(N + 1); + +C c; diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept39.C b/gcc/testsuite/g++.dg/cpp0x/noexcept39.C new file mode 100644 index 00000000000..fbebbed5e4c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept39.C @@ -0,0 +1,19 @@ +// PR c++/89612 +// { dg-do compile { target c++11 } } + +template +struct C { + template + friend void foo(T t) noexcept(sizeof(decltype(t)) > 1); + + template + friend void foo2(T t) noexcept(sizeof(decltype(t)) < 1); // { dg-error "different exception" } +}; + +template +void foo(int i) noexcept { } + +template +void foo2(int i) noexcept { } + +C c; diff --git a/gcc/testsuite/g++.dg/cpp1z/noexcept-type21.C b/gcc/testsuite/g++.dg/cpp1z/noexcept-type21.C new file mode 100644 index 00000000000..d0a61d95e87 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/noexcept-type21.C @@ -0,0 +1,16 @@ +// PR c++/89612 +// { dg-do compile { target c++17 } } + +template using b = typename a ::c; +template bool d; +template struct e { + template e(f, g) {} + template + friend auto k(h &&, const j &, i &&) noexcept(d, h> &&d, i>); +}; +template e(l, m)->e; +template +auto k(l &&, const j &, m &&) noexcept(d, l> &&d, m>); +int main() { + e(0, [] {}); +} -- 2.30.2