fix(tool): header parsing fails when prerequisite includes are supplied by the C consumer
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 3/5
- Tempo stimato
- 1-2 giorni
- Idoneità per principianti
- 64/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Ambito
- developer-experience, tooling
Direzione di ricerca
Start with listHeaderFiles and ParseSources in tool/gen.go, which sort selected headers and invoke ParseTranslationUnit separately for each one. Reproduce with the two listed glibc headers and the documented llcppg command, then use the composed rose-entry.h control to compare field types and exit behavior. Done means prerequisite declarations are visible when parsing context-dependent headers, the generated fields retain their native types, and generation fails when the selected inputs still produce parse errors.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
The prerequisite #include can be supplied by the consuming .c file while being absent from the .h file itself. llcppg currently parses the .h independently, so it does not have the declarations that are already visible when that header is included by a correctly composed C source file.
The difference between compiling the C consumer and parsing its header
For glibc 2.24, this minimal consumer illustrates the required include context:
/* consumer.c — minimal reproduction, not an upstream source excerpt */
#include <netax25/ax25.h>
#include <netrose/rose.h>
The .c includes netax25/ax25.h first. This provides ax25_address, AX25_MAX_DIGIS, and, through bits/sockaddr.h, sa_family_t. When Clang then expands netrose/rose.h inside the same translation unit, those declarations are already visible.
The installed netrose/rose.h itself does not contain that prerequisite include. It uses these names and documents its requirement for ax25.h, relying on the includer to establish the context. The include sequence above passes the recorded C syntax check.
llcppg instead takes netrose/rose.h directly as a translation unit's main input. It does not parse a consuming .c file with the preceding include, nor does listing ax25.h separately in Files put its declarations into that translation unit. Consequently, a header that works when included by the C consumer reports unknown types when parsed in isolation.
The observed downstream result is also incorrect: llcppg returns success and emits sockaddr_rose fields as c.Int where the native declarations require sa_family_t and ax25_address.
Reproduction
Use the Bootlin glibc 2.24 Linux arm64 headers under source/linux-arm64/include, with a source Go module requiring github.com/goplus/lib v0.7.0. The relevant configuration is:
{
"Name": "libc",
"Language": "c",
"Dir": "$GOOS-$GOARCH/include",
"Files": [
"netax25/ax25.h",
"netrose/rose.h"
],
"FailFast": 0,
"IgnoreInline": true
}
Leave Stdlib unset. In the tested Linux container, Clang's builtin headers and the staged glibc headers were selected with:
GOOS=linux GOARCH=arm64 \
C_INCLUDE_PATH="/usr/lib/llvm-22/lib/clang/22/include:$PWD/source/linux-arm64/include" \
llcppg ./generated ./source
This two-header reproduction emits 13 Clang errors, including:
netrose/rose.h:71:3: error: unknown type name 'sa_family_t'
netrose/rose.h:73:3: error: unknown type name 'ax25_address'
netrose/rose.h:94:28: error: use of undeclared identifier 'AX25_MAX_DIGIS'
All definitions are present in the staged include tree. netax25/ax25.h defines ax25_address and AX25_MAX_DIGIS, and includes bits/sockaddr.h, which defines sa_family_t. netrose/rose.h does not include ax25.h; its comment explicitly states that it requires that header.
The command nevertheless exits 0 and emits recovered, incorrect fields:
type SockaddrRose struct {
SroseFamily c.Int
SroseAddr RoseAddress
SroseCall c.Int
SroseNdigis c.Int
SroseDigi c.Int
}
Why ordering Files does not help
At the tested revision, listHeaderFiles and ParseSources sort the input paths and call ParseTranslationUnit separately for each header. Even though ax25.h is parsed first, its declarations are not available when Clang independently parses rose.h.
Clang is correct to reject that standalone input. An include search path only locates files named by #include; it does not load declarations automatically or resolve unknown type names by searching sibling headers.
Verified workaround
Create a single input rose-entry.h containing:
#include <netax25/ax25.h>
#include <netrose/rose.h>
Select only rose-entry.h in Files. With the same native headers and toolchain, generation exits 0 with no diagnostics, and the resulting fields use the declared types:
type SockaddrRose struct {
SroseFamily SaFamilyT
SroseAddr RoseAddress
SroseCall Ax25Address
SroseNdigis c.Int
SroseDigi Ax25Address
}
Related C parsing controls also pass when rpcsvc/nislib.h is reached through rpcsvc/nis.h, and when stdint.h precedes scsi/scsi_bsg_fc.h, scsi/scsi_netlink.h, or scsi/scsi_netlink_fc.h. Only the ROSE example above was compared through full llcppg generation in this focused reproduction.
Expected behavior
- Parse prerequisite-dependent headers with the declarations required by their native include contract visible, and preserve the actual field types shown by the composed-input control.
- If the selected inputs do not establish a valid include context, report the original parse errors and fail generation. Do not return success or emit bindings from the erroneous recovered declarations.
- Preserve the native API; removing the affected declarations or changing the installed headers is not a fix.
The composed entry header above is a verified workaround for this bug. The report does not prescribe a new configuration field, public API, or automatic ordering algorithm.
Related issues
#997 covers recursive discovery of context-dependent implementation headers; this reproduction uses an explicit two-file list. #998 concerns preprocessing arguments and include roots; here the files are already reachable. #1137 covers failure handling for fatal parse diagnostics; this case demonstrates ordinary unknown-type errors followed by successful generation of incorrect field types.
Reproduced with llcppg 90bd72cfb16ac56750116353b76ee9e6bf2ae892, LLVM/libclang 22.1.8 and LLGo 1.0.8 on Linux arm64. These are parser/generator results; no LLGo build, runtime, or ABI validation is claimed.
- Lingua principale
- Go
- Stelle
- 40
- Fork
- 13
- Merge medio
- 2h
- PR unite (30g)
- 150
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
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 70/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 38/100
goplus/llcppg#1136 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 72/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 72/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 3/5 1-2 giorni Idoneità per principianti 75/100
goplus/llcppg#1133 · 2 commenti ·
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 84/100
hyperledger/fabric-x-orderer#1409 ·
I maintainer di solito rispondono entro 3 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno
-
needs-area
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
Azure/typespec-azure#5936 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 70/100
-
Fix mode unpins a reusable workflow call when the same repository is also used as a step actionAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
github/gh-actions-lock#261 ·
I maintainer di solito rispondono entro 1 giorno