The original error is seen on https://www.dolphin-emu.org/ project as a build error. Minimized example looks the following: """ // $ cat.bug.cc struct a { int b; char c[100]; }; unsigned long d(long e) { return __builtin_offsetof(a, c[e]); } """ OK: $ LANG=C g++-10.1.0 -c bug.cc -o bug.o OK: $ LANG=C clang++-10 -c bug.cc -o bug.o FAIL: $ LANG=C g++-11.0.0 -c bug.cc -o bug.o bug.cc: In function 'void d(long int)': bug.cc:8:42: error: 'e' is not a constant expression 8 | void d(long e) { __builtin_offsetof(a, c[e]); } | Who is wrong here? gcc-10 or gcc-11?
Original code looks is at https://github.com/dolphin-emu/dolphin/blob/2e8d1dd1dbcca7095e9d842f1df037cbe76868e4/Source/Core/Core/DSP/Jit/x64/DSPEmitter.cpp#L476: """ ... Gen::OpArg DSPEmitter::M_SDSP_r_st(size_t index) { return MDisp(R15, static_cast<int>(offsetof(SDSP, r.st[index]))); } ... """
Changed in r11-557-gbeb019d346b903c16b9fd349937de444b6a8b6c0
Another example is edb-debugger project https://github.com/eteran/edb-debugger/blob/070d0196227a58ce2ba15c695944ba16ce66c080/plugins/DebuggerCore/unix/linux/arch/x86-generic/PlatformThread.cpp#L331: long PlatformThread::setDebugRegister(std::size_t n, unsigned long value) { return ptrace(PTRACE_POKEUSER, tid_, offsetof(struct user, u_debugreg[n]), value); } Fails build on gcc-11 as: edb-debugger/plugins/DebuggerCore/unix/linux/arch/x86-generic/PlatformThread.cpp:331:72: error: 'n' is not a constant expression 331 | return ptrace(PTRACE_POKEUSER, tid_, offsetof(struct user, u_debugreg[n]), value); | ^
struct S { int a; int b[15]; }; int foo (int n) { int m = n; return __builtin_offsetof (S, b[m]); } has been rejected for years, while struct S { int a; int b[15]; }; int foo (int n) { return __builtin_offsetof (S, b[n]); } has been accepted. The comment in cp/parser.c says: /* ??? For offsetof, there is a question of what to allow here. If offsetof is not being used in an integral constant expression context, then we *could* get the right answer by computing the value at runtime. If we are in an integral constant expression context, then we might could accept any constant expression; hard to say without analysis. Rather than open the barn door too wide right away, allow only integer constant expressions here. */
C11 says, ....and offsetof(type, member-designator) which expands to an integer constant expression that has type size_t, the value of which is the offset in bytes, to the structure member (designated by member-designator), from the beginning of its structure (designated by type). The type and member designator shall be such that given static type t; then the expression &(t.member-designator) evaluates to an address constant. (If the specified member is a bit-field, the behavior is undefined.) And __builtin_offsetof is only documented to be usable as an implementation of the offsetof macro. Since e is not constant, the expression above is not an address constant, so the offsetof expression is ill-formed. The change mentioned in comment #2 fixed this and various related issues with wrongly treating parameters as sufficiently constant.
Thank you! I'll report the bugs to affected upstreams.
*** Bug 100296 has been marked as a duplicate of this bug. ***
*** Bug 113804 has been marked as a duplicate of this bug. ***