From 07dca0fe14d717f7e44593d13d9a6767ec34a9cc Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 31 Jan 2023 11:34:16 -0800 Subject: go/types, types2: better error when trying to use ~ as bitwise operation When coming from C, the bitwise integer complement (bitwise negation) operator is ~, but in Go it is ^. Report an error mentioning ^ when ~ is used with an integer operand. Background: Some articles on the web claim that Go doesn't have a bitwise complement operator. Change-Id: I41185cae4a70d528754e44f42c13c013ed91bf27 Reviewed-on: https://go-review.googlesource.com/c/go/+/463747 Auto-Submit: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Griesemer Reviewed-by: Robert Findley TryBot-Result: Gopher Robot --- src/cmd/compile/internal/types2/expr.go | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'src/cmd/compile') diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 0433f8af95..472e30a069 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -178,7 +178,8 @@ func (check *Checker) unary(x *operand, e *syntax.Operation) { return } - switch e.Op { + op := e.Op + switch op { case syntax.And: // spec: "As an exception to the addressability // requirement x may also be a composite literal." @@ -215,13 +216,17 @@ func (check *Checker) unary(x *operand, e *syntax.Operation) { return case syntax.Tilde: - // Provide a better error position and message than what check.op below could do. - check.error(e, UndefinedOp, "cannot use ~ outside of interface or type constraint") - x.mode = invalid - return + // Provide a better error position and message than what check.op below would do. + if !allInteger(x.typ) { + check.error(e, UndefinedOp, "cannot use ~ outside of interface or type constraint") + x.mode = invalid + return + } + check.error(e, UndefinedOp, "cannot use ~ outside of interface or type constraint (use ^ for bitwise complement)") + op = syntax.Xor } - if !check.op(unaryOpPredicates, x, e.Op) { + if !check.op(unaryOpPredicates, x, op) { x.mode = invalid return } @@ -235,7 +240,7 @@ func (check *Checker) unary(x *operand, e *syntax.Operation) { if isUnsigned(x.typ) { prec = uint(check.conf.sizeof(x.typ) * 8) } - x.val = constant.UnaryOp(op2tok[e.Op], x.val, prec) + x.val = constant.UnaryOp(op2tok[op], x.val, prec) x.expr = e check.overflow(x) return -- cgit v1.3