[Clang] Missing constraint diagnostic for string literal initializer targeting a char subobject reached via designator
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
Tested locally on version 18.1.3 and on godbolt with version "trunk".
Clang accepts a program that appears to violate the scalar-initializer constraint in C17 6.7.9p11, even when compiled with `-std=c17 -pedantic`. GCC also accepts the program, but initializes the object differently.
### Reproducer:
```c
#include
struct {
char str[16];
} hello = {
"hello world",
.str[6] = 'W',
"ORLD"
};
int main(void) {
printf("hello.str = \"%s\"\n", hello.str);
printf("raw bytes: ");
for (int i = 0; i < 16; i++) {
printf("%d ", (unsigned char)hello.str[i]);
}
printf("\n");
return 0;
}
```
Godbolt link: https://godbolt.org/z/qK19WzT97
### Expected behavior:
This program should be rejected with a constraint diagnostic.
After `"hello world"` initializes `str`, the designator `.str[6] = 'W'` sets `str[6]`, and ISO/IEC 9899:2018 6.7.9p17 says that "initialization then continues forward in order, beginning with the next subobject after that described by the designator" -- i.e., `str[7]`, a `char`. The next initializer `"ORLD"` is a string literal of type `char[5]`, which is not a valid initializer for a scalar per 6.7.9p11: "The initializer for a scalar shall be a single expression [...] the same type constraints and conversions as for simple assignment apply."
Paragraph 14 authorizes a string literal to initialize an array of character type, but `str[7]` is not an array, so p14 does not apply at this position.
### Actual behavior:
Clang accepts the program and produces:
```
hello.str = "hello WORLD"
raw bytes: 104 101 108 108 111 32 87 79 82 76 68 0 0 0 0 0
```
It treats `"ORLD"` as continuing character-by-character from `str[7]`, preserving `"hello "` and the designated `'W'`.
### GCC behavior:
Like Clang, GCC accepts the program without a constraint diagnostic, but produces different output:
```
hello.str = "ORLD"
raw bytes: 79 82 76 68 0 0 0 0 0 0 0 0 0 0 0 0
```
That is, the string literal `"ORLD"` is treated as a fresh whole-array initializer for `str`, restarting at index 0 and clobbering both the earlier `"hello world"` and the designated `'W'` at `str[6]`. A separate bug report will be filed with GCC.
Contributor guide
Assessment
This issue has not been assessed yet.