fix: support go:linkname directive at any position in file#1790
fix: support go:linkname directive at any position in file#1790fennoai[bot] wants to merge 6 commits intomainfrom
Conversation
The go:linkname directive should work regardless of its position relative to the declaration it references. Previously, only directives placed as doc comments (immediately before the declaration) were processed. This adds processFloatingLinknames() to scan all file comments for linkname directives not attached as doc comments, matching Go compiler behavior. Generated with [codeagent](https://github.com/qbox/codeagent) Co-authored-by: visualfc <714279+visualfc@users.noreply.github.com>
There was a problem hiding this comment.
Review Summary
Clean, well-targeted fix for #1789. The approach of scanning file.Comments and filtering out doc comments via a pointer-identity set is sound. No security or performance concerns. A few code quality observations below — none are blocking.
| } | ||
| case *ast.GenDecl: | ||
| if decl.Doc != nil { | ||
| docComments[decl.Doc] = true | ||
| } |
There was a problem hiding this comment.
Spec-level doc comments not filtered: The docComments set tracks FuncDecl.Doc and GenDecl.Doc, but within a parenthesized GenDecl (e.g., var ( ... )), each ValueSpec can have its own .Doc comment group. These spec-level doc comments appear in file.Comments but won't be in docComments, so they'd be processed as "floating." In practice this is unlikely to cause visible issues since SetLinkname is idempotent, but it's worth noting for correctness.
| } | |
| case *ast.GenDecl: | |
| if decl.Doc != nil { | |
| docComments[decl.Doc] = true | |
| } | |
| case *ast.GenDecl: | |
| if decl.Doc != nil { | |
| docComments[decl.Doc] = true | |
| } | |
| for _, spec := range decl.Specs { | |
| switch s := spec.(type) { | |
| case *ast.ValueSpec: | |
| if s.Doc != nil { | |
| docComments[s.Doc] = true | |
| } | |
| case *ast.TypeSpec: | |
| if s.Doc != nil { | |
| docComments[s.Doc] = true | |
| } | |
| } | |
| } |
Nit / optional — just flagging the gap.
| p.initLinkname(c.Text, allowExport, func(inPkgName string, isExport bool) (fullName string, isVar, ok bool) { | ||
| if d, exists := decls[inPkgName]; exists { | ||
| return d.fullName, d.isVar, true |
There was a problem hiding this comment.
Subtle behavioral difference with //export acceptance logic: The floating callback unconditionally returns ok=true when the name matches in decls. The existing doc-based callback in processLinknameByDoc (line 307) has stricter logic: name == inPkgName || (isExport && enableExportRename). This means a floating //export directive bypasses the enableExportRename gate. Since //export in floating position is uncommon, this is unlikely to matter in practice, but the asymmetry is worth being aware of.
|
|
||
| // TestPreCollectLinknamesAfterDecl tests that go:linkname directives placed after | ||
| // function declarations are correctly processed. See #1789. | ||
| func TestPreCollectLinknamesAfterDecl(t *testing.T) { |
There was a problem hiding this comment.
Test coverage gaps (non-blocking): The new test only exercises PreCollectLinknames (which passes allowExport=false). A few additional cases would strengthen confidence:
- A
vardeclaration with a trailing//go:linkname(exercises thetoken.VARbranch inprocessFloatingLinknames) - The
// llgo:linkspaced variant in trailing position - A test covering the
initFilescode path (line 218), which passesallowExport=true
|
@xgopilot fix test |
Fixed: Floating linkname warnings causing test failures
Root cause: Fix (commit fbdf459):
|
Floating //go:linkname directives referencing names not declared in the same file (e.g., runtime/cgo _cgo_* symbols) were triggering spurious "linkname not found and ignored" warnings. Add linknameTarget() to pre-filter floating directives, only processing those whose target name is actually declared in the file. Generated with [codeagent](https://github.com/qbox/codeagent) Co-authored-by: visualfc <714279+visualfc@users.noreply.github.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1790 +/- ##
==========================================
+ Coverage 88.44% 88.47% +0.02%
==========================================
Files 50 50
Lines 13656 13696 +40
==========================================
+ Hits 12078 12117 +39
- Misses 1369 1370 +1
Partials 209 209 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
@xgopilot //go:linkname only support any position |
|
Updated Changes
|
Only //go:linkname is supported at any position in the file. //llgo:link and //export must remain as doc comments attached to declarations. Generated with [codeagent](https://github.com/qbox/codeagent) Co-authored-by: visualfc <714279+visualfc@users.noreply.github.com>
|
@xgopilot remove undeclared names check and test |
|
Removed the undeclared names check and associated tests as requested:
Commit: a1c652a |
Remove floatingLinknameTarget() and the undeclared names skip logic from processFloatingLinknames(), along with the associated tests TestFloatingLinknameIgnoresUndeclaredNames and TestFloatingLinknameTarget. Generated with [codeagent](https://github.com/qbox/codeagent) Co-authored-by: visualfc <714279+visualfc@users.noreply.github.com>
|
@xgopilot //go:linkname _cgo_init _cgo_init, //go:linkname _name1 _name2 skip _underline_name if _name1 == _name2 。 |
Implemented @visualfc's requestAdded skip logic for floating Changes
Commit: 1fc018b |
|
@xgopilot //go:linkname _cgo_init _cgo_init, //go:linkname _cgo_name1 _cgo_name2 skip _cgo_name if _cgo_name1 == _cgo_name2 。 |
Skip //go:linkname _name _name directives in processFloatingLinknames when the local name starts with "_" and equals the remote name (e.g., //go:linkname _cgo_init _cgo_init). These self-referencing underscore directives from cgo are no-ops and should be ignored. Generated with [codeagent](https://github.com/qbox/codeagent) Co-authored-by: visualfc <714279+visualfc@users.noreply.github.com>
|
Narrowed the floating linkname self-link skip to cgo names only (commit 3cb298f):
Note: LLVM headers are not available in the CI build environment, so tests could not be run locally. The logic change is minimal and consistent with the existing |
Change the self-link skip condition in processFloatingLinknames from any underscore-prefixed name to cgo-specific names using checkCgo(). Only //go:linkname _cgo_name _cgo_name (where checkCgo matches) is skipped; non-cgo underscore self-links are now processed normally. Generated with [codeagent](https://github.com/qbox/codeagent) Co-authored-by: visualfc <714279+visualfc@users.noreply.github.com>
Requested by @visualfc
Fixes #1789
Summary
processFloatingLinknames()to scan all file comments for//go:linkname///llgo:link///exportdirectives not attached as doc comments to declarationsinitFiles()andPreCollectLinknames()after existing doc comment processingRoot Cause
Both
initFiles()andPreCollectLinknames()incl/import.goonly processed//go:linknamefromdecl.Doc(the comment group immediately preceding a declaration). Per Go spec, the directive position does not change its effect, but when placed after the declaration it becomes a "floating" comment not inDocand was silently ignored.Test plan
TestPreCollectLinknamesAfterDeclwith cases for//go:linknameand//llgo:linkafter func declarationsTestPreCollectLinknamestests still pass (directive before declaration)gofmt