testcase, compile with -pedantic-errors (we don't reject it overwise in 4.3): unsigned char p; unsigned char p1 = p & 512; ------------- cut ------- We get: overflow-warn-5.c:7: warning: overflow in implicit constant conversion overflow-warn-5.c:7: error: overflow in constant expression Now there is an overflow but only because we optimize the IR (unsigned char)(((int)p)& 512) into: p & (unsigned char)512 and (unsigned char)512 is converted into 0 (with overflow) so we have p & 0 which is then optimized into 0(with overflow). So we are only rejecting this because of the overflow due to the conversion (which was due to fold). We don't reject as invalid code either: unsigned char p; unsigned char p1 = p & 0;
Note this was found while trying to fix PR 32628. The diagnostic issue is at least a regression from 4.0.1. Well and the accepts invalid (without -pedantic-errors for the first testcase). The second testcase was accepted wrongly in 4.0.1 also.
This quick hack fixes the problem for both testcases (the fold-const part is the only part required to fix the second testcase); Index: fold-const.c =================================================================== --- fold-const.c (revision 126396) +++ fold-const.c (working copy) @@ -3278,7 +3278,7 @@ { tree t = fold_convert (type, result); - if (TREE_SIDE_EFFECTS (omitted)) + if (folding_initializer || TREE_SIDE_EFFECTS (omitted)) return build2 (COMPOUND_EXPR, type, fold_ignored_result (omitted), t); return non_lvalue (t); @@ -3291,7 +3291,7 @@ { tree t = fold_convert (type, result); - if (TREE_SIDE_EFFECTS (omitted)) + if (folding_initializer || TREE_SIDE_EFFECTS (omitted)) return build2 (COMPOUND_EXPR, type, fold_ignored_result (omitted), t); return pedantic_non_lvalue (t); @@ -14438,6 +14438,10 @@ tree fold_ignored_result (tree t) { + /* Just for now, if this is an initializer. */ + if (folding_initializer) + return t; + if (!TREE_SIDE_EFFECTS (t)) return integer_zero_node; Index: c-typeck.c =================================================================== --- c-typeck.c (revision 126396) +++ c-typeck.c (working copy) @@ -3783,7 +3783,8 @@ enum tree_code coder; tree rname = NULL_TREE; bool objc_ok = false; - + int old_folding_initializer; + if (errtype == ic_argpass || errtype == ic_argpass_nonproto) { tree selector; @@ -3918,13 +3919,29 @@ && (coder == INTEGER_TYPE || coder == REAL_TYPE || coder == ENUMERAL_TYPE || coder == COMPLEX_TYPE || coder == BOOLEAN_TYPE)) - return convert_and_check (type, rhs); + { + tree new; + old_folding_initializer = folding_initializer; + if (errtype == ic_init) + folding_initializer = 1; + new = convert_and_check (type, rhs); + folding_initializer = old_folding_initializer; + return new; + } /* Aggregates in different TUs might need conversion. */ if ((codel == RECORD_TYPE || codel == UNION_TYPE) && codel == coder && comptypes (type, rhstype)) - return convert_and_check (type, rhs); + { + tree new; + old_folding_initializer = folding_initializer; + if (errtype == ic_init) + folding_initializer = 1; + new = convert_and_check (type, rhs); + folding_initializer = old_folding_initializer; + return new; + } /* Conversion to a transparent union from its member types. This applies only to function arguments. */
(In reply to comment #0) > testcase, compile with -pedantic-errors (we don't reject it overwise in 4.3): > unsigned char p; > unsigned char p1 = p & 512; > > Now there is an overflow but only because we optimize the IR (unsigned > char)(((int)p)& 512) into: > p & (unsigned char)512 and (unsigned char)512 is converted into 0 (with > overflow) so we have p & 0 which is then optimized into 0(with overflow). So > we are only rejecting this because of the overflow due to the conversion (which > was due to fold). There should not be any overflow? So the result is wrong independently whether this is an initialization or not? The operation should be done with int, isn't it? BTW, you should get two warnings when using -pedantic. > We don't reject as invalid code either: > unsigned char p; > unsigned char p1 = p & 0; Why should we? There is no overflow here, you mean that p is not constant? I think we have two issues in the first testcase, one is folding (X op 0), the other is converting 512 to uchar before performing the operation. Am I wrong?
(In reply to comment #3) > > We don't reject as invalid code either: > > unsigned char p; > > unsigned char p1 = p & 0; > > Why should we? There is no overflow here, you mean that p is not constant? I > think we have two issues in the first testcase, one is folding (X op 0), the > other is converting 512 to uchar before performing the operation. Am I wrong? Yes, the converting 512 to uchar is a valid optimization. That is: (char)(((int) a) & b) is the same as: a & ((char)b) if a is of type char. as there are no overflow concerns with AND. The folding gets us to the case where we have "a & 0" which is not a valid constant initializer at all. Note I found this while working on fixing PR 32628, where the patch which fixes that caues us to no longer emit a warning/error for the first testcase.
Confirmed.
Adjusting target milestone.
4.3.1 is being released, adjusting target milestone.
4.3.2 is released, changing milestones to 4.3.3.
Andrew, what is the status of this? Joseph, Will this be fixed by your new code for 4.5?
Subject: Re: [4.2/4.3/4.4 Regression] Wrong error message with unsigned char a = uchar&512 On Mon, 3 Nov 2008, manu at gcc dot gnu dot org wrote: > Joseph, > > Will this be fixed by your new code for 4.5? As I said in <http://gcc.gnu.org/ml/gcc-patches/2008-10/msg01061.html>, that patch does not fix this bug.
GCC 4.3.3 is being released, adjusting target milestone.
GCC 4.3.4 is being released, adjusting target milestone.
GCC 4.3.5 is being released, adjusting target milestone.
Not fixed by the constant expression work either.
4.3 branch is being closed, moving to 4.4.7 target.
4.4 branch is being closed, moving to 4.5.4 target.
The 4.5 branch is being closed, adjusting target milestone.
GCC 4.6.4 has been released and the branch has been closed.
The 4.7 branch is being closed, moving target milestone to 4.8.4.
GCC 4.8.4 has been released.
Not to sound pedantic, but https://gcc.gnu.org/bugs/management.html says: The target milestone should be set to the next release of the newest active release branch that needs fixing (the rationale is that a patch will have to go to the newest release branch before any other release branch). Thus, I think it should still be 6.0 until 6.1 is released.
Ok, so I have a patch that makes the original testcase pass, by allowing folding in get_unwidened depening on a new arg. That was: unsigned char p; unsigned char p1 = p & 512; But, how about char p2 = p & 512; Are we supposed to still warn about this (we do, with the patch I have)? Probably not, right?
Bernd, intuitively, I would not expect a warning in the case you ask about. -Woverflow is documented to "warn about compile-time overflow in constant expressions." A strict reading of this single sentence would suggest that since none of the initialization expressions in the original test case is a constant expression no warning should be issued (and the initialization expressions should perhaps be diagnosed as not constant). Alternatively, the documentation for the warning should explain what GCC considers a constant expression (if more than what's required by the C standard) and in what contexts and under what circumstances (e.g., per Josephs's description in the post referenced in comment #10). Otherwise, what should or shouldn't be expected to be diagnosed is open to debate. FWIW, to illustrate, GCC rejects some expressions with an error and not others based on what it considers a constant expression (i.e., what it folds). In my view, that's more of a problem than the warning. $ cat t.c && gcc t.c unsigned char p; char p2 = p & 512; char p3 = p & 2; t.c:3:11: warning: overflow in implicit constant conversion [-Woverflow] char p2 = p & 512; ^ t.c:4:11: error: initializer element is not constant char p3 = p & 2; ^ With -Wpedantic there is also a redundant warning: t.c:3:11: warning: overflow in implicit constant conversion [-Woverflow] char p2 = p & 512; ^ t.c:3:1: warning: overflow in constant expression [-Woverflow] char p2 = p & 512; ^~~~ t.c:4:11: error: initializer element is not constant char p3 = p & 2; ^
GCC 7.1 has been released.
GCC 7.3 is being released, adjusting target milestone.
The GCC 7 branch is being closed, re-targeting to GCC 8.4.
GCC 8.4.0 has been released, adjusting target milestone.
Fixed on trunk sofar.
Sorry, wrong bug...
No change in GCC 11: $ cat pr32643.c && gcc -S -Wall -Wpedantic pr32643.c unsigned char p; unsigned char p1 = p & 512; pr32643.c:2:20: warning: overflow in conversion from ‘int’ to ‘unsigned char’ changes value from ‘(int)p & 512’ to ‘0’ [-Woverflow] 2 | unsigned char p1 = p & 512; | ^ pr32643.c:2:1: warning: overflow in constant expression [-Woverflow] 2 | unsigned char p1 = p & 512; | ^~~~~~~~
GCC 8 branch is being closed.
GCC 9.4 is being released, retargeting bugs to GCC 9.5.
GCC 9 branch is being closed
GCC 10.4 is being released, retargeting bugs to GCC 10.5.
GCC 10 branch is being closed.
GCC 11 branch is being closed.