https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127096
Bug ID: 127096
Summary: [12.2 Regression] Wrong decltype((S::x)) in const
member function of unrelated class A
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: arthur.j.odwyer at gmail dot com
Target Milestone: ---
// https://godbolt.org/z/K951PhahT
template<class> int f();
struct S { int x; };
struct A { int g(); int g() const; };
struct B : S { int g(); int g() const; };
int A::g() { return f<decltype((S::x))>(); }
int A::g() const { return f<decltype((S::x))>(); }
int B::g() { return f<decltype((S::x))>(); }
int B::g() const { return f<decltype((S::x))>(); }
In GCC 12.1 and earlier, `int A::g() const` correctly calls `f<int&>`.
In GCC 12.2 and later, it wrongly calls `f<const int&>`, as if `A::g` were a
member of `S` or a class derived from `S`. That is, `A` starts behaving like
`B`!
The behavior of `A::g()`, `B::g()`, and `B::g() const` are all correct; it's
only `A::g() const` that inappropriately const-qualifies the type of an
unevaluated `S::x`.
The standard wording that makes this snippet (surprisingly) legal C++ is
[expr.prim.id]/4.3 ( https://eel.is/c++draft/expr.prim#id.general-4.3 ).