On Mon, 11 May 2015, Marek Polacek wrote:

> The problem here isn't in the -Wshift-negative-value warning itself; the
> problem is with marking -1 << 0 as a non-constant: later on, we warn in
> a context where a constant expression is needed ("initializer element is
> not a constant expression"), and for e.g. int foo = -1 << 0 | 9; there's
> an error ("initializer element is not constant").

For cases that are not integer constant expressions but can be folded to 
constants (e.g. where the unevaluated half of ?: contains a function call, 
which is not allowed in constant expressions), the general approach is a 
pedwarn-if-pedantic, e.g.:

          if (TREE_CODE (value) != INTEGER_CST)
            {
              value = c_fully_fold (value, false, NULL);
              if (TREE_CODE (value) == INTEGER_CST)
                pedwarn (loc, OPT_Wpedantic,
                         "enumerator value for %qE is not an integer "
                         "constant expression", name);
            }
          if (TREE_CODE (value) != INTEGER_CST)
            {
              error ("enumerator value for %qE is not an integer constant",
                     name);
              value = 0;
            }

(and similar for various cases other than enums - it turns out the Linux 
kernel has or had lots of cases that aren't strictly integer constant 
expressions but are used in contexts requiring such).

So I think the issue here is that the above expression isn't folded to a 
constant by c_fully_fold.  If the expression involves division by zero, 
say, clearly it's appropriate not to fold; no meaningful result value can 
be assigned.  But for the above expression, a meaningful result can be 
assigned, so it would seem to make sense to fold.  That is, it would make 
sense for c_fully_fold_internal to fold inside a C_MAYBE_CONST_EXPR with 
C_MAYBE_CONST_EXPR_INT_OPERANDS set, in the cases where meaningful results 
can be assigned.

The rationale for not folding the contents of a C_MAYBE_CONST_EXPR in 
c_fully_fold is that folding already took place when the 
C_MAYBE_CONST_EXPR was created, and it's inefficient to potentially fold 
the same expression recursively many times.  But that's only the case for 
"normal" C_MAYBE_CONST_EXPRs, not those with 
C_MAYBE_CONST_EXPR_INT_OPERANDS set that indicate something that could 
occur an unevaluated part of an integer constant expression.  And in any 
case, if folding had already occurred, there would already be the 
potential for duplicate folding through the existing uses of 
remove_c_maybe_const_expr.

Thus I think this issue should be addressed through folding in 
c_fully_fold_internal in this case, while watching carefully to make sure 
it doesn't reduce any other cases (division by zero, negative or out of 
range shift, overflows) to pedwarns-if-pedantic if they aren't already.

There would then remain the matter of "initializer element is not a 
constant expression" being an unconditional pedwarn_init rather than a 
pedwarn-if-pedantic, so I think you'd still get warnings that couldn't be 
disabled for the above code (which would turn into errors with -Werror).  
The answer for that is probably to make this pedwarn_init use 
OPT_Wpedantic, consistent with the various other cases that handle things 
that aren't constant expressions but folded to constants.

-- 
Joseph S. Myers
jos...@codesourcery.com

Reply via email to