bug: incomplete nested C member generation and declaration reuse
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 5/5
- Tiempo estimado
- Más de una semana
- Aptitud para principiantes
- 25/100
- Tipo de issue
- Error
- Claridad
- Bastante claro
- Estado de actividad
- Activo
- Área
- build-system, tooling
Línea de trabajo
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.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
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.
- Lenguaje dominante
- Go
- Estrellas
- 39
- Forks
- 13
- Merge medio
- 1 h 33 min
- PR fusionados (30 d)
- 256
Preparar el entorno
Este proyecto no incluye contenedor de desarrollo, Dockerfile ni guía de contribución, así que la configuración corre por tu cuenta: empieza por su README y consulta nuestra guía para la primera contribución para los pasos generales.
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de goplus/llcppg
-
Dificultad 3/5 1-2 días Aptitud para principiantes 35/100
Los mantenedores suelen responder en 1 día
-
configuration
Dificultad 4/5 3-5 días Aptitud para principiantes 30/100
Los mantenedores suelen responder en 1 día
-
Architecture-Design feature proposal
Dificultad 5/5 Más de una semana Aptitud para principiantes 15/100
goplus/llcppg#1056 · 6 comentarios ·
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 5/5 Más de una semana Aptitud para principiantes 28/100
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 4/5 3-5 días Aptitud para principiantes 55/100
Los mantenedores suelen responder en 1 día
Todos los issues de goplus/llcppg
Issues similares
-
documentation hacktoberfest priority: low skill: good first issue status: ready for dev
Dificultad 2/5 Medio día Aptitud para principiantes 85/100
hyperledger-labs/fabric-smart-client#2142 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 78/100
numberly/vault-db-injector#107 ·
Los mantenedores suelen responder en 1 día
-
area/import kind/bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 62/100
Los mantenedores suelen responder en 1 día
-
[DOC] Wrong sg_egress_ports range in the Terraform Databricks Guide for AWS Hub & Spoke with Network FirewallPosiblemente ocupada @akhil9tiet la tomó hoy. Abiertodocs
Dificultad 1/5 Menos de una hora Aptitud para principiantes 72/100
databricks/terraform-provider-databricks#6080 · 1 comentario ·
Los mantenedores suelen responder en 3 días
-
kind/documentation
Dificultad 2/5 1-3 horas Aptitud para principiantes 80/100
kubernetes-sigs/dra-driver-nvidia-gpu#1569 ·
Los mantenedores suelen responder en 1 día