Mangling visits the base template function type, prior to template resolution, and on such types, exception specifications may contain unresolved noexcept expressions. nothrow_spec_p is called on them even whe exception specifications are not part of function types, and it rejects unresolved noexcept expressions if processing_template_decl is not set.
Setting processing_template_decl while mangling what is indeed the (generic) type of a function template would solve this problem, but it would cause others: no_linkage_check, for example, returns early if processing_template_decl, and this regresses g++.dg/pr79091.C and g++.dg/abi/no-linkage-expr1.C. So, instead of setting processing_template_decl throughout, I'm introducing another flag, processing_template_function_signature, and using it to set processing_template_decl only while canonicalizing the exception spec, which is where nothrow_spec_p gets called. Regstrapped on i686- and x86_64-linux-gnu. Ok to install? for gcc/cp/ChangeLog PR c++/86397 * mangle.c (processing_template_function_signature): New var. (write_encoding): Set it while mangling generic template type. (canonicalize_for_substitution): Set processing_template_decl while handling exception specs if processing_template_function_signature. for gcc/testsuite/ChangeLog PR c++/86397 * g++.dg/cpp0x/pr86397-1.C: New. * g++.dg/cpp0x/pr86397-2.C: New. --- gcc/cp/mangle.c | 19 +++++++++++++++++++ gcc/testsuite/g++.dg/cpp0x/pr86397-1.C | 4 ++++ gcc/testsuite/g++.dg/cpp0x/pr86397-2.C | 4 ++++ 3 files changed, 27 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp0x/pr86397-1.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/pr86397-2.C diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c index 64415894bc57..a499ef97b3c6 100644 --- a/gcc/cp/mangle.c +++ b/gcc/cp/mangle.c @@ -170,6 +170,17 @@ integer_type_codes[itk_none] = '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' }; +/* Exception specifications may carry unresolved noexcept expressions + before template substitution, but nothrow_spec_p will fail an + assert check if it comes across such a spec while + !processing_template_decl. So, when we start processing the + signature of a template function, that may contain a such + unresolved expressions, we set this variable. Then, as we process + the exception spec, we set processing_template_decl. We don't want + to set processing_template_decl throughout, becuase this affects + other relevant tests, such as no_linkage_check. */ +static int processing_template_function_signature; + static int decl_is_template_id (const tree, tree* const); /* Functions for handling substitutions. */ @@ -418,7 +429,11 @@ canonicalize_for_substitution (tree node) || TREE_CODE (node) == METHOD_TYPE) { node = build_ref_qualified_type (node, type_memfn_rqual (orig)); + if (processing_template_function_signature) + processing_template_decl++; tree r = canonical_eh_spec (TYPE_RAISES_EXCEPTIONS (orig)); + if (processing_template_function_signature) + processing_template_decl--; if (flag_noexcept_type) node = build_exception_variant (node, r); else @@ -836,6 +851,7 @@ write_encoding (const tree decl) write_bare_function_type -- otherwise, it will get confused about which artificial parameters to skip. */ d = NULL_TREE; + ++processing_template_function_signature; } else { @@ -846,6 +862,9 @@ write_encoding (const tree decl) write_bare_function_type (fn_type, mangle_return_type_p (decl), d); + + if (tmpl) + --processing_template_function_signature; } } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr86397-1.C b/gcc/testsuite/g++.dg/cpp0x/pr86397-1.C new file mode 100644 index 000000000000..4f9f5fa7e4c8 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr86397-1.C @@ -0,0 +1,4 @@ +// { dg-do compile { target c++11 } } +void e(); +template <bool> void f(int() noexcept(e)) {} +template void f<false>(int()); // { dg-error "does not match" "" { target c++17 } } diff --git a/gcc/testsuite/g++.dg/cpp0x/pr86397-2.C b/gcc/testsuite/g++.dg/cpp0x/pr86397-2.C new file mode 100644 index 000000000000..fb43499526e8 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/pr86397-2.C @@ -0,0 +1,4 @@ +// { dg-do compile { target c++11 } } +void e(); +template <bool> void f(int() noexcept(e)) {} +template void f<false>(int() noexcept); -- Alexandre Oliva, freedom fighter https://FSFLA.org/blogs/lxo Be the change, be Free! FSF Latin America board member GNU Toolchain Engineer Free Software Evangelist Hay que enGNUrecerse, pero sin perder la terGNUra jamás-GNUChe