On Fri, 4 Nov 2011, Andrew MacLeod wrote:

> > Given that C and C++ allow variable arguments to the standard type-generic
> > macros/functions, it is also presumably OK - only undefined at runtime -
> > for a constant memory model argument of the correct type to have a value
> > representable in that type that isn't actually a valid memory model.  And
> > so this should generate a warning, not an error (ideally generating a trap
> > and an informative note that such a trap has been generated - remember
> > that the side-effects of the function arguments must be evaluated before
> > the trap, in case an argument exits the program, as in
> > gcc.c-torture/execute/{call-trap-1.c,va-arg-trap-1.c}).
> > 
> I don't think I agree.  All the __atomic operations are noexcept, so they
> can't throw.   We currently default unknown runtime values to seq-cst for

That they can't throw is true but irrelevant (the arguments to them - 
addresses of objects being operated on - can throw while being evaluated, 
and one of my points was that if you do generate a trap for execution-time 
undefined behavior that therefore needs to come after argument 
evaluation).

> inlined atomics, and presumably the library will also implement any unknown
> value as seq-cst.  There are very explicit enumerated types to be used, and I
> do not think its unreasonable to issue an error if someone provides an out of
> range value which can be determined at compile time.

It seems clear to me that

  if (0) call-with-non-const-argument ();

and

  if (0) call-with-const-argument ();

are exactly the same, supposing the arguments have the same types, and 
given that the first is valid (without depending on whether the compiler 
can work out the argument with constant propagation), the second is also 
valid if the argument has the right enum type even if the value is not one 
of the valid values (recall that for C an enum may have any value of the 
underlying integer type, typically unsigned int; for C++ it may at least 
have any value that can be represented with the bits set in any of the 
enumeration constants).  This is just the same as

  if (0) va_arg (ap, float);

being valid, though an execution of such a va_arg call will result in 
undefined behavior - and

  va_arg (*(exit (0), &ap), float);

also being valid on execution - exiting before the undefined behavior 
would otherwise occur.

DR#109 applies: "A conforming implementation must not fail to translate a 
strictly conforming program simply because some possible execution of that 
program would result in undefined behavior.".  The value of a function 
parameter (that has the right type) is a property of the execution of the 
program and undefined behavior occurs when the call is executed, after its 
arguments have been evaluated.

Generating a warning instead of an error and changing the constant to a 
valid one is probably the simplest fix (although generating a trap as 
well, after the arguments are evaluated, would be existing practice in 
GCC).

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

Reply via email to