Skip to content

Commit f5ef1f9

Browse files
committed
c++: ICE with unparsed noexcept [PR117106]
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. Reviewed-by: Jason Merrill <[email protected]>
1 parent 0b2f34c commit f5ef1f9

File tree

3 files changed

+32
-5
lines changed

3 files changed

+32
-5
lines changed

gcc/cp/pt.cc

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27453,7 +27453,8 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
2745327453
{
2745427454
static hash_set<tree>* fns = new hash_set<tree>;
2745527455
bool added = false;
27456-
if (DEFERRED_NOEXCEPT_PATTERN (noex) == NULL_TREE)
27456+
tree pattern = DEFERRED_NOEXCEPT_PATTERN (noex);
27457+
if (pattern == NULL_TREE)
2745727458
{
2745827459
spec = get_defaulted_eh_spec (fn, complain);
2745927460
if (spec == error_mark_node)
@@ -27464,13 +27465,19 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
2746427465
else if (!(added = !fns->add (fn)))
2746527466
{
2746627467
/* If hash_set::add returns true, the element was already there. */
27467-
location_t loc = cp_expr_loc_or_loc (DEFERRED_NOEXCEPT_PATTERN (noex),
27468-
DECL_SOURCE_LOCATION (fn));
27468+
location_t loc = cp_expr_loc_or_loc (pattern,
27469+
DECL_SOURCE_LOCATION (fn));
2746927470
error_at (loc,
2747027471
"exception specification of %qD depends on itself",
2747127472
fn);
2747227473
spec = noexcept_false_spec;
2747327474
}
27475+
else if (TREE_CODE (pattern) == DEFERRED_PARSE)
27476+
{
27477+
error ("exception specification of %qD is not available "
27478+
"until end of class definition", fn);
27479+
spec = noexcept_false_spec;
27480+
}
2747427481
else if (push_tinst_level (fn))
2747527482
{
2747627483
const bool push_to_top = maybe_push_to_top_level (fn);
@@ -27497,8 +27504,7 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
2749727504
++processing_template_decl;
2749827505

2749927506
/* Do deferred instantiation of the noexcept-specifier. */
27500-
noex = tsubst_expr (DEFERRED_NOEXCEPT_PATTERN (noex),
27501-
DEFERRED_NOEXCEPT_ARGS (noex),
27507+
noex = tsubst_expr (pattern, DEFERRED_NOEXCEPT_ARGS (noex),
2750227508
tf_warning_or_error, fn);
2750327509
/* Build up the noexcept-specification. */
2750427510
spec = build_noexcept_spec (noex, tf_warning_or_error);
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// PR c++/117106
2+
// { dg-do compile { target c++11 } }
3+
4+
struct A {
5+
int x;
6+
template<class>
7+
void foo() noexcept(noexcept(x)) {}
8+
auto bar() -> decltype(foo<int>()) {} // { dg-error "not available until end of class" }
9+
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// PR c++/118190
2+
// { dg-do compile { target c++11 } }
3+
4+
struct S {
5+
template<typename T>
6+
struct S5 {
7+
void f1() noexcept(noexcept(i)) { }
8+
int i;
9+
};
10+
S5<int> s5;
11+
static_assert (noexcept(s5.f1()), ""); // { dg-error "not available until end of class|static assertion failed" }
12+
};

0 commit comments

Comments
 (0)