In the testcase we SEGV due to infinite recursion because the noexcept-specifier of f depends on itself. Fixed by keeping track of which functions we're currently trying to instantiate noexcept for.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit 7a938fed4c07c7e28008b56e6bac05376b1f99fa Author: Jason Merrill <ja...@redhat.com> Date: Tue Jun 27 17:25:18 2017 -0400 PR c++/69300 - ICE with self-referential noexcept * pt.c (maybe_instantiate_noexcept): Check for recursion. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index fa75037..047d3ba 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -22557,8 +22557,20 @@ maybe_instantiate_noexcept (tree fn) if (TREE_CODE (noex) == DEFERRED_NOEXCEPT) { + static hash_set<tree>* fns = new hash_set<tree>; + bool added = false; if (DEFERRED_NOEXCEPT_PATTERN (noex) == NULL_TREE) spec = get_defaulted_eh_spec (fn); + else if (!(added = !fns->add (fn))) + { + /* If hash_set::add returns true, the element was already there. */ + location_t loc = EXPR_LOC_OR_LOC (DEFERRED_NOEXCEPT_PATTERN (noex), + DECL_SOURCE_LOCATION (fn)); + error_at (loc, + "exception specification of %qD depends on itself", + fn); + spec = noexcept_false_spec; + } else if (push_tinst_level (fn)) { push_access_scope (fn); @@ -22579,6 +22591,9 @@ maybe_instantiate_noexcept (tree fn) else spec = noexcept_false_spec; + if (added) + fns->remove (fn); + TREE_TYPE (fn) = build_exception_variant (fntype, spec); } diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept30.C b/gcc/testsuite/g++.dg/cpp0x/noexcept30.C new file mode 100644 index 0000000..c51e94e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept30.C @@ -0,0 +1,12 @@ +// PR c++/69300 +// { dg-do compile { target c++11 } } + +template<typename A> +struct F { + template<typename B> + void f() noexcept(&F::template f<B>) {} // { dg-error "exception specification" } +}; + +int main () { + F<void>().f<int>(); +}