Clang's support for aligned attributes on enums in C does not appear to have been thought through
- Dominant language
- LLVM
- Stars
- 40.5k
- Forks
- 18.7k
- PR merge metrics
- PR metrics pending
Description
This ticket is about the C compiler `clang`. I am no C++ expert, but it seems to me that enums in C++ are quite different from enums in C: this ticket is only about C. In C, each enum has a compatible integer type. For instance, with default settings, GCC and Clang both choose the compatible integer type `unsigned` for `enum E`:
```c
enum E { A, B };
```
It gets interesting when we write:
```c
enum __attribute__((aligned(8))) E1 { A1, B1 };
```
Compiler Explorer link: https://godbolt.org/z/hsvbn5jcx
Here the ideal compiler IMO would warn that the `aligned` attribute is ignored on `enum` declarations, because it only makes sense on struct members and possibly typedefs, and would then proceed to ignore the attribute. GCC appears to (but does not entirely, but that is for another ticket in another ticket system) ignore the attribute.
Both compilers continue to use `unsigned` as the compatible integer type for `enum E1`.
Clang attempts to honor the `aligned` attribute:
```c
int x = alignof(enum E1); // sets x to 8
enum E1 y; // generates .p2align 3, 0x0
```
However `enum E1` is still compatible with `unsigned`, and while distinct types with different levels of information about their layouts can be compatible (e.g. `int []` and `int [3]`), it seems in poor taste to have two distinct “compatible” types with known layouts that are different.
This results for instance in the following oddity (among others that could certainly be crafted):
```c
struct s { unsigned m; } s;
struct s { enum E1 m; }; // this is accepted and s has size 4
```
But at the same time:
```c
struct s { enum E1 m; };
struct s { unsigned m; } s; // this is accepted and s has size 8
```
The example above uses C23 struct redefinition in order to make the mismatch spectacular, but C23 struct redefinitions are likely not the problem here. The fundamental problem seems to be that `unsigned` and `enum E1` both are “compatible” in the sense of “compatible types” and also have each known, incompatible (in the layperson sense) layout.
(This issue was brought to my attention by my colleague @MisterDA)
Contributor guide
Assessment
This issue has not been assessed yet.