cgo: improve diagnostics

This makes CGo-emitted diagnostics very similar to regular errors
emitted while parsing/typechecking a package.
It's not complete, but after introducing some errors in testdata/cgo,
this is the resulting output:

    # ./testdata/cgo/
    testdata/cgo/main.h:18:11: error: a parameter list without types is only allowed in a function definition
    testdata/cgo/main.go:5:10: note: in file included from testdata/cgo/main.go!cgo.c:2:
    testdata/cgo/main.go:6:19: error: expected identifier or '('

Previously, this was the output:

    /home/ayke/src/github.com/tinygo-org/tinygo/testdata/cgo/main.h:18:11: error: a parameter list without types is only allowed in a function definition
    cgo-fake.c:3:19: error: expected identifier or '('
    # ./testdata/cgo/
    cgo: libclang cannot parse fragment
This commit is contained in:
Ayke van Laethem
2019-04-10 15:51:44 +02:00
committed by Ron Evans
parent e5029c63d1
commit 078dd9ff52
3 changed files with 70 additions and 13 deletions
+7 -4
View File
@@ -16,6 +16,7 @@ import (
// fileInfo holds all Cgo-related information of a given *ast.File.
type fileInfo struct {
*ast.File
*Package
filename string
functions map[string]*functionInfo
globals map[string]*globalInfo
@@ -78,9 +79,10 @@ typedef unsigned long long _Cgo_ulonglong;
// processCgo extracts the `import "C"` statement from the AST, parses the
// comment with libclang, and modifies the AST to use this information.
func (p *Package) processCgo(filename string, f *ast.File, cflags []string) error {
func (p *Package) processCgo(filename string, f *ast.File, cflags []string) []error {
info := &fileInfo{
File: f,
Package: p,
filename: filename,
functions: map[string]*functionInfo{},
globals: map[string]*globalInfo{},
@@ -114,9 +116,10 @@ func (p *Package) processCgo(filename string, f *ast.File, cflags []string) erro
// source location.
info.importCPos = spec.Path.ValuePos
err = info.parseFragment(cgoComment+cgoTypes, cflags)
if err != nil {
return err
pos := info.fset.PositionFor(genDecl.Doc.Pos(), true)
errs := info.parseFragment(cgoComment+cgoTypes, cflags, pos.Filename, pos.Line)
if errs != nil {
return errs
}
// Remove this import declaration.