From b2c06d053009d53be0d9b307e0ca02975c9ffbb6 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 19 Jan 2017 23:43:19 -0500 Subject: [PATCH] US 20 - forwarding references and class template argument deduction * cp-tree.h (TEMPLATE_TYPE_PARM_FOR_CLASS): New. * pt.c (push_template_decl_real): Set it. (maybe_adjust_types_for_deduction): Check it. (rewrite_template_parm): Copy it. From-SVN: r244682 --- gcc/cp/ChangeLog | 6 ++++ gcc/cp/cp-tree.h | 6 ++++ gcc/cp/pt.c | 29 +++++++++++++++---- .../g++.dg/cpp1z/class-deduction26.C | 23 +++++++++++++++ 4 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1z/class-deduction26.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index e16853971fb..bfd898d874b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2017-01-19 Jason Merrill + US 20 - forwarding references and class template argument deduction + * cp-tree.h (TEMPLATE_TYPE_PARM_FOR_CLASS): New. + * pt.c (push_template_decl_real): Set it. + (maybe_adjust_types_for_deduction): Check it. + (rewrite_template_parm): Copy it. + US 19 - deduction guides and constructors * call.c (joust): Prefer deduction guides to constructors. * pt.c (build_deduction_guide): Set DECL_ARTIFICIAL. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 9c4436710dd..f7c7a359a48 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -146,6 +146,7 @@ operator == (const cp_expr &lhs, tree rhs) BLOCK_OUTER_CURLY_BRACE_P (in BLOCK) FOLD_EXPR_MODOP_P (*_FOLD_EXPR) IF_STMT_CONSTEXPR_P (IF_STMT) + TEMPLATE_TYPE_PARM_FOR_CLASS (TEMPLATE_TYPE_PARM) 1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE) TI_PENDING_TEMPLATE_FLAG. TEMPLATE_PARMS_FOR_INLINE. @@ -5207,6 +5208,11 @@ enum auto_deduction_context adc_decomp_type /* Decomposition declaration initializer deduction */ }; +/* True if this type-parameter belongs to a class template, used by C++17 + class template argument deduction. */ +#define TEMPLATE_TYPE_PARM_FOR_CLASS(NODE) \ + (TREE_LANG_FLAG_0 (TEMPLATE_TYPE_PARM_CHECK (NODE))) + /* True iff this TEMPLATE_TYPE_PARM represents decltype(auto). */ #define AUTO_IS_DECLTYPE(NODE) \ (TYPE_LANG_FLAG_5 (TEMPLATE_TYPE_PARM_CHECK (NODE))) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index f683727e977..8c920c36442 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -5263,7 +5263,18 @@ push_template_decl_real (tree decl, bool is_friend) } else if (DECL_IMPLICIT_TYPEDEF_P (decl) && CLASS_TYPE_P (TREE_TYPE (decl))) - /* OK */; + { + /* Class template, set TEMPLATE_TYPE_PARM_FOR_CLASS. */ + tree parms = INNERMOST_TEMPLATE_PARMS (current_template_parms); + for (int i = 0; i < TREE_VEC_LENGTH (parms); ++i) + { + tree t = TREE_VALUE (TREE_VEC_ELT (parms, i)); + if (TREE_CODE (t) == TYPE_DECL) + t = TREE_TYPE (t); + if (TREE_CODE (t) == TEMPLATE_TYPE_PARM) + TEMPLATE_TYPE_PARM_FOR_CLASS (t) = true; + } + } else if (TREE_CODE (decl) == TYPE_DECL && TYPE_DECL_ALIAS_P (decl)) /* alias-declaration */ @@ -18649,12 +18660,16 @@ maybe_adjust_types_for_deduction (unification_kind_t strict, *arg = TYPE_MAIN_VARIANT (*arg); } - /* From C++0x [14.8.2.1/3 temp.deduct.call] (after DR606), "If P is - of the form T&&, where T is a template parameter, and the argument - is an lvalue, T is deduced as A& */ + /* [14.8.2.1/3 temp.deduct.call], "A forwarding reference is an rvalue + reference to a cv-unqualified template parameter that does not represent a + template parameter of a class template (during class template argument + deduction (13.3.1.8)). If P is a forwarding reference and the argument is + an lvalue, the type "lvalue reference to A" is used in place of A for type + deduction. */ if (TREE_CODE (*parm) == REFERENCE_TYPE && TYPE_REF_IS_RVALUE (*parm) && TREE_CODE (TREE_TYPE (*parm)) == TEMPLATE_TYPE_PARM + && !TEMPLATE_TYPE_PARM_FOR_CLASS (TREE_TYPE (*parm)) && cp_type_quals (TREE_TYPE (*parm)) == TYPE_UNQUALIFIED && (arg_expr ? lvalue_p (arg_expr) /* try_one_overload doesn't provide an arg_expr, but @@ -24798,8 +24813,12 @@ rewrite_template_parm (tree olddecl, unsigned index, unsigned level, if (TREE_CODE (olddecl) == TYPE_DECL || TREE_CODE (olddecl) == TEMPLATE_DECL) { - newtype = cxx_make_type (TREE_CODE (TREE_TYPE (olddecl))); + tree oldtype = TREE_TYPE (olddecl); + newtype = cxx_make_type (TREE_CODE (oldtype)); TYPE_MAIN_VARIANT (newtype) = newtype; + if (TREE_CODE (oldtype) == TEMPLATE_TYPE_PARM) + TEMPLATE_TYPE_PARM_FOR_CLASS (newtype) + = TEMPLATE_TYPE_PARM_FOR_CLASS (oldtype); } else newtype = tsubst (TREE_TYPE (olddecl), tsubst_args, diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction26.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction26.C new file mode 100644 index 00000000000..ea58af75de8 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction26.C @@ -0,0 +1,23 @@ +// Testcase from P0512R0 for C++17 NB comment US 20 +// { dg-options -std=c++1z } + +template struct same; +template struct same {}; + +template struct A { + template + A(T&&, U&&, int*); // #1: T&& is not a forwarding reference + // U&& is a forwarding reference + A(T&&, int*); // #2 +}; +template +A(T&&, int*) -> A; // #3: T&& is a forwarding reference + +int i; +int *ip; +A a0{0, 0, ip}; // uses #1 to deduce A and #1 to initialize +same> s1; +A a2{i, ip}; // uses #3 to deduce A and #2 to initialize +same> s2; + +A a{i, 0, ip}; // { dg-error "" } cannot deduce from #1 -- 2.30.2