fold-const: Fix ICE in extract_muldiv_1 [PR99777]
extract_muldiv{,_1} is apparently only prepared to handle scalar integer operations, the callers ensure it by only calling it if the divisor or one of the multiplicands is INTEGER_CST and because neither multiplication nor division nor modulo are really supported e.g. for pointer types, nullptr type etc. But the CASE_CONVERT handling doesn't really check if it isn't a cast from some other type kind, so on the testcase we end up trying to build MULT_EXPR in POINTER_TYPE which ICEs. A few years ago Marek has added ANY_INTEGRAL_TYPE_P checks to two spots, but the code uses TYPE_PRECISION which means something completely different for vector types, etc. So IMNSHO we should just punt on conversions from non-integrals or non-scalar integrals. 2021-03-29 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/99777 * fold-const.c (extract_muldiv_1): For conversions, punt on casts from types other than scalar integral types. * g++.dg/torture/pr99777.C: New test.
This commit is contained in:
parent
d579e2e76f
commit
25e515d219
@ -6713,6 +6713,8 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
|
||||
break;
|
||||
|
||||
CASE_CONVERT: case NON_LVALUE_EXPR:
|
||||
if (!INTEGRAL_TYPE_P (TREE_TYPE (op0)))
|
||||
break;
|
||||
/* If op0 is an expression ... */
|
||||
if ((COMPARISON_CLASS_P (op0)
|
||||
|| UNARY_CLASS_P (op0)
|
||||
@ -6721,8 +6723,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
|
||||
|| EXPRESSION_CLASS_P (op0))
|
||||
/* ... and has wrapping overflow, and its type is smaller
|
||||
than ctype, then we cannot pass through as widening. */
|
||||
&& (((ANY_INTEGRAL_TYPE_P (TREE_TYPE (op0))
|
||||
&& TYPE_OVERFLOW_WRAPS (TREE_TYPE (op0)))
|
||||
&& ((TYPE_OVERFLOW_WRAPS (TREE_TYPE (op0))
|
||||
&& (TYPE_PRECISION (ctype)
|
||||
> TYPE_PRECISION (TREE_TYPE (op0))))
|
||||
/* ... or this is a truncation (t is narrower than op0),
|
||||
@ -6737,8 +6738,7 @@ extract_muldiv_1 (tree t, tree c, enum tree_code code, tree wide_type,
|
||||
/* ... or has undefined overflow while the converted to
|
||||
type has not, we cannot do the operation in the inner type
|
||||
as that would introduce undefined overflow. */
|
||||
|| ((ANY_INTEGRAL_TYPE_P (TREE_TYPE (op0))
|
||||
&& TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0)))
|
||||
|| (TYPE_OVERFLOW_UNDEFINED (TREE_TYPE (op0))
|
||||
&& !TYPE_OVERFLOW_UNDEFINED (type))))
|
||||
break;
|
||||
|
||||
|
44
gcc/testsuite/g++.dg/torture/pr99777.C
Normal file
44
gcc/testsuite/g++.dg/torture/pr99777.C
Normal file
@ -0,0 +1,44 @@
|
||||
// PR tree-optimization/99777
|
||||
|
||||
template <typename T>
|
||||
inline const T &
|
||||
min (const T &a, const T &b)
|
||||
{
|
||||
if (b < a)
|
||||
return b;
|
||||
return a;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline const T &
|
||||
max (const T &a, const T &b)
|
||||
{
|
||||
if (a < b)
|
||||
return b;
|
||||
return a;
|
||||
}
|
||||
|
||||
extern int o, a, c;
|
||||
long h;
|
||||
unsigned long long e;
|
||||
signed char d;
|
||||
extern short p[][7][5][30];
|
||||
|
||||
void
|
||||
test (long long b, short f[][17][25][22][20])
|
||||
{
|
||||
for (char i = 0; i < 7; i += 3)
|
||||
for (unsigned char l = e; l < 5; l += 2)
|
||||
{
|
||||
if (max (0LL, min (7LL, b)))
|
||||
for (bool j = 0; j < 1; j = b)
|
||||
{
|
||||
for (unsigned k = d; k < 20; k++)
|
||||
h = f[0][i][l][b][k];
|
||||
for (int m = 0; m < 5; m++)
|
||||
p[c][i][l][m] = 0;
|
||||
}
|
||||
for (int n = 0; n < 4; n += a)
|
||||
o = n;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user