mirror of git://gcc.gnu.org/git/gcc.git
re PR c++/69958 (sizeof... computes wrong size)
PR c++/69958 * pt.c (make_argument_pack): New. (tsubst_copy) [SIZEOF_EXPR]: Handle partial expansion. (tsubst_copy_and_build): Likewise. From-SVN: r233758
This commit is contained in:
parent
622174b20d
commit
56cde07776
|
|
@ -1,3 +1,10 @@
|
|||
2016-02-26 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/69958
|
||||
* pt.c (make_argument_pack): New.
|
||||
(tsubst_copy) [SIZEOF_EXPR]: Handle partial expansion.
|
||||
(tsubst_copy_and_build): Likewise.
|
||||
|
||||
2016-02-25 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/69889
|
||||
|
|
|
|||
43
gcc/cp/pt.c
43
gcc/cp/pt.c
|
|
@ -11117,6 +11117,25 @@ get_pattern_parm (tree parm, tree tmpl)
|
|||
return patparm;
|
||||
}
|
||||
|
||||
/* Make an argument pack out of the TREE_VEC VEC. */
|
||||
|
||||
static tree
|
||||
make_argument_pack (tree vec)
|
||||
{
|
||||
tree pack;
|
||||
tree elt = TREE_VEC_ELT (vec, 0);
|
||||
if (TYPE_P (elt))
|
||||
pack = cxx_make_type (TYPE_ARGUMENT_PACK);
|
||||
else
|
||||
{
|
||||
pack = make_node (NONTYPE_ARGUMENT_PACK);
|
||||
TREE_TYPE (pack) = TREE_TYPE (elt);
|
||||
TREE_CONSTANT (pack) = 1;
|
||||
}
|
||||
SET_ARGUMENT_PACK_ARGS (pack, vec);
|
||||
return pack;
|
||||
}
|
||||
|
||||
/* Substitute ARGS into the vector or list of template arguments T. */
|
||||
|
||||
static tree
|
||||
|
|
@ -14066,7 +14085,8 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
|
|||
}
|
||||
|
||||
case SIZEOF_EXPR:
|
||||
if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
|
||||
if (PACK_EXPANSION_P (TREE_OPERAND (t, 0))
|
||||
|| ARGUMENT_PACK_P (TREE_OPERAND (t, 0)))
|
||||
{
|
||||
tree expanded, op = TREE_OPERAND (t, 0);
|
||||
int len = 0;
|
||||
|
|
@ -14077,7 +14097,11 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
|
|||
++cp_unevaluated_operand;
|
||||
++c_inhibit_evaluation_warnings;
|
||||
/* We only want to compute the number of arguments. */
|
||||
expanded = tsubst_pack_expansion (op, args, complain, in_decl);
|
||||
if (PACK_EXPANSION_P (op))
|
||||
expanded = tsubst_pack_expansion (op, args, complain, in_decl);
|
||||
else
|
||||
expanded = tsubst_template_args (ARGUMENT_PACK_ARGS (op),
|
||||
args, complain, in_decl);
|
||||
--cp_unevaluated_operand;
|
||||
--c_inhibit_evaluation_warnings;
|
||||
|
||||
|
|
@ -14093,13 +14117,15 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
|
|||
return error_mark_node;
|
||||
else if (PACK_EXPANSION_P (expanded)
|
||||
|| (TREE_CODE (expanded) == TREE_VEC
|
||||
&& len > 0
|
||||
&& PACK_EXPANSION_P (TREE_VEC_ELT (expanded, len-1))))
|
||||
&& pack_expansion_args_count (expanded)))
|
||||
|
||||
{
|
||||
if (TREE_CODE (expanded) == TREE_VEC)
|
||||
expanded = TREE_VEC_ELT (expanded, len - 1);
|
||||
if (PACK_EXPANSION_P (expanded))
|
||||
/* OK. */;
|
||||
else if (TREE_VEC_LENGTH (expanded) == 1)
|
||||
expanded = TREE_VEC_ELT (expanded, 0);
|
||||
else
|
||||
PACK_EXPANSION_SIZEOF_P (expanded) = true;
|
||||
expanded = make_argument_pack (expanded);
|
||||
|
||||
if (TYPE_P (expanded))
|
||||
return cxx_sizeof_or_alignof_type (expanded, SIZEOF_EXPR,
|
||||
|
|
@ -16162,7 +16188,8 @@ tsubst_copy_and_build (tree t,
|
|||
length, stride, TREE_TYPE (op1)));
|
||||
}
|
||||
case SIZEOF_EXPR:
|
||||
if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
|
||||
if (PACK_EXPANSION_P (TREE_OPERAND (t, 0))
|
||||
|| ARGUMENT_PACK_P (TREE_OPERAND (t, 0)))
|
||||
RETURN (tsubst_copy (t, args, complain, in_decl));
|
||||
/* Fall through */
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
// PR c++/69958
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
typedef decltype(sizeof(int)) size_t;
|
||||
|
||||
template <typename...Ts>
|
||||
struct list { };
|
||||
|
||||
template <size_t N>
|
||||
struct size { };
|
||||
|
||||
template <typename...Ts>
|
||||
using size_for = size<sizeof...(Ts)>;
|
||||
|
||||
template<class T, class U> struct assert_same;
|
||||
template<class T> struct assert_same<T,T> {};
|
||||
|
||||
template <typename T, typename...Ts>
|
||||
using wrapped = list<T, size_for<T, Ts...>>;
|
||||
|
||||
// This assertion fails (produces size<4>)
|
||||
assert_same<
|
||||
list<float, size<5>>,
|
||||
wrapped<float, int, double, char, unsigned>> a3;
|
||||
|
||||
|
||||
template <typename T, typename...Ts>
|
||||
using wrapped2 = list<T, size_for<Ts..., T>>;
|
||||
|
||||
// This assertion fails (produces size<2>)
|
||||
assert_same<
|
||||
list<float, size<5>>,
|
||||
wrapped2<float, int, double, char, unsigned>> a4;
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
// PR c++/69958
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
typedef decltype(sizeof(int)) size_t;
|
||||
|
||||
template <typename...Ts>
|
||||
struct list { };
|
||||
|
||||
template <size_t N>
|
||||
struct size { };
|
||||
|
||||
template <unsigned...Ts>
|
||||
using size_for = size<sizeof...(Ts)>;
|
||||
|
||||
template<class T, class U> struct assert_same;
|
||||
template<class T> struct assert_same<T,T> {};
|
||||
|
||||
template <typename T, unsigned...Ts>
|
||||
using wrapped = list<T, size_for<0, Ts...>>;
|
||||
|
||||
// This assertion fails (produces size<4>)
|
||||
assert_same<
|
||||
list<float, size<5>>,
|
||||
wrapped<float,2,3,4,5>> a3;
|
||||
|
||||
|
||||
template <typename T, unsigned...Ts>
|
||||
using wrapped2 = list<T, size_for<Ts..., 0>>;
|
||||
|
||||
// This assertion fails (produces size<2>)
|
||||
assert_same<
|
||||
list<float, size<5>>,
|
||||
wrapped2<float,2,3,4,5>> a4;
|
||||
Loading…
Reference in New Issue