Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

bug: incomplete nested C member generation and declaration reuse

Abierto
#1,032 0 comentarios 0 reacciones 0 asignados Ver en GitHub

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
Stack tecnológico
c, go

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: 6997fe3717414c50632600d684dd3c855cffd9c0 with 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/_testcpp when 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

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de goplus/llcppg

Todos los issues de goplus/llcppg

Issues similares

Más issues de Go

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.