Commit ef4bac78 by Marek Polacek Committed by Marek Polacek

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
parent 6c384511
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
......
......@@ -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:
......
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>
......
// 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));
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment