llvm / llvm/llvm-project

[Clang] Missing constraint diagnostic for string literal initializer targeting a char subobject reached via designator

Open
#190,858 8 comments 0 reactions 0 assignees View on GitHub
c99 clang:frontend waiting-for-wg14
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.