bug: incomplete nested C member generation and declaration reuse
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 25/100
- Loại issue
- Lỗi
- Độ rõ ràng
- Khá rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Lĩnh vực
- build-system, tooling
Hướng nghiên cứu
Start with the retained C reproducers and generated Go outputs linked in the evidence comment; read the conversion sources at the referenced #1031 snapshot and compare them with the current generator. Reproduce the cases individually, since the inputs reuse owner names and enum constants. Done means supported inputs retain owners, members, accessors, and shared declarations with correct union storage; several failures remain unresolved and the local follow-up is unmerged.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Summary
Valid non-array C member declarations can make llcppg panic, silently omit the enclosing record, duplicate declarations, or generate incorrect union access/storage. This issue tracks those concrete bugs, rather than a new conversion framework or a catalogue of already-supported syntax.
The reproduced failures fall into six groups:
| Failing C case | Actual behavior | Expected behavior |
|---|---|---|
| Pointer to an inline anonymous struct/union/enum | Struct owner omitted or union pointee lookup panics | Retain the owner, resolve the declared type and preserve pointer levels |
| Tagged struct/union declared inside a union | The inner declaration is unavailable to its pointer member | Resolve the tag in its actual C scope |
| Nested enum values/pointers | Enum lookup fails or owner is omitted | Emit and reuse the enum and its constants |
| Multiple members from one anonymous declaration | Distinct Go types or duplicate enum constants; a value-plus-pointer case omits its owner | Reuse one declaration across all of its declarators |
| Fieldless anonymous struct inside a union | Promoted member accessors are missing | Expose the promoted fields at their actual offsets |
| Scalar classification through that fieldless struct | Integer leaves are missed and storage is incorrectly all-floating | Include all stored scalar leaves when selecting the union representation |
A successful process exit is not sufficient: several cases return success with missing or incorrect declarations.
Environment and evidence
- Scalar/enum and later declaration probes: llcppg
6950e22b8e0c2008384bc06d02575c03e20323a2, the published #1031 snapshot. - Earlier record probes:
6997fe3717414c50632600d684dd3c855cffd9c0with the same conversion change; relevant conversion sources were checked byte-identical. - Linux/amd64, Clang/LLVM 22.1.8, LLGo
b86d349178d6. - These are recorded generation/output inspections and the previously documented package-build checks, not a new full rerun on every later main revision or a general ABI certification.
Each numbered C block below is a separate include/in.h input using the normal C generator configuration. Do not concatenate the blocks: owner names and enum constants are deliberately reused. For non-panic cases, the following Go block is the complete recorded generated/in.go, including files containing only a package declaration. Companion llcppg.i.go files contain only package/marker declarations and do not restore omitted owners.
The same 19 inputs and nine non-panic Go outputs are retained in the evidence comment.
Fix status
- Nested anonymous union support in #1015 is merged and is not a remaining defect listed here.
- Anonymous structs used as named union value members are implemented in the still-open #1031; that is not a merged-main support claim.
- Fieldless-struct promotion and scalar-leaf classification now have a local, uncommitted follow-up on the #1031 worktree. C/C++ fixtures, generator tests, and actual member-address/layout/write checks passed on Linux/amd64 with LLVM 22. Those changes are not yet pushed or merged, so the original failing case remains recorded below.
- Pointer/declaration-registration/enum/declaration-reuse failures below remain unresolved in the recorded implementation.
Reproducers: C input, actual output, expected behavior
1. Pointers to inline anonymous types
Expected: resolve the anonymous declaration once and preserve the pointer member. Struct owners must retain their pointer field; union owners must retain the existing pointer-slot reference representation (**T for a stored T *). Neither owner omission nor a pointee-lookup panic is acceptable.
1. Anonymous struct pointer in a struct
struct StructOwner { struct { int x; } *p; };
Actual generated in.go:
// Code generated by llcppg; DO NOT EDIT.
package pointerprobe
Observed: The enclosing StructOwner is omitted after unsupported anonymous-pointee lookup.
2. Anonymous struct pointer in a union
union UnionOwner { struct { int x; } *p; };
Observed: Panics on the anonymous struct pointee.
3. Anonymous union pointer in a struct
struct StructOwner { union { int x; double d; } *p; };
Actual generated in.go:
// Code generated by llcppg; DO NOT EDIT.
package pointerprobe
Observed: The enclosing StructOwner is omitted after unsupported anonymous-pointee lookup.
4. Anonymous union pointer in a union
union UnionOwner { union { int x; double d; } *p; };
Observed: Panics on the anonymous union pointee.
5. Anonymous enum pointer in a struct
struct Owner {
enum { EZero, EOne } *pointer;
};
Actual generated in.go:
// Code generated by llcppg; DO NOT EDIT.
package scalarprobe
Observed: The enclosing Owner is omitted after unsupported anonymous-enum lookup.
6. Anonymous enum pointer in a union
union Owner {
enum { EZero, EOne } *pointer;
};
Observed: Panics on the anonymous enum pointee.
2. Tagged record declarations inside a union are not registered
Expected: the inner tagged struct/union must be available to its member references. Preserve the named type and the stored pointer; moving the declaration outside the owner must not be required.
7. Inner tagged struct pointer (original combined input)
union UnionOwner { struct InnerS { int x; } *sp; union InnerU { int x; double d; } *up; };
Observed: Panics on struct InnerS * before reaching up. This is the original recorded input, not a claim that both members were independently reached in this run.
8. Inner tagged union pointer, isolated
union UnionOwner { union InnerU { int x; double d; } *up; };
Observed: Panics on union InnerU *; this separately establishes the failure of the second shape above.
3. Nested enum values and named enum pointers
Expected: emit the enum type/constants once and retain the owner's value or pointer member using the enum's actual underlying C integer type.
9. Anonymous enum value in a union
union Owner {
enum { EZero, EOne } value;
};
Observed: Panics on the unresolved anonymous enum. The struct-owner version of this value-only case works and is not listed as a failure.
10. Inner named enum value in a struct
struct Owner {
enum Local { EZero, EOne } value;
};
Actual generated in.go:
// Code generated by llcppg; DO NOT EDIT.
package scalarprobe
Observed: Logs unsupported enum Local and omits Owner.
11. Inner named enum value in a union
union Owner {
enum Local { EZero, EOne } value;
};
Observed: Panics on unsupported enum Local.
12. Inner named enum pointer in a struct
struct Owner {
enum Local { EZero, EOne } *pointer;
};
Actual generated in.go:
// Code generated by llcppg; DO NOT EDIT.
package scalarprobe
Observed: Logs unsupported enum Local and omits Owner.
13. Inner named enum pointer in a union
union Owner {
enum Local { EZero, EOne } *pointer;
};
Observed: Panics on unsupported enum Local *.
4. Shared anonymous declaration identity and multiple declarators
Expected: one C declaration produces one shared Go type and, for enums, one constant set. Apply each declarator's value/pointer layers to that shared type. Separate C declarations must not be merged merely because their fields look alike.
14. Two values of the same anonymous struct declaration
struct Owner { struct { int x, y; } first, second; };
Actual generated in.go:
// Code generated by llcppg; DO NOT EDIT.
package multidecl
import "github.com/goplus/lib/c"
type Owner struct {
First _llcppg_anon_0
Second _llcppg_anon_1
}
type _llcppg_anon_0 struct {
X c.Int
Y c.Int
}
type _llcppg_anon_1 struct {
X c.Int
Y c.Int
}
Observed: Generates First _llcppg_anon_0 and Second _llcppg_anon_1: one C declaration becomes two distinct Go named types instead of one reused type. This is an incorrect-generation result, not a reported CLI panic.
15. Two values of the same anonymous union declaration
struct Owner { union { int x; double y; } first, second; };
Actual generated in.go:
// Code generated by llcppg; DO NOT EDIT.
package multidecl
import (
"github.com/goplus/lib/c"
"unsafe"
)
type Owner struct {
First _llcppg_anon_0
Second _llcppg_anon_1
}
type _llcppg_anon_0 struct {
_xgo_union [1]uint64
}
type _llcppg_anon_1 struct {
_xgo_union [1]uint64
}
func (p *_llcppg_anon_0) XGof_ref_x() *c.Int {
return (*c.Int)(unsafe.Pointer(p))
}
func (p *_llcppg_anon_0) XGof_ref_y() *c.Double {
return (*c.Double)(unsafe.Pointer(p))
}
func (p *_llcppg_anon_1) XGof_ref_x() *c.Int {
return (*c.Int)(unsafe.Pointer(p))
}
func (p *_llcppg_anon_1) XGof_ref_y() *c.Double {
return (*c.Double)(unsafe.Pointer(p))
}
Observed: Generates two separate anonymous Go union types and two accessor sets instead of reusing the one C declaration.
16. Two values of the same anonymous enum declaration in a struct
struct Owner {
enum { EZero, EOne } first, second;
};
Observed: Panics with EZero redeclared in this block because the enum constants are emitted again.
17. Two values of the same anonymous enum declaration in a union
union Owner {
enum { EZero, EOne } first, second;
};
Observed: Fails earlier on unresolved anonymous-enum lookup; constant deduplication is not reached in this input.
18. Value and pointer sharing one anonymous struct declaration
struct Owner { struct { int x, y; } value, *pointer; };
Actual generated in.go:
// Code generated by llcppg; DO NOT EDIT.
package multidecl
import "github.com/goplus/lib/c"
type _llcppg_anon_0 struct {
X c.Int
Y c.Int
}
Observed: Emits the anonymous struct type but then fails to resolve the pointer member and omits Owner. This exact mixed-declarator case has a recorded failure; it should not be generalized to all other untested combinations.
5–6. Fieldless anonymous struct: missing promoted accessors and wrong union storage classification
Expected: promote the actual fieldless struct members through the existing union accessor convention, using their real Clang offsets in the outer union. Include those members in scalar-leaf classification. Named members must keep their access level. A local follow-up now passes this case, but it has not been pushed or merged; the code below records the original failure.
19. One input exposing two independent omissions
union DirectAnonymousStruct {
struct {
int x;
int y;
};
double raw;
};
_Static_assert(__builtin_offsetof(union DirectAnonymousStruct, x) == 0, "x offset");
_Static_assert(__builtin_offsetof(union DirectAnonymousStruct, y) == sizeof(int), "y offset");
Actual generated in.go:
// Code generated by llcppg; DO NOT EDIT.
package directanon
import (
"github.com/goplus/lib/c"
"unsafe"
)
type DirectAnonymousStruct struct {
_xgo_union [1]float64
}
func (p *DirectAnonymousStruct) XGof_ref_raw() *c.Double {
return (*c.Double)(unsafe.Pointer(p))
}
Observed: Only XGof_ref_raw is generated; XGof_ref_x and XGof_ref_y are missing. The same output uses _xgo_union [1]float64, because the leaf walk ignores the inner integer fields. Under the existing union representation rule, this mixed integer/double case needs integer storage ([1]uint64 on the tested target). The C assertions also establish distinct member offsets: x at 0 and y at sizeof(int) (4 here).
Acceptance and boundaries
- Every successfully supported input must retain the owner, all requested members/accessors, and the required types/constants. Do not treat an empty or partial generated package as a passing result.
- Declaration reuse must preserve C type identity, member order and pointer levels. Union members must continue to overlap the same storage; promoted struct fields retain nonzero offsets.
- Preserve already-working external named/typedef references, ordinary scalar fields, callback metadata and named nested access levels.
- Unverified mixed-declarator combinations are not promoted to confirmed failures or verified successes. Invalid/declaration-only spellings that do not create storage members are not missing member bindings.
- Arrays/flexible arrays are tracked in #1035; special types/qualifier and calling semantics in #1033; union bit-fields in #1034. Global variable bindings and unrelated CLI-wide partial-output policy changes are not selected here.
- New public generator APIs, binding constructors or fallback representations are not specified by this bug report. Use existing fixture-driven verification under
_testc/_testcppwhen implementing fixes.
The published reproductions remain unchanged by the local fieldless fix; its outputs must be evaluated separately from the historical failing outputs above.
- Ngôn ngữ chính
- Go
- Star
- 40
- Fork
- 13
- Merge trung bình
- 2 giờ 22 phút
- Pull request đã merge (30 ngày)
- 125
Chuẩn bị môi trường
Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của goplus/llcppg
-
feature proposal
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 25/100
Maintainer thường phản hồi trong vòng 1 ngày
-
proposal
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 28/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 64/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 70/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 38/100
goplus/llcppg#1136 · 1 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của goplus/llcppg
Issue tương tự
-
needs-triage
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
Maintainer thường phản hồi trong vòng 1 ngày
-
WriterSetTimes: the UTIME_NOW check fails when the kernel uses its coarse clockCó thể đã có người làm @JakeChampion đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
JakeChampion/lang#14224 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
docs(reference): pi stream-filter bullet says tool_execution_update passes through unchangedĐang mởagent-butler-finding bug
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 88/100
jordansmall/spindrift#6391 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
common.Retry: data race on the shared response/err variables when the request context ends mid-attempt (v65.127.0, v65.128.0)Có thể đã có người làm @kmohit00 đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
oracle/oci-go-sdk#676 ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
SAP/crossplane-provider-btp#1175 ·
Maintainer thường phản hồi trong vòng 1 ngày