diff options
author | Jason Merrill <jason@redhat.com> | 2013-10-16 17:58:19 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2013-10-16 17:58:19 -0400 |
commit | 06ea1376317074e9d9f4ddb727b93871f23535c5 (patch) | |
tree | 7ebdf49640d63cbdbfcc797e6c6186699f67f2d7 | |
parent | fac91973cceae62ffa4a3cd285cb4c9557f83416 (diff) | |
download | gcc-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
-rw-r--r-- | gcc/cp/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/cp/pt.c | 146 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/initlist74.C | 7 |
3 files changed, 96 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: diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist74.C b/gcc/testsuite/g++.dg/cpp0x/initlist74.C new file mode 100644 index 0000000..4305b59 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist74.C @@ -0,0 +1,7 @@ +// Core 1591 +// { dg-require-effective-target c++11 } + +template<class T, int N> void g(T const (&)[N]); +void f() { + g( { 1, 2, 3, 4 } ); +} |