aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2015-03-30 18:39:17 +0000
committerMarek Polacek <mpolacek@gcc.gnu.org>2015-03-30 18:39:17 +0000
commitef4bac7802534e52d3031dccf0cdfb2c53b2d836 (patch)
tree05c8ccb5585dce489c8e83023f76d83a742cb992
parent6c384511a36aa97eda218a2935fe3a14720e3b59 (diff)
downloadgcc-ef4bac7802534e52d3031dccf0cdfb2c53b2d836.zip
gcc-ef4bac7802534e52d3031dccf0cdfb2c53b2d836.tar.gz
gcc-ef4bac7802534e52d3031dccf0cdfb2c53b2d836.tar.bz2
re PR c++/65398 ([C++11] GCC rejects constexpr variable definitions with valid initialization)
PR c++/65398 * constexpr.c (cxx_fold_indirect_ref): Don't perform the *(&A[i] p+ j) => A[i + j] transformation here. (cxx_eval_pointer_plus_expression): New function. (cxx_eval_constant_expression): Use it here. * g++.dg/cpp0x/pr65398-2.C: New test. From-SVN: r221777
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/constexpr.c72
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr65398-2.C38
4 files changed, 102 insertions, 21 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a9f872d..ec35f22 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+2015-03-30 Marek Polacek <polacek@redhat.com>
+
+ PR c++/65398
+ * constexpr.c (cxx_fold_indirect_ref): Don't perform the
+ *(&A[i] p+ j) => A[i + j] transformation here.
+ (cxx_eval_pointer_plus_expression): New function.
+ (cxx_eval_constant_expression): Use it here.
+
2015-03-27 Tobias Burnus <burnus@net-b.de>
PR c/65586
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 2f09472..2100f94 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -2427,27 +2427,6 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
break;
}
}
- /* *(&A[i] p+ j) => A[i + j] */
- else if (TREE_CODE (op00) == ARRAY_REF
- && TREE_CODE (TREE_OPERAND (op00, 1)) == INTEGER_CST
- && TREE_CODE (op01) == INTEGER_CST)
- {
- tree t = fold_convert_loc (loc, ssizetype,
- TREE_OPERAND (op00, 1));
- tree nelts
- = array_type_nelts_top (TREE_TYPE (TREE_OPERAND (op00, 0)));
- /* Don't fold an out-of-bound access. */
- if (!tree_int_cst_le (t, nelts))
- 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),
- TYPE_SIZE_UNIT (type));
- t = size_binop_loc (loc, PLUS_EXPR, op01, t);
- return build4_loc (loc, ARRAY_REF, type, TREE_OPERAND (op00, 0),
- t, NULL_TREE, NULL_TREE);
- }
}
}
/* *(foo *)fooarrptr => (*fooarrptr)[0] */
@@ -2942,6 +2921,51 @@ cxx_eval_switch_expr (const constexpr_ctx *ctx, tree t,
return NULL_TREE;
}
+/* Subroutine of cxx_eval_constant_expression.
+ Attempt to reduce a POINTER_PLUS_EXPR expression T. */
+
+static tree
+cxx_eval_pointer_plus_expression (const constexpr_ctx *ctx, tree t,
+ bool lval, bool *non_constant_p,
+ bool *overflow_p)
+{
+ tree op00 = TREE_OPERAND (t, 0);
+ tree op01 = TREE_OPERAND (t, 1);
+ location_t loc = EXPR_LOCATION (t);
+
+ STRIP_NOPS (op00);
+ if (TREE_CODE (op00) != ADDR_EXPR)
+ return NULL_TREE;
+
+ op00 = TREE_OPERAND (op00, 0);
+
+ /* &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 type = TREE_TYPE (op00);
+ t = fold_convert_loc (loc, ssizetype, TREE_OPERAND (op00, 1));
+ tree nelts = array_type_nelts_top (TREE_TYPE (TREE_OPERAND (op00, 0)));
+ /* Don't fold an out-of-bound access. */
+ if (!tree_int_cst_le (t, nelts))
+ 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),
+ 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);
+ return cxx_eval_constant_expression (ctx, t, lval, non_constant_p,
+ overflow_p);
+ }
+
+ return NULL_TREE;
+}
+
/* Attempt to reduce the expression T to a constant value.
On failure, issue diagnostic and return error_mark_node. */
/* FIXME unify with c_fully_fold */
@@ -3247,6 +3271,12 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
break;
case POINTER_PLUS_EXPR:
+ r = cxx_eval_pointer_plus_expression (ctx, t, lval, non_constant_p,
+ overflow_p);
+ if (r)
+ break;
+ /* else fall through */
+
case PLUS_EXPR:
case MINUS_EXPR:
case MULT_EXPR:
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 792c267..d792b9f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,10 @@
2015-03-30 Marek Polacek <polacek@redhat.com>
+ PR c++/65398
+ * g++.dg/cpp0x/pr65398-2.C: New test.
+
+2015-03-30 Marek Polacek <polacek@redhat.com>
+
* c-c++-common/pr65556.c: Change the width of bit-fields.
2015-03-27 Jan Hubicka <hubicka@ucw.cz>
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr65398-2.C b/gcc/testsuite/g++.dg/cpp0x/pr65398-2.C
new file mode 100644
index 0000000..f920b03
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr65398-2.C
@@ -0,0 +1,38 @@
+// PR c++/65398
+// { dg-do compile { target c++11 } }
+
+#define SA(X) static_assert((X),#X)
+
+constexpr char s[] = "abc";
+
+SA((&s[0] + 0) == (&s[0] + 0));
+SA((&s[0] + 1) == (&s[1] + 0));
+SA((&s[0] + 2) == (&s[1] + 1));
+SA((&s[0] + 3) == (&s[1] + 2));
+SA((&s[0] + 4) == (&s[1] + 3));
+SA((&s[2] + 0) == (&s[0] + 2));
+SA((&s[2] + 1) == (&s[3] + 0));
+SA((&s[2] + 2) == (&s[3] + 1));
+SA((&s[4] + 0) == (&s[2] + 2));
+
+SA((&s[0] + 0) != (&s[1] + 0));
+SA((&s[0] + 2) != (&s[1] + 0));
+SA((&s[2] + 0) != (&s[2] + 1));
+SA((&s[1] + 1) != (&s[0] + 1));
+
+constexpr int l[] = { 'c', 'd', 'e', '\0' };
+
+SA((&l[0] + 0) == (&l[0] + 0));
+SA((&l[0] + 1) == (&l[1] + 0));
+SA((&l[0] + 2) == (&l[1] + 1));
+SA((&l[0] + 3) == (&l[1] + 2));
+SA((&l[0] + 4) == (&l[1] + 3));
+SA((&l[2] + 0) == (&l[0] + 2));
+SA((&l[2] + 1) == (&l[3] + 0));
+SA((&l[2] + 2) == (&l[3] + 1));
+SA((&l[4] + 0) == (&l[2] + 2));
+
+SA((&l[0] + 0) != (&l[1] + 0));
+SA((&l[0] + 2) != (&l[1] + 0));
+SA((&l[2] + 0) != (&l[2] + 1));
+SA((&l[1] + 1) != (&l[0] + 1));