@@ -7,6 +7,7 @@ package gc_test
7
7
import (
8
8
"cmd/internal/objfile"
9
9
"debug/dwarf"
10
+ "fmt"
10
11
"internal/testenv"
11
12
"io/ioutil"
12
13
"os"
@@ -39,6 +40,12 @@ type testline struct {
39
40
// Must be ordered alphabetically.
40
41
// Set to nil to skip the check.
41
42
vars []string
43
+
44
+ // decl is the list of variables declared at this line.
45
+ decl []string
46
+
47
+ // declBefore is the list of variables declared at or before this line.
48
+ declBefore []string
42
49
}
43
50
44
51
var testfile = []testline {
@@ -58,11 +65,11 @@ var testfile = []testline{
58
65
{line : "var floatch = make(chan float64)" },
59
66
{line : "var iface interface{}" },
60
67
{line : "func TestNestedFor() {" , vars : []string {"var a int" }},
61
- {line : " a := 0" },
68
+ {line : " a := 0" , decl : [] string { "a" } },
62
69
{line : " f1(a)" },
63
- {line : " for i := 0; i < 5; i++ {" , scopes : []int {1 }, vars : []string {"var i int" }},
70
+ {line : " for i := 0; i < 5; i++ {" , scopes : []int {1 }, vars : []string {"var i int" }, decl : [] string { "i" } },
64
71
{line : " f2(i)" , scopes : []int {1 }},
65
- {line : " for i := 0; i < 5; i++ {" , scopes : []int {1 , 2 }, vars : []string {"var i int" }},
72
+ {line : " for i := 0; i < 5; i++ {" , scopes : []int {1 , 2 }, vars : []string {"var i int" }, decl : [] string { "i" } },
66
73
{line : " f3(i)" , scopes : []int {1 , 2 }},
67
74
{line : " }" },
68
75
{line : " f4(i)" , scopes : []int {1 }},
@@ -153,7 +160,7 @@ var testfile = []testline{
153
160
{line : "}" },
154
161
{line : "func TestClosureScope() {" , vars : []string {"var a int" , "var b int" , "var f func(int)" }},
155
162
{line : " a := 1; b := 1" },
156
- {line : " f := func(c int) {" , scopes : []int {0 }, vars : []string {"arg c int" , "var &b *int" , "var a int" , "var d int" }},
163
+ {line : " f := func(c int) {" , scopes : []int {0 }, vars : []string {"arg c int" , "var &b *int" , "var a int" , "var d int" }, declBefore : [] string { "&b" , "a" } },
157
164
{line : " d := 3" },
158
165
{line : " f1(c); f1(d)" },
159
166
{line : " if e := 3; e != 0 {" , scopes : []int {1 }, vars : []string {"var e int" }},
@@ -286,7 +293,18 @@ func TestScopeRanges(t *testing.T) {
286
293
if len (out ) > 0 {
287
294
varsok = checkVars (testfile [i ].vars , out [len (out )- 1 ].vars )
288
295
if ! varsok {
289
- t .Logf ("variable mismatch at line %d %q for scope %d: expected: %v got: %v\n " , i , testfile [i ].line , out [len (out )- 1 ].id , testfile [i ].vars , out [len (out )- 1 ].vars )
296
+ t .Logf ("variable mismatch at line %d %q for scope %d: expected: %v got: %v\n " , i + 1 , testfile [i ].line , out [len (out )- 1 ].id , testfile [i ].vars , out [len (out )- 1 ].vars )
297
+ }
298
+ for j := range testfile [i ].decl {
299
+ if line := declLineForVar (out [len (out )- 1 ].vars , testfile [i ].decl [j ]); line != i + 1 {
300
+ t .Errorf ("wrong declaration line for variable %s, expected %d got: %d" , testfile [i ].decl [j ], i + 1 , line )
301
+ }
302
+ }
303
+
304
+ for j := range testfile [i ].declBefore {
305
+ if line := declLineForVar (out [len (out )- 1 ].vars , testfile [i ].declBefore [j ]); line > i + 1 {
306
+ t .Errorf ("wrong declaration line for variable %s, expected %d (or less) got: %d" , testfile [i ].declBefore [j ], i + 1 , line )
307
+ }
290
308
}
291
309
}
292
310
}
@@ -323,25 +341,43 @@ func checkScopes(tgt []int, out []*lexblock) bool {
323
341
return true
324
342
}
325
343
326
- func checkVars (tgt , out []string ) bool {
344
+ func checkVars (tgt [] string , out []variable ) bool {
327
345
if len (tgt ) != len (out ) {
328
346
return false
329
347
}
330
348
for i := range tgt {
331
- if tgt [i ] != out [i ] {
349
+ if tgt [i ] != out [i ]. expr {
332
350
return false
333
351
}
334
352
}
335
353
return true
336
354
}
337
355
356
+ func declLineForVar (scope []variable , name string ) int {
357
+ for i := range scope {
358
+ if scope [i ].name () == name {
359
+ return scope [i ].declLine
360
+ }
361
+ }
362
+ return - 1
363
+ }
364
+
338
365
type lexblock struct {
339
366
id int
340
367
ranges [][2 ]uint64
341
- vars []string
368
+ vars []variable
342
369
scopes []lexblock
343
370
}
344
371
372
+ type variable struct {
373
+ expr string
374
+ declLine int
375
+ }
376
+
377
+ func (v * variable ) name () string {
378
+ return strings .Split (v .expr , " " )[1 ]
379
+ }
380
+
345
381
type line struct {
346
382
file string
347
383
lineno int
@@ -369,20 +405,22 @@ func readScope(ctxt *scopexplainContext, scope *lexblock, entry *dwarf.Entry) {
369
405
}
370
406
switch e .Tag {
371
407
case 0 :
372
- sort .Strings (scope .vars )
408
+ sort .Slice (scope .vars , func (i , j int ) bool {
409
+ return scope .vars [i ].expr < scope .vars [j ].expr
410
+ })
373
411
return
374
412
case dwarf .TagFormalParameter :
375
413
typ , err := ctxt .dwarfData .Type (e .Val (dwarf .AttrType ).(dwarf.Offset ))
376
414
if err != nil {
377
415
panic (err )
378
416
}
379
- scope .vars = append (scope .vars , "arg " + e . Val ( dwarf . AttrName ).( string ) + " " + typ . String ( ))
417
+ scope .vars = append (scope .vars , entryToVar ( e , "arg" , typ ))
380
418
case dwarf .TagVariable :
381
419
typ , err := ctxt .dwarfData .Type (e .Val (dwarf .AttrType ).(dwarf.Offset ))
382
420
if err != nil {
383
421
panic (err )
384
422
}
385
- scope .vars = append (scope .vars , "var " + e . Val ( dwarf . AttrName ).( string ) + " " + typ . String ( ))
423
+ scope .vars = append (scope .vars , entryToVar ( e , "var" , typ ))
386
424
case dwarf .TagLexDwarfBlock :
387
425
scope .scopes = append (scope .scopes , lexblock {id : ctxt .scopegen })
388
426
ctxt .scopegen ++
@@ -391,6 +429,13 @@ func readScope(ctxt *scopexplainContext, scope *lexblock, entry *dwarf.Entry) {
391
429
}
392
430
}
393
431
432
+ func entryToVar (e * dwarf.Entry , kind string , typ dwarf.Type ) variable {
433
+ return variable {
434
+ fmt .Sprintf ("%s %s %s" , kind , e .Val (dwarf .AttrName ).(string ), typ .String ()),
435
+ int (e .Val (dwarf .AttrDeclLine ).(int64 )),
436
+ }
437
+ }
438
+
394
439
// markLines marks all lines that belong to this scope with this scope
395
440
// Recursively calls markLines for all children scopes.
396
441
func (scope * lexblock ) markLines (pcln objfile.Liner , lines map [line ][]* lexblock ) {
0 commit comments