Commit 4ba1f258 authored by Robert Griesemer's avatar Robert Griesemer

go/types: better error message for certain unary/binary expression errors

Port of https://go-review.googlesource.com/11363.

Fixes #11367.

Change-Id: Ie0a82bcfab782c514d1947e7a6b190e286afd159
Reviewed-on: https://go-review.googlesource.com/11367Reviewed-by: default avatarAlan Donovan <adonovan@google.com>
parent a8ae93fd
...@@ -78,7 +78,8 @@ func (check *Checker) op(m opPredicates, x *operand, op token.Token) bool { ...@@ -78,7 +78,8 @@ func (check *Checker) op(m opPredicates, x *operand, op token.Token) bool {
return true return true
} }
func (check *Checker) unary(x *operand, op token.Token) { // The unary expression e may be nil. It's passed in for better error messages only.
func (check *Checker) unary(x *operand, e *ast.UnaryExpr, op token.Token) {
switch op { switch op {
case token.AND: case token.AND:
// spec: "As an exception to the addressability // spec: "As an exception to the addressability
...@@ -125,6 +126,9 @@ func (check *Checker) unary(x *operand, op token.Token) { ...@@ -125,6 +126,9 @@ func (check *Checker) unary(x *operand, op token.Token) {
// Typed constants must be representable in // Typed constants must be representable in
// their type after each constant operation. // their type after each constant operation.
if isTyped(typ) { if isTyped(typ) {
if e != nil {
x.expr = e // for better error message
}
check.representable(x, typ) check.representable(x, typ)
} }
return return
...@@ -721,7 +725,8 @@ var binaryOpPredicates = opPredicates{ ...@@ -721,7 +725,8 @@ var binaryOpPredicates = opPredicates{
token.LOR: isBoolean, token.LOR: isBoolean,
} }
func (check *Checker) binary(x *operand, lhs, rhs ast.Expr, op token.Token) { // The binary expression e may be nil. It's passed in for better error messages only.
func (check *Checker) binary(x *operand, e *ast.BinaryExpr, lhs, rhs ast.Expr, op token.Token) {
var y operand var y operand
check.expr(x, lhs) check.expr(x, lhs)
...@@ -787,6 +792,9 @@ func (check *Checker) binary(x *operand, lhs, rhs ast.Expr, op token.Token) { ...@@ -787,6 +792,9 @@ func (check *Checker) binary(x *operand, lhs, rhs ast.Expr, op token.Token) {
// Typed constants must be representable in // Typed constants must be representable in
// their type after each constant operation. // their type after each constant operation.
if isTyped(typ) { if isTyped(typ) {
if e != nil {
x.expr = e // for better error message
}
check.representable(x, typ) check.representable(x, typ)
} }
return return
...@@ -1374,7 +1382,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { ...@@ -1374,7 +1382,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
if x.mode == invalid { if x.mode == invalid {
goto Error goto Error
} }
check.unary(x, e.Op) check.unary(x, e, e.Op)
if x.mode == invalid { if x.mode == invalid {
goto Error goto Error
} }
...@@ -1384,7 +1392,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { ...@@ -1384,7 +1392,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
} }
case *ast.BinaryExpr: case *ast.BinaryExpr:
check.binary(x, e.X, e.Y, e.Op) check.binary(x, e, e.X, e.Y, e.Op)
if x.mode == invalid { if x.mode == invalid {
goto Error goto Error
} }
......
...@@ -277,7 +277,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { ...@@ -277,7 +277,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
} }
var x operand var x operand
Y := &ast.BasicLit{ValuePos: s.X.Pos(), Kind: token.INT, Value: "1"} // use x's position Y := &ast.BasicLit{ValuePos: s.X.Pos(), Kind: token.INT, Value: "1"} // use x's position
check.binary(&x, s.X, Y, op) check.binary(&x, nil, s.X, Y, op)
if x.mode == invalid { if x.mode == invalid {
return return
} }
...@@ -309,7 +309,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) { ...@@ -309,7 +309,7 @@ func (check *Checker) stmt(ctxt stmtContext, s ast.Stmt) {
return return
} }
var x operand var x operand
check.binary(&x, s.Lhs[0], s.Rhs[0], op) check.binary(&x, nil, s.Lhs[0], s.Rhs[0], op)
if x.mode == invalid { if x.mode == invalid {
return return
} }
......
...@@ -25,6 +25,12 @@ var ( ...@@ -25,6 +25,12 @@ var (
b12 = <-b0 /* ERROR "cannot receive" */ b12 = <-b0 /* ERROR "cannot receive" */
b13 = & & /* ERROR "cannot take address" */ b0 b13 = & & /* ERROR "cannot take address" */ b0
// byte
_ = byte(0)
_ = byte(- /* ERROR "cannot convert" */ 1)
_ = - /* ERROR "-byte\(1\) \(constant -1 of type byte\) overflows byte" */ byte(1) // test for issue 11367
_ = byte /* ERROR "overflows byte" */ (0) - byte(1)
// int // int
i0 = 1 i0 = 1
i1 int = i0 i1 int = i0
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment