commit 0ff4fb22ceeccec01a08fd768f9f5710a7c124d2
Author: Jason Merrill <jason@redhat.com>
Date: Tue Oct 26 21:37:07 2010 -0400
* call.c (build_integral_nontype_arg_conv): New.
* cp-tree.h: Declare it.
* pt.c (convert_nontype_argument): Use it.
@@ -3165,6 +3165,76 @@ build_user_type_conversion (tree totype, tree expr, int flags)
return NULL_TREE;
}
+/* Subroutine of convert_nontype_argument.
+
+ EXPR is an argument for a template non-type parameter of integral or
+ enumeration type. Do any necessary conversions (that are permitted for
+ non-type arguments) to convert it to the parameter type.
+
+ If conversion is successful, returns the converted expression;
+ otherwise, returns error_mark_node. */
+
+tree
+build_integral_nontype_arg_conv (tree type, tree expr, tsubst_flags_t complain)
+{
+ conversion *conv;
+ void *p;
+ tree t;
+
+ if (error_operand_p (expr))
+ return error_mark_node;
+
+ gcc_assert (INTEGRAL_OR_ENUMERATION_TYPE_P (type));
+
+ /* Get the high-water mark for the CONVERSION_OBSTACK. */
+ p = conversion_obstack_alloc (0);
+
+ conv = implicit_conversion (type, TREE_TYPE (expr), expr,
+ /*c_cast_p=*/false,
+ LOOKUP_IMPLICIT);
+
+ /* for a non-type template-parameter of integral or
+ enumeration type, integral promotions (4.5) and integral
+ conversions (4.7) are applied. */
+ /* It should be sufficient to check the outermost conversion step, since
+ there are no qualification conversions to integer type. */
+ if (conv)
+ switch (conv->kind)
+ {
+ /* A conversion function is OK. If it isn't constexpr, we'll
+ complain later that the argument isn't constant. */
+ case ck_user:
+ /* The lvalue-to-rvalue conversion is OK. */
+ case ck_rvalue:
+ case ck_identity:
+ break;
+
+ case ck_std:
+ t = conv->u.next->type;
+ if (INTEGRAL_OR_ENUMERATION_TYPE_P (t))
+ break;
+
+ if (complain & tf_error)
+ error ("conversion from %qT to %qT not considered for "
+ "non-type template argument", t, type);
+ /* and fall through. */
+
+ default:
+ conv = NULL;
+ break;
+ }
+
+ if (conv)
+ expr = convert_like (conv, expr, complain);
+ else
+ expr = error_mark_node;
+
+ /* Free all the conversions we allocated. */
+ obstack_free (&conversion_obstack, p);
+
+ return expr;
+}
+
/* Do any initial processing on the arguments to a function call. */
static VEC(tree,gc) *
@@ -4651,6 +4651,7 @@ extern tree strip_top_quals (tree);
extern bool reference_related_p (tree, tree);
extern tree perform_implicit_conversion (tree, tree, tsubst_flags_t);
extern tree perform_implicit_conversion_flags (tree, tree, tsubst_flags_t, int);
+extern tree build_integral_nontype_arg_conv (tree, tree, tsubst_flags_t);
extern tree perform_direct_initialization_if_possible (tree, tree, bool,
tsubst_flags_t);
extern tree in_charge_arg_for_name (tree);
@@ -5069,10 +5069,17 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
(_conv.integral_) are applied. */
if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
{
- if (!INTEGRAL_OR_ENUMERATION_TYPE_P (expr_type))
+ tree t = build_integral_nontype_arg_conv (type, expr, complain);
+ t = fold_decl_constant_value (t);
+ if (t != error_mark_node)
+ expr = t;
+
+ if (!same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (expr)))
return error_mark_node;
- expr = fold_decl_constant_value (expr);
+ /* Conversion was allowed: fold it to a bare integer constant. */
+ expr = fold (expr);
+
/* Notice that there are constant expressions like '4 % 0' which
do not fold into integer constants. */
if (TREE_CODE (expr) != INTEGER_CST)
@@ -5082,16 +5089,6 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
"because it is a non-constant expression", expr, type);
return NULL_TREE;
}
-
- /* At this point, an implicit conversion does what we want,
- because we already know that the expression is of integral
- type. */
- expr = perform_implicit_conversion (type, expr, complain);
- if (expr == error_mark_node)
- return error_mark_node;
-
- /* Conversion was allowed: fold it to a bare integer constant. */
- expr = fold (expr);
}
/* [temp.arg.nontype]/5, bullet 2