8000 codegen: a public function returning a struct is declared `extern "C"` before the struct, failing as C++ · Issue #266 · google/wuffs · GitHub
[go: up one dir, main page]

Skip to content
< 7FFF link rel="preload" as="image" href="https://github.githubassets.com/assets/platform-4ce65ae0bf273ce2.png"/>

codegen: a public function returning a struct is declared extern "C" before the struct, failing as C++ #266

Open

Description

@dio-gh

Hi,

General context of this work is in #188, including the AI-disclaimers.

No in-tree codec is affected by this issue; no std public function returns a struct of its package. Claude judges the prospective risk of it as "low": the C compiles, but C++ compilation fails under MSVC and clang with -Werror.

The following is Sol 6.1's writeup of the issue. Includes a repro, the generated declaration order, compiler diagnostics, and compile results from gcc 13.3 as C, clang++ 18 and g++ 13.3 as C++, and MSVC as C and C++. The cause is reasoned from source.


cgen writes public function prototypes inside extern "C", before the struct definitions. A public function without a receiver that returns a struct of its package is therefore declared with C linkage while the struct is incomplete, and in C++ that struct is a class with member functions.

Minimal repro:

pub struct repro?(
	v : base.u32,
)

pub func f(x: base.u32) repro {
	var t : repro

	return t
}

Actual: at b36a81d3, wuffs-c gen -package_name repro plain_arg.wuffs exits 0 with empty stderr. The header declares wuffs_repro__repro wuffs_repro__f(uint32_t a_x); at line 63, inside the extern "C" block on lines 25 to 66, and defines struct wuffs_repro__repro__struct at line 78.

As C, gcc 13.3 -Wall -Werror and MSVC compile it. As C++, with only the base and repro modules enabled, g++ 13.3 accepts it, clang++ 18 warns and fails with -Werror, and MSVC /TP fails with exit code 2:

plain_arg-release.c:7939:1: error: 'wuffs_repro__f' has C-linkage specified, but returns incomplete type 'wuffs_repro__repro' (aka 'wuffs_repro__repro__struct') which could be incompatible with C [-Werror,-Wreturn-type-c-linkage]
plain_arg-release.c(7939): error C2526: 'wuffs_repro__f': C linkage function cannot return C++ class 'wuffs_repro__repro__struct'
plain_arg-release.c(26145): error C2556: 'wuffs_repro__repro wuffs_repro__f(uint32_t)': overloaded function differs only by return type from 'void wuffs_repro__f(uint32_t)'

Expected: declare such functions outside extern "C" for C++, after the struct definitions, or reject struct results of public functions.

Cause: public function prototypes are written inside extern "C", before the struct definitions:

wuffs/internal/cgen/cgen.go

Lines 848 to 866 in b36a81d

b.writes("// ---------------- Public Function Prototypes\n\n")
if err := g.forEachFunc(b, pubOnly, (*gen).writeFuncPrototype); err != nil {
return err
}
b.writes("#ifdef __cplusplus\n} // extern \"C\"\n#endif\n\n")
b.writes("// ---------------- Struct Definitions\n\n")
b.writes("// These structs' fields, and the sizeof them, are private implementation\n")
b.writes("// details that aren't guaranteed to be stable across Wuffs versions.\n")
b.writes("//\n")
b.writes("// See https://en.wikipedia.org/wiki/Opaque_pointer#C\n\n")
b.writes("#if defined(__cplusplus) || defined(WUFFS_IMPLEMENTATION)\n\n")
for _, n := range g.structList {
if err := g.writeStruct(b, n); err != nil {
return err
}
}

With a refined argument, as in pub func f(x: base.u32[..= 1]) repro, the C itself fails to compile because the failed argument check writes to self (#201).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      0