re PR c++/65736 (ICE (in process_init_constructor_array, at cp/typeck2.c:1263))
authorJakub Jelinek <jakub@gcc.gnu.org>
Sun, 12 Apr 2015 19:10:58 +0000 (21:10 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Sun, 12 Apr 2015 19:10:58 +0000 (21:10 +0200)
PR c++/65736
* constexpr.c (cxx_eval_pointer_plus_expression): Don't fold for VLAs,
don't fold if op01 isn't divisible by TYPE_SIZE_UNIT.  Convert
the expression to the original type at the end.

* g++.dg/cpp0x/pr65736.C: New test.

From-SVN: r222022

gcc/ChangeLog
gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/pr65736.C [new file with mode: 0644]

index d65662f7ea295440e4aa3995904159c1e268745b..aa9349aafbd097342e4ee9c963622c2f8df1eca3 100644 (file)
@@ -2,7 +2,7 @@
 
        * doc/contrib.texi (Contributors): Add Maxim Kuvyrkov.
 
-2015-04-11 Jan Hubicka  <hubicka@ucw.cz>
+2015-04-11  Jan Hubicka  <hubicka@ucw.cz>
 
        PR ipa/65743
        * ipa-inline-transform.c (speculation_removed): Remove static var.
@@ -12,8 +12,8 @@
        * ipa-prop.c (ipa_make_edge_direct_to_target): Do not
        consider non-invariants.
 
-2015-04-11 Jan Hubicka  <hubicka@ucw.cz>
-          Martin Liska  <mliska@suse.cz>
+2015-04-11  Jan Hubicka  <hubicka@ucw.cz>
+           Martin Liska  <mliska@suse.cz>
 
        PR ipa/65722
        * ipa-icf.c (sem_item::compare_cgraph_references): function and
index 91ddee0233c105b3f2fe723b454f48186cf16140..e5a6ae2ea5f3edf5117850e5ab67b694a9b198cd 100644 (file)
@@ -1,3 +1,10 @@
+2015-04-12  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/65736
+       * constexpr.c (cxx_eval_pointer_plus_expression): Don't fold for VLAs,
+       don't fold if op01 isn't divisible by TYPE_SIZE_UNIT.  Convert
+       the expression to the original type at the end.
+
 2015-04-09  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/65690
index f5be8dfb46c61fed70d4b5c35c77b44133dd7f70..2952cbe1c592a2d136f33f16b58a8b4257b0739b 100644 (file)
@@ -2929,6 +2929,7 @@ cxx_eval_pointer_plus_expression (const constexpr_ctx *ctx, tree t,
                                  bool lval, bool *non_constant_p,
                                  bool *overflow_p)
 {
+  tree orig_type = TREE_TYPE (t);
   tree op00 = TREE_OPERAND (t, 0);
   tree op01 = TREE_OPERAND (t, 1);
   location_t loc = EXPR_LOCATION (t);
@@ -2945,7 +2946,9 @@ cxx_eval_pointer_plus_expression (const constexpr_ctx *ctx, tree t,
   /* &A[i] p+ j => &A[i + j] */
   if (TREE_CODE (op00) == ARRAY_REF
       && TREE_CODE (TREE_OPERAND (op00, 1)) == INTEGER_CST
-      && TREE_CODE (op01) == INTEGER_CST)
+      && TREE_CODE (op01) == INTEGER_CST
+      && TYPE_SIZE_UNIT (TREE_TYPE (op00))
+      && TREE_CODE (TYPE_SIZE_UNIT (TREE_TYPE (op00))) == INTEGER_CST)
     {
       tree type = TREE_TYPE (op00);
       t = fold_convert_loc (loc, ssizetype, TREE_OPERAND (op00, 1));
@@ -2953,15 +2956,21 @@ cxx_eval_pointer_plus_expression (const constexpr_ctx *ctx, tree t,
       /* Don't fold an out-of-bound access.  */
       if (!tree_int_cst_le (t, nelts))
        return NULL_TREE;
+      op01 = cp_fold_convert (ssizetype, op01);
+      /* Don't fold if op01 can't be divided exactly by TYPE_SIZE_UNIT.
+        constexpr int A[1]; ... (char *)&A[0] + 1 */
+      if (!integer_zerop (fold_build2_loc (loc, TRUNC_MOD_EXPR, sizetype,
+                                          op01, TYPE_SIZE_UNIT (type))))
+       return NULL_TREE;
       /* Make sure to treat the second operand of POINTER_PLUS_EXPR
         as signed.  */
-      op01 = fold_build2_loc (loc, EXACT_DIV_EXPR, ssizetype,
-                             cp_fold_convert (ssizetype, op01),
+      op01 = fold_build2_loc (loc, EXACT_DIV_EXPR, ssizetype, op01,
                              TYPE_SIZE_UNIT (type));
       t = size_binop_loc (loc, PLUS_EXPR, op01, t);
       t = build4_loc (loc, ARRAY_REF, type, TREE_OPERAND (op00, 0),
                      t, NULL_TREE, NULL_TREE);
       t = cp_build_addr_expr (t, tf_warning_or_error);
+      t = cp_fold_convert (orig_type, t);
       return cxx_eval_constant_expression (ctx, t, lval, non_constant_p,
                                           overflow_p);
     }
index 401bf14cc55385334f9fa07ffb0bc523768bf8c0..ea6b3a487fe39875cc0b6cb3672f948081ee02fd 100644 (file)
@@ -1,5 +1,10 @@
-2015-04-11 Jan Hubicka  <hubicka@ucw.cz>
-          Martin Liska  <mliska@suse.cz>
+2015-04-12  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/65736
+       * g++.dg/cpp0x/pr65736.C: New test.
+
+2015-04-11  Jan Hubicka  <hubicka@ucw.cz>
+           Martin Liska  <mliska@suse.cz>
 
        PR ipa/65722
        * g++.dg/ipa/pr65722.C: New testcase.
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr65736.C b/gcc/testsuite/g++.dg/cpp0x/pr65736.C
new file mode 100644 (file)
index 0000000..6e9c7fb
--- /dev/null
@@ -0,0 +1,5 @@
+// PR c++/65736
+// { dg-do compile { target c++11 } }
+
+int a[1];                                                                                                                                 
+char *b[1] { (char *)&a[0] + 1 };