Hi,
this error-recovery regressions is mostly another case - similar to
c++/89488 - where we want to check that maybe_instantiate_noexcept
actually succeeds before calling a function that asserts
!DEFERRED_NOEXCEPT_SPEC_P, nothrow_spec_p this time. I think we want to
do that consistently in both the semantics.c places. Beyond that, there
is a secondary issue with -std=c++98, because, in that case,
synthesized_method_walk, called by implicitly_declare_fn, sets raises to
error_mark_node and we can't pass it to build_exception_variant (we
explicitly avoid that elsewhere too). Tested x86_64-linux.
Thanks, Paolo.
////////////////////
/cp
2019-04-05 Paolo Carlini <paolo.carl...@oracle.com>
PR c++/89914
* semantics.c (trait_expr_value): Don't use TYPE_NOTHROW_P
when maybe_instantiate_noexcept fails.
(classtype_has_nothrow_assign_or_copy_p): Likewise.
* method.c (implicitly_declare_fn): Avoid passing error_mark_node
to build_exception_variant.
/testsuite
2019-04-05 Paolo Carlini <paolo.carl...@oracle.com>
PR c++/89914
* g++.dg/ext/has_nothrow_constructor-3.C: New.
Index: cp/method.c
===================================================================
--- cp/method.c (revision 270145)
+++ cp/method.c (working copy)
@@ -2061,7 +2061,14 @@ implicitly_declare_fn (special_function_kind kind,
/* Create the function. */
fn_type = build_method_type_directly (type, return_type, parameter_types);
if (raises)
- fn_type = build_exception_variant (fn_type, raises);
+ {
+ if (raises != error_mark_node)
+ fn_type = build_exception_variant (fn_type, raises);
+ else
+ /* Can happen, eg, in C++98 mode for an ill-formed non-static data
+ member initializer (c++/89914). */
+ gcc_assert (seen_error ());
+ }
fn = build_lang_decl (FUNCTION_DECL, name, fn_type);
if (kind != sfk_inheriting_constructor)
DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (TYPE_NAME (type));
Index: cp/semantics.c
===================================================================
--- cp/semantics.c (revision 270145)
+++ cp/semantics.c (working copy)
@@ -9551,8 +9551,8 @@ classtype_has_nothrow_assign_or_copy_p (tree type,
if (copy_fn_p (fn) > 0)
{
saw_copy = true;
- maybe_instantiate_noexcept (fn);
- if (!TYPE_NOTHROW_P (TREE_TYPE (fn)))
+ if (!maybe_instantiate_noexcept (fn)
+ || !TYPE_NOTHROW_P (TREE_TYPE (fn)))
return false;
}
}
@@ -9594,8 +9594,8 @@ trait_expr_value (cp_trait_kind kind, tree type1,
return (trait_expr_value (CPTK_HAS_TRIVIAL_CONSTRUCTOR, type1, type2)
|| (CLASS_TYPE_P (type1)
&& (t = locate_ctor (type1))
- && (maybe_instantiate_noexcept (t),
- TYPE_NOTHROW_P (TREE_TYPE (t)))));
+ && maybe_instantiate_noexcept (t)
+ && TYPE_NOTHROW_P (TREE_TYPE (t))));
case CPTK_HAS_TRIVIAL_CONSTRUCTOR:
type1 = strip_array_types (type1);
Index: testsuite/g++.dg/ext/has_nothrow_constructor-3.C
===================================================================
--- testsuite/g++.dg/ext/has_nothrow_constructor-3.C (nonexistent)
+++ testsuite/g++.dg/ext/has_nothrow_constructor-3.C (working copy)
@@ -0,0 +1,9 @@
+// PR c++/89914
+
+struct A
+{
+ int i = ; // { dg-error "expected" }
+ // { dg-error "non-static data member" "" { target c++98_only } .-1 }
+};
+
+bool b = __has_nothrow_constructor (A);