PR c++/79092 - non-type args of different types are different
* tree.c (cp_tree_equal): Check the type of constants. * pt.c (unify) [TEMPLATE_PARM_INDEX]: Handle UNIFY_ALLOW_INTEGER when comparing to previously deduced argument. (maybe_convert_nontype_argument): New. (convert_nontype_argument): Call it. (tsubst_copy_and_build): Handle partial instantiation of IMPLICIT_CONV_EXPR. (unify): Ignore type when deducing from array bound. (dependent_type_p_r): Handle DEFERRED_NOEXCEPT. (value_dependent_expression_p): Any type-dependent expression is value-dependent. Handle IMPLICIT_CONV_EXPR. * cp-tree.h (IMPLICIT_CONV_EXPR_NONTYPE_ARG): New. * mangle.c (write_template_arg): Strip IMPLICIT_CONV_EXPR. From-SVN: r254843
This commit is contained in:
parent
285346b5eb
commit
6296cf8e09
@ -1,3 +1,20 @@
|
||||
2017-11-16 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/79092 - non-type args of different types are different
|
||||
* tree.c (cp_tree_equal): Check the type of constants.
|
||||
* pt.c (unify) [TEMPLATE_PARM_INDEX]: Handle UNIFY_ALLOW_INTEGER
|
||||
when comparing to previously deduced argument.
|
||||
(maybe_convert_nontype_argument): New.
|
||||
(convert_nontype_argument): Call it.
|
||||
(tsubst_copy_and_build): Handle partial instantiation of
|
||||
IMPLICIT_CONV_EXPR.
|
||||
(unify): Ignore type when deducing from array bound.
|
||||
(dependent_type_p_r): Handle DEFERRED_NOEXCEPT.
|
||||
(value_dependent_expression_p): Any type-dependent expression is
|
||||
value-dependent. Handle IMPLICIT_CONV_EXPR.
|
||||
* cp-tree.h (IMPLICIT_CONV_EXPR_NONTYPE_ARG): New.
|
||||
* mangle.c (write_template_arg): Strip IMPLICIT_CONV_EXPR.
|
||||
|
||||
2017-11-16 Nathan Sidwell <nathan@acm.org>
|
||||
|
||||
PR c++/82836
|
||||
|
@ -382,6 +382,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
|
||||
TINFO_USED_TEMPLATE_ID (in TEMPLATE_INFO)
|
||||
PACK_EXPANSION_SIZEOF_P (in *_PACK_EXPANSION)
|
||||
OVL_USING_P (in OVERLOAD)
|
||||
IMPLICIT_CONV_EXPR_NONTYPE_ARG (in IMPLICIT_CONV_EXPR)
|
||||
2: IDENTIFIER_KIND_BIT_2 (in IDENTIFIER_NODE)
|
||||
ICS_THIS_FLAG (in _CONV)
|
||||
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL)
|
||||
@ -4126,6 +4127,11 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
|
||||
#define IMPLICIT_CONV_EXPR_DIRECT_INIT(NODE) \
|
||||
(TREE_LANG_FLAG_0 (IMPLICIT_CONV_EXPR_CHECK (NODE)))
|
||||
|
||||
/* True if NODE represents a dependent conversion of a non-type template
|
||||
argument. Set by maybe_convert_nontype_argument. */
|
||||
#define IMPLICIT_CONV_EXPR_NONTYPE_ARG(NODE) \
|
||||
(TREE_LANG_FLAG_1 (IMPLICIT_CONV_EXPR_CHECK (NODE)))
|
||||
|
||||
/* Nonzero means that an object of this type can not be initialized using
|
||||
an initializer list. */
|
||||
#define CLASSTYPE_NON_AGGREGATE(NODE) \
|
||||
|
@ -2836,7 +2836,7 @@ write_expression (tree expr)
|
||||
while (CONVERT_EXPR_CODE_P (code)
|
||||
/* Parentheses aren't mangled. */
|
||||
|| code == PAREN_EXPR
|
||||
|| TREE_CODE (expr) == NON_LVALUE_EXPR)
|
||||
|| code == NON_LVALUE_EXPR)
|
||||
{
|
||||
expr = TREE_OPERAND (expr, 0);
|
||||
code = TREE_CODE (expr);
|
||||
@ -3407,6 +3407,9 @@ write_template_arg (tree node)
|
||||
}
|
||||
}
|
||||
|
||||
/* Strip a conversion added by convert_nontype_argument. */
|
||||
if (TREE_CODE (node) == IMPLICIT_CONV_EXPR)
|
||||
node = TREE_OPERAND (node, 0);
|
||||
if (REFERENCE_REF_P (node))
|
||||
node = TREE_OPERAND (node, 0);
|
||||
if (TREE_CODE (node) == NOP_EXPR
|
||||
|
76
gcc/cp/pt.c
76
gcc/cp/pt.c
@ -7519,6 +7519,31 @@ convert_wildcard_argument (tree parm, tree arg)
|
||||
return arg;
|
||||
}
|
||||
|
||||
/* We can't fully resolve ARG given as a non-type template argument to TYPE,
|
||||
because one of them is dependent. But we need to represent the
|
||||
conversion for the benefit of cp_tree_equal. */
|
||||
|
||||
static tree
|
||||
maybe_convert_nontype_argument (tree type, tree arg)
|
||||
{
|
||||
/* Auto parms get no conversion. */
|
||||
if (type_uses_auto (type))
|
||||
return arg;
|
||||
/* We don't need or want to add this conversion now if we're going to use the
|
||||
argument for deduction. */
|
||||
if (value_dependent_expression_p (arg))
|
||||
return arg;
|
||||
|
||||
type = cv_unqualified (type);
|
||||
tree argtype = TREE_TYPE (arg);
|
||||
if (same_type_p (type, argtype))
|
||||
return arg;
|
||||
|
||||
arg = build1 (IMPLICIT_CONV_EXPR, type, arg);
|
||||
IMPLICIT_CONV_EXPR_NONTYPE_ARG (arg) = true;
|
||||
return arg;
|
||||
}
|
||||
|
||||
/* Convert the indicated template ARG as necessary to match the
|
||||
indicated template PARM. Returns the converted ARG, or
|
||||
error_mark_node if the conversion was unsuccessful. Error and
|
||||
@ -7774,7 +7799,11 @@ convert_template_argument (tree parm,
|
||||
argument specification is valid. */
|
||||
val = convert_nontype_argument (t, orig_arg, complain);
|
||||
else
|
||||
val = canonicalize_expr_argument (orig_arg, complain);
|
||||
{
|
||||
val = canonicalize_expr_argument (orig_arg, complain);
|
||||
val = maybe_convert_nontype_argument (t, val);
|
||||
}
|
||||
|
||||
|
||||
if (val == NULL_TREE)
|
||||
val = error_mark_node;
|
||||
@ -17097,6 +17126,17 @@ tsubst_copy_and_build (tree t,
|
||||
{
|
||||
tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
|
||||
tree expr = RECUR (TREE_OPERAND (t, 0));
|
||||
if (dependent_type_p (type) || type_dependent_expression_p (expr))
|
||||
{
|
||||
retval = copy_node (t);
|
||||
TREE_TYPE (retval) = type;
|
||||
TREE_OPERAND (retval, 0) = expr;
|
||||
RETURN (retval);
|
||||
}
|
||||
if (IMPLICIT_CONV_EXPR_NONTYPE_ARG (t))
|
||||
/* We'll pass this to convert_nontype_argument again, we don't need
|
||||
to actually perform any conversion here. */
|
||||
RETURN (expr);
|
||||
int flags = LOOKUP_IMPLICIT;
|
||||
if (IMPLICIT_CONV_EXPR_DIRECT_INIT (t))
|
||||
flags = LOOKUP_NORMAL;
|
||||
@ -20886,6 +20926,11 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
|
||||
|
||||
if (targ)
|
||||
{
|
||||
if ((strict & UNIFY_ALLOW_INTEGER)
|
||||
&& TREE_TYPE (targ) && TREE_TYPE (arg)
|
||||
&& CP_INTEGRAL_TYPE_P (TREE_TYPE (targ)))
|
||||
/* We're deducing from an array bound, the type doesn't matter. */
|
||||
arg = fold_convert (TREE_TYPE (targ), arg);
|
||||
int x = !cp_tree_equal (targ, arg);
|
||||
if (x)
|
||||
unify_inconsistency (explain_p, parm, targ, arg);
|
||||
@ -23704,13 +23749,15 @@ dependent_type_p_r (tree type)
|
||||
if (dependent_type_p (TREE_VALUE (arg_type)))
|
||||
return true;
|
||||
if (cxx_dialect >= cxx17)
|
||||
{
|
||||
/* A value-dependent noexcept-specifier makes the type dependent. */
|
||||
tree spec = TYPE_RAISES_EXCEPTIONS (type);
|
||||
if (spec && TREE_PURPOSE (spec)
|
||||
&& value_dependent_expression_p (TREE_PURPOSE (spec)))
|
||||
return true;
|
||||
}
|
||||
/* A value-dependent noexcept-specifier makes the type dependent. */
|
||||
if (tree spec = TYPE_RAISES_EXCEPTIONS (type))
|
||||
if (tree noex = TREE_PURPOSE (spec))
|
||||
/* Treat DEFERRED_NOEXCEPT as non-dependent, since it doesn't
|
||||
affect overload resolution and treating it as dependent breaks
|
||||
things. */
|
||||
if (TREE_CODE (noex) != DEFERRED_NOEXCEPT
|
||||
&& value_dependent_expression_p (noex))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
/* -- an array type constructed from any dependent type or whose
|
||||
@ -23875,8 +23922,8 @@ value_dependent_expression_p (tree expression)
|
||||
if (!processing_template_decl || expression == NULL_TREE)
|
||||
return false;
|
||||
|
||||
/* A name declared with a dependent type. */
|
||||
if (DECL_P (expression) && type_dependent_expression_p (expression))
|
||||
/* A type-dependent expression is also value-dependent. */
|
||||
if (type_dependent_expression_p (expression))
|
||||
return true;
|
||||
|
||||
switch (TREE_CODE (expression))
|
||||
@ -23918,13 +23965,12 @@ value_dependent_expression_p (tree expression)
|
||||
&& (TREE_CODE (DECL_INITIAL (expression)) == TREE_LIST
|
||||
/* cp_finish_decl doesn't fold reference initializers. */
|
||||
|| TREE_CODE (TREE_TYPE (expression)) == REFERENCE_TYPE
|
||||
|| type_dependent_expression_p (DECL_INITIAL (expression))
|
||||
|| value_dependent_expression_p (DECL_INITIAL (expression))))
|
||||
return true;
|
||||
if (DECL_HAS_VALUE_EXPR_P (expression))
|
||||
{
|
||||
tree value_expr = DECL_VALUE_EXPR (expression);
|
||||
if (type_dependent_expression_p (value_expr))
|
||||
if (value_dependent_expression_p (value_expr))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -23934,6 +23980,7 @@ value_dependent_expression_p (tree expression)
|
||||
case CONST_CAST_EXPR:
|
||||
case REINTERPRET_CAST_EXPR:
|
||||
case CAST_EXPR:
|
||||
case IMPLICIT_CONV_EXPR:
|
||||
/* These expressions are value-dependent if the type to which
|
||||
the cast occurs is dependent or the expression being casted
|
||||
is value-dependent. */
|
||||
@ -24078,10 +24125,7 @@ value_dependent_expression_p (tree expression)
|
||||
}
|
||||
|
||||
case TEMPLATE_ID_EXPR:
|
||||
/* If a TEMPLATE_ID_EXPR involves a dependent name, it will be
|
||||
type-dependent. */
|
||||
return type_dependent_expression_p (expression)
|
||||
|| variable_concept_p (TREE_OPERAND (expression, 0));
|
||||
return variable_concept_p (TREE_OPERAND (expression, 0));
|
||||
|
||||
case CONSTRUCTOR:
|
||||
{
|
||||
|
@ -3494,6 +3494,10 @@ cp_tree_equal (tree t1, tree t2)
|
||||
if (code1 != code2)
|
||||
return false;
|
||||
|
||||
if (CONSTANT_CLASS_P (t1)
|
||||
&& !same_type_p (TREE_TYPE (t1), TREE_TYPE (t2)))
|
||||
return false;
|
||||
|
||||
switch (code1)
|
||||
{
|
||||
case VOID_CST:
|
||||
|
6
gcc/testsuite/g++.dg/cpp1z/nontype-auto12.C
Normal file
6
gcc/testsuite/g++.dg/cpp1z/nontype-auto12.C
Normal file
@ -0,0 +1,6 @@
|
||||
// PR c++/79092
|
||||
// { dg-options -std=c++17 }
|
||||
|
||||
template<auto V> struct val {};
|
||||
|
||||
struct type : val<0>, val<0u> {};
|
Loading…
Reference in New Issue
Block a user