From 3aa3c9fc9a5f82f23717386df7fa342e0a89b627 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Thu, 14 May 2015 11:42:53 +0000 Subject: [PATCH] re PR c/66066 (r222889 causes bogus error: initializer element is not constant) PR c/66066 PR c/66127 * c-common.c (c_fully_fold): Pass false down to c_fully_fold_internal. (c_fully_fold_internal): Fold C_MAYBE_CONST_EXPRs with C_MAYBE_CONST_EXPR_INT_OPERANDS set. Add FOR_INT_CONST argument and use it. If FOR_INT_CONST, require that all evaluated operands be INTEGER_CSTs. * c-typeck.c (digest_init): Call pedwarn_init with OPT_Wpedantic rather than with 0. * gcc.dg/pr14649-1.c: Add -Wpedantic. * gcc.dg/pr19984.c: Likewise. * gcc.dg/pr66066-1.c: New test. * gcc.dg/pr66066-2.c: New test. * gcc.dg/pr66066-3.c: New test. From-SVN: r223193 --- gcc/c-family/ChangeLog | 10 +++++ gcc/c-family/c-common.c | 66 ++++++++++++++++++++++++-------- gcc/c/ChangeLog | 7 ++++ gcc/c/c-typeck.c | 2 +- gcc/testsuite/ChangeLog | 10 +++++ gcc/testsuite/gcc.dg/pr14649-1.c | 2 +- gcc/testsuite/gcc.dg/pr19984.c | 2 +- gcc/testsuite/gcc.dg/pr66066-1.c | 37 ++++++++++++++++++ gcc/testsuite/gcc.dg/pr66066-2.c | 37 ++++++++++++++++++ gcc/testsuite/gcc.dg/pr66066-3.c | 37 ++++++++++++++++++ 10 files changed, 191 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr66066-1.c create mode 100644 gcc/testsuite/gcc.dg/pr66066-2.c create mode 100644 gcc/testsuite/gcc.dg/pr66066-3.c diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 52b4d5cb7a4..48d483e7b1b 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,13 @@ +2015-05-14 Marek Polacek + + PR c/66066 + PR c/66127 + * c-common.c (c_fully_fold): Pass false down to c_fully_fold_internal. + (c_fully_fold_internal): Fold C_MAYBE_CONST_EXPRs with + C_MAYBE_CONST_EXPR_INT_OPERANDS set. Add FOR_INT_CONST argument and + use it. If FOR_INT_CONST, require that all evaluated operands be + INTEGER_CSTs. + 2015-05-12 David Malcolm * c-common.h (warn_for_misleading_indentation): New prototype. diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 7e5ac72900b..31c4c0d16e0 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -315,7 +315,7 @@ const struct fname_var_t fname_vars[] = /* Global visibility options. */ struct visibility_flags visibility_options; -static tree c_fully_fold_internal (tree expr, bool, bool *, bool *); +static tree c_fully_fold_internal (tree expr, bool, bool *, bool *, bool); static tree check_case_value (location_t, tree); static bool check_case_bounds (location_t, tree, tree, tree *, tree *); @@ -1148,7 +1148,7 @@ c_fully_fold (tree expr, bool in_init, bool *maybe_const) expr = TREE_OPERAND (expr, 0); } ret = c_fully_fold_internal (expr, in_init, maybe_const, - &maybe_const_itself); + &maybe_const_itself, false); if (eptype) ret = fold_convert_loc (loc, eptype, ret); *maybe_const &= maybe_const_itself; @@ -1161,11 +1161,13 @@ c_fully_fold (tree expr, bool in_init, bool *maybe_const) arithmetic overflow (for C90, *MAYBE_CONST_OPERANDS is carried from both evaluated and unevaluated subexpressions while *MAYBE_CONST_ITSELF is carried from only evaluated - subexpressions). */ + subexpressions). FOR_INT_CONST indicates if EXPR is an expression + with integer constant operands, and if any of the operands doesn't + get folded to an integer constant, don't fold the expression itself. */ static tree c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands, - bool *maybe_const_itself) + bool *maybe_const_itself, bool for_int_const) { tree ret = expr; enum tree_code code = TREE_CODE (expr); @@ -1209,7 +1211,11 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands, if (C_MAYBE_CONST_EXPR_NON_CONST (expr)) *maybe_const_operands = false; if (C_MAYBE_CONST_EXPR_INT_OPERANDS (expr)) - *maybe_const_itself = false; + { + *maybe_const_itself = false; + inner = c_fully_fold_internal (inner, in_init, maybe_const_operands, + maybe_const_itself, true); + } if (pre && !in_init) ret = build2 (COMPOUND_EXPR, TREE_TYPE (expr), pre, inner); else @@ -1259,7 +1265,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands, op1 = TREE_OPERAND (expr, 1); op2 = TREE_OPERAND (expr, 2); op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands, - maybe_const_itself); + maybe_const_itself, for_int_const); STRIP_TYPE_NOPS (op0); if (op0 != orig_op0) ret = build3 (COMPONENT_REF, TREE_TYPE (expr), op0, op1, op2); @@ -1276,10 +1282,10 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands, op2 = TREE_OPERAND (expr, 2); op3 = TREE_OPERAND (expr, 3); op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands, - maybe_const_itself); + maybe_const_itself, for_int_const); STRIP_TYPE_NOPS (op0); op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands, - maybe_const_itself); + maybe_const_itself, for_int_const); STRIP_TYPE_NOPS (op1); op1 = decl_constant_value_for_optimization (op1); if (op0 != orig_op0 || op1 != orig_op1) @@ -1336,7 +1342,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands, orig_op0 = op0 = TREE_OPERAND (expr, 0); orig_op1 = op1 = TREE_OPERAND (expr, 1); op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands, - maybe_const_itself); + maybe_const_itself, for_int_const); STRIP_TYPE_NOPS (op0); if (code != MODIFY_EXPR && code != PREDECREMENT_EXPR @@ -1348,9 +1354,14 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands, expression for the sake of conversion warnings. */ if (code != MODIFY_EXPR) op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands, - maybe_const_itself); + maybe_const_itself, for_int_const); STRIP_TYPE_NOPS (op1); op1 = decl_constant_value_for_optimization (op1); + + if (for_int_const && (TREE_CODE (op0) != INTEGER_CST + || TREE_CODE (op1) != INTEGER_CST)) + goto out; + if (op0 != orig_op0 || op1 != orig_op1 || in_init) ret = in_init ? fold_build2_initializer_loc (loc, code, TREE_TYPE (expr), op0, op1) @@ -1420,10 +1431,14 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands, /* Unary operations. */ orig_op0 = op0 = TREE_OPERAND (expr, 0); op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands, - maybe_const_itself); + maybe_const_itself, for_int_const); STRIP_TYPE_NOPS (op0); if (code != ADDR_EXPR && code != REALPART_EXPR && code != IMAGPART_EXPR) op0 = decl_constant_value_for_optimization (op0); + + if (for_int_const && TREE_CODE (op0) != INTEGER_CST) + goto out; + /* ??? Cope with user tricks that amount to offsetof. The middle-end is not prepared to deal with them if they occur in initializers. */ if (op0 != orig_op0 @@ -1468,17 +1483,25 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands, arguments. */ orig_op0 = op0 = TREE_OPERAND (expr, 0); orig_op1 = op1 = TREE_OPERAND (expr, 1); - op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self); + op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self, + for_int_const); STRIP_TYPE_NOPS (op0); unused_p = (op0 == (code == TRUTH_ANDIF_EXPR ? truthvalue_false_node : truthvalue_true_node)); c_disable_warnings (unused_p); - op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self); + op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self, + for_int_const); STRIP_TYPE_NOPS (op1); c_enable_warnings (unused_p); + if (for_int_const + && (TREE_CODE (op0) != INTEGER_CST + /* Require OP1 be an INTEGER_CST only if it's evaluated. */ + || (!unused_p && TREE_CODE (op1) != INTEGER_CST))) + goto out; + if (op0 != orig_op0 || op1 != orig_op1 || in_init) ret = in_init ? fold_build2_initializer_loc (loc, code, TREE_TYPE (expr), op0, op1) @@ -1506,19 +1529,30 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands, orig_op0 = op0 = TREE_OPERAND (expr, 0); orig_op1 = op1 = TREE_OPERAND (expr, 1); orig_op2 = op2 = TREE_OPERAND (expr, 2); - op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self); + op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self, + for_int_const); STRIP_TYPE_NOPS (op0); c_disable_warnings (op0 == truthvalue_false_node); - op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self); + op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self, + for_int_const); STRIP_TYPE_NOPS (op1); c_enable_warnings (op0 == truthvalue_false_node); c_disable_warnings (op0 == truthvalue_true_node); - op2 = c_fully_fold_internal (op2, in_init, &op2_const, &op2_const_self); + op2 = c_fully_fold_internal (op2, in_init, &op2_const, &op2_const_self, + for_int_const); STRIP_TYPE_NOPS (op2); c_enable_warnings (op0 == truthvalue_true_node); + if (for_int_const + && (TREE_CODE (op0) != INTEGER_CST + /* Only the evaluated operand must be an INTEGER_CST. */ + || (op0 == truthvalue_true_node + ? TREE_CODE (op1) != INTEGER_CST + : TREE_CODE (op2) != INTEGER_CST))) + goto out; + if (op0 != orig_op0 || op1 != orig_op1 || op2 != orig_op2) ret = fold_build3_loc (loc, code, TREE_TYPE (expr), op0, op1, op2); else diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index f1c40738b41..ebf9759bc9b 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,10 @@ +2015-05-14 Marek Polacek + + PR c/66066 + PR c/66127 + * c-typeck.c (digest_init): Call pedwarn_init with OPT_Wpedantic + rather than with 0. + 2015-05-12 David Malcolm * c-parser.c (c_parser_if_body): Add param "if_loc", use it diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 3fcb7c2c5e7..9b883a22f2b 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -6864,7 +6864,7 @@ digest_init (location_t init_loc, tree type, tree init, tree origtype, inside_init = error_mark_node; } else if (require_constant && !maybe_const) - pedwarn_init (init_loc, 0, + pedwarn_init (init_loc, OPT_Wpedantic, "initializer element is not a constant expression"); /* Added to enable additional -Wsuggest-attribute=format warnings. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5daa442ba99..ef46d503bf5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2015-05-14 Marek Polacek + + PR c/66066 + PR c/66127 + * gcc.dg/pr14649-1.c: Add -Wpedantic. + * gcc.dg/pr19984.c: Likewise. + * gcc.dg/pr66066-1.c: New test. + * gcc.dg/pr66066-2.c: New test. + * gcc.dg/pr66066-3.c: New test. + 2015-05-13 Kyrylo Tkachov * gcc.target/aarch64/pow-sqrt-synth-1.c: New test. diff --git a/gcc/testsuite/gcc.dg/pr14649-1.c b/gcc/testsuite/gcc.dg/pr14649-1.c index 34f42f08f2c..b9fc4b94616 100644 --- a/gcc/testsuite/gcc.dg/pr14649-1.c +++ b/gcc/testsuite/gcc.dg/pr14649-1.c @@ -1,6 +1,6 @@ /* PR c/14649 */ /* { dg-do compile } */ -/* { dg-options "-O2" } */ +/* { dg-options "-O2 -Wpedantic" } */ double atan(double); diff --git a/gcc/testsuite/gcc.dg/pr19984.c b/gcc/testsuite/gcc.dg/pr19984.c index 5323c461fb0..a628e0e91ea 100644 --- a/gcc/testsuite/gcc.dg/pr19984.c +++ b/gcc/testsuite/gcc.dg/pr19984.c @@ -1,6 +1,6 @@ /* PR c/19984 */ /* { dg-do compile } */ -/* { dg-options "-O2 -std=c99" } */ +/* { dg-options "-O2 -std=c99 -Wpedantic" } */ double nan (const char *); diff --git a/gcc/testsuite/gcc.dg/pr66066-1.c b/gcc/testsuite/gcc.dg/pr66066-1.c new file mode 100644 index 00000000000..7a1d342c808 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr66066-1.c @@ -0,0 +1,37 @@ +/* PR c/66066 */ +/* { dg-do compile } */ +/* { dg-options "-Wno-div-by-zero" } */ + +/* Accept these unless -pedantic-errors/-Werror. */ +int a1 = -1 << 0; +int a2 = -1 << 0 | 0; +int a3 = -1 << 0 & 1; +int a4 = -1 << 2 ^ 1; +int a5 = 4 & -1 << 2; +int a6 = (-1 << 2) ^ (1 >> 1); +int a7 = 0 || (-1 << 1); +int a8 = 0 ? 2 : (-1 << 1); +int a9 = 1 && -1 << 0; +int a10 = !(-1 << 0); + +/* Don't accept these. */ +int b1 = 1 / 0; /* { dg-error "initializer element is not constant" } */ +int b2 = 1 / (1 / 0); /* { dg-error "initializer element is not constant" } */ +int b3 = 0 ? 2 : 1 / 0; /* { dg-error "initializer element is not constant" } */ +int b4 = 0 || 1 / 0; /* { dg-error "initializer element is not constant" } */ +int b5 = 0 * (1 / 0); /* { dg-error "initializer element is not constant" } */ +int b6 = 1 * (1 / 0); /* { dg-error "initializer element is not constant" } */ +int b7 = (1 / 0) * 0; /* { dg-error "initializer element is not constant" } */ +int b8 = (1 / 0) * 1; /* { dg-error "initializer element is not constant" } */ +int b9 = 1 && 1 / 0; /* { dg-error "initializer element is not constant" } */ +int b10 = !(1 / 0); /* { dg-error "initializer element is not constant" } */ +int c1 = 1 % 0; /* { dg-error "initializer element is not constant" } */ +int c2 = 1 / (1 % 0); /* { dg-error "initializer element is not constant" } */ +int c3 = 0 ? 2 : 1 % 0; /* { dg-error "initializer element is not constant" } */ +int c4 = 0 || 1 % 0; /* { dg-error "initializer element is not constant" } */ +int c5 = 0 * (1 % 0); /* { dg-error "initializer element is not constant" } */ +int c6 = 1 * (1 % 0); /* { dg-error "initializer element is not constant" } */ +int c7 = (1 % 0) * 0; /* { dg-error "initializer element is not constant" } */ +int c8 = (1 % 0) * 1; /* { dg-error "initializer element is not constant" } */ +int c9 = 1 && 1 % 0; /* { dg-error "initializer element is not constant" } */ +int c10 = !(1 % 0); /* { dg-error "initializer element is not constant" } */ diff --git a/gcc/testsuite/gcc.dg/pr66066-2.c b/gcc/testsuite/gcc.dg/pr66066-2.c new file mode 100644 index 00000000000..848fe854bf8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr66066-2.c @@ -0,0 +1,37 @@ +/* PR c/66066 */ +/* { dg-do compile } */ +/* { dg-options "-Wno-div-by-zero -Wpedantic" } */ + +/* Accept these unless -pedantic-errors/-Werror. */ +int a1 = -1 << 0; /* { dg-warning "initializer element is not a constant expression" } */ +int a2 = -1 << 0 | 0; /* { dg-warning "initializer element is not a constant expression" } */ +int a3 = -1 << 0 & 1; /* { dg-warning "initializer element is not a constant expression" } */ +int a4 = -1 << 2 ^ 1; /* { dg-warning "initializer element is not a constant expression" } */ +int a5 = 4 & -1 << 2; /* { dg-warning "initializer element is not a constant expression" } */ +int a6 = (-1 << 2) ^ (1 >> 1); /* { dg-warning "initializer element is not a constant expression" } */ +int a7 = 0 || (-1 << 1); /* { dg-warning "initializer element is not a constant expression" } */ +int a8 = 0 ? 2 : (-1 << 1); /* { dg-warning "initializer element is not a constant expression" } */ +int a9 = 1 && -1 << 0; /* { dg-warning "initializer element is not a constant expression" } */ +int a10 = !(-1 << 0); /* { dg-warning "initializer element is not a constant expression" } */ + +/* Don't accept these. */ +int b1 = 1 / 0; /* { dg-error "initializer element is not constant" } */ +int b2 = 1 / (1 / 0); /* { dg-error "initializer element is not constant" } */ +int b3 = 0 ? 2 : 1 / 0; /* { dg-error "initializer element is not constant" } */ +int b4 = 0 || 1 / 0; /* { dg-error "initializer element is not constant" } */ +int b5 = 0 * (1 / 0); /* { dg-error "initializer element is not constant" } */ +int b6 = 1 * (1 / 0); /* { dg-error "initializer element is not constant" } */ +int b7 = (1 / 0) * 0; /* { dg-error "initializer element is not constant" } */ +int b8 = (1 / 0) * 1; /* { dg-error "initializer element is not constant" } */ +int b9 = 1 && 1 / 0; /* { dg-error "initializer element is not constant" } */ +int b10 = !(1 / 0); /* { dg-error "initializer element is not constant" } */ +int c1 = 1 % 0; /* { dg-error "initializer element is not constant" } */ +int c2 = 1 / (1 % 0); /* { dg-error "initializer element is not constant" } */ +int c3 = 0 ? 2 : 1 % 0; /* { dg-error "initializer element is not constant" } */ +int c4 = 0 || 1 % 0; /* { dg-error "initializer element is not constant" } */ +int c5 = 0 * (1 % 0); /* { dg-error "initializer element is not constant" } */ +int c6 = 1 * (1 % 0); /* { dg-error "initializer element is not constant" } */ +int c7 = (1 % 0) * 0; /* { dg-error "initializer element is not constant" } */ +int c8 = (1 % 0) * 1; /* { dg-error "initializer element is not constant" } */ +int c9 = 1 && 1 % 0; /* { dg-error "initializer element is not constant" } */ +int c10 = !(1 % 0); /* { dg-error "initializer element is not constant" } */ diff --git a/gcc/testsuite/gcc.dg/pr66066-3.c b/gcc/testsuite/gcc.dg/pr66066-3.c new file mode 100644 index 00000000000..99ffec62556 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr66066-3.c @@ -0,0 +1,37 @@ +/* PR c/66066 */ +/* { dg-do compile } */ +/* { dg-options "-Wno-div-by-zero -pedantic-errors" } */ + +/* Accept these unless -pedantic-errors/-Werror. */ +int a1 = -1 << 0; /* { dg-error "initializer element is not a constant expression" } */ +int a2 = -1 << 0 | 0; /* { dg-error "initializer element is not a constant expression" } */ +int a3 = -1 << 0 & 1; /* { dg-error "initializer element is not a constant expression" } */ +int a4 = -1 << 2 ^ 1; /* { dg-error "initializer element is not a constant expression" } */ +int a5 = 4 & -1 << 2; /* { dg-error "initializer element is not a constant expression" } */ +int a6 = (-1 << 2) ^ (1 >> 1); /* { dg-error "initializer element is not a constant expression" } */ +int a7 = 0 || (-1 << 1); /* { dg-error "initializer element is not a constant expression" } */ +int a8 = 0 ? 2 : (-1 << 1); /* { dg-error "initializer element is not a constant expression" } */ +int a9 = 1 && -1 << 0; /* { dg-error "initializer element is not a constant expression" } */ +int a10 = !(-1 << 0); /* { dg-error "initializer element is not a constant expression" } */ + +/* Don't accept these. */ +int b1 = 1 / 0; /* { dg-error "initializer element is not constant" } */ +int b2 = 1 / (1 / 0); /* { dg-error "initializer element is not constant" } */ +int b3 = 0 ? 2 : 1 / 0; /* { dg-error "initializer element is not constant" } */ +int b4 = 0 || 1 / 0; /* { dg-error "initializer element is not constant" } */ +int b5 = 0 * (1 / 0); /* { dg-error "initializer element is not constant" } */ +int b6 = 1 * (1 / 0); /* { dg-error "initializer element is not constant" } */ +int b7 = (1 / 0) * 0; /* { dg-error "initializer element is not constant" } */ +int b8 = (1 / 0) * 1; /* { dg-error "initializer element is not constant" } */ +int b9 = 1 && 1 / 0; /* { dg-error "initializer element is not constant" } */ +int b10 = !(1 / 0); /* { dg-error "initializer element is not constant" } */ +int c1 = 1 % 0; /* { dg-error "initializer element is not constant" } */ +int c2 = 1 / (1 % 0); /* { dg-error "initializer element is not constant" } */ +int c3 = 0 ? 2 : 1 % 0; /* { dg-error "initializer element is not constant" } */ +int c4 = 0 || 1 % 0; /* { dg-error "initializer element is not constant" } */ +int c5 = 0 * (1 % 0); /* { dg-error "initializer element is not constant" } */ +int c6 = 1 * (1 % 0); /* { dg-error "initializer element is not constant" } */ +int c7 = (1 % 0) * 0; /* { dg-error "initializer element is not constant" } */ +int c8 = (1 % 0) * 1; /* { dg-error "initializer element is not constant" } */ +int c9 = 1 && 1 % 0; /* { dg-error "initializer element is not constant" } */ +int c10 = !(1 % 0); /* { dg-error "initializer element is not constant" } */ -- 2.30.2