From 570457e1deae9750c3a514620177970f0f6c7992 Mon Sep 17 00:00:00 2001 From: xushiwei <396972+xushiwei@users.noreply.github.com> Date: Tue, 6 Oct 2026 14:01:07 +0000 Subject: [PATCH] cl: emit // llgo:type C for records with callback fields A C/C++ struct/class whose members include function-pointer (callback) fields must carry the // llgo:type C directive so those callbacks use the C calling convention, consistent with how function-pointer typedefs are already handled in defineTypedef. featHasCallback is propagated up from toTypeEx while visiting the record members, so after the member-visit loop in initClassTypeEx we upgrade the doc-only comment to the directive form via directiveTypeC. Updates the affected golden test expectations (TestPython MemAllocatorEx, plus CursorAndRangeVisitor and IndexerCallbacks in the clang-c cases). Fixes #952 --- cl/class.go | 9 +++++++++ tool/_testc/clang-c-22.1.8/Index.go | 4 ++++ tool/_testc/clang-c-22.1.8/Index/out.go | 4 ++++ tool/_testc/python-3.14.8/pythread.go | 2 ++ 4 files changed, 19 insertions(+) diff --git a/cl/class.go b/cl/class.go index f1338e961..4b9ece9ff 100644 --- a/cl/class.go +++ b/cl/class.go @@ -251,6 +251,15 @@ func initClassTypeEx(ctx *pkgCtx, typDecl typDecl, this *classCtx, goName string if *feats&featAllIgnore != 0 { return } + // A record that holds a callback (function pointer) field must carry the + // "// llgo:type C" directive so those callbacks use the C calling + // convention, mirroring how function-pointer typedefs are handled (see + // defineTypedef). featHasCallback is set by toTypeEx while visiting the + // members above, so it is only known now; upgrade the doc-only comment set + // at the top of this function to the directive form. + if *feats&featHasCallback != 0 { + typDecl.defs.SetComments(ctx.directiveTypeC(cls, true)) + } // Establish the layout at offset 0, following the C++ Itanium ABI. A // polymorphic class shares its vptr with its primary base (the first // non-virtual *polymorphic* direct base in declaration order); that base is diff --git a/tool/_testc/clang-c-22.1.8/Index.go b/tool/_testc/clang-c-22.1.8/Index.go index 0755834d8..bb913e91c 100644 --- a/tool/_testc/clang-c-22.1.8/Index.go +++ b/tool/_testc/clang-c-22.1.8/Index.go @@ -2470,6 +2470,8 @@ type InclusionVisitor = func(_llcppg_param1 File, _llcppg_param2 *SourceLocation // Evaluation result of a cursor type EvalResult uintptr + +// llgo:type C type CursorAndRangeVisitor struct { Context unsafe.Pointer Visit func(_llcppg_param1 unsafe.Pointer, _llcppg_param2 Cursor, _llcppg_param3 SourceRange) VisitorResult @@ -2605,6 +2607,8 @@ type IdxEntityRefInfo struct { // A group of callbacks used by #clang_indexSourceFile and // #clang_indexTranslationUnit. +// +// llgo:type C type IndexerCallbacks struct { AbortQuery func(_llcppg_param1 ClientData, _llcppg_param2 unsafe.Pointer) c.Int Diagnostic func(_llcppg_param1 ClientData, _llcppg_param2 DiagnosticSet, _llcppg_param3 unsafe.Pointer) diff --git a/tool/_testc/clang-c-22.1.8/Index/out.go b/tool/_testc/clang-c-22.1.8/Index/out.go index a13eab4ae..24484d70d 100644 --- a/tool/_testc/clang-c-22.1.8/Index/out.go +++ b/tool/_testc/clang-c-22.1.8/Index/out.go @@ -2644,6 +2644,8 @@ type InclusionVisitor = func(_llcppg_param1 CXFile.File, _llcppg_param2 *CXSourc // Evaluation result of a cursor type EvalResult uintptr + +// llgo:type C type CursorAndRangeVisitor struct { Context unsafe.Pointer Visit func(_llcppg_param1 unsafe.Pointer, _llcppg_param2 Cursor, _llcppg_param3 CXSourceLocation.SourceRange) VisitorResult @@ -2779,6 +2781,8 @@ type IdxEntityRefInfo struct { // A group of callbacks used by #clang_indexSourceFile and // #clang_indexTranslationUnit. +// +// llgo:type C type IndexerCallbacks struct { AbortQuery func(_llcppg_param1 ClientData, _llcppg_param2 unsafe.Pointer) c.Int Diagnostic func(_llcppg_param1 ClientData, _llcppg_param2 CXDiagnostic.DiagnosticSet, _llcppg_param3 unsafe.Pointer) diff --git a/tool/_testc/python-3.14.8/pythread.go b/tool/_testc/python-3.14.8/pythread.go index fb2b53eeb..59c341b2f 100644 --- a/tool/_testc/python-3.14.8/pythread.go +++ b/tool/_testc/python-3.14.8/pythread.go @@ -42,6 +42,8 @@ type TssT = X_tssT type X_object struct { } type Object = X_object + +// llgo:type C type MemAllocatorEx struct { Ctx unsafe.Pointer Malloc func(_llcppg_param1 unsafe.Pointer, _llcppg_param2 c.SizeT) unsafe.Pointer