mirror of
https://github.com/golang/go
synced 2024-10-14 20:05:36 +00:00
cmd/compile: don't constant-fold non-Go constants in the frontend
Abort evconst if its argument isn't a Go constant. The SSA backend will do the optimizations in question later. They tend to be weird cases, like uintptr(unsafe.Pointer(uintptr(1))). Fix OADDSTR and OCOMPLEX cases in isGoConst. OADDSTR has its arguments in n.List, not n.Left and n.Right. OCOMPLEX might have a 2-result function as its arg in List[0] (in which case it isn't a Go constant). Fixes #24760 Change-Id: Iab312d994240d99b3f69bfb33a443607e872b01d Reviewed-on: https://go-review.googlesource.com/c/151338 Run-TryBot: Keith Randall <khr@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
57c8eb92b7
commit
1602e49701
|
@ -584,6 +584,14 @@ func Isconst(n *Node, ct Ctype) bool {
|
|||
|
||||
// evconst rewrites constant expressions into OLITERAL nodes.
|
||||
func evconst(n *Node) {
|
||||
if !n.isGoConst() {
|
||||
// Avoid constant evaluation of things that aren't actually constants
|
||||
// according to the spec. See issue 24760.
|
||||
// The SSA backend has a more robust optimizer that will catch
|
||||
// all of these weird cases (like uintptr(unsafe.Pointer(uintptr(1)))).
|
||||
return
|
||||
}
|
||||
|
||||
nl, nr := n.Left, n.Right
|
||||
|
||||
// Pick off just the opcodes that can be constant evaluated.
|
||||
|
@ -1268,7 +1276,7 @@ func nonnegintconst(n *Node) int64 {
|
|||
//
|
||||
// Expressions derived from nil, like string([]byte(nil)), while they
|
||||
// may be known at compile time, are not Go language constants.
|
||||
// Only called for expressions known to evaluated to compile-time
|
||||
// Only called for expressions known to evaluate to compile-time
|
||||
// constants.
|
||||
func (n *Node) isGoConst() bool {
|
||||
if n.Orig != nil {
|
||||
|
@ -1277,7 +1285,6 @@ func (n *Node) isGoConst() bool {
|
|||
|
||||
switch n.Op {
|
||||
case OADD,
|
||||
OADDSTR,
|
||||
OAND,
|
||||
OANDAND,
|
||||
OANDNOT,
|
||||
|
@ -1301,13 +1308,25 @@ func (n *Node) isGoConst() bool {
|
|||
OSUB,
|
||||
OXOR,
|
||||
OIOTA,
|
||||
OCOMPLEX,
|
||||
OREAL,
|
||||
OIMAG:
|
||||
if n.Left.isGoConst() && (n.Right == nil || n.Right.isGoConst()) {
|
||||
return true
|
||||
}
|
||||
|
||||
case OCOMPLEX:
|
||||
if n.List.Len() == 0 && n.Left.isGoConst() && n.Right.isGoConst() {
|
||||
return true
|
||||
}
|
||||
|
||||
case OADDSTR:
|
||||
for _, n1 := range n.List.Slice() {
|
||||
if !n1.isGoConst() {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
|
||||
case OCONV:
|
||||
if okforconst[n.Type.Etype] && n.Left.isGoConst() {
|
||||
return true
|
||||
|
|
|
@ -1400,9 +1400,16 @@ func (n *Node) exprfmt(s fmt.State, prec int, mode fmtMode) {
|
|||
}
|
||||
mode.Fprintf(s, "sliceheader{%v,%v,%v}", n.Left, n.List.First(), n.List.Second())
|
||||
|
||||
case OCOPY, OCOMPLEX:
|
||||
case OCOPY:
|
||||
mode.Fprintf(s, "%#v(%v, %v)", n.Op, n.Left, n.Right)
|
||||
|
||||
case OCOMPLEX:
|
||||
if n.List.Len() == 1 {
|
||||
mode.Fprintf(s, "%#v(%v)", n.Op, n.List.First())
|
||||
} else {
|
||||
mode.Fprintf(s, "%#v(%v, %v)", n.Op, n.Left, n.Right)
|
||||
}
|
||||
|
||||
case OCONV,
|
||||
OCONVIFACE,
|
||||
OCONVNOP,
|
||||
|
|
|
@ -692,7 +692,7 @@ const (
|
|||
OIOTA // iota
|
||||
OREAL // real(Left)
|
||||
OIMAG // imag(Left)
|
||||
OCOMPLEX // complex(Left, Right)
|
||||
OCOMPLEX // complex(Left, Right) or complex(List[0]) where List[0] is a 2-result function call
|
||||
OALIGNOF // unsafe.Alignof(Left)
|
||||
OOFFSETOF // unsafe.Offsetof(Left)
|
||||
OSIZEOF // unsafe.Sizeof(Left)
|
||||
|
|
|
@ -6,4 +6,4 @@
|
|||
|
||||
package main
|
||||
|
||||
const A = complex(0()) // ERROR "cannot call non-function"
|
||||
const A = complex(0()) // ERROR "cannot call non-function" "const initializer .* is not a constant"
|
||||
|
|
12
test/fixedbugs/issue24760.go
Normal file
12
test/fixedbugs/issue24760.go
Normal file
|
@ -0,0 +1,12 @@
|
|||
// compile
|
||||
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package p
|
||||
|
||||
import "unsafe"
|
||||
|
||||
var _ = string([]byte(nil))[0]
|
||||
var _ = uintptr(unsafe.Pointer(uintptr(1))) << 100
|
Loading…
Reference in a new issue