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
This commit is contained in:
parent
689f867c9c
commit
b2c06d0530
4 changed files with 59 additions and 5 deletions
|
@ -1,5 +1,11 @@
|
|||
2017-01-19 Jason Merrill <jason@redhat.com>
|
||||
|
||||
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.
|
||||
|
|
|
@ -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)))
|
||||
|
|
29
gcc/cp/pt.c
29
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,
|
||||
|
|
23
gcc/testsuite/g++.dg/cpp1z/class-deduction26.C
Normal file
23
gcc/testsuite/g++.dg/cpp1z/class-deduction26.C
Normal file
|
@ -0,0 +1,23 @@
|
|||
// Testcase from P0512R0 for C++17 NB comment US 20
|
||||
// { dg-options -std=c++1z }
|
||||
|
||||
template <class,class> struct same;
|
||||
template <class T> struct same<T,T> {};
|
||||
|
||||
template<class T> struct A {
|
||||
template<class U>
|
||||
A(T&&, U&&, int*); // #1: T&& is not a forwarding reference
|
||||
// U&& is a forwarding reference
|
||||
A(T&&, int*); // #2
|
||||
};
|
||||
template<class T>
|
||||
A(T&&, int*) -> A<T>; // #3: T&& is a forwarding reference
|
||||
|
||||
int i;
|
||||
int *ip;
|
||||
A a0{0, 0, ip}; // uses #1 to deduce A<int> and #1 to initialize
|
||||
same<decltype(a0),A<int>> s1;
|
||||
A a2{i, ip}; // uses #3 to deduce A<int&> and #2 to initialize
|
||||
same<decltype(a2),A<int&>> s2;
|
||||
|
||||
A a{i, 0, ip}; // { dg-error "" } cannot deduce from #1
|
Loading…
Add table
Reference in a new issue