fix(cl): union bit-fields generate incorrect reference accessors and duplicate methods
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 55/100
Direzione di ricerca
Start in cl/union.go at initUnionType and genUnionAccessor, then read cl/bitfield.go to follow the existing getter/setter convention. Reproduce with either C input and run llcppg -v generated followed by llgo build ./generated; inspect generated accessors and add focused fixtures in the existing _testc or _testcpp harness. Done means named fields use width and signedness correctly, unnamed fields emit no methods, and the generated code compiles.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Problem
Union bit-fields currently take the ordinary reference-accessor path. This causes two distinct problems:
- Named bit-fields get pointers to whole integers rather than width-aware accessors.
- Unnamed/zero-width bit-fields get empty-suffix methods; multiple such fields produce duplicate
XGof_ref_declarations and the generated package fails to compile.
This is an implementation bug under the existing bit-field contract in #770, tracked separately from the broader generation proposal #1032.
Verified environment
- llcppg snapshot:
6950e22b8e0c2008384bc06d02575c03e20323a2(the #1031 branch snapshot). - Linux/amd64, Clang/LLVM 22.1.8.
- LLGo
b86d349178d610e6b15e95c2a5fdfcb130d09fa1,github.com/goplus/lib v0.6.1.
Both C inputs below passed the strict C11 syntax check. The report uses the saved generation/build results from that snapshot; it does not claim fresh validation of a newer main or other platforms. The named-field defect is established by the emitted accessors and source path, not by a claimed runtime test.
Case 1: named union bit-fields lose their access semantics
C input:
union Owner {
unsigned int a : 1;
unsigned int b : 3;
int signed_value : 5;
};
Actual generated Go (package/import boilerplate omitted):
type Owner struct {
_xgo_union [1]uint32
}
func (p *Owner) XGof_ref_a() *c.Uint {
return (*c.Uint)(unsafe.Pointer(p))
}
func (p *Owner) XGof_ref_b() *c.Uint {
return (*c.Uint)(unsafe.Pointer(p))
}
func (p *Owner) XGof_ref_signed_value() *c.Int {
return (*c.Int)(unsafe.Pointer(p))
}
Generation exits 0 and the generated package builds with LLGo, but these are whole-integer accesses. They do not mask writes to widths 1/3/5, preserve unrelated bits during a field assignment, or sign-extend a five-bit signed read. A C bit-field is not an addressable ordinary integer member.
All three fields being at bit offset zero is correct for a union; ignoring their different widths and signedness is not.
Case 2: unnamed and zero-width fields produce duplicate methods
C input:
union Owner {
unsigned int : 3;
unsigned int value : 5;
unsigned int : 0;
};
Actual generated Go (package/import boilerplate omitted):
type Owner struct {
_xgo_union [1]uint32
}
func (p *Owner) XGof_ref_() *c.Uint {
return (*c.Uint)(unsafe.Pointer(p))
}
func (p *Owner) XGof_ref_value() *c.Uint {
return (*c.Uint)(unsafe.Pointer(p))
}
func (p *Owner) XGof_ref_() *c.Uint {
return (*c.Uint)(unsafe.Pointer(p))
}
Generation again exits 0. Building the full generated file fails with:
generated/in.go:20:17: method Owner.XGof_ref_ already declared at generated/in.go:14:17
cannot build SSA for package example.com/scalarprobe/c/generated
cannot build SSA for packages
Unnamed and zero-width bit-fields have no callable member names. They must not become methods with an empty suffix.
Reproduction
Use either input independently as include/in.h in an isolated fixture directory.
llcppg.cfg:
{"Name":"scalarprobe","Language":"c","Dir":"./include"}
go.mod:
module example.com/scalarprobe/c
go 1.23
require github.com/goplus/lib v0.6.1
With llcppg built from the stated snapshot using LLGo, prepare the dependency checksums and run:
go mod download github.com/goplus/lib
llcppg -v generated
llgo build ./generated
The module-download command only prepares dependency metadata; compilation uses LLGo. Inspect the generated methods for case 1 even though the build passes.
Source path
In the inspected cl/union.go, initUnionType collects each Cursor_FieldDecl and later calls genUnionAccessor for it. That accessor derives a name from the field spelling and casts the union base to a pointer to the field's whole declared type. It does not choose a bit-field path based on bit offset, width, signedness, or whether there is a member name.
The nearby comment says bit-fields are skipped, but the recorded output shows that the implementation does not enforce that distinction.
The existing struct bit-field path in cl/bitfield.go already uses github.com/goplus/lib/c/bitfield and the getter/setter convention.
Expected behavior and proposed fix boundary
- Named union bit-fields use the existing
XGof_get_<member>/XGof_set_<member>contract from #770, notXGof_ref_<member>. - Use the actual target bit offset, width and signedness. Reads zero/sign-extend as appropriate; writes update only the field's bits.
- Unnamed and zero-width bit-fields contribute any required layout effects but generate no accessors.
- Ordinary non-bit-field union members retain their reference accessors and the union retains one shared storage block.
- Reuse the existing bit-field generation semantics from
cl/bitfield.go; distinguish bit-fields before selecting accessors incl/union.go. No new accessor family is needed.
Focused fixture coverage should include signed/unsigned named fields, unnamed and zero-width fields, mixed ordinary/bit-field union members, and promoted nested bit-fields with the correct receiver-relative offset. Generated code must compile; width/sign behavior and preservation of unrelated bits also need checks, since compilation alone misses case 1. Keep fixture work in the existing _testc/_testcpp harnesses and do not assume additional platform coverage from these Linux/amd64 results.
No implementation change is included in this report.
- Lingua principale
- Go
- Stelle
- 39
- Fork
- 13
- Merge medio
- 1h 27m
- PR unite (30g)
- 256
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di goplus/llcppg
-
fix(cl): preserve imports for types initialized across filesForse già presa @luoliwoshang l’ha presa 1 giorno fa. Aperta
Difficoltà 4/5 3-5 giorni Idoneità per principianti 22/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 28/100
I maintainer di solito rispondono entro 1 giorno
-
feature proposal
Difficoltà 5/5 Più di una settimana Idoneità per principianti 18/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 5/5 Più di una settimana Idoneità per principianti 25/100
I maintainer di solito rispondono entro 1 giorno
-
Architecture-Design feature to be confirm
Difficoltà 5/5 Più di una settimana Idoneità per principianti 35/100
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di goplus/llcppg
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
limitlessprojects/Go-Hybrid#50 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
vinyldns/go-vinyldns#106 ·
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
praetorian-inc/augustus#334 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
ClickHouse/clickhouse-go#2066 ·
I maintainer di solito rispondono entro 1 giorno