I have code like this:
$ cat test.c
#include
typedef struct
{
const int x;
} SX;
static SX mksx(void)
{
return (SX) { .x = 10 };
}
The C99 standard says in 6.5.16:2:
An assignment operator shall have a modifiable lvalue as its left operand.
and in 6.3.2.1:1:
A modifiable lvalue is an lvalue that does not have array type, does not have an incomplete type, does not have a const-qualified type, and if it is a structure or union, does not have any member (including, recursively, any member or element of all contained aggregates or unions) with a const-qualified type.
So GCC is right to warn.
In addition, the clause 6.5.16:2 is in a “Constraints” section of the C99 standard, so a conforming compiler is required to emit a diagnostic for a program that breaks the clause. It is still undefined behavior: the compiler can still do what it wants after the diagnostic is emitted. But there has to be a message. In consequence, Clang is behaving in a non-conforming manner here.
const
variable can't be modified after initialization, otherwise it's undefined behavior.
Since it is undefined behavior, I think one can say both gcc and clang follow the standard. (Although gcc's choice seems better, it deserves a warning) (See EDIT below)
The only way to give the variable x
a value with defined behavior is to initialize it:
SX sx = { .x = 10 };
EDIT: As @Keith Thompson comments below, it's more than just undefined behavior in this case:
C99 §6.5.16 Assignment operators
Constraints
An assignment operator shall have a modifiable lvalue as its left operand.
This is a constraint, and according to:
C99 §5.1.1.3 Diagnostics
A conforming implementation shall produce at least one diagnostic message (identified in an implementation-defined manner) if a preprocessing translation unit or translation unit contains a violation of any syntax rule or constraint, even if the behavior is also explicitly specified as undefined or implementation-defined. Diagnostic messages need not be produced in other circumstances.
A compiler must issue a diagnostic for any program that violates a constraint.
Back to the question, gcc is correct is generate a warning, while clang fails to do so.