diff options
author | Patrick Palka <ppalka@redhat.com> | 2022-02-03 18:54:23 -0500 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2022-02-03 18:54:23 -0500 |
commit | 82e31c8973eb1a752c2ffd01005efe291d35cee3 (patch) | |
tree | f7539fe6e73b907c3edab5be373b8424bb597d1b /gcc | |
parent | 3ef328c293a336df0aead2d72c0c5ed9781a9861 (diff) | |
download | gcc-82e31c8973eb1a752c2ffd01005efe291d35cee3.zip gcc-82e31c8973eb1a752c2ffd01005efe291d35cee3.tar.gz gcc-82e31c8973eb1a752c2ffd01005efe291d35cee3.tar.bz2 |
c++: dependence of member noexcept-spec [PR104079]
Here a stale TYPE_DEPENDENT_P/_P_VALID value for f's function type
after replacing the type's DEFERRED_NOEXCEPT with the parsed dependent
noexcept-spec causes us to try to instantiate g's noexcept-spec ahead
of time (since it in turn appears non-dependent), leading to an ICE.
This patch fixes this by clearing TYPE_DEPENDENT_P_VALID in
fixup_deferred_exception_variants appropriately (as in
build_cp_fntype_variant).
That turns out to fix the testcase for C++17 but not for C++11/14,
because it's not until C++17 that a noexcept-spec is part of (and
therefore affects dependence of) the function type. Since dependence of
NOEXCEPT_EXPR is defined in terms of instantiation dependence, the most
appropriate fix for earlier dialects seems to be to make instantiation
dependence consider dependence of a noexcept-spec.
PR c++/104079
gcc/cp/ChangeLog:
* pt.cc (value_dependent_noexcept_spec_p): New predicate split
out from ...
(dependent_type_p_r): ... here.
(instantiation_dependent_r): Use value_dependent_noexcept_spec_p
to consider dependence of a noexcept-spec before C++17.
* tree.cc (fixup_deferred_exception_variants): Clear
TYPE_DEPENDENT_P_VALID.
gcc/testsuite/ChangeLog:
* g++.dg/cpp0x/noexcept74.C: New test.
* g++.dg/cpp0x/noexcept74a.C: New test.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/pt.cc | 42 | ||||
-rw-r--r-- | gcc/cp/tree.cc | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/noexcept74.C | 11 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/noexcept74a.C | 12 |
4 files changed, 59 insertions, 10 deletions
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 6e129da..60641d8 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -27003,6 +27003,24 @@ invalid_nontype_parm_type_p (tree type, tsubst_flags_t complain) return true; } +/* Returns true iff the noexcept-specifier for TYPE is value-dependent. */ + +static bool +value_dependent_noexcept_spec_p (tree type) +{ + if (tree spec = TYPE_RAISES_EXCEPTIONS (type)) + if (tree noex = TREE_PURPOSE (spec)) + /* Treat DEFERRED_NOEXCEPT as non-dependent, since it doesn't + affect overload resolution and treating it as dependent breaks + things. Same for an unparsed noexcept expression. */ + if (TREE_CODE (noex) != DEFERRED_NOEXCEPT + && TREE_CODE (noex) != DEFERRED_PARSE + && value_dependent_expression_p (noex)) + return true; + + return false; +} + /* Returns TRUE if TYPE is dependent, in the sense of [temp.dep.type]. Assumes that TYPE really is a type, and not the ERROR_MARK_NODE.*/ @@ -27055,17 +27073,10 @@ dependent_type_p_r (tree type) arg_type = TREE_CHAIN (arg_type)) if (dependent_type_p (TREE_VALUE (arg_type))) return true; - if (cxx_dialect >= cxx17) + if (cxx_dialect >= cxx17 + && value_dependent_noexcept_spec_p (type)) /* A value-dependent noexcept-specifier makes the type dependent. */ - if (tree spec = TYPE_RAISES_EXCEPTIONS (type)) - if (tree noex = TREE_PURPOSE (spec)) - /* Treat DEFERRED_NOEXCEPT as non-dependent, since it doesn't - affect overload resolution and treating it as dependent breaks - things. Same for an unparsed noexcept expression. */ - if (TREE_CODE (noex) != DEFERRED_NOEXCEPT - && TREE_CODE (noex) != DEFERRED_PARSE - && value_dependent_expression_p (noex)) - return true; + return true; return false; } /* -- an array type constructed from any dependent type or whose @@ -27874,6 +27885,17 @@ instantiation_dependent_r (tree *tp, int *walk_subtrees, return *tp; break; + case TEMPLATE_DECL: + case FUNCTION_DECL: + /* Before C++17, a noexcept-specifier isn't part of the function type + so it doesn't affect type dependence, but we still want to consider it + for instantiation dependence. */ + if (cxx_dialect < cxx17 + && DECL_DECLARES_FUNCTION_P (*tp) + && value_dependent_noexcept_spec_p (TREE_TYPE (*tp))) + return *tp; + break; + default: break; } diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc index 056f10f..2d8f2c5 100644 --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -2839,6 +2839,10 @@ fixup_deferred_exception_variants (tree type, tree raises) } else TYPE_RAISES_EXCEPTIONS (variant) = raises; + + if (!TYPE_DEPENDENT_P (variant)) + /* We no longer know that it's not type-dependent. */ + TYPE_DEPENDENT_P_VALID (variant) = false; } } diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept74.C b/gcc/testsuite/g++.dg/cpp0x/noexcept74.C new file mode 100644 index 0000000..c439c9d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept74.C @@ -0,0 +1,11 @@ +// PR c++/104079 +// { dg-do compile { target c++11 } } + +template<bool B> +struct AT { + static void f() noexcept(B); + + void g() noexcept(noexcept(f())) { + static_assert(noexcept(f()), ""); + } +}; diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept74a.C b/gcc/testsuite/g++.dg/cpp0x/noexcept74a.C new file mode 100644 index 0000000..008654d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept74a.C @@ -0,0 +1,12 @@ +// PR c++/104079 +// { dg-do compile { target c++11 } } +// A variant of noexcept74.C where f is a function template. + +template<bool B> +struct AT { + template<class...> static void f() noexcept(B); + + void g() noexcept(noexcept(f())) { + static_assert(noexcept(f()), ""); + } +}; |