aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2013-10-16 17:58:19 -0400
committerJason Merrill <jason@gcc.gnu.org>2013-10-16 17:58:19 -0400
commit06ea1376317074e9d9f4ddb727b93871f23535c5 (patch)
tree7ebdf49640d63cbdbfcc797e6c6186699f67f2d7 /gcc/cp
parentfac91973cceae62ffa4a3cd285cb4c9557f83416 (diff)
downloadgcc-06ea1376317074e9d9f4ddb727b93871f23535c5.zip
gcc-06ea1376317074e9d9f4ddb727b93871f23535c5.tar.gz
gcc-06ea1376317074e9d9f4ddb727b93871f23535c5.tar.bz2
Core 1591
Core 1591 * pt.c (unify_array_domain): Split out from unify. (unify): Use it for list deduction, too. From-SVN: r203725
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog4
-rw-r--r--gcc/cp/pt.c146
2 files changed, 89 insertions, 61 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a325988..2852f1f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,9 @@
2013-10-16 Jason Merrill <jason@redhat.com>
+ Core 1591
+ * pt.c (unify_array_domain): Split out from unify.
+ (unify): Use it for list deduction, too.
+
PR c++/57850
* decl2.c (dump_tu): Split out from...
(cp_write_global_declarations): ...here. Call it in PCH mode.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index eed648a..a1eb7a2 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -17007,6 +17007,72 @@ unify_pack_expansion (tree tparms, tree targs, tree packed_parms,
return unify_success (explain_p);
}
+/* Handle unification of the domain of an array. PARM_DOM and ARG_DOM are
+ INTEGER_TYPEs representing the TYPE_DOMAIN of ARRAY_TYPEs. The other
+ parameters and return value are as for unify. */
+
+static int
+unify_array_domain (tree tparms, tree targs,
+ tree parm_dom, tree arg_dom,
+ bool explain_p)
+{
+ tree parm_max;
+ tree arg_max;
+ bool parm_cst;
+ bool arg_cst;
+
+ /* Our representation of array types uses "N - 1" as the
+ TYPE_MAX_VALUE for an array with "N" elements, if "N" is
+ not an integer constant. We cannot unify arbitrarily
+ complex expressions, so we eliminate the MINUS_EXPRs
+ here. */
+ parm_max = TYPE_MAX_VALUE (parm_dom);
+ parm_cst = TREE_CODE (parm_max) == INTEGER_CST;
+ if (!parm_cst)
+ {
+ gcc_assert (TREE_CODE (parm_max) == MINUS_EXPR);
+ parm_max = TREE_OPERAND (parm_max, 0);
+ }
+ arg_max = TYPE_MAX_VALUE (arg_dom);
+ arg_cst = TREE_CODE (arg_max) == INTEGER_CST;
+ if (!arg_cst)
+ {
+ /* The ARG_MAX may not be a simple MINUS_EXPR, if we are
+ trying to unify the type of a variable with the type
+ of a template parameter. For example:
+
+ template <unsigned int N>
+ void f (char (&) [N]);
+ int g();
+ void h(int i) {
+ char a[g(i)];
+ f(a);
+ }
+
+ Here, the type of the ARG will be "int [g(i)]", and
+ may be a SAVE_EXPR, etc. */
+ if (TREE_CODE (arg_max) != MINUS_EXPR)
+ return unify_vla_arg (explain_p, arg_dom);
+ arg_max = TREE_OPERAND (arg_max, 0);
+ }
+
+ /* If only one of the bounds used a MINUS_EXPR, compensate
+ by adding one to the other bound. */
+ if (parm_cst && !arg_cst)
+ parm_max = fold_build2_loc (input_location, PLUS_EXPR,
+ integer_type_node,
+ parm_max,
+ integer_one_node);
+ else if (arg_cst && !parm_cst)
+ arg_max = fold_build2_loc (input_location, PLUS_EXPR,
+ integer_type_node,
+ arg_max,
+ integer_one_node);
+
+ return unify (tparms, targs, parm_max, arg_max,
+ UNIFY_ALLOW_INTEGER, explain_p);
+}
+
/* Deduce the value of template parameters. TPARMS is the (innermost)
set of template parameters to a template. TARGS is the bindings
for those template parameters, as determined thus far; TARGS may
@@ -17092,13 +17158,17 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
&& flag_deduce_init_list)
parm = listify (parm);
- if (!is_std_init_list (parm))
+ if (!is_std_init_list (parm)
+ && TREE_CODE (parm) != ARRAY_TYPE)
/* We can only deduce from an initializer list argument if the
- parameter is std::initializer_list; otherwise this is a
- non-deduced context. */
+ parameter is std::initializer_list or an array; otherwise this
+ is a non-deduced context. */
return unify_success (explain_p);
- elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (parm), 0);
+ if (TREE_CODE (parm) == ARRAY_TYPE)
+ elttype = TREE_TYPE (parm);
+ else
+ elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (parm), 0);
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (arg), i, elt)
{
@@ -17121,6 +17191,15 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
explain_p);
}
+ if (TREE_CODE (parm) == ARRAY_TYPE)
+ {
+ /* Also deduce from the length of the initializer list. */
+ tree max = size_int (CONSTRUCTOR_NELTS (arg));
+ tree idx = compute_array_index_type (NULL_TREE, max, tf_none);
+ return unify_array_domain (tparms, targs, TYPE_DOMAIN (parm),
+ idx, explain_p);
+ }
+
/* If the std::initializer_list<T> deduction worked, replace the
deduced A with std::initializer_list<A>. */
if (orig_parm != parm)
@@ -17494,63 +17573,8 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
RECUR_AND_CHECK_FAILURE (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg),
strict & UNIFY_ALLOW_MORE_CV_QUAL, explain_p);
if (TYPE_DOMAIN (parm) != NULL_TREE)
- {
- tree parm_max;
- tree arg_max;
- bool parm_cst;
- bool arg_cst;
-
- /* Our representation of array types uses "N - 1" as the
- TYPE_MAX_VALUE for an array with "N" elements, if "N" is
- not an integer constant. We cannot unify arbitrarily
- complex expressions, so we eliminate the MINUS_EXPRs
- here. */
- parm_max = TYPE_MAX_VALUE (TYPE_DOMAIN (parm));
- parm_cst = TREE_CODE (parm_max) == INTEGER_CST;
- if (!parm_cst)
- {
- gcc_assert (TREE_CODE (parm_max) == MINUS_EXPR);
- parm_max = TREE_OPERAND (parm_max, 0);
- }
- arg_max = TYPE_MAX_VALUE (TYPE_DOMAIN (arg));
- arg_cst = TREE_CODE (arg_max) == INTEGER_CST;
- if (!arg_cst)
- {
- /* The ARG_MAX may not be a simple MINUS_EXPR, if we are
- trying to unify the type of a variable with the type
- of a template parameter. For example:
-
- template <unsigned int N>
- void f (char (&) [N]);
- int g();
- void h(int i) {
- char a[g(i)];
- f(a);
- }
-
- Here, the type of the ARG will be "int [g(i)]", and
- may be a SAVE_EXPR, etc. */
- if (TREE_CODE (arg_max) != MINUS_EXPR)
- return unify_vla_arg (explain_p, arg);
- arg_max = TREE_OPERAND (arg_max, 0);
- }
-
- /* If only one of the bounds used a MINUS_EXPR, compensate
- by adding one to the other bound. */
- if (parm_cst && !arg_cst)
- parm_max = fold_build2_loc (input_location, PLUS_EXPR,
- integer_type_node,
- parm_max,
- integer_one_node);
- else if (arg_cst && !parm_cst)
- arg_max = fold_build2_loc (input_location, PLUS_EXPR,
- integer_type_node,
- arg_max,
- integer_one_node);
-
- RECUR_AND_CHECK_FAILURE (tparms, targs, parm_max, arg_max,
- UNIFY_ALLOW_INTEGER, explain_p);
- }
+ return unify_array_domain (tparms, targs, TYPE_DOMAIN (parm),
+ TYPE_DOMAIN (arg), explain_p);
return unify_success (explain_p);
case REAL_TYPE: