aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2010-10-27 11:59:54 -0400
committerJason Merrill <jason@gcc.gnu.org>2010-10-27 11:59:54 -0400
commit61f8d16512a62120c29e1cc82cddbc4d3816a1c4 (patch)
treec7e91a2823c3f547d1962dd84e91b0b537670714 /gcc
parent2842beb62d01d883db7c770291e15f4de8202174 (diff)
downloadgcc-61f8d16512a62120c29e1cc82cddbc4d3816a1c4.zip
gcc-61f8d16512a62120c29e1cc82cddbc4d3816a1c4.tar.gz
gcc-61f8d16512a62120c29e1cc82cddbc4d3816a1c4.tar.bz2
call.c (build_integral_nontype_arg_conv): New.
* call.c (build_integral_nontype_arg_conv): New. * cp-tree.h: Declare it. * pt.c (convert_nontype_argument): Use it. From-SVN: r166011
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/call.c70
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/pt.c21
4 files changed, 84 insertions, 12 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 4bbb0db..c752736 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,9 @@
2010-10-27 Jason Merrill <jason@redhat.com>
+ * call.c (build_integral_nontype_arg_conv): New.
+ * cp-tree.h: Declare it.
+ * pt.c (convert_nontype_argument): Use it.
+
* error.c (dump_simple_decl): Print constexpr.
* cvt.c (build_up_reference): Use target_type for the temporary var.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 1831718..204fda5 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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) *
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 05282ba..ec026a4 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 1de5d55..8a6d451 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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