From: Jakub Jelinek Date: Mon, 29 Mar 2021 10:35:32 +0000 (+0200) Subject: fold-const: Fix ICE in extract_muldiv_1 [PR99777] X-Git-Tag: basepoints/gcc-12~370 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=25e515d2199d555848dfba01fd5364df94096496;p=thirdparty%2Fgcc.git 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 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. --- diff --git a/gcc/fold-const.c b/gcc/fold-const.c index 4c48d7076e79..d4c5a9c299f2 100644 --- a/gcc/fold-const.c +++ b/gcc/fold-const.c @@ -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; diff --git a/gcc/testsuite/g++.dg/torture/pr99777.C b/gcc/testsuite/g++.dg/torture/pr99777.C new file mode 100644 index 000000000000..3cddde58bdd2 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr99777.C @@ -0,0 +1,44 @@ +// PR tree-optimization/99777 + +template +inline const T & +min (const T &a, const T &b) +{ + if (b < a) + return b; + return a; +} + +template +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; + } +}