diff --git a/internal/clang/emit.go b/internal/clang/emit.go index 2091f4b1..3484a994 100644 --- a/internal/clang/emit.go +++ b/internal/clang/emit.go @@ -127,8 +127,11 @@ func (g *Generator) emitImpl(w io.Writer) { g.emitEmbeds(w, g.embeds.impl) g.emitUnexportedTypes(w) g.emitResultTypes(w, false) - g.emitPackageVars(w) + // Forward func decls before package vars: a package-var initializer may + // reference a function (e.g. a func-typed struct field), and a function + // prototype never references a package var, so this order satisfies both. g.emitForwardFuncDecls(w) + g.emitPackageVars(w) multiFile := len(g.pkg.Syntax) > 1 if !multiFile { diff --git a/internal/clang/symbols.go b/internal/clang/symbols.go index 262b06bb..a8ae9f50 100644 --- a/internal/clang/symbols.go +++ b/internal/clang/symbols.go @@ -240,8 +240,9 @@ func (g *Generator) collectFuncDecl(d *ast.FuncDecl) { } // emitPackageVars writes all package-level variable and constant -// declarations at the top of the .c file, before forward declarations. -// This ensures they are defined before any function that references them. +// declarations at the top of the .c file, after forward func declarations +// (so initializers can reference functions) but before any function body +// (so functions can reference these vars). func (g *Generator) emitPackageVars(w io.Writer) { var symbols []symbol for _, sym := range g.symbols { diff --git a/testdata/lang/arrays/dst/main.c b/testdata/lang/arrays/dst/main.c index fecd4b44..c36a9631 100644 --- a/testdata/lang/arrays/dst/main.c +++ b/testdata/lang/arrays/dst/main.c @@ -15,13 +15,13 @@ typedef struct arange { uint8_t hi; } arange; -// -- Variables and constants -- -static arange aranges[16] = {[0] = (arange){0x10, 0x20}, [1] = (arange){0x30, 0x40}, [2] = (arange){0x50, 0x60}}; - // -- Forward declarations -- static void change(so_int a[3]); static box newBox(void); +// -- Variables and constants -- +static arange aranges[16] = {[0] = (arange){0x10, 0x20}, [1] = (arange){0x30, 0x40}, [2] = (arange){0x50, 0x60}}; + // -- Implementation -- static void change(so_int a[3]) { diff --git a/testdata/lang/attr/dst/main.c b/testdata/lang/attr/dst/main.c index 1c8dd934..941ca351 100644 --- a/testdata/lang/attr/dst/main.c +++ b/testdata/lang/attr/dst/main.c @@ -22,6 +22,9 @@ typedef struct __attribute__((packed, aligned(16))) aligned { // typedef __attribute__((aligned(8))) so_int myInt; +// -- Forward declarations -- +static __attribute__((noinline)) void helper(void); + // -- Variables and constants -- // Unexported volatile variable. @@ -44,9 +47,6 @@ _Thread_local so_int main_PerThread = 0; // static _Thread_local volatile so_int flags = 0; -// -- Forward declarations -- -static __attribute__((noinline)) void helper(void); - // -- Implementation -- // Exported function with so:attr. diff --git a/testdata/lang/comments/dst/main.c b/testdata/lang/comments/dst/main.c index f24d944b..4e0ac122 100644 --- a/testdata/lang/comments/dst/main.c +++ b/testdata/lang/comments/dst/main.c @@ -1,13 +1,13 @@ #include "main.h" +// -- Forward declarations -- +static main_Point offset(main_Point p, so_int dx, so_int dy); + // -- Variables and constants -- // MaxCoord is the maximum coordinate value. const so_int main_MaxCoord = 1000; -// -- Forward declarations -- -static main_Point offset(main_Point p, so_int dx, so_int dy); - // -- Implementation -- // NewPoint creates a new Point. diff --git a/testdata/lang/defer/dst/main.c b/testdata/lang/defer/dst/main.c index 777bef5c..5ad4de3f 100644 --- a/testdata/lang/defer/dst/main.c +++ b/testdata/lang/defer/dst/main.c @@ -1,8 +1,5 @@ #include "main.h" -// -- Variables and constants -- -static so_int state = 0; - // -- Forward declarations -- static void xopen(so_int* x); static void xclose(void* a); @@ -10,6 +7,9 @@ static void funcScope(void); static so_int funcWithReturn(void); static void blockScope(void); +// -- Variables and constants -- +static so_int state = 0; + // -- Implementation -- static void xopen(so_int* x) { diff --git a/testdata/lang/errors/dst/main.c b/testdata/lang/errors/dst/main.c index 8d69b8df..d55bfefe 100644 --- a/testdata/lang/errors/dst/main.c +++ b/testdata/lang/errors/dst/main.c @@ -1,12 +1,12 @@ #include "main.h" -// -- Variables and constants -- -so_Error main_ErrOutOfTea = errors_New("no more tea available"); - // -- Forward declarations -- static so_Error makeTea(so_int arg); static so_R_int_err work(so_int n); +// -- Variables and constants -- +so_Error main_ErrOutOfTea = errors_New("no more tea available"); + // -- Implementation -- static so_Error makeTea(so_int arg) { diff --git a/testdata/lang/export/dst/main.c b/testdata/lang/export/dst/main.c index 40f4c0cf..2da8f206 100644 --- a/testdata/lang/export/dst/main.c +++ b/testdata/lang/export/dst/main.c @@ -1,14 +1,14 @@ #include "main.h" +// -- Forward declarations -- +static bool someFunc(so_int x, so_int y); + // -- Variables and constants -- static const int64_t someConst = 7; const int64_t main_SomeConst = 7; static so_int someVar = 42; so_int main_SomeVar = 42; -// -- Forward declarations -- -static bool someFunc(so_int x, so_int y); - // -- Implementation -- static bool someFunc(so_int x, so_int y) { diff --git a/testdata/lang/init/dst/main.c b/testdata/lang/init/dst/main.c index 71b7ef7d..0a4effb3 100644 --- a/testdata/lang/init/dst/main.c +++ b/testdata/lang/init/dst/main.c @@ -8,12 +8,12 @@ typedef struct value { so_int x; } value; -// -- Variables and constants -- -static so_int state = 0; - // -- Forward declarations -- static void value_init(void* self, so_int x); +// -- Variables and constants -- +static so_int state = 0; + // -- Implementation -- static void value_init(void* self, so_int x) { diff --git a/testdata/lang/multi-file/dst/main.c b/testdata/lang/multi-file/dst/main.c index f4383bbc..4b01c744 100644 --- a/testdata/lang/multi-file/dst/main.c +++ b/testdata/lang/multi-file/dst/main.c @@ -1,13 +1,13 @@ #include "main.h" +// -- Forward declarations -- +static so_int add(so_int a, so_int b); + // -- Variables and constants -- static so_int x = 11; so_int main_Y = 22; static const so_int z = 33; -// -- Forward declarations -- -static so_int add(so_int a, so_int b); - // -- add.go -- static so_int add(so_int a, so_int b) { diff --git a/testdata/lang/multi-return-err/dst/main.c b/testdata/lang/multi-return-err/dst/main.c index 029edf06..0ec7f937 100644 --- a/testdata/lang/multi-return-err/dst/main.c +++ b/testdata/lang/multi-return-err/dst/main.c @@ -16,9 +16,6 @@ typedef struct pointResult { so_Error err; } pointResult; -// -- Variables and constants -- -static main_File file = {0}; - // -- Forward declarations -- static main_FileResult makeFile(so_int size); static so_R_ptr_err returnPtr(void); @@ -30,6 +27,9 @@ static so_R_str_err returnString(void); static so_R_slice_err returnSlice(void); static so_R_int_err forwardCall(void); +// -- Variables and constants -- +static main_File file = {0}; + // -- Implementation -- static main_FileResult makeFile(so_int size) { diff --git a/testdata/lang/packages/dst/geom/geom.c b/testdata/lang/packages/dst/geom/geom.c index 0717f10c..08888450 100644 --- a/testdata/lang/packages/dst/geom/geom.c +++ b/testdata/lang/packages/dst/geom/geom.c @@ -1,11 +1,11 @@ #include "geom.h" -// -- Variables and constants -- -const double geom_Pi = 3.14159; - // -- Forward declarations -- static double rectArea(double width, double height); +// -- Variables and constants -- +const double geom_Pi = 3.14159; + // -- Implementation -- static double rectArea(double width, double height) { diff --git a/testdata/lang/panic/dst/main.c b/testdata/lang/panic/dst/main.c index a2837355..7fd842f9 100644 --- a/testdata/lang/panic/dst/main.c +++ b/testdata/lang/panic/dst/main.c @@ -1,13 +1,13 @@ #include "main.h" -// -- Variables and constants -- -so_Error main_ErrNotFound = errors_New("not found"); - // -- Forward declarations -- static void panicLiteral(void); static void panicString(void); static void panicError(void); +// -- Variables and constants -- +so_Error main_ErrNotFound = errors_New("not found"); + // -- Implementation -- static void panicLiteral(void) {