// newHeapaddr allocates heap memory for n and sets its heap address.
func (s *state) newHeapaddr(n *ir.Name) {
- s.setHeapaddr(n.Pos(), n, s.newObject(n.Type()))
+ s.setHeapaddr(n.Pos(), n, s.newObject(n.Type(), nil))
}
// setHeapaddr allocates a new PAUTO variable to store ptr (which must be non-nil)
}
// newObject returns an SSA value denoting new(typ).
-func (s *state) newObject(typ *types.Type) *ssa.Value {
+func (s *state) newObject(typ *types.Type, rtype *ssa.Value) *ssa.Value {
if typ.Size() == 0 {
return s.newValue1A(ssa.OpAddr, types.NewPtr(typ), ir.Syms.Zerobase, s.sb)
}
- return s.rtcall(ir.Syms.Newobject, true, []*types.Type{types.NewPtr(typ)}, s.reflectType(typ))[0]
+ if rtype == nil {
+ rtype = s.reflectType(typ)
+ }
+ return s.rtcall(ir.Syms.Newobject, true, []*types.Type{types.NewPtr(typ)}, rtype)[0]
}
func (s *state) checkPtrAlignment(n *ir.ConvExpr, v *ssa.Value, count *ssa.Value) {
if !n.Type().IsPtr() {
s.Fatalf("expected pointer type: %v", n.Type())
}
- elem := n.Type().Elem()
+ elem, rtypeExpr := n.Type().Elem(), n.ElemRType
if count != nil {
if !elem.IsArray() {
s.Fatalf("expected array type: %v", elem)
}
- elem = elem.Elem()
+ elem, rtypeExpr = elem.Elem(), n.ElemElemRType
}
size := elem.Size()
// Casting from larger type to smaller one is ok, so for smallest type, do nothing.
if count.Type.Size() != s.config.PtrSize {
s.Fatalf("expected count fit to an uintptr size, have: %d, want: %d", count.Type.Size(), s.config.PtrSize)
}
- s.rtcall(ir.Syms.CheckPtrAlignment, true, nil, v, s.reflectType(elem), count)
+ var rtype *ssa.Value
+ if rtypeExpr != nil {
+ rtype = s.expr(rtypeExpr)
+ } else {
+ rtype = s.reflectType(elem)
+ }
+ s.rtcall(ir.Syms.CheckPtrAlignment, true, nil, v, rtype, count)
}
// reflectType returns an SSA value representing a pointer to typ's
// reflection type descriptor.
func (s *state) reflectType(typ *types.Type) *ssa.Value {
+ // TODO(mdempsky): Make this Fatalf under Unified IR; frontend needs
+ // to supply RType expressions.
lsym := reflectdata.TypeLinksym(typ)
return s.entryNewValue1A(ssa.OpAddr, types.NewPtr(types.Types[types.TUINT8]), lsym, s.sb)
}
case ir.OLABEL:
n := n.(*ir.LabelStmt)
sym := n.Label
+ if sym.IsBlank() {
+ // Nothing to do because the label isn't targetable. See issue 52278.
+ break
+ }
lab := s.label(sym)
// The label might already have a target block via a goto.
case ir.ONEW:
n := n.(*ir.UnaryExpr)
- return s.newObject(n.Type().Elem())
+ var rtype *ssa.Value
+ if x, ok := n.X.(*ir.DynamicType); ok && x.Op() == ir.ODYNAMICTYPE {
+ rtype = s.expr(x.RType)
+ }
+ return s.newObject(n.Type().Elem(), rtype)
case ir.OUNSAFEADD:
n := n.(*ir.BinaryExpr)
if n.ITab != nil {
targetItab = s.expr(n.ITab)
}
- return s.dottype1(n.Pos(), n.X.Type(), n.Type(), iface, target, targetItab, commaok)
+ return s.dottype1(n.Pos(), n.X.Type(), n.Type(), iface, nil, target, targetItab, commaok)
}
func (s *state) dynamicDottype(n *ir.DynamicTypeAssertExpr, commaok bool) (res, resok *ssa.Value) {
iface := s.expr(n.X)
- var target, targetItab *ssa.Value
+ var source, target, targetItab *ssa.Value
+ if n.SrcRType != nil {
+ source = s.expr(n.SrcRType)
+ }
if !n.X.Type().IsEmptyInterface() && !n.Type().IsInterface() {
byteptr := s.f.Config.Types.BytePtr
targetItab = s.expr(n.ITab)
} else {
target = s.expr(n.RType)
}
- return s.dottype1(n.Pos(), n.X.Type(), n.Type(), iface, target, targetItab, commaok)
+ return s.dottype1(n.Pos(), n.X.Type(), n.Type(), iface, source, target, targetItab, commaok)
}
// dottype1 implements a x.(T) operation. iface is the argument (x), dst is the type we're asserting to (T)
// and src is the type we're asserting from.
+// source is the *runtime._type of src
// target is the *runtime._type of dst.
// If src is a nonempty interface and dst is not an interface, targetItab is an itab representing (dst, src). Otherwise it is nil.
// commaok is true if the caller wants a boolean success value. Otherwise, the generated code panics if the conversion fails.
-func (s *state) dottype1(pos src.XPos, src, dst *types.Type, iface, target, targetItab *ssa.Value, commaok bool) (res, resok *ssa.Value) {
+func (s *state) dottype1(pos src.XPos, src, dst *types.Type, iface, source, target, targetItab *ssa.Value, commaok bool) (res, resok *ssa.Value) {
byteptr := s.f.Config.Types.BytePtr
if dst.IsInterface() {
if dst.IsEmptyInterface() {
if !commaok {
// on failure, panic by calling panicdottype
s.startBlock(bFail)
- taddr := s.reflectType(src)
+ taddr := source
+ if taddr == nil {
+ taddr = s.reflectType(src)
+ }
if src.IsEmptyInterface() {
s.rtcall(ir.Syms.PanicdottypeE, false, nil, itab, target, taddr)
} else {
}
var env = func() (res envVars) {
- cmd := exec.Command("go", "env", "-json")
+ cmd := exec.Command(goTool(), "env", "-json")
stdout, err := cmd.StdoutPipe()
if err != nil {
log.Fatal("StdoutPipe:", err)
if tempDirIsGOPATH {
cmd.Env = append(cmd.Env, "GOPATH="+t.tempDir)
}
+ // Put the bin directory of the GOROOT that built this program
+ // first in the path. This ensures that tests that use the "go"
+ // tool use the same one that built this program. This ensures
+ // that if you do "../bin/go run run.go" in this directory, all
+ // the tests that start subprocesses that "go tool compile" or
+ // whatever, use ../bin/go as their go tool, not whatever happens
+ // to be first in the user's path.
+ path := os.Getenv("PATH")
+ newdir := filepath.Join(runtime.GOROOT(), "bin")
+ if path != "" {
+ path = newdir + string(filepath.ListSeparator) + path
+ } else {
+ path = newdir
+ }
+ cmd.Env = append(cmd.Env, "PATH="+path)
+
cmd.Env = append(cmd.Env, runenv...)
var err error
)
var go118Failures = setOf(
- "typeparam/nested.go", // 1.18 compiler doesn't support function-local types with generics
- "typeparam/issue51521.go", // 1.18 compiler produces bad panic message and link error
+ "typeparam/nested.go", // 1.18 compiler doesn't support function-local types with generics
+ "typeparam/issue51521.go", // 1.18 compiler produces bad panic message and link error
+ "typeparam/mdempsky/16.go", // 1.18 compiler uses interface shape type in failed type assertions
+ "typeparam/mdempsky/17.go", // 1.18 compiler mishandles implicit conversions from range loops
+ "typeparam/mdempsky/18.go", // 1.18 compiler mishandles implicit conversions in select statements
)
// In all of these cases, the 1.17 compiler reports reasonable errors, but either the
)
var unifiedFailures = setOf(
- "closure3.go", // unified IR numbers closures differently than -d=inlfuncswithclosures
- "escape4.go", // unified IR can inline f5 and f6; test doesn't expect this
- "inline.go", // unified IR reports function literal diagnostics on different lines than -d=inlfuncswithclosures
- "linkname3.go", // unified IR is missing some linkname errors
-
- "fixedbugs/issue42284.go", // prints "T(0) does not escape", but test expects "a.I(a.T(0)) does not escape"
- "fixedbugs/issue7921.go", // prints "… escapes to heap", but test expects "string(…) escapes to heap"
- "typeparam/issue47631.go", // unified IR can handle local type declarations
- "fixedbugs/issue42058a.go", // unified IR doesn't report channel element too large
- "fixedbugs/issue42058b.go", // unified IR doesn't report channel element too large
- "fixedbugs/issue49767.go", // unified IR doesn't report channel element too large
- "fixedbugs/issue49814.go", // unified IR doesn't report array type too large
+ "closure3.go", // unified IR numbers closures differently than -d=inlfuncswithclosures
+ "escape4.go", // unified IR can inline f5 and f6; test doesn't expect this
+
+ "typeparam/issue47631.go", // unified IR can handle local type declarations
)
func setOf(keys ...string) map[string]bool {