https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116011
--- Comment #7 from Andrew Pinski <pinskia at gcc dot gnu.org> --- (In reply to Hubert Tong from comment #5) > I updated the summary title again to reflect that the issue is specific to > declaration matching. > > GCC does differentiate between &(T::x) and &T::x (except that it conflates > them when matching templated declarations. > > For example, the following compiles: > ``` > struct A { int x; }; > > char q(int *); > short q(int A::*); > > template <typename T> > constexpr int f1(char (*)[sizeof(q(&T::x))]) { return 1; } > > template <typename T> > constexpr int f2(char (*)[sizeof(q(&(T::x)))]) { return 2; } > > constexpr int g(char (*p)[sizeof(char)] = 0) { return f2<A>(p); } > constexpr int h(char (*p)[sizeof(short)] = 0) { return f1<A>(p); } > > static_assert(g() == 2, ""); > static_assert(h() == 1, ""); > ``` Those are all unevulated context.that is sizeof and decltype are both considered unevulated context. In them, gcc does not think &(T::x) and &T::x act differently. Gcc does the right thing outside of unevulated context though.