Bug 95942 - [11 regression] offsetof on an array: error: 'e' is not a constant expression
Summary: [11 regression] offsetof on an array: error: 'e' is not a constant expression
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 11.0
: P1 normal
Target Milestone: 11.0
Assignee: Not yet assigned to anyone
URL:
Keywords: rejects-valid
: 100296 113804 (view as bug list)
Depends on:
Blocks:
 
Reported: 2020-06-27 18:22 UTC by Sergei Trofimovich
Modified: 2024-02-07 15:06 UTC (History)
8 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2020-07-15 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Sergei Trofimovich 2020-06-27 18:22:43 UTC
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?
Comment 1 Sergei Trofimovich 2020-06-27 18:29:03 UTC
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])));
}
...
"""
Comment 2 Marek Polacek 2020-06-27 18:34:15 UTC
Changed in r11-557-gbeb019d346b903c16b9fd349937de444b6a8b6c0
Comment 3 Sergei Trofimovich 2020-07-15 20:56:47 UTC
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);
        |                                       ^
Comment 4 Jakub Jelinek 2020-07-15 21:09:40 UTC
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.  */
Comment 5 Jason Merrill 2020-10-15 16:45:52 UTC
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.
Comment 6 Sergei Trofimovich 2020-10-15 21:40:26 UTC
Thank you! I'll report the bugs to affected upstreams.
Comment 7 Jakub Jelinek 2021-04-27 19:39:33 UTC
*** Bug 100296 has been marked as a duplicate of this bug. ***
Comment 8 Andrew Pinski 2024-02-07 15:06:10 UTC
*** Bug 113804 has been marked as a duplicate of this bug. ***