if n.Op == OLITERAL && !reuse {
// Can't always set n.Type directly on OLITERAL nodes.
// See discussion on CL 20813.
- n = n.copy()
+ n = n.rawcopy()
reuse = true
}
// Ensure n.Orig still points to a semantically-equivalent
// expression after we rewrite n into a constant.
if n.Orig == n {
- n.Orig = n.copy()
- n.Orig.Orig = n.Orig
+ n.Orig = n.sepcopy()
}
*n = Node{
}
if n.Op == OLITERAL && !reuse {
- n = n.copy()
+ n = n.rawcopy()
reuse = true
}
if l == n.Left {
return n
}
- a := n.copy()
- a.Orig = a
+ a := n.sepcopy()
a.Left = l
return typecheck(a, Erv)
}
if l == n.Left {
return n
}
- a := n.copy()
- a.Orig = a
+ a := n.sepcopy()
a.Left = l
return typecheck(a, Erv)
if l == n.Left {
return n
}
- a := n.copy()
- a.Orig = a
+ a := n.sepcopy()
a.Left = l
return typecheck(a, Erv)
if l == n.Left && r == n.Right {
return n
}
- a := n.copy()
- a.Orig = a
+ a := n.sepcopy()
a.Left = l
a.Right = r
return typecheck(a, Erv)
gdata(n, e.Expr, int(n.Type.Width))
continue
}
- ll := n.copy()
- ll.Orig = ll // completely separate copy
+ ll := n.sepcopy()
if staticassign(ll, e.Expr, out) {
continue
}
// Requires computation, but we're
// copying someone else's computation.
- rr := orig.copy()
- rr.Orig = rr // completely separate copy
+ rr := orig.sepcopy()
rr.Type = ll.Type
rr.Xoffset += e.Xoffset
setlineno(rr)
continue
}
setlineno(e.Expr)
- a := n.copy()
- a.Orig = a // completely separate copy
+ a := n.sepcopy()
if !staticassign(a, e.Expr, out) {
*out = append(*out, nod(OAS, a, e.Expr))
}
// Copy val directly into n.
n.Type = val.Type
setlineno(val)
- a := n.copy()
- a.Orig = a
+ a := n.sepcopy()
if !staticassign(a, val, out) {
*out = append(*out, nod(OAS, a, val))
}
return n
}
+// rawcopy returns a shallow copy of n.
+// Note: copy or sepcopy (rather than rawcopy) is usually the
+// correct choice (see comment with Node.copy, below).
+func (n *Node) rawcopy() *Node {
+ copy := *n
+ return ©
+}
+
+// sepcopy returns a separate shallow copy of n, with the copy's
+// Orig pointing to itself.
+func (n *Node) sepcopy() *Node {
+ copy := *n
+ copy.Orig = ©
+ return ©
+}
+
+// copy returns shallow copy of n and adjusts the copy's Orig if
+// necessary: In general, if n.Orig points to itself, the copy's
+// Orig should point to itself as well. Otherwise, if n is modified,
+// the copy's Orig node appears modified, too, and then doesn't
+// represent the original node anymore.
+// (This caused the wrong complit Op to be used when printing error
+// messages; see issues #26855, #27765).
func (n *Node) copy() *Node {
- n2 := *n
- return &n2
+ copy := *n
+ if n.Orig == n {
+ copy.Orig = ©
+ }
+ return ©
}
// methcmp sorts methods by symbol.
switch n.Op {
default:
- m := n.copy()
- m.Orig = m
+ m := n.sepcopy()
m.Left = treecopy(n.Left, pos)
m.Right = treecopy(n.Right, pos)
m.List.Set(listtreecopy(n.List.Slice(), pos))
// Save original node (including n.Right)
norig := n.copy()
- // If n.Orig points to itself, norig.Orig must point to itself, too.
- // Otherwise, because n.Op is changed below, n.Orig's Op is changed
- // as well because it (and the copy norig) still point to the original
- // node n. This caused the wrong complit Op to be used when printing
- // error messages (issue #26855).
- if n.Orig == n {
- norig.Orig = norig
- }
setlineno(n.Right)
n.Right = typecheck(n.Right, Etype|Ecomplit)
// The result of substArgTypes MUST be assigned back to old, e.g.
// n.Left = substArgTypes(n.Left, t1, t2)
func substArgTypes(old *Node, types_ ...*types.Type) *Node {
- n := old.copy() // make shallow copy
+ n := old.copy()
for _, t := range types_ {
dowidth(t)