diff options
author | Marek Polacek <polacek@redhat.com> | 2015-03-30 18:39:17 +0000 |
---|---|---|
committer | Marek Polacek <mpolacek@gcc.gnu.org> | 2015-03-30 18:39:17 +0000 |
commit | ef4bac7802534e52d3031dccf0cdfb2c53b2d836 (patch) | |
tree | 05c8ccb5585dce489c8e83023f76d83a742cb992 | |
parent | 6c384511a36aa97eda218a2935fe3a14720e3b59 (diff) | |
download | gcc-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/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 72 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/pr65398-2.C | 38 |
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)); |