On Fri, Jan 02, 2026 at 10:45:29AM +0100, Jakub Jelinek wrote:
> Seems we already do support the gnu_inline extern inline behavior for
> namespace scope functions as well as member functions if just
> declared constexpr and gnu_inline inside of the class and defined
> extern constexpr right after the class (but the dtor if any needs to be
> defined first), e.g. -O2
Actually, I was wrong, as documented for C++ [[gnu::gnu_inline]] doesn't
even need the extern keyword.
So:
[[gnu::gnu_inline]] constexpr inline int foo (int x) { return x + 42; }
static_assert (foo (0) == 42);
int bar (int x) { return foo (x); }
auto p = &foo;
struct S {
[[gnu::gnu_inline]] constexpr inline int qux (int x) { return x + 42; }
[[gnu::gnu_inline]] constexpr inline virtual int garply (int x) { return x +
43; }
[[gnu::gnu_inline]] constexpr inline virtual ~S () {}
};
static_assert (S {}.qux (0) == 42);
static_assert (S {}.garply (0) == 43);
int freddy (S s, int x) { return s.qux (x); }
int corge (S s, int x) { return s.garply (x); }
auto q = &S::qux;
int plugh (S &s, int x) { return s.garply (x); }
//S s;
already works the intended way except for key method and the question how to
cleanly define the out-of-line copy of it.
For the key method, if people don't use gnu_inline attribute on virtual
methods in the wild perhaps we could just allow virtual methods with
gnu_inline attribute to be key methods. Because if people used it in the
wild, it wouldn't work very well before.
struct T {
[[gnu::gnu_inline]] virtual inline int garply (int x) { return x + 43; }
[[gnu::gnu_inline]] virtual inline ~T () {}
};
T t;
Without the explicit inline (or constexpr) keyword we get warnings:
/tmp/05.C:2:48: warning: ‘gnu_inline’ attribute ignored [-Wattributes]
2 | [[gnu::gnu_inline]] virtual int garply (int x) { return x + 43; }
| ^
/tmp/05.C:3:35: warning: ‘gnu_inline’ attribute ignored [-Wattributes]
3 | [[gnu::gnu_inline]] virtual ~T () {}
| ^
and with inline or constexpr we get the vtable/rtti emitted in the current
TU, but those refer to the methods that need to be defined somewhere else
with no clean way to define those right now.
Jakub