c++: Fix ICEs with large initializer lists or ones including #embed [PR118124]
The following testcases ICE due to RAW_DATA_CST not being handled where it should be during ck_list conversions. The last 2 testcases started ICEing with r15-6339 committed yesterday (speedup of large initializers), the first two already with r15-5958 (#embed optimization for C++). For conversion to initializer_list<unsigned char> or char/signed char we can optimize and keep RAW_DATA_CST with adjusted type if we report narrowing errors if needed, for others this converts each element separately. 2025-01-15 Jakub Jelinek <jakub@redhat.com> PR c++/118124 * call.cc (convert_like_internal): Handle RAW_DATA_CST in ck_list handling. Formatting fixes. * g++.dg/cpp/embed-15.C: New test. * g++.dg/cpp/embed-16.C: New test. * g++.dg/cpp0x/initlist-opt3.C: New test. * g++.dg/cpp0x/initlist-opt4.C: New test.
This commit is contained in:
parent
40ad10f708
commit
f263f2d525
5 changed files with 209 additions and 6 deletions
|
@ -8806,8 +8806,9 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum,
|
|||
|
||||
if (tree init = maybe_init_list_as_array (elttype, expr))
|
||||
{
|
||||
elttype = cp_build_qualified_type
|
||||
(elttype, cp_type_quals (elttype) | TYPE_QUAL_CONST);
|
||||
elttype
|
||||
= cp_build_qualified_type (elttype, (cp_type_quals (elttype)
|
||||
| TYPE_QUAL_CONST));
|
||||
array = build_array_of_n_type (elttype, len);
|
||||
array = build_vec_init_expr (array, init, complain);
|
||||
array = get_target_expr (array);
|
||||
|
@ -8815,13 +8816,94 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum,
|
|||
}
|
||||
else if (len)
|
||||
{
|
||||
tree val; unsigned ix;
|
||||
|
||||
tree val;
|
||||
unsigned ix;
|
||||
tree new_ctor = build_constructor (init_list_type_node, NULL);
|
||||
|
||||
/* Convert all the elements. */
|
||||
FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), ix, val)
|
||||
{
|
||||
if (TREE_CODE (val) == RAW_DATA_CST)
|
||||
{
|
||||
tree elt_type;
|
||||
conversion *next;
|
||||
/* For conversion to initializer_list<unsigned char> or
|
||||
initializer_list<char> or initializer_list<signed char>
|
||||
we can optimize and keep RAW_DATA_CST with adjusted
|
||||
type if we report narrowing errors if needed, for
|
||||
others this converts each element separately. */
|
||||
if (convs->u.list[ix]->kind == ck_std
|
||||
&& (elt_type = convs->u.list[ix]->type)
|
||||
&& (TREE_CODE (elt_type) == INTEGER_TYPE
|
||||
|| is_byte_access_type (elt_type))
|
||||
&& TYPE_PRECISION (elt_type) == CHAR_BIT
|
||||
&& (next = next_conversion (convs->u.list[ix]))
|
||||
&& next->kind == ck_identity)
|
||||
{
|
||||
if (!TYPE_UNSIGNED (elt_type)
|
||||
/* For RAW_DATA_CST, TREE_TYPE (val) can be
|
||||
either integer_type_node (when it has been
|
||||
created by the lexer from CPP_EMBED) or
|
||||
after digestion/conversion some integral
|
||||
type with CHAR_BIT precision. For int with
|
||||
precision higher than CHAR_BIT or unsigned char
|
||||
diagnose narrowing conversions from
|
||||
that int/unsigned char to signed char if any
|
||||
byte has most significant bit set. */
|
||||
&& (TYPE_UNSIGNED (TREE_TYPE (val))
|
||||
|| (TYPE_PRECISION (TREE_TYPE (val))
|
||||
> CHAR_BIT)))
|
||||
for (int i = 0; i < RAW_DATA_LENGTH (val); ++i)
|
||||
{
|
||||
if (RAW_DATA_SCHAR_ELT (val, i) >= 0)
|
||||
continue;
|
||||
else if (complain & tf_error)
|
||||
{
|
||||
location_t loc
|
||||
= cp_expr_loc_or_input_loc (val);
|
||||
int savederrorcount = errorcount;
|
||||
permerror_opt (loc, OPT_Wnarrowing,
|
||||
"narrowing conversion of "
|
||||
"%qd from %qH to %qI",
|
||||
RAW_DATA_UCHAR_ELT (val, i),
|
||||
TREE_TYPE (val), elt_type);
|
||||
if (errorcount != savederrorcount)
|
||||
return error_mark_node;
|
||||
}
|
||||
else
|
||||
return error_mark_node;
|
||||
}
|
||||
tree sub = copy_node (val);
|
||||
TREE_TYPE (sub) = elt_type;
|
||||
CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_ctor),
|
||||
NULL_TREE, sub);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < RAW_DATA_LENGTH (val); ++i)
|
||||
{
|
||||
tree elt
|
||||
= build_int_cst (TREE_TYPE (val),
|
||||
RAW_DATA_UCHAR_ELT (val, i));
|
||||
tree sub
|
||||
= convert_like (convs->u.list[ix], elt,
|
||||
fn, argnum, false, false,
|
||||
/*nested_p=*/true, complain);
|
||||
if (sub == error_mark_node)
|
||||
return sub;
|
||||
if (!check_narrowing (TREE_TYPE (sub), elt,
|
||||
complain))
|
||||
return error_mark_node;
|
||||
tree nc = new_ctor;
|
||||
CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (nc),
|
||||
NULL_TREE, sub);
|
||||
if (!TREE_CONSTANT (sub))
|
||||
TREE_CONSTANT (new_ctor) = false;
|
||||
}
|
||||
}
|
||||
len += RAW_DATA_LENGTH (val) - 1;
|
||||
continue;
|
||||
}
|
||||
tree sub = convert_like (convs->u.list[ix], val, fn,
|
||||
argnum, false, false,
|
||||
/*nested_p=*/true, complain);
|
||||
|
@ -8836,8 +8918,9 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum,
|
|||
TREE_CONSTANT (new_ctor) = false;
|
||||
}
|
||||
/* Build up the array. */
|
||||
elttype = cp_build_qualified_type
|
||||
(elttype, cp_type_quals (elttype) | TYPE_QUAL_CONST);
|
||||
elttype
|
||||
= cp_build_qualified_type (elttype, (cp_type_quals (elttype)
|
||||
| TYPE_QUAL_CONST));
|
||||
array = build_array_of_n_type (elttype, len);
|
||||
array = finish_compound_literal (array, new_ctor, complain);
|
||||
/* This is dubious now, should be blessed by P2752. */
|
||||
|
|
35
gcc/testsuite/g++.dg/cpp/embed-15.C
Normal file
35
gcc/testsuite/g++.dg/cpp/embed-15.C
Normal file
|
@ -0,0 +1,35 @@
|
|||
// PR c++/118124
|
||||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options "-O2" }
|
||||
|
||||
namespace std {
|
||||
template <class T> struct initializer_list {
|
||||
private:
|
||||
const T *_M_array;
|
||||
__SIZE_TYPE__ _M_len;
|
||||
};
|
||||
}
|
||||
struct A {
|
||||
A (std::initializer_list<char>);
|
||||
};
|
||||
A a {
|
||||
#embed __FILE__
|
||||
};
|
||||
struct B {
|
||||
B (std::initializer_list<unsigned char>);
|
||||
};
|
||||
B b {
|
||||
#embed __FILE__
|
||||
};
|
||||
struct C {
|
||||
C (std::initializer_list<int>);
|
||||
};
|
||||
C c {
|
||||
#embed __FILE__
|
||||
};
|
||||
struct D {
|
||||
D (std::initializer_list<float>);
|
||||
};
|
||||
D d {
|
||||
#embed __FILE__
|
||||
};
|
18
gcc/testsuite/g++.dg/cpp/embed-16.C
Normal file
18
gcc/testsuite/g++.dg/cpp/embed-16.C
Normal file
|
@ -0,0 +1,18 @@
|
|||
// PR c++/118124
|
||||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options "-O2" }
|
||||
// non-ASCII chars here: áéí
|
||||
|
||||
namespace std {
|
||||
template <class T> struct initializer_list {
|
||||
private:
|
||||
const T *_M_array;
|
||||
__SIZE_TYPE__ _M_len;
|
||||
};
|
||||
}
|
||||
struct A {
|
||||
A (std::initializer_list<signed char>);
|
||||
};
|
||||
A a {
|
||||
#embed __FILE__
|
||||
}; // { dg-error "narrowing conversion of '\[0-9]*' from 'int' to 'signed char'" }
|
47
gcc/testsuite/g++.dg/cpp0x/initlist-opt3.C
Normal file
47
gcc/testsuite/g++.dg/cpp0x/initlist-opt3.C
Normal file
|
@ -0,0 +1,47 @@
|
|||
// PR c++/118124
|
||||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options "-O2" }
|
||||
|
||||
namespace std {
|
||||
template <class T> struct initializer_list {
|
||||
private:
|
||||
const T *_M_array;
|
||||
__SIZE_TYPE__ _M_len;
|
||||
};
|
||||
}
|
||||
struct A {
|
||||
A (std::initializer_list<char>);
|
||||
};
|
||||
A a { 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1,
|
||||
2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3,
|
||||
4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5,
|
||||
6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 };
|
||||
struct B {
|
||||
B (std::initializer_list<unsigned char>);
|
||||
};
|
||||
B b { 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1,
|
||||
2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3,
|
||||
4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5,
|
||||
6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 };
|
||||
struct C {
|
||||
C (std::initializer_list<int>);
|
||||
};
|
||||
C c { 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1,
|
||||
2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3,
|
||||
4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5,
|
||||
6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 };
|
||||
struct D {
|
||||
D (std::initializer_list<float>);
|
||||
};
|
||||
D d { 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1,
|
||||
2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3,
|
||||
4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5,
|
||||
6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 };
|
20
gcc/testsuite/g++.dg/cpp0x/initlist-opt4.C
Normal file
20
gcc/testsuite/g++.dg/cpp0x/initlist-opt4.C
Normal file
|
@ -0,0 +1,20 @@
|
|||
// PR c++/118124
|
||||
// { dg-do compile { target c++11 } }
|
||||
// { dg-options "-O2" }
|
||||
|
||||
namespace std {
|
||||
template <class T> struct initializer_list {
|
||||
private:
|
||||
const T *_M_array;
|
||||
__SIZE_TYPE__ _M_len;
|
||||
};
|
||||
}
|
||||
struct A {
|
||||
A (std::initializer_list<signed char>);
|
||||
};
|
||||
A a { 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7,
|
||||
8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1,
|
||||
2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 209, 0, 1, 2, 3,
|
||||
4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5,
|
||||
6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 }; // { dg-error "narrowing conversion of '209' from 'int' to 'signed char'" }
|
Loading…
Add table
Reference in a new issue