You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(extract): cgo is invisible — the C preamble inside a .go file is never parsed, and C.f() calls produce no edges
Status: draft implementation-proposal open — PR #1947 for the three bounded pieces (//export linkage as export_linkage contracts, C. pseudo-namespace veto, preamble flagged in parse coverage); marked ready on maintainer design ack. The design-sized fourth piece — parsing the preamble with the C grammar — remains open here. (The adjacent import "C" hijack is #1926, fixed by #1931.)
What is missing
A cgo file is one file in two languages: the comment block above import "C" is C, the rest is Go. cbm parses it with the Go grammar only, so:
Preamble-defined C functions/types get no node — and no parse_partial entry either: the Go grammar sees a comment, not an error, so coverage reports the file as fully indexed.
C.f(...) calls produce no CALLS edge — nothing to bind to, and no notion of a C pseudo-namespace.
//export Name linkage is unread — inbound C→Go edges appear only by short-name luck.
No occurrence of the string cgo exists under src/.
Damage measured (~1150-file Go+C repo)
source
graph
files with import "C"
27
—
C.<ident> references / call-shaped C.f(
141 / 39
0 CALLS edges
preamble-defined C functions (one file alone)
12
0 nodes
//export directives
22
22 inbound edges, all unique_name @ 0.38–0.75
cgo files flagged in parse_partial
—
0 (silent)
The //export row matters most: those 22 C→Go edges are right by accident — name guesses standing in for a declared ABI contract. Any name collision moves them silently. (Pre-#1906 there was exactly 1 C.* CALLS edge, itself a lucky unique_name guess; the Go guard correctly removed it.)
Minimal reproduction
// fx/cgo_use.gopackage fx
/*static int helper(int a) { return a + 1; }static const int kAnswer = 42;*/import"C"funcRun(aint) int { returnint(C.helper(C.int(a))) }
//export GoCallbackfuncGoCallback(v C.int) C.int { returnv }
Result: nodes for Run and GoCallback only; no helper/kAnswer nodes; no CALLS out of Run; no linkage marker on GoCallback.
Detection recipe
SELECTcount(*) FROM edges
WHERE type='CALLS'AND json_extract(properties,'$.callee') GLOB 'C.*';
-- compare: grep -rhoE '\bC\.[A-Za-z_][A-Za-z0-9_]*\(' --include='*.go' . | wc -l
//export linkage (cheapest, best value/effort): record the exported C symbol name on the Go def; C-side calls bind by declared contract instead of luck — strictly upgrades 22 existing edges.
feat(extract): cgo is invisible — the C preamble inside a
.gofile is never parsed, andC.f()calls produce no edgesStatus: draft implementation-proposal open — PR #1947 for the three bounded pieces (//export linkage as
export_linkagecontracts,C.pseudo-namespace veto, preamble flagged in parse coverage); marked ready on maintainer design ack. The design-sized fourth piece — parsing the preamble with the C grammar — remains open here. (The adjacentimport "C"hijack is #1926, fixed by #1931.)What is missing
A cgo file is one file in two languages: the comment block above
import "C"is C, the rest is Go. cbm parses it with the Go grammar only, so:parse_partialentry either: the Go grammar sees a comment, not an error, so coverage reports the file as fully indexed.C.f(...)calls produce no CALLS edge — nothing to bind to, and no notion of aCpseudo-namespace.//export Namelinkage is unread — inbound C→Go edges appear only by short-name luck.No occurrence of the string
cgoexists undersrc/.Damage measured (~1150-file Go+C repo)
import "C"C.<ident>references / call-shapedC.f(//exportdirectivesunique_name@ 0.38–0.75parse_partialThe
//exportrow matters most: those 22 C→Go edges are right by accident — name guesses standing in for a declared ABI contract. Any name collision moves them silently. (Pre-#1906 there was exactly 1C.*CALLS edge, itself a luckyunique_nameguess; the Go guard correctly removed it.)Minimal reproduction
Result: nodes for
RunandGoCallbackonly; nohelper/kAnswernodes; no CALLS out ofRun; no linkage marker onGoCallback.Detection recipe
Fix sketch (three separable pieces, increasing cost)
//exportlinkage (cheapest, best value/effort): record the exported C symbol name on the Go def; C-side calls bind by declared contract instead of luck — strictly upgrades 22 existing edges.C.as a known pseudo-namespace: resolveC.f()to a synthetic external node or suppress explicitly — never let it enter the general registry (a standing Go: weak short-name strategies fabricate CALLS edges for selector calls (stdlib receivers hijack project symbols) #1906-shaped hijack surface).parse_partialaccounting and file attribution (Nondeterministic Java USAGE-edge misattribution since #667 — edges attach to wrong source files on every fresh index #787) — this is the piece needing maintainer input. Even flagging the preamble range inparse_partialalone would beat today's silence.Related: #1926/#1931, #787, #725, #1906; tracked in #1932.