Martin Uecker
Blog
Contact/Impressum
Nested Functions with GCC and Clang
Martin Uecker, 2026-08-06
Introduction
Last time I discussed how one can use GCC's<br>nested functions for callbacks with requiring an executable stack. This will<br>be possible in GCC 17 with the help of two new built-in functions that provide<br>explicit access to the static chain and code pointer.
Today, I want to show two macros that I already use to implement nested functions<br>in a way that is portable across both GCC and Clang.
GCC 17: Nested Functions
To be able to use nested functions as callbacks without the need for trampolines or<br>executable stack, we used three macros to define a wide pointer<br>type and to wrap the new built-in functions.
#define wide(T) struct wide_##T { typeof(T) *code; void *chain; }<br>#define CALL(ptr, args) __builtin_call_with_static_chain(ptr.code(args), ptr.chain)<br>#define CLOSURE(T, x) (wide(T)){ __builtin_call_code_address(x), __builtin_call_static_chain(x) }
Our toy example then looks quite nice.
typedef int cb_f(int y);
int baz(wide(cb_f) p, int x)<br>return CALL(p, (x));
int foo(int k)<br>int bar(int x) { return k + x; }<br>return baz(CLOSURE(cb_f, bar), 2 * k);
Somewhat Portable Nested Functions
We now add versions of the macros that allow us to compile the code using Clang's<br>Blocks extension and on older versions of GCC using trampolines (next time I will<br>explain a hack how trampolines can be avoided even on old versions of GCC).<br>As Blocks comes with a built-in wide pointer type with function call<br>semantics, the corresponding macros essentially become no-ops, while<br>a new NESTED macro which is a no-op on GCC defines a named wide pointer variable<br>on Clang using Blocks syntax.
#ifndef __clang__<br>#if __GNUC__<br>The following version compiles on both GCC and Clang<br>(Godbolt Example).<br>Note that an additional semicolon is required after the definition<br>of the nested function which luckily is ignored by GCC.
typedef int cb_f(int y);
int baz(wide(cb_f) p, int x)<br>return CALL(p, (x));
int foo(int k)<br>NESTED(int, bar, (int x))<br>return k + x;<br>};<br>return baz(CLOSURE(cb_f, bar), 2 * k);
Caveats for Clang
While this is quite nice, there are still some annoying limitations related<br>to the Blocks extension.
The most annoying limitation is that arrays in the parent function can not be<br>accessed when using Blocks (Godbolt Example).
Another limitation is that variables automatically become read-only if not<br>marked with the __block keyword (Godbolt Example).<br>This keyword then has to be hidden in a macro which expands to nothing on GCC.<br>Also note that despite being read-only the type of the variable does not become const-qualified.
Finally, to be able to invoke a nested function recursively, the variable<br>defined for the function itself needs to be marked with __block<br>iself, otherwise the program will be silently miscompiled<br>(Godbolt Example).
Literature
GCC, Nested Functions
GCC, Constructing Function Calls