aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2018-02-09 05:46:18 +0000
committerJakub Jelinek <jakub@gcc.gnu.org>2018-02-09 06:46:18 +0100
commitebe4bf41d2b96a6b2f1de6a184eb0a7f5c2e5d00 (patch)
treeb8a9d8946a8bf5dbff8138544a0e796605787045 /gcc
parent5800666390320080558b2766738c21e82bf570e7 (diff)
downloadgcc-ebe4bf41d2b96a6b2f1de6a184eb0a7f5c2e5d00.zip
gcc-ebe4bf41d2b96a6b2f1de6a184eb0a7f5c2e5d00.tar.gz
gcc-ebe4bf41d2b96a6b2f1de6a184eb0a7f5c2e5d00.tar.bz2
re PR c++/83659 (ICE on compilable C++ code: in tree_to_shwi, at tree.c:6821)
PR c++/83659 * fold-const.c (fold_indirect_ref_1): Use VECTOR_TYPE_P macro. Formatting fixes. Verify first that tree_fits_poly_int64_p (op01). Sync some changes from cxx_fold_indirect_ref. * constexpr.c (cxx_fold_indirect_ref): Sync some changes from fold_indirect_ref_1, including poly_*int64. Verify first that tree_fits_poly_int64_p (op01). Formatting fixes. * g++.dg/torture/pr83659.C: New test. Co-Authored-By: Jakub Jelinek <jakub@redhat.com> From-SVN: r257512
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog8
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/constexpr.c51
-rw-r--r--gcc/fold-const.c27
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/torture/pr83659.C18
6 files changed, 90 insertions, 28 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b5e19ed..d9c5443 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,11 @@
+2018-02-09 Marek Polacek <polacek@redhat.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/83659
+ * fold-const.c (fold_indirect_ref_1): Use VECTOR_TYPE_P macro.
+ Formatting fixes. Verify first that tree_fits_poly_int64_p (op01).
+ Sync some changes from cxx_fold_indirect_ref.
+
2018-02-09 Alexandre Oliva <aoliva@redhat.com>
* cfgexpand.c (expand_gimple_basic_block): Handle inline entry
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index be4db4b..ac53a74 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+2018-02-09 Marek Polacek <polacek@redhat.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/83659
+ * constexpr.c (cxx_fold_indirect_ref): Sync some changes from
+ fold_indirect_ref_1, including poly_*int64. Verify first that
+ tree_fits_poly_int64_p (op01). Formatting fixes.
+
2018-02-08 Paolo Carlini <paolo.carlini@oracle.com>
* constexpr.c (cxx_eval_component_reference): Use INDIRECT_REF_P.
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 39a2e1a..7292441 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -3025,9 +3025,10 @@ cxx_eval_vec_init (const constexpr_ctx *ctx, tree t,
static tree
cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
{
- tree sub, subtype;
+ tree sub = op0;
+ tree subtype;
+ poly_uint64 const_op01;
- sub = op0;
STRIP_NOPS (sub);
subtype = TREE_TYPE (sub);
if (!POINTER_TYPE_P (subtype))
@@ -3082,7 +3083,8 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
{
tree part_width = TYPE_SIZE (type);
tree index = bitsize_int (0);
- return fold_build3_loc (loc, BIT_FIELD_REF, type, op, part_width, index);
+ return fold_build3_loc (loc, BIT_FIELD_REF, type, op, part_width,
+ index);
}
/* Also handle conversion to an empty base class, which
is represented with a NOP_EXPR. */
@@ -3107,7 +3109,7 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
}
}
else if (TREE_CODE (sub) == POINTER_PLUS_EXPR
- && TREE_CODE (TREE_OPERAND (sub, 1)) == INTEGER_CST)
+ && poly_int_tree_p (TREE_OPERAND (sub, 1), &const_op01))
{
tree op00 = TREE_OPERAND (sub, 0);
tree op01 = TREE_OPERAND (sub, 1);
@@ -3121,29 +3123,37 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
/* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */
if (VECTOR_TYPE_P (op00type)
- && (same_type_ignoring_top_level_qualifiers_p
- (type, TREE_TYPE (op00type))))
+ && same_type_ignoring_top_level_qualifiers_p
+ (type, TREE_TYPE (op00type))
+ /* POINTER_PLUS_EXPR second operand is sizetype, unsigned,
+ but we want to treat offsets with MSB set as negative.
+ For the code below negative offsets are invalid and
+ TYPE_SIZE of the element is something unsigned, so
+ check whether op01 fits into poly_int64, which implies
+ it is from 0 to INTTYPE_MAXIMUM (HOST_WIDE_INT), and
+ then just use poly_uint64 because we want to treat the
+ value as unsigned. */
+ && tree_fits_poly_int64_p (op01))
{
- HOST_WIDE_INT offset = tree_to_shwi (op01);
tree part_width = TYPE_SIZE (type);
- unsigned HOST_WIDE_INT part_widthi = tree_to_shwi (part_width)/BITS_PER_UNIT;
- unsigned HOST_WIDE_INT indexi = offset * BITS_PER_UNIT;
- tree index = bitsize_int (indexi);
-
- if (known_lt (offset / part_widthi,
- TYPE_VECTOR_SUBPARTS (op00type)))
- return fold_build3_loc (loc,
- BIT_FIELD_REF, type, op00,
- part_width, index);
-
+ poly_uint64 max_offset
+ = (tree_to_uhwi (part_width) / BITS_PER_UNIT
+ * TYPE_VECTOR_SUBPARTS (op00type));
+ if (known_lt (const_op01, max_offset))
+ {
+ tree index = bitsize_int (const_op01 * BITS_PER_UNIT);
+ return fold_build3_loc (loc,
+ BIT_FIELD_REF, type, op00,
+ part_width, index);
+ }
}
/* ((foo*)&complexfoo)[1] => __imag__ complexfoo */
else if (TREE_CODE (op00type) == COMPLEX_TYPE
&& (same_type_ignoring_top_level_qualifiers_p
(type, TREE_TYPE (op00type))))
{
- tree size = TYPE_SIZE_UNIT (type);
- if (tree_int_cst_equal (size, op01))
+ if (known_eq (wi::to_poly_offset (TYPE_SIZE_UNIT (type)),
+ const_op01))
return fold_build1_loc (loc, IMAGPART_EXPR, type, op00);
}
/* ((foo *)&fooarray)[1] => fooarray[1] */
@@ -3198,7 +3208,8 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
{
tree type_domain;
tree min_val = size_zero_node;
- tree newsub = cxx_fold_indirect_ref (loc, TREE_TYPE (subtype), sub, NULL);
+ tree newsub
+ = cxx_fold_indirect_ref (loc, TREE_TYPE (subtype), sub, NULL);
if (newsub)
sub = newsub;
else
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index c86c3f9..87d00a5 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -14115,6 +14115,7 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0)
{
tree op = TREE_OPERAND (sub, 0);
tree optype = TREE_TYPE (op);
+
/* *&CONST_DECL -> to the value of the const decl. */
if (TREE_CODE (op) == CONST_DECL)
return DECL_INITIAL (op);
@@ -14148,12 +14149,13 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0)
&& type == TREE_TYPE (optype))
return fold_build1_loc (loc, REALPART_EXPR, type, op);
/* *(foo *)&vectorfoo => BIT_FIELD_REF<vectorfoo,...> */
- else if (TREE_CODE (optype) == VECTOR_TYPE
+ else if (VECTOR_TYPE_P (optype)
&& type == TREE_TYPE (optype))
{
tree part_width = TYPE_SIZE (type);
tree index = bitsize_int (0);
- return fold_build3_loc (loc, BIT_FIELD_REF, type, op, part_width, index);
+ return fold_build3_loc (loc, BIT_FIELD_REF, type, op, part_width,
+ index);
}
}
@@ -14171,8 +14173,17 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0)
op00type = TREE_TYPE (op00);
/* ((foo*)&vectorfoo)[1] => BIT_FIELD_REF<vectorfoo,...> */
- if (TREE_CODE (op00type) == VECTOR_TYPE
- && type == TREE_TYPE (op00type))
+ if (VECTOR_TYPE_P (op00type)
+ && type == TREE_TYPE (op00type)
+ /* POINTER_PLUS_EXPR second operand is sizetype, unsigned,
+ but we want to treat offsets with MSB set as negative.
+ For the code below negative offsets are invalid and
+ TYPE_SIZE of the element is something unsigned, so
+ check whether op01 fits into poly_int64, which implies
+ it is from 0 to INTTYPE_MAXIMUM (HOST_WIDE_INT), and
+ then just use poly_uint64 because we want to treat the
+ value as unsigned. */
+ && tree_fits_poly_int64_p (op01))
{
tree part_width = TYPE_SIZE (type);
poly_uint64 max_offset
@@ -14199,16 +14210,16 @@ fold_indirect_ref_1 (location_t loc, tree type, tree op0)
&& type == TREE_TYPE (op00type))
{
tree type_domain = TYPE_DOMAIN (op00type);
- tree min = size_zero_node;
+ tree min_val = size_zero_node;
if (type_domain && TYPE_MIN_VALUE (type_domain))
- min = TYPE_MIN_VALUE (type_domain);
+ min_val = TYPE_MIN_VALUE (type_domain);
offset_int off = wi::to_offset (op01);
offset_int el_sz = wi::to_offset (TYPE_SIZE_UNIT (type));
offset_int remainder;
off = wi::divmod_trunc (off, el_sz, SIGNED, &remainder);
- if (remainder == 0 && TREE_CODE (min) == INTEGER_CST)
+ if (remainder == 0 && TREE_CODE (min_val) == INTEGER_CST)
{
- off = off + wi::to_offset (min);
+ off = off + wi::to_offset (min_val);
op01 = wide_int_to_tree (sizetype, off);
return build4_loc (loc, ARRAY_REF, type, op00, op01,
NULL_TREE, NULL_TREE);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index dfa8cb8..49a2275 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2018-02-09 Marek Polacek <polacek@redhat.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/83659
+ * g++.dg/torture/pr83659.C: New test.
+
2018-02-08 David Malcolm <dmalcolm@redhat.com>
PR tree-optimization/84136
diff --git a/gcc/testsuite/g++.dg/torture/pr83659.C b/gcc/testsuite/g++.dg/torture/pr83659.C
new file mode 100644
index 0000000..bdcdca2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr83659.C
@@ -0,0 +1,18 @@
+// PR c++/83659
+// { dg-do compile }
+
+typedef int V __attribute__ ((__vector_size__ (16)));
+V a;
+V b[2];
+
+int
+foo ()
+{
+ return reinterpret_cast <int *> (&a)[-1] += 1;
+}
+
+int
+bar ()
+{
+ return reinterpret_cast <int *> (&a[1])[-1];
+}