https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112521
Bug ID: 112521
Summary: __float128 miscompilation: assignment as an aggregate
field
Product: gcc
Version: 14.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: andrew at ziglang dot org
Target Milestone: ---
https://godbolt.org/z/3hfrTxvE3
typedef signed char i8;
typedef unsigned char u8;
typedef signed short int i16;
typedef unsigned short int u16;
typedef signed int i32;
typedef unsigned int u32;
typedef signed long int isize;
typedef unsigned long int usize;
typedef signed long long int i64;
typedef unsigned long long int u64;
typedef signed __int128 i128;
typedef unsigned __int128 u128;
typedef _Float16 f16;
typedef float f32;
typedef double f64;
typedef long double f80;
typedef __float128 f128;
extern void *memcpy(void *restrict, void const *restrict, usize);
struct Storage {
union {
f16 flt16;
f32 flt32;
f64 flt64;
f80 flt80;
f128 flt128;
} flt;
enum {
flt16,
flt32,
flt64,
flt80,
flt128,
} tag;
};
struct Storage readFromMemory(const u8 *buffer, u32 bits);
[[gnu::noinline]] struct Storage readFromMemory(const u8 *buffer, u32 bits) {
struct Storage storage1, storage2;
switch (bits) {
case 16: {
f16 flt;
memcpy(&flt, buffer, 2);
storage1.flt.flt16 = flt;
storage1.tag = flt16;
storage2 = storage1;
break;
}
case 32: {
f32 flt;
memcpy(&flt, buffer, 4);
storage1.flt.flt32 = flt;
storage1.tag = flt32;
storage2 = storage1;
break;
}
case 64: {
f64 flt;
memcpy(&flt, buffer, 8);
storage1.flt.flt64 = flt;
storage1.tag = flt64;
storage2 = storage1;
break;
}
case 80: {
f80 flt;
memcpy(&flt, buffer, 10);
storage1.flt.flt80 = flt;
storage1.tag = flt80;
storage2 = storage1;
break;
}
case 128: {
f128 flt;
memcpy(&flt, buffer, 16);
storage1.flt.flt128 = flt;
storage1.tag = flt128;
storage2 = storage1;
break;
}
default:
__builtin_unreachable();
}
return storage2;
}
extern int printf(const char *restrict format, ...);
int main() {
u8 buffer[16] =
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x3F};
struct Storage storage = readFromMemory(buffer, 128);
u64 repr[2];
memcpy(repr, &storage.flt.flt128, 16);
printf("0x%016llX%016llX\n", repr[1], repr[0]);
}
compile with gcc -O1. it prints 0x0040 however the
correct answer is 0x3FFF which is what clang
prints.