diff options
author | Ayke van Laethem <[email protected]> | 2024-01-17 15:55:07 +0100 |
---|---|---|
committer | Ayke van Laethem <[email protected]> | 2024-01-18 20:19:15 +0100 |
commit | 53db436a7d3bdfe7682c97e21fe1249a29156a35 (patch) | |
tree | 33ae159dd096abc4205d2928590421d07592e470 | |
parent | 0ad15551c84c39d53a9aef1c20c9e9ed8c9e1110 (diff) | |
download | tinygo-53db436a7d3bdfe7682c97e21fe1249a29156a35.tar.gz tinygo-53db436a7d3bdfe7682c97e21fe1249a29156a35.zip |
cgo: add file AST for fake C file locations
This is needed for the type checker, otherwise it doesn't know which Go
version it should use for type checking.
-rw-r--r-- | cgo/cgo.go | 12 | ||||
-rw-r--r-- | cgo/cgo_go122.go | 17 | ||||
-rw-r--r-- | cgo/cgo_test.go | 6 | ||||
-rw-r--r-- | cgo/libclang.go | 7 | ||||
-rw-r--r-- | loader/loader.go | 2 |
5 files changed, 38 insertions, 6 deletions
diff --git a/cgo/cgo.go b/cgo/cgo.go index f28c30246..d5f122120 100644 --- a/cgo/cgo.go +++ b/cgo/cgo.go @@ -25,9 +25,15 @@ import ( "golang.org/x/tools/go/ast/astutil" ) +// Function that's only defined in Go 1.22. +var setASTFileFields = func(f *ast.File, start, end token.Pos) { +} + // cgoPackage holds all CGo-related information of a package. type cgoPackage struct { generated *ast.File + packageName string + cgoFiles []*ast.File generatedPos token.Pos errors []error currentDir string // current working directory @@ -165,8 +171,9 @@ func GoBytes(ptr unsafe.Pointer, length C.int) []byte { // functions), the CFLAGS and LDFLAGS found in #cgo lines, and a map of file // hashes of the accessed C header files. If there is one or more error, it // returns these in the []error slice but still modifies the AST. -func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cflags []string) (*ast.File, []string, []string, []string, map[string][]byte, []error) { +func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cflags []string) ([]*ast.File, []string, []string, []string, map[string][]byte, []error) { p := &cgoPackage{ + packageName: files[0].Name.Name, currentDir: dir, importPath: importPath, fset: fset, @@ -202,6 +209,7 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl // This is always a bug in the cgo package. panic("unexpected error: " + err.Error()) } + p.cgoFiles = append(p.cgoFiles, p.generated) // If the Comments field is not set to nil, the go/format package will get // confused about where comments should go. p.generated.Comments = nil @@ -332,7 +340,7 @@ func Process(files []*ast.File, dir, importPath string, fset *token.FileSet, cfl // Print the newly generated in-memory AST, for debugging. //ast.Print(fset, p.generated) - return p.generated, p.cgoHeaders, p.cflags, p.ldflags, p.visitedFiles, p.errors + return p.cgoFiles, p.cgoHeaders, p.cflags, p.ldflags, p.visitedFiles, p.errors } func (p *cgoPackage) newCGoFile(file *ast.File, index int) *cgoFile { diff --git a/cgo/cgo_go122.go b/cgo/cgo_go122.go new file mode 100644 index 000000000..7304aaa28 --- /dev/null +++ b/cgo/cgo_go122.go @@ -0,0 +1,17 @@ +//go:build go1.22 + +package cgo + +// Code specifically for Go 1.22. + +import ( + "go/ast" + "go/token" +) + +func init() { + setASTFileFields = func(f *ast.File, start, end token.Pos) { + f.FileStart = start + f.FileEnd = end + } +} diff --git a/cgo/cgo_test.go b/cgo/cgo_test.go index 24a1289d7..5425d2779 100644 --- a/cgo/cgo_test.go +++ b/cgo/cgo_test.go @@ -55,7 +55,7 @@ func TestCGo(t *testing.T) { } // Process the AST with CGo. - cgoAST, _, _, _, _, cgoErrors := Process([]*ast.File{f}, "testdata", "main", fset, cflags) + cgoFiles, _, _, _, _, cgoErrors := Process([]*ast.File{f}, "testdata", "main", fset, cflags) // Check the AST for type errors. var typecheckErrors []error @@ -66,7 +66,7 @@ func TestCGo(t *testing.T) { Importer: simpleImporter{}, Sizes: types.SizesFor("gccgo", "arm"), } - _, err = config.Check("", fset, []*ast.File{f, cgoAST}, nil) + _, err = config.Check("", fset, append([]*ast.File{f}, cgoFiles...), nil) if err != nil && len(typecheckErrors) == 0 { // Only report errors when no type errors are found (an // unexpected condition). @@ -91,7 +91,7 @@ func TestCGo(t *testing.T) { } buf.WriteString("\n") } - err = format.Node(buf, fset, cgoAST) + err = format.Node(buf, fset, cgoFiles[0]) if err != nil { t.Errorf("could not write out CGo AST: %v", err) } diff --git a/cgo/libclang.go b/cgo/libclang.go index 1f2922c56..0860c6af4 100644 --- a/cgo/libclang.go +++ b/cgo/libclang.go @@ -589,6 +589,13 @@ func (p *cgoPackage) getClangLocationPosition(location C.CXSourceLocation, tu C. f := p.fset.AddFile(filename, -1, int(size)) f.SetLines(lines) p.tokenFiles[filename] = f + // Add dummy file AST, to satisfy the type checker. + astFile := &ast.File{ + Package: f.Pos(0), + Name: ast.NewIdent(p.packageName), + } + setASTFileFields(astFile, f.Pos(0), f.Pos(int(size))) + p.cgoFiles = append(p.cgoFiles, astFile) } positionFile := p.tokenFiles[filename] diff --git a/loader/loader.go b/loader/loader.go index ccc72aeac..9b46aa614 100644 --- a/loader/loader.go +++ b/loader/loader.go @@ -447,7 +447,7 @@ func (p *Package) parseFiles() ([]*ast.File, error) { if errs != nil { fileErrs = append(fileErrs, errs...) } - files = append(files, generated) + files = append(files, generated...) p.program.LDFlags = append(p.program.LDFlags, ldflags...) } |