Skip to content

Commit 7929a0d

Browse files
dr2chasersc
authored andcommitted
cmd/compile: initialize line number properly for temporaries
The expansion of structure, array, slice, and map literals does not use the right line number in its introduced assignments to temporaries, which leads to incorrect line number attribution for expressions in those literals. Inlining also incorrectly replaced the line numbers of args to inlined functions. This was revealed in CL 9721 because a now-avoided temporary assignment introduced the correct line number. I.e. before CL 9721 "tmp_wrongline := expr" was transformed to "tmp_rightline := expr; tmp_wrongline := tmp_rightline" Also includes a repair to CL 10334 involving line numbers where a spurious -1 remained (should have been 0, now is 0). Fixes #11400. Change-Id: I3a4687efe463977fa1e2c996606f4d91aaf22722 Reviewed-on: https://go-review.googlesource.com/11730 Run-TryBot: David Chase <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Sameer Ajmani <[email protected]> Reviewed-by: Russ Cox <[email protected]>
1 parent 2028077 commit 7929a0d

File tree

4 files changed

+123
-1
lines changed

4 files changed

+123
-1
lines changed

src/cmd/compile/internal/gc/inl.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -787,8 +787,15 @@ func mkinlcall1(np **Node, fn *Node, isddd bool) {
787787
call.Type = n.Type
788788
call.Typecheck = 1
789789

790+
// Hide the args from setlno -- the parameters to the inlined
791+
// call already have good line numbers that should be preserved.
792+
args := as.Rlist
793+
as.Rlist = nil
794+
790795
setlno(call, int(n.Lineno))
791796

797+
as.Rlist = args
798+
792799
//dumplist("call body", body);
793800

794801
*np = call

src/cmd/compile/internal/gc/sinit.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,7 @@ func staticcopy(l *Node, r *Node, out **NodeList) bool {
380380
rr.Orig = rr // completely separate copy
381381
rr.Type = ll.Type
382382
rr.Xoffset += e.Xoffset
383+
setlineno(rr)
383384
*out = list(*out, Nod(OAS, ll, rr))
384385
}
385386
}
@@ -484,6 +485,7 @@ func staticassign(l *Node, r *Node, out **NodeList) bool {
484485
if e.Expr.Op == OLITERAL {
485486
gdata(&n1, e.Expr, int(n1.Type.Width))
486487
} else {
488+
setlineno(e.Expr)
487489
a = Nod(OXXX, nil, nil)
488490
*a = n1
489491
a.Orig = a // completely separate copy
@@ -636,6 +638,7 @@ func structlit(ctxt int, pass int, n *Node, var_ *Node, init **NodeList) {
636638
}
637639

638640
// build list of var.field = expr
641+
setlineno(value)
639642
a = Nod(ODOT, var_, newname(index.Sym))
640643

641644
a = Nod(OAS, a, value)
@@ -703,6 +706,7 @@ func arraylit(ctxt int, pass int, n *Node, var_ *Node, init **NodeList) {
703706
}
704707

705708
// build list of var[index] = value
709+
setlineno(value)
706710
a = Nod(OINDEX, var_, index)
707711

708712
a = Nod(OAS, a, value)
@@ -866,6 +870,7 @@ func slicelit(ctxt int, n *Node, var_ *Node, init **NodeList) {
866870
}
867871

868872
// build list of var[c] = expr
873+
setlineno(value)
869874
a = Nod(OAS, a, value)
870875

871876
typecheck(&a, Etop)
@@ -954,6 +959,7 @@ func maplit(ctxt int, n *Node, var_ *Node, init **NodeList) {
954959

955960
if isliteral(index) && isliteral(value) {
956961
// build vstat[b].a = key;
962+
setlineno(index)
957963
a = Nodintconst(b)
958964

959965
a = Nod(OINDEX, vstat, a)
@@ -965,6 +971,7 @@ func maplit(ctxt int, n *Node, var_ *Node, init **NodeList) {
965971
*init = list(*init, a)
966972

967973
// build vstat[b].b = value;
974+
setlineno(value)
968975
a = Nodintconst(b)
969976

970977
a = Nod(OINDEX, vstat, a)
@@ -1032,15 +1039,18 @@ func maplit(ctxt int, n *Node, var_ *Node, init **NodeList) {
10321039
val = temp(var_.Type.Type)
10331040
}
10341041

1042+
setlineno(r.Left)
10351043
a = Nod(OAS, key, r.Left)
10361044
typecheck(&a, Etop)
10371045
walkstmt(&a)
10381046
*init = list(*init, a)
1047+
setlineno(r.Right)
10391048
a = Nod(OAS, val, r.Right)
10401049
typecheck(&a, Etop)
10411050
walkstmt(&a)
10421051
*init = list(*init, a)
10431052

1053+
setlineno(val)
10441054
a = Nod(OAS, Nod(OINDEX, var_, key), val)
10451055
typecheck(&a, Etop)
10461056
walkstmt(&a)

src/cmd/compile/internal/gc/subr.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -770,7 +770,7 @@ func treecopy(n *Node, lineno int32) *Node {
770770
m.Left = treecopy(n.Left, lineno)
771771
m.Right = treecopy(n.Right, lineno)
772772
m.List = listtreecopy(n.List, lineno)
773-
if lineno != -1 {
773+
if lineno != 0 {
774774
m.Lineno = lineno
775775
}
776776
if m.Name != nil && n.Op != ODCLFIELD {

src/runtime/symtab_test.go

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,108 @@ func testCallerBar(t *testing.T) {
4545
}
4646
}
4747
}
48+
49+
func lineNumber() int {
50+
_, _, line, _ := runtime.Caller(1)
51+
return line // return 0 for error
52+
}
53+
54+
// Do not add/remove lines in this block without updating the line numbers.
55+
var firstLine = lineNumber() // 0
56+
var ( // 1
57+
lineVar1 = lineNumber() // 2
58+
lineVar2a, lineVar2b = lineNumber(), lineNumber() // 3
59+
) // 4
60+
var compLit = []struct { // 5
61+
lineA, lineB int // 6
62+
}{ // 7
63+
{ // 8
64+
lineNumber(), lineNumber(), // 9
65+
}, // 10
66+
{ // 11
67+
lineNumber(), // 12
68+
lineNumber(), // 13
69+
}, // 14
70+
{ // 15
71+
lineB: lineNumber(), // 16
72+
lineA: lineNumber(), // 17
73+
}, // 18
74+
} // 19
75+
var arrayLit = [...]int{lineNumber(), // 20
76+
lineNumber(), lineNumber(), // 21
77+
lineNumber(), // 22
78+
} // 23
79+
var sliceLit = []int{lineNumber(), // 24
80+
lineNumber(), lineNumber(), // 25
81+
lineNumber(), // 26
82+
} // 27
83+
var mapLit = map[int]int{ // 28
84+
29: lineNumber(), // 29
85+
30: lineNumber(), // 30
86+
lineNumber(): 31, // 31
87+
lineNumber(): 32, // 32
88+
} // 33
89+
var intLit = lineNumber() + // 34
90+
lineNumber() + // 35
91+
lineNumber() // 36
92+
func trythis() { // 37
93+
recordLines(lineNumber(), // 38
94+
lineNumber(), // 39
95+
lineNumber()) // 40
96+
}
97+
98+
// Modifications below this line are okay.
99+
100+
var l38, l39, l40 int
101+
102+
func recordLines(a, b, c int) {
103+
l38 = a
104+
l39 = b
105+
l40 = c
106+
}
107+
108+
func TestLineNumber(t *testing.T) {
109+
trythis()
110+
for _, test := range []struct {
111+
name string
112+
val int
113+
want int
114+
}{
115+
{"firstLine", firstLine, 0},
116+
{"lineVar1", lineVar1, 2},
117+
{"lineVar2a", lineVar2a, 3},
118+
{"lineVar2b", lineVar2b, 3},
119+
{"compLit[0].lineA", compLit[0].lineA, 9},
120+
{"compLit[0].lineB", compLit[0].lineB, 9},
121+
{"compLit[1].lineA", compLit[1].lineA, 12},
122+
{"compLit[1].lineB", compLit[1].lineB, 13},
123+
{"compLit[2].lineA", compLit[2].lineA, 17},
124+
{"compLit[2].lineB", compLit[2].lineB, 16},
125+
126+
{"arrayLit[0]", arrayLit[0], 20},
127+
{"arrayLit[1]", arrayLit[1], 21},
128+
{"arrayLit[2]", arrayLit[2], 21},
129+
{"arrayLit[3]", arrayLit[3], 22},
130+
131+
{"sliceLit[0]", sliceLit[0], 24},
132+
{"sliceLit[1]", sliceLit[1], 25},
133+
{"sliceLit[2]", sliceLit[2], 25},
134+
{"sliceLit[3]", sliceLit[3], 26},
135+
136+
{"mapLit[29]", mapLit[29], 29},
137+
{"mapLit[30]", mapLit[30], 30},
138+
{"mapLit[31]", mapLit[31+firstLine] + firstLine, 31}, // nb it's the key not the value
139+
{"mapLit[32]", mapLit[32+firstLine] + firstLine, 32}, // nb it's the key not the value
140+
141+
{"intLit", intLit - 2*firstLine, 34 + 35 + 36},
142+
143+
{"l38", l38, 38},
144+
{"l39", l39, 39},
145+
{"l40", l40, 40},
146+
} {
147+
if got := test.val - firstLine; got != test.want {
148+
t.Errorf("%s on firstLine+%d want firstLine+%d (firstLine=%d, val=%d)",
149+
test.name, got, test.want, firstLine, test.val)
150+
}
151+
}
152+
}

0 commit comments

Comments
 (0)