On 2/6/25 1:48 PM, Marek Polacek wrote:
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
OK.
-- >8 --
In a member-specification of a class, a noexcept-specifier is
a complete-class context. Thus we delay parsing until the end of
the class via our DEFERRED_PARSE mechanism; see cp_parser_save_noexcept
and cp_parser_late_noexcept_specifier.
We also attempt to defer instantiation of noexcept-specifiers in order
to reduce the number of instantiations; this is done via DEFERRED_NOEXCEPT.
We can even have both, as in noexcept65.C: a DEFERRED_PARSE wrapped in
DEFERRED_NOEXCEPT, which uses the DEFPARSE_INSTANTIATIONS mechanism.
noexcept65.C works, because when we really need the noexcept, which is
when parsing the body of S::A::A(), the noexcept will have been parsed
already; noexcepts are parsed before bodies of member function.
But in this test we have:
struct A {
int x;
template<class>
void foo() noexcept(noexcept(x)) {}
auto bar() -> decltype(foo<int>()) {} // #1
};
and I think the decltype in #1 needs the unparsed noexcept before it
could have been parsed. clang++ rejects the test and I suppose we
should reject it as well, rather than crashing on a DEFERRED_PARSE
in tsubst_expr.
PR c++/117106
PR c++/118190
gcc/cp/ChangeLog:
* pt.cc (maybe_instantiate_noexcept): Give an error if the noexcept
hasn't been parsed yet.
gcc/testsuite/ChangeLog:
* g++.dg/cpp0x/noexcept89.C: New test.
* g++.dg/cpp0x/noexcept90.C: New test.
---
gcc/cp/pt.cc | 16 +++++++++++-----
gcc/testsuite/g++.dg/cpp0x/noexcept89.C | 9 +++++++++
gcc/testsuite/g++.dg/cpp0x/noexcept90.C | 12 ++++++++++++
3 files changed, 32 insertions(+), 5 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept89.C
create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept90.C
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 39232b5e67f..8108bf5de65 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -27453,7 +27453,8 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t
complain)
{
static hash_set<tree>* fns = new hash_set<tree>;
bool added = false;
- if (DEFERRED_NOEXCEPT_PATTERN (noex) == NULL_TREE)
+ tree pattern = DEFERRED_NOEXCEPT_PATTERN (noex);
+ if (pattern == NULL_TREE)
{
spec = get_defaulted_eh_spec (fn, complain);
if (spec == error_mark_node)
@@ -27464,13 +27465,19 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t
complain)
else if (!(added = !fns->add (fn)))
{
/* If hash_set::add returns true, the element was already there. */
- location_t loc = cp_expr_loc_or_loc (DEFERRED_NOEXCEPT_PATTERN (noex),
- DECL_SOURCE_LOCATION (fn));
+ location_t loc = cp_expr_loc_or_loc (pattern,
+ DECL_SOURCE_LOCATION (fn));
error_at (loc,
"exception specification of %qD depends on itself",
fn);
spec = noexcept_false_spec;
}
+ else if (TREE_CODE (pattern) == DEFERRED_PARSE)
+ {
+ error ("exception specification of %qD is not available "
+ "until end of class definition", fn);
+ spec = noexcept_false_spec;
+ }
else if (push_tinst_level (fn))
{
const bool push_to_top = maybe_push_to_top_level (fn);
@@ -27497,8 +27504,7 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t
complain)
++processing_template_decl;
/* Do deferred instantiation of the noexcept-specifier. */
- noex = tsubst_expr (DEFERRED_NOEXCEPT_PATTERN (noex),
- DEFERRED_NOEXCEPT_ARGS (noex),
+ noex = tsubst_expr (pattern, DEFERRED_NOEXCEPT_ARGS (noex),
tf_warning_or_error, fn);
/* Build up the noexcept-specification. */
spec = build_noexcept_spec (noex, tf_warning_or_error);
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept89.C
b/gcc/testsuite/g++.dg/cpp0x/noexcept89.C
new file mode 100644
index 00000000000..308abf6fb45
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept89.C
@@ -0,0 +1,9 @@
+// PR c++/117106
+// { dg-do compile { target c++11 } }
+
+struct A {
+ int x;
+ template<class>
+ void foo() noexcept(noexcept(x)) {}
+ auto bar() -> decltype(foo<int>()) {} // { dg-error "not available until end of
class" }
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept90.C
b/gcc/testsuite/g++.dg/cpp0x/noexcept90.C
new file mode 100644
index 00000000000..6d403f66e72
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/noexcept90.C
@@ -0,0 +1,12 @@
+// PR c++/118190
+// { dg-do compile { target c++11 } }
+
+struct S {
+ template<typename T>
+ struct S5 {
+ void f1() noexcept(noexcept(i)) { }
+ int i;
+ };
+ S5<int> s5;
+ static_assert (noexcept(s5.f1()), ""); // { dg-error "not available until end of
class|static assertion failed" }
+};
base-commit: a69b728b5b9efa34d0af9f9ce0b248d05f7791b0