This is a backport of r251426 which incidentally fixed PR 81860 and its dup. The bug was closed as fixed, but as a regression it should be fixed for 7.x too.
The patch applied cleanly to the branch except for a minor conflict in get_defaulted_eh_spec because r250994 isn't on the branch. Tested x86_64-linux, OK for gcc-7-branch? Backport from mainline 2017-08-29 Jason Merrill <ja...@redhat.com> * method.c (synthesized_method_base_walk): Replace an inherited template with its specialization. (synthesized_method_walk): Make inheriting_ctor a pointer. (maybe_explain_implicit_delete, explain_implicit_non_constexpr) (deduce_inheriting_ctor, implicitly_declare_fn): Adjust. Backport from mainline 2018-01-02 Marek Polacek <pola...@redhat.com> PR c++/81860 * g++.dg/cpp0x/inh-ctor30.C: New test.
commit 89229ea7637591687eec623839dc2a3b93c2c99d Author: Jonathan Wakely <jwak...@redhat.com> Date: Fri Jan 26 12:24:24 2018 +0000 Fix lambdas in template default argument of inherited ctor. Backport from mainline 2017-08-29 Jason Merrill <ja...@redhat.com> * method.c (synthesized_method_base_walk): Replace an inherited template with its specialization. (synthesized_method_walk): Make inheriting_ctor a pointer. (maybe_explain_implicit_delete, explain_implicit_non_constexpr) (deduce_inheriting_ctor, implicitly_declare_fn): Adjust. Backport from mainline 2018-01-02 Marek Polacek <pola...@redhat.com> PR c++/81860 * g++.dg/cpp0x/inh-ctor30.C: New test. diff --git a/gcc/cp/method.c b/gcc/cp/method.c index c7b67589924..59ad43f73fe 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -1430,7 +1430,7 @@ static tree synthesized_method_base_walk (tree binfo, tree base_binfo, int quals, bool copy_arg_p, bool move_p, bool ctor_p, - tree inheriting_ctor, tree inherited_parms, + tree *inheriting_ctor, tree inherited_parms, tree fnname, int flags, bool diag, tree *spec_p, bool *trivial_p, bool *deleted_p, bool *constexpr_p) @@ -1441,8 +1441,9 @@ synthesized_method_base_walk (tree binfo, tree base_binfo, if (copy_arg_p) argtype = build_stub_type (BINFO_TYPE (base_binfo), quals, move_p); - else if ((inherited_binfo - = binfo_inherited_from (binfo, base_binfo, inheriting_ctor))) + else if (inheriting_ctor + && (inherited_binfo + = binfo_inherited_from (binfo, base_binfo, *inheriting_ctor))) { argtype = inherited_parms; /* Don't check access on the inherited constructor. */ @@ -1464,6 +1465,12 @@ synthesized_method_base_walk (tree binfo, tree base_binfo, if (defer != dk_no_deferred) pop_deferring_access_checks (); + /* Replace an inherited template with the appropriate specialization. */ + if (inherited_binfo && rval + && DECL_P (*inheriting_ctor) && DECL_P (rval) + && DECL_CONTEXT (*inheriting_ctor) == DECL_CONTEXT (rval)) + *inheriting_ctor = DECL_CLONED_FUNCTION (rval); + process_subob_fn (rval, spec_p, trivial_p, deleted_p, constexpr_p, diag, BINFO_TYPE (base_binfo)); if (ctor_p && @@ -1498,7 +1505,7 @@ static void synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, tree *spec_p, bool *trivial_p, bool *deleted_p, bool *constexpr_p, bool diag, - tree inheriting_ctor, tree inherited_parms) + tree *inheriting_ctor, tree inherited_parms) { tree binfo, base_binfo, fnname; int i; @@ -1553,7 +1560,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, } gcc_assert ((sfk == sfk_inheriting_constructor) - == (inheriting_ctor != NULL_TREE)); + == (inheriting_ctor && *inheriting_ctor != NULL_TREE)); /* If that user-written default constructor would satisfy the requirements of a constexpr constructor (7.1.5), the @@ -1628,7 +1635,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, tree scope = push_scope (ctype); int flags = LOOKUP_NORMAL | LOOKUP_SPECULATIVE; - if (!inheriting_ctor) + if (sfk != sfk_inheriting_constructor) flags |= LOOKUP_DEFAULTED; tsubst_flags_t complain = diag ? tf_warning_or_error : tf_none; @@ -1731,9 +1738,9 @@ get_defaulted_eh_spec (tree decl) tree parm_type = TREE_VALUE (parms); bool const_p = CP_TYPE_CONST_P (non_reference (parm_type)); tree spec = empty_except_spec; + tree inh = DECL_INHERITED_CTOR (decl); synthesized_method_walk (ctype, sfk, const_p, &spec, NULL, NULL, - NULL, false, DECL_INHERITED_CTOR (decl), - parms); + NULL, false, &inh, parms); return spec; } @@ -1810,10 +1817,11 @@ maybe_explain_implicit_delete (tree decl) tree raises = NULL_TREE; bool deleted_p = false; tree scope = push_scope (ctype); + tree inh = DECL_INHERITED_CTOR (decl); synthesized_method_walk (ctype, sfk, const_p, &raises, NULL, &deleted_p, NULL, false, - DECL_INHERITED_CTOR (decl), parms); + &inh, parms); if (deleted_p) { inform (DECL_SOURCE_LOCATION (decl), @@ -1821,7 +1829,7 @@ maybe_explain_implicit_delete (tree decl) "definition would be ill-formed:", decl); synthesized_method_walk (ctype, sfk, const_p, NULL, NULL, NULL, NULL, true, - DECL_INHERITED_CTOR (decl), parms); + &inh, parms); } else if (!comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl)), @@ -1850,11 +1858,12 @@ explain_implicit_non_constexpr (tree decl) { tree parm_type = TREE_VALUE (FUNCTION_FIRST_USER_PARMTYPE (decl)); bool const_p = CP_TYPE_CONST_P (non_reference (parm_type)); + tree inh = DECL_INHERITED_CTOR (decl); bool dummy; synthesized_method_walk (DECL_CLASS_CONTEXT (decl), special_function_p (decl), const_p, NULL, NULL, NULL, &dummy, true, - DECL_INHERITED_CTOR (decl), + &inh, FUNCTION_FIRST_USER_PARMTYPE (decl)); } @@ -1869,22 +1878,25 @@ deduce_inheriting_ctor (tree decl) gcc_assert (DECL_INHERITED_CTOR (decl)); tree spec; bool trivial, constexpr_, deleted; + tree inh = DECL_INHERITED_CTOR (decl); synthesized_method_walk (DECL_CONTEXT (decl), sfk_inheriting_constructor, false, &spec, &trivial, &deleted, &constexpr_, /*diag*/false, - DECL_INHERITED_CTOR (decl), + &inh, FUNCTION_FIRST_USER_PARMTYPE (decl)); if (TREE_CODE (inherited_ctor_binfo (decl)) != TREE_BINFO) /* Inherited the same constructor from different base subobjects. */ deleted = true; DECL_DELETED_FN (decl) = deleted; TREE_TYPE (decl) = build_exception_variant (TREE_TYPE (decl), spec); + SET_DECL_INHERITED_CTOR (decl, inh); tree clone; FOR_EACH_CLONE (clone, decl) { DECL_DELETED_FN (clone) = deleted; TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone), spec); + SET_DECL_INHERITED_CTOR (clone, inh); } } @@ -1999,12 +2011,12 @@ implicitly_declare_fn (special_function_kind kind, tree type, raises = unevaluated_noexcept_spec (); synthesized_method_walk (type, kind, const_p, NULL, &trivial_p, &deleted_p, &constexpr_p, false, - inherited_ctor, inherited_parms); + &inherited_ctor, inherited_parms); } else synthesized_method_walk (type, kind, const_p, &raises, &trivial_p, &deleted_p, &constexpr_p, false, - inherited_ctor, inherited_parms); + &inherited_ctor, inherited_parms); /* Don't bother marking a deleted constructor as constexpr. */ if (deleted_p) constexpr_p = false; @@ -2120,7 +2132,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, input_location = DECL_SOURCE_LOCATION (fn); synthesized_method_walk (type, kind, const_p, NULL, NULL, NULL, NULL, true, - NULL_TREE, NULL_TREE); + NULL, NULL_TREE); input_location = loc; } diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor30.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor30.C new file mode 100644 index 00000000000..04c58636d8d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor30.C @@ -0,0 +1,27 @@ +// PR c++/81860 +// { dg-do compile { target c++11 } } +// { dg-final { scan-assembler "_ZN1AIjEC\[12\]Ev" } } + +template <typename T> +struct A +{ + A() {} +}; + +struct B +{ + template <typename D> + B(D, const A<unsigned>& a = A<unsigned>()) : a(a) {} + + A<unsigned> a; +}; + +struct C : B +{ + using B::B; +}; + +int main() +{ + C c(0); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle5.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle5.C new file mode 100644 index 00000000000..dd95894755c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-mangle5.C @@ -0,0 +1,15 @@ +// { dg-do compile { target c++11 } } +// { dg-final { scan-assembler "_ZZN1AIiEC4IiEET_S2_Ed_NKUlvE_clEv" } } + +template <class T> struct A +{ + template <class U> + A(U, U = []{ return 42; }()); +}; + +struct B: A<int> +{ + using A::A; +}; + +B b(24);