diff --git a/pkg/lint/load.go b/pkg/lint/load.go index 3133d95a..b54c980c 100644 --- a/pkg/lint/load.go +++ b/pkg/lint/load.go @@ -3,8 +3,10 @@ package lint import ( "context" "fmt" + "go/ast" "go/build" "go/parser" + "go/token" "os" "path/filepath" "strings" @@ -12,6 +14,7 @@ import ( "github.com/golangci/golangci-lint/pkg/goutils" "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/result/processors" "github.com/golangci/go-tools/ssa" "github.com/golangci/go-tools/ssa/ssautil" @@ -258,6 +261,30 @@ func separateNotCompilingPackages(lintCtx *linter.Context) { } } +func removeFakePkgFiles(info *loader.PackageInfo, fset *token.FileSet) { + newFiles := make([]*ast.File, 0, len(info.Files)) + for _, f := range info.Files { + if !processors.IsCgoFilename(fset.Position(f.Pos()).Filename) { + newFiles = append(newFiles, f) + } + } + info.Files = newFiles +} + +func removeFakePackages(prog *loader.Program) { + if prog.Created != nil { + for _, info := range prog.Created { + removeFakePkgFiles(info, prog.Fset) + } + } + + if prog.Imported != nil { + for _, info := range prog.Imported { + removeFakePkgFiles(info, prog.Fset) + } + } +} + //nolint:gocyclo func LoadContext(ctx context.Context, linters []linter.Config, cfg *config.Config, log logutils.Log) (*linter.Context, error) { @@ -298,6 +325,10 @@ func LoadContext(ctx context.Context, linters []linter.Config, cfg *config.Confi ssaProg = buildSSAProgram(ctx, prog, log) } + if prog != nil { + removeFakePackages(prog) + } + astLog := log.Child("astcache") var astCache *astcache.Cache if prog != nil { diff --git a/pkg/result/processors/utils.go b/pkg/result/processors/utils.go index 0d84ad90..c577f550 100644 --- a/pkg/result/processors/utils.go +++ b/pkg/result/processors/utils.go @@ -2,7 +2,7 @@ package processors import ( "fmt" - "strings" + "path/filepath" "github.com/golangci/golangci-lint/pkg/result" ) @@ -47,5 +47,5 @@ func transformIssues(issues []result.Issue, transform func(i *result.Issue) *res } func IsCgoFilename(f string) bool { - return f == "C" || strings.HasSuffix(f, "/C") + return filepath.Base(f) == "C" } diff --git a/test/run_test.go b/test/run_test.go index b778c356..2c4216b4 100644 --- a/test/run_test.go +++ b/test/run_test.go @@ -131,6 +131,22 @@ func TestTestsAreLintedByDefault(t *testing.T) { assert.Equal(t, exitcodes.Success, exitCode, out) } +func TestCgoOk(t *testing.T) { + out, exitCode := runGolangciLint(t, "--enable-all", filepath.Join(testdataDir, "cgo")) + checkNoIssuesRun(t, out, exitCode) +} + +func TestUnsafeOk(t *testing.T) { + out, exitCode := runGolangciLint(t, "--enable-all", filepath.Join(testdataDir, "unsafe")) + checkNoIssuesRun(t, out, exitCode) +} + +func TestDeadcodeNoFalsePositivesInMainPkg(t *testing.T) { + out, exitCode := runGolangciLint(t, "--no-config", "--disable-all", "-Edeadcode", + filepath.Join(testdataDir, "deadcode_main_pkg")) + checkNoIssuesRun(t, out, exitCode) +} + func TestConfigFileIsDetected(t *testing.T) { checkGotConfig := func(out string, exitCode int) { assert.Equal(t, exitcodes.Success, exitCode, out) diff --git a/test/testdata/cgo/main.go b/test/testdata/cgo/main.go new file mode 100644 index 00000000..832bbbcc --- /dev/null +++ b/test/testdata/cgo/main.go @@ -0,0 +1,19 @@ +package cgoexample + +/* +#include +#include + +void myprint(char* s) { + printf("%d\n", s); +} +*/ +import "C" + +import "unsafe" + +func Example() { + cs := C.CString("Hello from stdio\n") + C.myprint(cs) + C.free(unsafe.Pointer(cs)) +} diff --git a/test/testdata/unsafe/pkg.go b/test/testdata/unsafe/pkg.go new file mode 100644 index 00000000..0a7e5874 --- /dev/null +++ b/test/testdata/unsafe/pkg.go @@ -0,0 +1,14 @@ +package pkg + +import ( + "log" + "unsafe" +) + +func F() { + x := 123 // of type int + p := unsafe.Pointer(&x) + pp := &p // of type *unsafe.Pointer + p = unsafe.Pointer(pp) + log.Print(p) +}