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