"fmt"
"go/constant"
"go/token"
+ "io"
"os"
"path/filepath"
"runtime"
"unicode/utf8"
"cmd/compile/internal/base"
+ "cmd/compile/internal/importer"
"cmd/compile/internal/ir"
"cmd/compile/internal/syntax"
"cmd/compile/internal/typecheck"
"cmd/compile/internal/types"
+ "cmd/compile/internal/types2"
"cmd/internal/objabi"
"cmd/internal/src"
)
// Each declaration in every *syntax.File is converted to a syntax tree
// and its root represented by *Node is appended to Target.Decls.
// Returns the total count of parsed lines.
-func ParseFiles(filenames []string) uint {
+func ParseFiles(filenames []string) (lines uint) {
noders := make([]*noder, 0, len(filenames))
// Limit the number of simultaneously open files.
sem := make(chan struct{}, runtime.GOMAXPROCS(0)+10)
sem <- struct{}{}
defer func() { <-sem }()
defer close(p.err)
- base := syntax.NewFileBase(filename)
+ fbase := syntax.NewFileBase(filename)
f, err := os.Open(filename)
if err != nil {
}
defer f.Close()
- p.file, _ = syntax.Parse(base, f, p.error, p.pragma, syntax.CheckBranches) // errors are tracked via p.error
+ mode := syntax.CheckBranches
+ if base.Flag.G != 0 {
+ mode |= syntax.AllowGenerics
+ }
+ p.file, _ = syntax.Parse(fbase, f, p.error, p.pragma, mode) // errors are tracked via p.error
}(filename)
}
- var lines uint
+ // generic noding phase (using new typechecker)
+ if base.Flag.G != 0 {
+ // setup and syntax error reporting
+ nodersmap := make(map[string]*noder)
+ var files []*syntax.File
+ for _, p := range noders {
+ for e := range p.err {
+ p.errorAt(e.Pos, "%s", e.Msg)
+ }
+
+ nodersmap[p.file.Pos().RelFilename()] = p
+ files = append(files, p.file)
+ lines += p.file.EOF.Line()
+
+ }
+ if base.SyntaxErrors() != 0 {
+ base.ErrorExit()
+ }
+
+ // typechecking
+ conf := types2.Config{
+ InferFromConstraints: true,
+ IgnoreBranches: true, // parser already checked via syntax.CheckBranches mode
+ CompilerErrorMessages: true, // use error strings matching existing compiler errors
+ Error: func(err error) {
+ terr := err.(types2.Error)
+ if len(terr.Msg) > 0 && terr.Msg[0] == '\t' {
+ // types2 reports error clarifications via separate
+ // error messages which are indented with a tab.
+ // Ignore them to satisfy tools and tests that expect
+ // only one error in such cases.
+ // TODO(gri) Need to adjust error reporting in types2.
+ return
+ }
+ p := nodersmap[terr.Pos.RelFilename()]
+ base.ErrorfAt(p.makeXPos(terr.Pos), "%s", terr.Msg)
+ },
+ Importer: &gcimports{
+ packages: make(map[string]*types2.Package),
+ lookup: func(path string) (io.ReadCloser, error) {
+ file, ok := findpkg(path)
+ if !ok {
+ return nil, fmt.Errorf("can't find import: %q", path)
+ }
+ return os.Open(file)
+ },
+ },
+ }
+ info := types2.Info{
+ Types: make(map[syntax.Expr]types2.TypeAndValue),
+ Defs: make(map[*syntax.Name]types2.Object),
+ Uses: make(map[*syntax.Name]types2.Object),
+ Selections: make(map[*syntax.SelectorExpr]*types2.Selection),
+ // expand as needed
+ }
+ conf.Check(base.Ctxt.Pkgpath, files, &info)
+ base.ExitIfErrors()
+ if base.Flag.G < 2 {
+ return
+ }
+
+ // noding
+ for _, p := range noders {
+ // errors have already been reported
+
+ p.typeInfo = &info
+ p.node()
+ lines += p.file.EOF.Line()
+ p.file = nil // release memory
+ base.ExitIfErrors()
+
+ // Always run testdclstack here, even when debug_dclstack is not set, as a sanity measure.
+ types.CheckDclstack()
+ }
+
+ types.LocalPkg.Height = myheight
+ return
+ }
+
+ // traditional (non-generic) noding phase
for _, p := range noders {
for e := range p.err {
p.errorAt(e.Pos, "%s", e.Msg)
}
p.node()
- lines += p.file.Lines
+ lines += p.file.EOF.Line()
p.file = nil // release memory
-
if base.SyntaxErrors() != 0 {
base.ErrorExit()
}
+
// Always run testdclstack here, even when debug_dclstack is not set, as a sanity measure.
types.CheckDclstack()
}
}
types.LocalPkg.Height = myheight
+ return
+}
- return lines
+// Temporary import helper to get type2-based type-checking going.
+type gcimports struct {
+ packages map[string]*types2.Package
+ lookup func(path string) (io.ReadCloser, error)
+}
+
+func (m *gcimports) Import(path string) (*types2.Package, error) {
+ return m.ImportFrom(path, "" /* no vendoring */, 0)
+}
+
+func (m *gcimports) ImportFrom(path, srcDir string, mode types2.ImportMode) (*types2.Package, error) {
+ if mode != 0 {
+ panic("mode must be 0")
+ }
+ return importer.Import(m.packages, path, srcDir, m.lookup)
}
// makeSrcPosBase translates from a *syntax.PosBase to a *src.PosBase.
trackScopes bool
scopeVars []int
+ // typeInfo provides access to the type information computed by the new
+ // typechecker. It is only present if -G is set, and all noders point to
+ // the same types.Info. For now this is a local field, if need be we can
+ // make it global.
+ typeInfo *types2.Info
+
lastCloseScopePos syntax.Pos
}
+// For now we provide these basic accessors to get to type and object
+// information of expression nodes during noding. Eventually we will
+// attach this information directly to the syntax tree which should
+// simplify access and make it more efficient as well.
+
+// typ returns the type and value information for the given expression.
+func (p *noder) typ(x syntax.Expr) types2.TypeAndValue {
+ return p.typeInfo.Types[x]
+}
+
+// def returns the object for the given name in its declaration.
+func (p *noder) def(x *syntax.Name) types2.Object {
+ return p.typeInfo.Defs[x]
+}
+
+// use returns the object for the given name outside its declaration.
+func (p *noder) use(x *syntax.Name) types2.Object {
+ return p.typeInfo.Uses[x]
+}
+
+// sel returns the selection information for the given selector expression.
+func (p *noder) sel(x *syntax.SelectorExpr) *types2.Selection {
+ return p.typeInfo.Selections[x]
+}
+
func (p *noder) funcBody(fn *ir.Func, block *syntax.BlockStmt) {
oldScope := p.scope
p.scope = 0
}
func (p *noder) importDecl(imp *syntax.ImportDecl) {
- if imp.Path.Bad {
+ if imp.Path == nil || imp.Path.Bad {
return // avoid follow-on errors if there was a syntax error
}
func (p *noder) varDecl(decl *syntax.VarDecl) []ir.Node {
names := p.declNames(ir.ONAME, decl.NameList)
typ := p.typeExprOrNil(decl.Type)
-
- var exprs []ir.Node
- if decl.Values != nil {
- exprs = p.exprList(decl.Values)
- }
+ exprs := p.exprList(decl.Values)
if pragma, ok := decl.Pragma.(*pragmas); ok {
if len(pragma.Embeds) > 0 {
}
func (p *noder) exprList(expr syntax.Expr) []ir.Node {
- if list, ok := expr.(*syntax.ListExpr); ok {
- return p.exprs(list.ElemList)
+ switch expr := expr.(type) {
+ case nil:
+ return nil
+ case *syntax.ListExpr:
+ return p.exprs(expr.ElemList)
+ default:
+ return []ir.Node{p.expr(expr)}
}
- return []ir.Node{p.expr(expr)}
}
func (p *noder) exprs(exprs []syntax.Expr) []ir.Node {
case *syntax.Name:
return p.mkname(expr)
case *syntax.BasicLit:
- n := ir.NewLiteral(p.basicLit(expr))
+ n := ir.NewBasicLit(p.pos(expr), p.basicLit(expr))
if expr.Kind == syntax.RuneLit {
n.SetType(types.UntypedRune)
}
n.SetDiag(expr.Bad) // avoid follow-on errors if there was a syntax error
return n
case *syntax.CompositeLit:
- n := ir.NewCompLitExpr(p.pos(expr), ir.OCOMPLIT, nil, nil)
- if expr.Type != nil {
- n.Ntype = ir.Node(p.expr(expr.Type)).(ir.Ntype)
- }
+ n := ir.NewCompLitExpr(p.pos(expr), ir.OCOMPLIT, p.typeExpr(expr.Type), nil)
l := p.exprs(expr.ElemList)
for i, e := range l {
l[i] = p.wrapname(expr.ElemList[i], e)
if expr.Full {
op = ir.OSLICE3
}
- n := ir.NewSliceExpr(p.pos(expr), op, p.expr(expr.X))
+ x := p.expr(expr.X)
var index [3]ir.Node
- for i, x := range &expr.Index {
- if x != nil {
- index[i] = p.expr(x)
+ for i, n := range &expr.Index {
+ if n != nil {
+ index[i] = p.expr(n)
}
}
- n.SetSliceBounds(index[0], index[1], index[2])
- return n
+ return ir.NewSliceExpr(p.pos(expr), op, x, index[0], index[1], index[2])
case *syntax.AssertExpr:
- return ir.NewTypeAssertExpr(p.pos(expr), p.expr(expr.X), p.typeExpr(expr.Type).(ir.Ntype))
+ return ir.NewTypeAssertExpr(p.pos(expr), p.expr(expr.X), p.typeExpr(expr.Type))
case *syntax.Operation:
if expr.Op == syntax.Add && expr.Y != nil {
return p.sum(expr)
}
return ir.NewBinaryExpr(pos, op, x, y)
case *syntax.CallExpr:
- n := ir.NewCallExpr(p.pos(expr), ir.OCALL, p.expr(expr.Fun), nil)
- n.Args.Set(p.exprs(expr.ArgList))
+ n := ir.NewCallExpr(p.pos(expr), ir.OCALL, p.expr(expr.Fun), p.exprs(expr.ArgList))
n.IsDDD = expr.HasDots
return n
func (p *noder) stmtFall(stmt syntax.Stmt, fallOK bool) ir.Node {
p.setlineno(stmt)
switch stmt := stmt.(type) {
- case *syntax.EmptyStmt:
+ case nil, *syntax.EmptyStmt:
return nil
case *syntax.LabeledStmt:
return p.labeledStmt(stmt, fallOK)
}
return ir.NewGoDeferStmt(p.pos(stmt), op, p.expr(stmt.Call))
case *syntax.ReturnStmt:
- var results []ir.Node
- if stmt.Results != nil {
- results = p.exprList(stmt.Results)
- }
- n := ir.NewReturnStmt(p.pos(stmt), nil)
- n.Results.Set(results)
+ n := ir.NewReturnStmt(p.pos(stmt), p.exprList(stmt.Results))
if len(n.Results) == 0 && ir.CurFunc != nil {
for _, ln := range ir.CurFunc.Dcl {
if ln.Class_ == ir.PPARAM {
func (p *noder) ifStmt(stmt *syntax.IfStmt) ir.Node {
p.openScope(stmt.Pos())
- n := ir.NewIfStmt(p.pos(stmt), nil, nil, nil)
- if stmt.Init != nil {
- *n.PtrInit() = []ir.Node{p.stmt(stmt.Init)}
+ init := p.stmt(stmt.Init)
+ n := ir.NewIfStmt(p.pos(stmt), p.expr(stmt.Cond), p.blockStmt(stmt.Then), nil)
+ if init != nil {
+ *n.PtrInit() = []ir.Node{init}
}
- if stmt.Cond != nil {
- n.Cond = p.expr(stmt.Cond)
- }
- n.Body.Set(p.blockStmt(stmt.Then))
if stmt.Else != nil {
e := p.stmt(stmt.Else)
if e.Op() == ir.OBLOCK {
panic("unexpected RangeClause")
}
- n := ir.NewRangeStmt(p.pos(r), nil, p.expr(r.X), nil)
+ n := ir.NewRangeStmt(p.pos(r), nil, nil, p.expr(r.X), nil)
if r.Lhs != nil {
n.Def = r.Def
- n.Vars.Set(p.assignList(r.Lhs, n, n.Def))
+ lhs := p.assignList(r.Lhs, n, n.Def)
+ n.Key = lhs[0]
+ if len(lhs) > 1 {
+ n.Value = lhs[1]
+ }
}
n.Body.Set(p.blockStmt(stmt.Body))
p.closeAnotherScope()
return n
}
- n := ir.NewForStmt(p.pos(stmt), nil, nil, nil, nil)
- if stmt.Init != nil {
- *n.PtrInit() = []ir.Node{p.stmt(stmt.Init)}
- }
- if stmt.Cond != nil {
- n.Cond = p.expr(stmt.Cond)
- }
- if stmt.Post != nil {
- n.Post = p.stmt(stmt.Post)
- }
- n.Body.Set(p.blockStmt(stmt.Body))
+ n := ir.NewForStmt(p.pos(stmt), p.stmt(stmt.Init), p.expr(stmt.Cond), p.stmt(stmt.Post), p.blockStmt(stmt.Body))
p.closeAnotherScope()
return n
}
func (p *noder) switchStmt(stmt *syntax.SwitchStmt) ir.Node {
p.openScope(stmt.Pos())
- n := ir.NewSwitchStmt(p.pos(stmt), nil, nil)
- if stmt.Init != nil {
- *n.PtrInit() = []ir.Node{p.stmt(stmt.Init)}
- }
- if stmt.Tag != nil {
- n.Tag = p.expr(stmt.Tag)
+
+ init := p.stmt(stmt.Init)
+ n := ir.NewSwitchStmt(p.pos(stmt), p.expr(stmt.Tag), nil)
+ if init != nil {
+ *n.PtrInit() = []ir.Node{init}
}
var tswitch *ir.TypeSwitchGuard
if l := n.Tag; l != nil && l.Op() == ir.OTYPESW {
tswitch = l.(*ir.TypeSwitchGuard)
}
- n.Cases.Set(p.caseClauses(stmt.Body, tswitch, stmt.Rbrace))
+ n.Cases = p.caseClauses(stmt.Body, tswitch, stmt.Rbrace)
p.closeScope(stmt.Rbrace)
return n
}
- func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *ir.TypeSwitchGuard, rbrace syntax.Pos) []ir.Node {
- nodes := make([]ir.Node, 0, len(clauses))
+ func (p *noder) caseClauses(clauses []*syntax.CaseClause, tswitch *ir.TypeSwitchGuard, rbrace syntax.Pos) []*ir.CaseClause {
+ nodes := make([]*ir.CaseClause, 0, len(clauses))
for i, clause := range clauses {
p.setlineno(clause)
if i > 0 {
}
p.openScope(clause.Pos())
- n := ir.NewCaseStmt(p.pos(clause), nil, nil)
- if clause.Cases != nil {
- n.List.Set(p.exprList(clause.Cases))
- }
+ n := ir.NewCaseStmt(p.pos(clause), p.exprList(clause.Cases), nil)
if tswitch != nil && tswitch.Tag != nil {
nn := typecheck.NewName(tswitch.Tag.Sym())
typecheck.Declare(nn, typecheck.DeclContext)
- n.Vars = []ir.Node{nn}
+ n.Var = nn
// keep track of the instances for reporting unused
nn.Defn = tswitch
}
}
func (p *noder) selectStmt(stmt *syntax.SelectStmt) ir.Node {
- n := ir.NewSelectStmt(p.pos(stmt), nil)
- n.Cases.Set(p.commClauses(stmt.Body, stmt.Rbrace))
- return n
+ return ir.NewSelectStmt(p.pos(stmt), p.commClauses(stmt.Body, stmt.Rbrace))
}
- func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []ir.Node {
- nodes := make([]ir.Node, 0, len(clauses))
+ func (p *noder) commClauses(clauses []*syntax.CommClause, rbrace syntax.Pos) []*ir.CommClause {
+ nodes := make([]*ir.CommClause, len(clauses))
for i, clause := range clauses {
p.setlineno(clause)
if i > 0 {
}
p.openScope(clause.Pos())
- n := ir.NewCaseStmt(p.pos(clause), nil, nil)
- if clause.Comm != nil {
- n.List = []ir.Node{p.stmt(clause.Comm)}
- }
- n.Body.Set(p.stmts(clause.Body))
- nodes = append(nodes, n)
+ nodes[i] = ir.NewCommStmt(p.pos(clause), p.stmt(clause.Comm), p.stmts(clause.Body))
}
if len(clauses) > 0 {
p.closeScope(rbrace)
c = typecheck.NewName(s)
c.Class_ = ir.PAUTOHEAP
c.SetIsClosureVar(true)
- c.SetIsDDD(n.IsDDD())
c.Defn = n
// Link into list of active closure variables.
func _() {
// Note: if the next line changes to x, the error silences the x+x etc below!
- x1 // ERROR "x1 evaluated but not used"
+ x1 // ERROR "x1 .* not used"
- nil // ERROR "nil evaluated but not used"
- C // ERROR "C evaluated but not used"
- 1 // ERROR "1 evaluated but not used"
- x + x // ERROR "x \+ x evaluated but not used"
- x - x // ERROR "x - x evaluated but not used"
- x | x // ERROR "x \| x evaluated but not used"
- "a" + s // ERROR ".a. \+ s evaluated but not used"
- &x // ERROR "&x evaluated but not used"
- b && b // ERROR "b && b evaluated but not used"
- append(slice, 1) // ERROR "append\(slice, 1\) evaluated but not used"
- string(bytes) // ERROR "string\(bytes\) evaluated but not used"
- string(runes) // ERROR "string\(runes\) evaluated but not used"
+ nil // ERROR "nil .* not used"
+ C // ERROR "C .* not used"
+ 1 // ERROR "1 .* not used"
+ x + x // ERROR "x \+ x .* not used"
+ x - x // ERROR "x - x .* not used"
+ x | x // ERROR "x \| x .* not used"
+ "a" + s // ERROR ".a. \+ s .* not used"
+ &x // ERROR "&x .* not used"
+ b && b // ERROR "b && b .* not used"
+ append(slice, 1) // ERROR "append\(slice, 1\) .* not used"
+ string(bytes) // ERROR "string\(bytes\) .* not used"
+ string(runes) // ERROR "string\(runes\) .* not used"
f0() // ok
f1() // ok
f2() // ok
- _ = f0() // ERROR "f0\(\) used as value"
+ _ = f0() // ERROR "f0\(\) .*used as value"
_ = f1() // ok
_, _ = f2() // ok
- _ = f2() // ERROR "assignment mismatch: 1 variable but f2 returns 2 values"
- _ = f1(), 0 // ERROR "assignment mismatch: 1 variable but 2 values"
- T.M0 // ERROR "T.M0 evaluated but not used"
- t.M0 // ERROR "t.M0 evaluated but not used"
- cap // ERROR "use of builtin cap not in function call"
- cap(slice) // ERROR "cap\(slice\) evaluated but not used"
+ _ = f2() // ERROR "assignment mismatch: 1 variable but f2 returns 2 values|cannot assign"
++ _ = f1(), 0 // ERROR "assignment mismatch: 1 variable but 2 values|cannot assign"
+ T.M0 // ERROR "T.M0 .* not used"
+ t.M0 // ERROR "t.M0 .* not used"
+ cap // ERROR "use of builtin cap not in function call|must be called"
+ cap(slice) // ERROR "cap\(slice\) .* not used"
close(c) // ok
- _ = close(c) // ERROR "close\(c\) used as value"
- func() {} // ERROR "func literal evaluated but not used"
+ _ = close(c) // ERROR "close\(c\) .*used as value"
+ func() {} // ERROR "func literal .* not used|is not used"
X{} // ERROR "undefined: X"
- map[string]int{} // ERROR "map\[string\]int{} evaluated but not used"
- struct{}{} // ERROR "struct ?{}{} evaluated but not used"
- [1]int{} // ERROR "\[1\]int{} evaluated but not used"
- []int{} // ERROR "\[\]int{} evaluated but not used"
- &struct{}{} // ERROR "&struct ?{}{} evaluated but not used"
- float32(x) // ERROR "float32\(x\) evaluated but not used"
- I(t) // ERROR "I\(t\) evaluated but not used"
- int(x) // ERROR "int\(x\) evaluated but not used"
+ map[string]int{} // ERROR "map\[string\]int{} .* not used"
+ struct{}{} // ERROR "struct ?{}{} .* not used"
+ [1]int{} // ERROR "\[1\]int{} .* not used"
+ []int{} // ERROR "\[\]int{} .* not used"
+ &struct{}{} // ERROR "&struct ?{}{} .* not used"
+ float32(x) // ERROR "float32\(x\) .* not used"
+ I(t) // ERROR "I\(t\) .* not used"
+ int(x) // ERROR "int\(x\) .* not used"
copy(slice, slice) // ok
_ = copy(slice, slice) // ok
delete(m, 1) // ok
- _ = delete(m, 1) // ERROR "delete\(m, 1\) used as value"
- t.X // ERROR "t.X evaluated but not used"
- tp.X // ERROR "tp.X evaluated but not used"
- t.M // ERROR "t.M evaluated but not used"
- I.M // ERROR "I.M evaluated but not used"
- i.(T) // ERROR "i.\(T\) evaluated but not used"
- x == x // ERROR "x == x evaluated but not used"
- x != x // ERROR "x != x evaluated but not used"
- x != x // ERROR "x != x evaluated but not used"
- x < x // ERROR "x < x evaluated but not used"
- x >= x // ERROR "x >= x evaluated but not used"
- x > x // ERROR "x > x evaluated but not used"
- *tp // ERROR "\*tp evaluated but not used"
- slice[0] // ERROR "slice\[0\] evaluated but not used"
- m[1] // ERROR "m\[1\] evaluated but not used"
- len(slice) // ERROR "len\(slice\) evaluated but not used"
- make(chan int) // ERROR "make\(chan int\) evaluated but not used"
- make(map[int]int) // ERROR "make\(map\[int\]int\) evaluated but not used"
- make([]int, 1) // ERROR "make\(\[\]int, 1\) evaluated but not used"
- x * x // ERROR "x \* x evaluated but not used"
- x / x // ERROR "x / x evaluated but not used"
- x % x // ERROR "x % x evaluated but not used"
- x << x // ERROR "x << x evaluated but not used"
- x >> x // ERROR "x >> x evaluated but not used"
- x & x // ERROR "x & x evaluated but not used"
- x &^ x // ERROR "x &\^ x evaluated but not used"
- new(int) // ERROR "new\(int\) evaluated but not used"
- !b // ERROR "!b evaluated but not used"
- ^x // ERROR "\^x evaluated but not used"
- +x // ERROR "\+x evaluated but not used"
- -x // ERROR "-x evaluated but not used"
- b || b // ERROR "b \|\| b evaluated but not used"
+ _ = delete(m, 1) // ERROR "delete\(m, 1\) .*used as value"
+ t.X // ERROR "t.X .* not used"
+ tp.X // ERROR "tp.X .* not used"
+ t.M // ERROR "t.M .* not used"
+ I.M // ERROR "I.M .* not used"
+ i.(T) // ERROR "i.\(T\) .* not used"
+ x == x // ERROR "x == x .* not used"
+ x != x // ERROR "x != x .* not used"
+ x != x // ERROR "x != x .* not used"
+ x < x // ERROR "x < x .* not used"
+ x >= x // ERROR "x >= x .* not used"
+ x > x // ERROR "x > x .* not used"
+ *tp // ERROR "\*tp .* not used"
+ slice[0] // ERROR "slice\[0\] .* not used"
+ m[1] // ERROR "m\[1\] .* not used"
+ len(slice) // ERROR "len\(slice\) .* not used"
+ make(chan int) // ERROR "make\(chan int\) .* not used"
+ make(map[int]int) // ERROR "make\(map\[int\]int\) .* not used"
+ make([]int, 1) // ERROR "make\(\[\]int, 1\) .* not used"
+ x * x // ERROR "x \* x .* not used"
+ x / x // ERROR "x / x .* not used"
+ x % x // ERROR "x % x .* not used"
+ x << x // ERROR "x << x .* not used"
+ x >> x // ERROR "x >> x .* not used"
+ x & x // ERROR "x & x .* not used"
+ x &^ x // ERROR "x &\^ x .* not used"
+ new(int) // ERROR "new\(int\) .* not used"
+ !b // ERROR "!b .* not used"
+ ^x // ERROR "\^x .* not used"
+ +x // ERROR "\+x .* not used"
+ -x // ERROR "-x .* not used"
+ b || b // ERROR "b \|\| b .* not used"
panic(1) // ok
- _ = panic(1) // ERROR "panic\(1\) used as value"
+ _ = panic(1) // ERROR "panic\(1\) .*used as value"
print(1) // ok
- _ = print(1) // ERROR "print\(1\) used as value"
+ _ = print(1) // ERROR "print\(1\) .*used as value"
println(1) // ok
- _ = println(1) // ERROR "println\(1\) used as value"
+ _ = println(1) // ERROR "println\(1\) .*used as value"
c <- 1 // ok
- slice[1:1] // ERROR "slice\[1:1\] evaluated but not used"
- array[1:1] // ERROR "array\[1:1\] evaluated but not used"
- s[1:1] // ERROR "s\[1:1\] evaluated but not used"
- slice[1:1:1] // ERROR "slice\[1:1:1\] evaluated but not used"
- array[1:1:1] // ERROR "array\[1:1:1\] evaluated but not used"
+ slice[1:1] // ERROR "slice\[1:1\] .* not used"
+ array[1:1] // ERROR "array\[1:1\] .* not used"
+ s[1:1] // ERROR "s\[1:1\] .* not used"
+ slice[1:1:1] // ERROR "slice\[1:1:1\] .* not used"
+ array[1:1:1] // ERROR "array\[1:1:1\] .* not used"
recover() // ok
<-c // ok
- string(r) // ERROR "string\(r\) evaluated but not used"
- iota // ERROR "undefined: iota"
- real(cp) // ERROR "real\(cp\) evaluated but not used"
- imag(cp) // ERROR "imag\(cp\) evaluated but not used"
- complex(1, 2) // ERROR "complex\(1, 2\) evaluated but not used"
- unsafe.Alignof(t.X) // ERROR "unsafe.Alignof\(t.X\) evaluated but not used"
- unsafe.Offsetof(t.X) // ERROR "unsafe.Offsetof\(t.X\) evaluated but not used"
- unsafe.Sizeof(t) // ERROR "unsafe.Sizeof\(t\) evaluated but not used"
- _ = int // ERROR "type int is not an expression"
- (x) // ERROR "x evaluated but not used"
- _ = new(x2) // ERROR "x2 is not a type"
- _ = new(1 + 1) // ERROR "1 \+ 1 is not a type"
+ string(r) // ERROR "string\(r\) .* not used"
+ iota // ERROR "undefined: iota|cannot use iota"
+ real(cp) // ERROR "real\(cp\) .* not used"
+ imag(cp) // ERROR "imag\(cp\) .* not used"
+ complex(1, 2) // ERROR "complex\(1, 2\) .* not used"
+ unsafe.Alignof(t.X) // ERROR "unsafe.Alignof\(t.X\) .* not used"
+ unsafe.Offsetof(t.X) // ERROR "unsafe.Offsetof\(t.X\) .* not used"
+ unsafe.Sizeof(t) // ERROR "unsafe.Sizeof\(t\) .* not used"
+ _ = int // ERROR "type int is not an expression|not an expression"
+ (x) // ERROR "x .* not used|not used"
+ _ = new(x2) // ERROR "x2 is not a type|not a type"
+ // Disabled due to issue #43125.
+ // _ = new(1 + 1) // DISABLED "1 \+ 1 is not a type"
}