Keith Thompson <
Keith.S.T...@gmail.com> writes:
> Citations are from N1570 (C11 draft). I don't think there are any
> relevant differences in other editions or drafts of the standard.
>
> Quick summary: Why is
> int n = {{0}};
> undefined behavior rather than a constraint violation?
Because there is no practical benefit to changing what the
standard says now.
> 6.7.9 (Initialization) includes a list of constraints, starting
> with "No initializer shall attempt to provide a value for an
> object not contained within the entity being initialized."
>
> 6.7.9p11 says:
>
> The initializer for a scalar shall be a single expression,
> optionally enclosed in braces. The initial value of the
> object is that of the expression (after conversion); the same
> type constraints and conversions as for simple assignment
> apply, taking the type of the scalar to be the unqualified
> version of its declared type.
>
> (I presume that "optionally enclosed in braces" is not intended to
> permit more than one level of braces.)
>
> Both
> int n = 0;
> and
> int n = {0};
> are clearly valid, with identical semantics. But this:
> int n = {{0}};
> violates that requirement. Since the requirement is under
> Semantics, not Constraints, code that violates it has undefined
> behavior. Starting with C99, this is mentioned in Annex J.
>
> My question: Why is this undefined behavior rather than a
> constraint violation?
There's no practical benefit to changing it. The current rule
has been in place since the original ANSI C standard, more than
30 years ago. Whatever the motivation may have been at that
time, there is no incentive to change the rules now; compilers
already give diagnostics in such cases, even though they don't
have to. Changing the rules would mean throwing away a degree
of freedom with no significant benefit.
> I suggest that moving that paragraph from Semantics to Constraints
> would be an improvement. Extra braces on a scalar initializer are
> easy to detect,
All work is easy if it's someone else who is doing it. Certainly
it would be easier just to leave things as is.
> and requiring a diagnostic should not be a significant burden,
This statement assumes other people have the same reaction that
you do. Not everyone does.
> and would promote consistency. [...]
There is already consistency. There is no evidence to suggest
that changing the standard would make a difference at all to what
code people write. Most people are driven by what warnings or
errors they get, and compilers already give these messages.
> With the current requirements, a compiler could quietly generate
> code to set n to 42, though I doubt that anyone would do that.
If such forms were constraint violations, compilers could give a
warning (which they already do), and then generate code to set n
to 42. In practical terms there is no difference from the
current situation.
> (I note that gcc issues a non-fatal warning with "-std=c17
> -pedantic-errors", while clang treats it as a fatal error.)
If anyone absolutely wants a diagnostic, they can simply compile
with gcc or clang.
Note that clang has a compiler option to turn off the diagnostic
for such cases. Presumably that option is there because some
people want to use it. Making double braces a constraint violation
would interfere with what they want to do. What is suggested as an
improvement looks like all downside and no upside.