diff --git a/gcc/cp/call.c b/gcc/cp/call.c index e757e1893c7..4b81d0ff333 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -8947,8 +8947,13 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) /* OK, we're actually calling this inherited constructor; set its deletedness appropriately. We can get away with doing this here because calling is the only way to refer to a constructor. */ - if (DECL_INHERITED_CTOR (fn)) - deduce_inheriting_ctor (fn); + if (DECL_INHERITED_CTOR (fn) + && !deduce_inheriting_ctor (fn)) + { + if (complain & tf_error) + mark_used (fn); + return error_mark_node; + } /* Make =delete work with SFINAE. */ if (DECL_DELETED_FN (fn)) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index e68e3905f80..f6470524cf8 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6915,7 +6915,7 @@ extern bool is_xible (enum tree_code, tree, tree); extern tree get_defaulted_eh_spec (tree, tsubst_flags_t = tf_warning_or_error); extern bool maybe_explain_implicit_delete (tree); extern void explain_implicit_non_constexpr (tree); -extern void deduce_inheriting_ctor (tree); +extern bool deduce_inheriting_ctor (tree); extern bool decl_remember_implicit_trigger_p (tree); extern void synthesize_method (tree); extern tree lazily_declare_fn (special_function_kind, diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 3fe3bd82a7d..25c1e681b99 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -2789,9 +2789,9 @@ explain_implicit_non_constexpr (tree decl) /* DECL is an instantiation of an inheriting constructor template. Deduce the correct exception-specification and deletedness for this particular - specialization. */ + specialization. Return true if the deduction succeeds; false otherwise. */ -void +bool deduce_inheriting_ctor (tree decl) { decl = DECL_ORIGIN (decl); @@ -2804,6 +2804,8 @@ deduce_inheriting_ctor (tree decl) /*diag*/false, &inh, FUNCTION_FIRST_USER_PARMTYPE (decl)); + if (spec == error_mark_node) + return false; if (TREE_CODE (inherited_ctor_binfo (decl)) != TREE_BINFO) /* Inherited the same constructor from different base subobjects. */ deleted = true; @@ -2818,6 +2820,8 @@ deduce_inheriting_ctor (tree decl) TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone), spec); SET_DECL_INHERITED_CTOR (clone, inh); } + + return true; } /* Implicitly declare the special function indicated by KIND, as a @@ -2993,9 +2997,17 @@ implicitly_declare_fn (special_function_kind kind, tree type, 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 ()); + { + /* Can happen, e.g., in C++98 mode for an ill-formed non-static data + member initializer (c++/89914). Also, in C++98, we might have + failed to deduce RAISES, so try again but complain this time. */ + if (cxx_dialect < cxx11) + synthesized_method_walk (type, kind, const_p, nullptr, nullptr, + nullptr, nullptr, /*diag=*/true, + &inherited_ctor, inherited_parms); + /* We should have seen an error at this point. */ + gcc_assert (seen_error ()); + } } fn = build_lang_decl (FUNCTION_DECL, name, fn_type); if (kind != sfk_inheriting_constructor) diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor37.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor37.C new file mode 100644 index 00000000000..7d12b534d95 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor37.C @@ -0,0 +1,26 @@ +// PR c++/94751 +// { dg-do compile } +// { dg-options "-w" } + +struct A { + A(float); +}; + +template +struct B : A { + using A::A; + + struct C { + C(int); + }; + + C c{ "foo" }; // { dg-error "invalid conversion" } +}; + +struct S { S(B *); }; + +S +fn () +{ + return S(new B(10.5)); // { dg-error "no matching function" "" { target c++98_only } } +}