Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign up#[repr(C)] enum bit width determination algo does not match that of the C compiler #28925
Comments
This comment has been minimized.
This comment has been minimized.
|
Credit goes out to @retep998 for discovering this. |
mzabaluev
changed the title
`#[repr(C)]` enum bit width determination algo does not match that of the C compiler
#[repr(C)] enum bit width determination algo does not match that of the C compiler
Oct 12, 2015
This comment has been minimized.
This comment has been minimized.
briansmith
commented
Oct 22, 2015
|
See also |
This comment has been minimized.
This comment has been minimized.
|
@briansmith: I think |
huonw
added
A-ffi
T-compiler
labels
Jan 6, 2016
retep998
referenced this issue
Apr 13, 2016
Closed
The definition of Status will result in undefined behavior #1
This comment has been minimized.
This comment has been minimized.
briansmith
commented
May 27, 2016
I think what the C compiler does by default is sometimes determined by the ABI. For example, I believe sometimes GCC's default for that flag differs depending on how GCC was configured when it was built. IMO, instead of matching the default of "the" C compiler (in fact, there is often more than one C compiler, each of which may have a different default), Rust should default to matching the ABI. |
retep998
referenced this issue
Jul 4, 2016
Closed
size_of and initializer type mismatch for C enums #34641
This comment has been minimized.
This comment has been minimized.
|
I tripped over this while trying to add |
Mark-Simulacrum
added
the
C-feature-request
label
Jul 24, 2017
fitzgen
referenced this issue
Aug 14, 2017
Closed
Default to generating constified enums, rather than generating Rust enums #758
This comment has been minimized.
This comment has been minimized.
This by itself is arguably a bug, even on boring platforms like x86 Linux. Simple constructive proof: #include <stdio.h>
enum E {
L = 0,
H = 0x100000000
};
int main() {
printf("%zu > %zu\n", sizeof(enum E), sizeof(void*));
return 0;
}
That isn't portable ISO C, but GCC and Clang accept it without warnings unless The original discriminant sizing (and So, trying to summarize the problems here:
As for |
mzabaluev commentedOct 9, 2015
In C, support for enum determinants that cannot be represented by an
intis implementation-defined. Many compilers choose a different basic type for representation, based on the types or the values of the determinants. This is where the algorithm currently used by Rust for#[repr(C)]enums may differ from the one used by the C compiler, although the difference can be observed in fairly marginal cases.GCC uses the types of the determinant expressions to find the best fit, so this is a 32-bit type on 64-bit Linux:
Yet this is 64-bit:
This is because the type of integer constant
0x80000000is determined asunsigned intdue to its hexadecimal notation, and the negation preserves the type.Rust first coerces all discriminants to
isizeand then apparently works out the best fitting representation type from the value range, where fitting means that negative values are preserved as such. So this ends up being 64-bit:I'm uncertain as to which approach is the best for fixing this. Trying to match the behavior of C compilers quirk-for-quirk does not seem to be feasible: there may be more than one compiler per target, and in fact the behavior even changes with compiler options, as e.g. the type of an integer constant is determined differently pre-C99 and post-C99. Perhaps a more conservative solution would be to lint on discriminant values that are out of the
libc::c_intdomain and suggest using fixed-width representations such as#[repr(u32)].