diff options
author | Jason Merrill <jason@redhat.com> | 2010-10-27 11:59:54 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2010-10-27 11:59:54 -0400 |
commit | 61f8d16512a62120c29e1cc82cddbc4d3816a1c4 (patch) | |
tree | c7e91a2823c3f547d1962dd84e91b0b537670714 /gcc | |
parent | 2842beb62d01d883db7c770291e15f4de8202174 (diff) | |
download | gcc-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/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/cp/call.c | 70 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/pt.c | 21 |
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 |