mirror of
https://github.com/golang/go
synced 2024-10-01 07:38:32 -06:00
go.tools/go/types: test against test/fixedbugs
Fixed several bugs: - lhs blank identifier may be parenthesized: (_) = 0 is ok - constant shift counts in non-constant shifts must be >= 0 - init functions must have a body Classified currently failing tests: - 10 classes of errors not checked at the moment R=adonovan, r CC=golang-dev https://golang.org/cl/11952046
This commit is contained in:
parent
976d735966
commit
caf3fc90ed
@ -110,12 +110,13 @@ func (check *checker) assignVar(lhs ast.Expr, x *operand) Type {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't evaluate lhs if it is the blank identifier.
|
// Don't evaluate lhs if it is the (possibly parenthesized) blank identifier.
|
||||||
if ident, _ := lhs.(*ast.Ident); ident != nil && ident.Name == "_" {
|
if ident, _ := unparen(lhs).(*ast.Ident); ident != nil && ident.Name == "_" {
|
||||||
check.recordObject(ident, nil)
|
check.recordObject(ident, nil)
|
||||||
// If the lhs is untyped, determine the default type.
|
// If the lhs is untyped, determine the default type.
|
||||||
// The spec is unclear about this, but gc appears to
|
// The spec is unclear about this, but gc appears to
|
||||||
// do this.
|
// do this.
|
||||||
|
// TODO(gri) This is still not correct (try: _ = nil; _ = 1<<1e3)
|
||||||
typ := x.typ
|
typ := x.typ
|
||||||
if isUntyped(typ) {
|
if isUntyped(typ) {
|
||||||
// convert untyped types to default types
|
// convert untyped types to default types
|
||||||
|
@ -542,7 +542,7 @@ func (check *checker) shift(x, y *operand, op token.Token) {
|
|||||||
const stupidShift = 1023 - 1 + 52 // so we can express smallestFloat64
|
const stupidShift = 1023 - 1 + 52 // so we can express smallestFloat64
|
||||||
s, ok := exact.Uint64Val(y.val)
|
s, ok := exact.Uint64Val(y.val)
|
||||||
if !ok || s > stupidShift {
|
if !ok || s > stupidShift {
|
||||||
check.invalidOp(y.pos(), "%s: stupid shift", y)
|
check.invalidOp(y.pos(), "stupid shift count %s", y)
|
||||||
x.mode = invalid
|
x.mode = invalid
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -577,6 +577,11 @@ func (check *checker) shift(x, y *operand, op token.Token) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// constant rhs must be >= 0
|
||||||
|
if y.mode == constant && exact.Sign(y.val) < 0 {
|
||||||
|
check.invalidOp(y.pos(), "shift count %s must not be negative", y)
|
||||||
|
}
|
||||||
|
|
||||||
// non-constant shift - lhs must be an integer
|
// non-constant shift - lhs must be an integer
|
||||||
if !isInteger(x.typ) {
|
if !isInteger(x.typ) {
|
||||||
check.invalidOp(x.pos(), "shifted operand %s must be integer", x)
|
check.invalidOp(x.pos(), "shifted operand %s must be integer", x)
|
||||||
|
@ -288,6 +288,11 @@ func (check *checker) resolveFiles(files []*ast.File) {
|
|||||||
// don't declare init functions in the package scope - they are invisible
|
// don't declare init functions in the package scope - they are invisible
|
||||||
obj.parent = pkg.scope
|
obj.parent = pkg.scope
|
||||||
check.recordObject(d.Name, obj)
|
check.recordObject(d.Name, obj)
|
||||||
|
// init functions must have a body
|
||||||
|
if d.Body == nil {
|
||||||
|
check.errorf(obj.pos, "missing function body")
|
||||||
|
// ok to continue
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
check.declareObj(pkg.scope, d.Name, obj)
|
check.declareObj(pkg.scope, d.Name, obj)
|
||||||
}
|
}
|
||||||
|
@ -37,34 +37,21 @@ func TestStdlib(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStdtest(t *testing.T) {
|
func testTestDir(t *testing.T, path string, ignore ...string) {
|
||||||
path := filepath.Join(runtime.GOROOT(), "test")
|
|
||||||
|
|
||||||
files, err := ioutil.ReadDir(path)
|
files, err := ioutil.ReadDir(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
excluded := make(map[string]bool)
|
||||||
|
for _, filename := range ignore {
|
||||||
|
excluded[filename] = true
|
||||||
|
}
|
||||||
|
|
||||||
fset := token.NewFileSet()
|
fset := token.NewFileSet()
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
// filter directory contents
|
// filter directory contents
|
||||||
if f.IsDir() || !strings.HasSuffix(f.Name(), ".go") {
|
if f.IsDir() || !strings.HasSuffix(f.Name(), ".go") || excluded[f.Name()] {
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// explicitly exclude files that the type-checker still has problems with
|
|
||||||
switch f.Name() {
|
|
||||||
case "cmplxdivide.go":
|
|
||||||
// This test also needs file cmplxdivide1.go; ignore.
|
|
||||||
continue
|
|
||||||
case "goto.go", "label1.go":
|
|
||||||
// TODO(gri) implement missing label checks
|
|
||||||
continue
|
|
||||||
case "sizeof.go", "switch.go":
|
|
||||||
// TODO(gri) tone down duplicate checking in expression switches
|
|
||||||
continue
|
|
||||||
case "typeswitch2.go":
|
|
||||||
// TODO(gri) implement duplicate checking in type switches
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,13 +63,13 @@ func TestStdtest(t *testing.T) {
|
|||||||
file, err := parser.ParseFile(fset, filename, nil, parser.ParseComments|parser.AllErrors)
|
file, err := parser.ParseFile(fset, filename, nil, parser.ParseComments|parser.AllErrors)
|
||||||
|
|
||||||
// check per-file instructions
|
// check per-file instructions
|
||||||
// For now we only check two cases.
|
// For now we only check some cases.
|
||||||
expectErrors := false
|
expectErrors := false
|
||||||
if len(file.Comments) > 0 {
|
if len(file.Comments) > 0 {
|
||||||
if group := file.Comments[0]; len(group.List) > 0 {
|
if group := file.Comments[0]; len(group.List) > 0 {
|
||||||
cmd := strings.TrimSpace(group.List[0].Text[2:]) // 2: ignore // or /* of comment
|
cmd := strings.TrimSpace(group.List[0].Text[2:]) // 2: ignore // or /* of comment
|
||||||
switch cmd {
|
switch cmd {
|
||||||
case "skip":
|
case "skip", "compiledir":
|
||||||
continue
|
continue
|
||||||
case "errorcheck":
|
case "errorcheck":
|
||||||
expectErrors = true
|
expectErrors = true
|
||||||
@ -107,6 +94,33 @@ func TestStdtest(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestStdtest(t *testing.T) {
|
||||||
|
testTestDir(t, filepath.Join(runtime.GOROOT(), "test"),
|
||||||
|
"cmplxdivide.go", // also needs file cmplxdivide1.go - ignore
|
||||||
|
"goto.go", "label1.go", // TODO(gri) implement missing label checks
|
||||||
|
"sizeof.go", "switch.go", // TODO(gri) tone down duplicate checking in expr switches
|
||||||
|
"typeswitch2.go", // TODO(gri) implement duplicate checking in type switches
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestStdfixed(t *testing.T) {
|
||||||
|
testTestDir(t, filepath.Join(runtime.GOROOT(), "test/fixedbugs"),
|
||||||
|
"bug050.go", "bug088.go", "bug106.go", // TODO(gri) parser loses comments when bailing out early
|
||||||
|
"bug222.go", "bug282.go", "bug306.go", // TODO(gri) parser loses comments when bailing out early
|
||||||
|
"bug136.go", "bug179.go", "bug344.go", // TODO(gri) implement missing label checks
|
||||||
|
"bug165.go", // TODO(gri) isComparable not working for incomplete struct type
|
||||||
|
"bug176.go", // TODO(gri) composite literal array index must be non-negative constant
|
||||||
|
"bug200.go", // TODO(gri) complete duplicate checking in expr switches
|
||||||
|
"bug223.go", "bug413.go", "bug459.go", // TODO(gri) complete initialization checks
|
||||||
|
"bug248.go", "bug302.go", "bug369.go", // complex test instructions - ignore
|
||||||
|
"bug250.go", // TODO(gri) fix recursive interfaces
|
||||||
|
"bug326.go", // TODO(gri) assignment doesn't guard against len(rhs) == 0
|
||||||
|
"bug373.go", // TODO(gri) implement use checks
|
||||||
|
"bug376.go", // TODO(gri) built-ins must be called (no built-in function expressions)
|
||||||
|
"issue3924.go", // TODO(gri) && and || produce bool result (not untyped bool)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Package paths of excluded packages.
|
// Package paths of excluded packages.
|
||||||
var excluded = map[string]bool{
|
var excluded = map[string]bool{
|
||||||
"builtin": true,
|
"builtin": true,
|
||||||
|
1
go/types/testdata/decls0.src
vendored
1
go/types/testdata/decls0.src
vendored
@ -57,6 +57,7 @@ type init /* ERROR "cannot declare init" */ struct{}
|
|||||||
var _, init /* ERROR "cannot declare init" */ int
|
var _, init /* ERROR "cannot declare init" */ int
|
||||||
|
|
||||||
func init() {}
|
func init() {}
|
||||||
|
func init /* ERROR "missing function body" */ ()
|
||||||
|
|
||||||
func _() { const init = 0 }
|
func _() { const init = 0 }
|
||||||
func _() { type init int }
|
func _() { type init int }
|
||||||
|
25
go/types/testdata/shifts.src
vendored
25
go/types/testdata/shifts.src
vendored
@ -11,6 +11,7 @@ func shifts0() {
|
|||||||
_ = 0<<0
|
_ = 0<<0
|
||||||
_ = 1<<s
|
_ = 1<<s
|
||||||
_ = 1<<- /* ERROR "stupid shift" */ 1
|
_ = 1<<- /* ERROR "stupid shift" */ 1
|
||||||
|
_ = 1<<1075 /* ERROR "stupid shift" */
|
||||||
_ = 2.0<<1
|
_ = 2.0<<1
|
||||||
|
|
||||||
_ int = 2<<s
|
_ int = 2<<s
|
||||||
@ -30,20 +31,20 @@ func shifts0() {
|
|||||||
func shifts1() {
|
func shifts1() {
|
||||||
// basic non-constant shifts
|
// basic non-constant shifts
|
||||||
var (
|
var (
|
||||||
i0 int
|
i int
|
||||||
u0 uint
|
u uint
|
||||||
|
|
||||||
v0 = 1<<0
|
_ = 1<<0
|
||||||
v1 = 1<<i0 /* ERROR "must be unsigned" */
|
_ = 1<<i /* ERROR "must be unsigned" */
|
||||||
v2 = 1<<u0
|
_ = 1<<u
|
||||||
v3 = 1<<"foo" /* ERROR "cannot convert" */
|
_ = 1<<"foo" /* ERROR "cannot convert" */
|
||||||
v4 = 1<<- /* ERROR "stupid shift" */ 1
|
_ = i<<0
|
||||||
v5 = 1<<1075 /* ERROR "stupid shift" */
|
_ = i<<- /* ERROR "must not be negative" */ 1
|
||||||
v6 = 1 /* ERROR "overflows" */ <<100
|
_ = 1 /* ERROR "overflows" */ <<100
|
||||||
|
|
||||||
v10 uint = 1 << 0
|
_ uint = 1 << 0
|
||||||
v11 uint = 1 << u0
|
_ uint = 1 << u
|
||||||
v12 float32 = 1 /* ERROR "must be integer" */ << u0
|
_ float32 = 1 /* ERROR "must be integer" */ << u
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
5
go/types/testdata/stmt0.src
vendored
5
go/types/testdata/stmt0.src
vendored
@ -55,6 +55,11 @@ func assignments() {
|
|||||||
g := func(int, bool){}
|
g := func(int, bool){}
|
||||||
var m map[int]int
|
var m map[int]int
|
||||||
g/* ERROR "too few arguments" */ (m[0])
|
g/* ERROR "too few arguments" */ (m[0])
|
||||||
|
|
||||||
|
// assignments to _
|
||||||
|
_ = nil /* ERROR "use of untyped nil" */
|
||||||
|
_ = 1<<1000 // TODO(gri) this should fail
|
||||||
|
(_) = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func shortVarDecls() {
|
func shortVarDecls() {
|
||||||
|
Loading…
Reference in New Issue
Block a user