Skip to content

Commit f2a5ed8

Browse files
author
Bryan C. Mills
committed
cmd/cgo: use a named type to indicate syntactic context
We previously used bare strings, which made it difficult to see (and to cross-reference) the set of allowed context values. This change is purely cosmetic, but makes it easier for me to understand how to address #21878. updates #21878 Change-Id: I9027d94fd5997a0fe857c0055dea8719e1511f03 Reviewed-on: https://go-review.googlesource.com/63830 Run-TryBot: Bryan Mills <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent 3066dba commit f2a5ed8

File tree

3 files changed

+127
-105
lines changed

3 files changed

+127
-105
lines changed

src/cmd/cgo/ast.go

Lines changed: 116 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -126,16 +126,16 @@ func (f *File) ParseGo(name string, src []byte) {
126126
if f.Ref == nil {
127127
f.Ref = make([]*Ref, 0, 8)
128128
}
129-
f.walk(ast2, "prog", (*File).saveExprs)
129+
f.walk(ast2, ctxProg, (*File).saveExprs)
130130

131131
// Accumulate exported functions.
132132
// The comments are only on ast1 but we need to
133133
// save the function bodies from ast2.
134134
// The first walk fills in ExpFunc, and the
135135
// second walk changes the entries to
136136
// refer to ast2 instead.
137-
f.walk(ast1, "prog", (*File).saveExport)
138-
f.walk(ast2, "prog", (*File).saveExport2)
137+
f.walk(ast1, ctxProg, (*File).saveExport)
138+
f.walk(ast2, ctxProg, (*File).saveExport2)
139139

140140
f.Comments = ast1.Comments
141141
f.AST = ast2
@@ -166,7 +166,7 @@ func commentText(g *ast.CommentGroup) string {
166166
}
167167

168168
// Save various references we are going to need later.
169-
func (f *File) saveExprs(x interface{}, context string) {
169+
func (f *File) saveExprs(x interface{}, context astContext) {
170170
switch x := x.(type) {
171171
case *ast.Expr:
172172
switch (*x).(type) {
@@ -179,7 +179,7 @@ func (f *File) saveExprs(x interface{}, context string) {
179179
}
180180

181181
// Save references to C.xxx for later processing.
182-
func (f *File) saveRef(n *ast.Expr, context string) {
182+
func (f *File) saveRef(n *ast.Expr, context astContext) {
183183
sel := (*n).(*ast.SelectorExpr)
184184
// For now, assume that the only instance of capital C is when
185185
// used as the imported package identifier.
@@ -189,10 +189,10 @@ func (f *File) saveRef(n *ast.Expr, context string) {
189189
if l, ok := sel.X.(*ast.Ident); !ok || l.Name != "C" {
190190
return
191191
}
192-
if context == "as2" {
193-
context = "expr"
192+
if context == ctxAssign2 {
193+
context = ctxExpr
194194
}
195-
if context == "embed-type" {
195+
if context == ctxEmbedType {
196196
error_(sel.Pos(), "cannot embed C type")
197197
}
198198
goname := sel.Sel.Name
@@ -223,20 +223,20 @@ func (f *File) saveRef(n *ast.Expr, context string) {
223223
}
224224

225225
// Save calls to C.xxx for later processing.
226-
func (f *File) saveCall(call *ast.CallExpr, context string) {
226+
func (f *File) saveCall(call *ast.CallExpr, context astContext) {
227227
sel, ok := call.Fun.(*ast.SelectorExpr)
228228
if !ok {
229229
return
230230
}
231231
if l, ok := sel.X.(*ast.Ident); !ok || l.Name != "C" {
232232
return
233233
}
234-
c := &Call{Call: call, Deferred: context == "defer"}
234+
c := &Call{Call: call, Deferred: context == ctxDefer}
235235
f.Calls = append(f.Calls, c)
236236
}
237237

238238
// If a function should be exported add it to ExpFunc.
239-
func (f *File) saveExport(x interface{}, context string) {
239+
func (f *File) saveExport(x interface{}, context astContext) {
240240
n, ok := x.(*ast.FuncDecl)
241241
if !ok {
242242
return
@@ -276,7 +276,7 @@ func (f *File) saveExport(x interface{}, context string) {
276276
}
277277

278278
// Make f.ExpFunc[i] point at the Func from this AST instead of the other one.
279-
func (f *File) saveExport2(x interface{}, context string) {
279+
func (f *File) saveExport2(x interface{}, context astContext) {
280280
n, ok := x.(*ast.FuncDecl)
281281
if !ok {
282282
return
@@ -290,8 +290,30 @@ func (f *File) saveExport2(x interface{}, context string) {
290290
}
291291
}
292292

293+
type astContext int
294+
295+
const (
296+
ctxProg astContext = iota
297+
ctxEmbedType
298+
ctxType
299+
ctxStmt
300+
ctxExpr
301+
ctxField
302+
ctxParam
303+
ctxAssign2 // assignment of a single expression to two variables
304+
ctxSwitch
305+
ctxTypeSwitch
306+
ctxFile
307+
ctxDecl
308+
ctxSpec
309+
ctxDefer
310+
ctxCall // any function call other than ctxCall2
311+
ctxCall2 // function call whose result is assigned to two variables
312+
ctxSelector
313+
)
314+
293315
// walk walks the AST x, calling visit(f, x, context) for each node.
294-
func (f *File) walk(x interface{}, context string, visit func(*File, interface{}, string)) {
316+
func (f *File) walk(x interface{}, context astContext, visit func(*File, interface{}, astContext)) {
295317
visit(f, x, context)
296318
switch n := x.(type) {
297319
case *ast.Expr:
@@ -306,10 +328,10 @@ func (f *File) walk(x interface{}, context string, visit func(*File, interface{}
306328

307329
// These are ordered and grouped to match ../../go/ast/ast.go
308330
case *ast.Field:
309-
if len(n.Names) == 0 && context == "field" {
310-
f.walk(&n.Type, "embed-type", visit)
331+
if len(n.Names) == 0 && context == ctxField {
332+
f.walk(&n.Type, ctxEmbedType, visit)
311333
} else {
312-
f.walk(&n.Type, "type", visit)
334+
f.walk(&n.Type, ctxType, visit)
313335
}
314336
case *ast.FieldList:
315337
for _, field := range n.List {
@@ -320,163 +342,163 @@ func (f *File) walk(x interface{}, context string, visit func(*File, interface{}
320342
case *ast.Ellipsis:
321343
case *ast.BasicLit:
322344
case *ast.FuncLit:
323-
f.walk(n.Type, "type", visit)
324-
f.walk(n.Body, "stmt", visit)
345+
f.walk(n.Type, ctxType, visit)
346+
f.walk(n.Body, ctxStmt, visit)
325347
case *ast.CompositeLit:
326-
f.walk(&n.Type, "type", visit)
327-
f.walk(n.Elts, "expr", visit)
348+
f.walk(&n.Type, ctxType, visit)
349+
f.walk(n.Elts, ctxExpr, visit)
328350
case *ast.ParenExpr:
329351
f.walk(&n.X, context, visit)
330352
case *ast.SelectorExpr:
331-
f.walk(&n.X, "selector", visit)
353+
f.walk(&n.X, ctxSelector, visit)
332354
case *ast.IndexExpr:
333-
f.walk(&n.X, "expr", visit)
334-
f.walk(&n.Index, "expr", visit)
355+
f.walk(&n.X, ctxExpr, visit)
356+
f.walk(&n.Index, ctxExpr, visit)
335357
case *ast.SliceExpr:
336-
f.walk(&n.X, "expr", visit)
358+
f.walk(&n.X, ctxExpr, visit)
337359
if n.Low != nil {
338-
f.walk(&n.Low, "expr", visit)
360+
f.walk(&n.Low, ctxExpr, visit)
339361
}
340362
if n.High != nil {
341-
f.walk(&n.High, "expr", visit)
363+
f.walk(&n.High, ctxExpr, visit)
342364
}
343365
if n.Max != nil {
344-
f.walk(&n.Max, "expr", visit)
366+
f.walk(&n.Max, ctxExpr, visit)
345367
}
346368
case *ast.TypeAssertExpr:
347-
f.walk(&n.X, "expr", visit)
348-
f.walk(&n.Type, "type", visit)
369+
f.walk(&n.X, ctxExpr, visit)
370+
f.walk(&n.Type, ctxType, visit)
349371
case *ast.CallExpr:
350-
if context == "as2" {
351-
f.walk(&n.Fun, "call2", visit)
372+
if context == ctxAssign2 {
373+
f.walk(&n.Fun, ctxCall2, visit)
352374
} else {
353-
f.walk(&n.Fun, "call", visit)
375+
f.walk(&n.Fun, ctxCall, visit)
354376
}
355-
f.walk(n.Args, "expr", visit)
377+
f.walk(n.Args, ctxExpr, visit)
356378
case *ast.StarExpr:
357379
f.walk(&n.X, context, visit)
358380
case *ast.UnaryExpr:
359-
f.walk(&n.X, "expr", visit)
381+
f.walk(&n.X, ctxExpr, visit)
360382
case *ast.BinaryExpr:
361-
f.walk(&n.X, "expr", visit)
362-
f.walk(&n.Y, "expr", visit)
383+
f.walk(&n.X, ctxExpr, visit)
384+
f.walk(&n.Y, ctxExpr, visit)
363385
case *ast.KeyValueExpr:
364-
f.walk(&n.Key, "expr", visit)
365-
f.walk(&n.Value, "expr", visit)
386+
f.walk(&n.Key, ctxExpr, visit)
387+
f.walk(&n.Value, ctxExpr, visit)
366388

367389
case *ast.ArrayType:
368-
f.walk(&n.Len, "expr", visit)
369-
f.walk(&n.Elt, "type", visit)
390+
f.walk(&n.Len, ctxExpr, visit)
391+
f.walk(&n.Elt, ctxType, visit)
370392
case *ast.StructType:
371-
f.walk(n.Fields, "field", visit)
393+
f.walk(n.Fields, ctxField, visit)
372394
case *ast.FuncType:
373-
f.walk(n.Params, "param", visit)
395+
f.walk(n.Params, ctxParam, visit)
374396
if n.Results != nil {
375-
f.walk(n.Results, "param", visit)
397+
f.walk(n.Results, ctxParam, visit)
376398
}
377399
case *ast.InterfaceType:
378-
f.walk(n.Methods, "field", visit)
400+
f.walk(n.Methods, ctxField, visit)
379401
case *ast.MapType:
380-
f.walk(&n.Key, "type", visit)
381-
f.walk(&n.Value, "type", visit)
402+
f.walk(&n.Key, ctxType, visit)
403+
f.walk(&n.Value, ctxType, visit)
382404
case *ast.ChanType:
383-
f.walk(&n.Value, "type", visit)
405+
f.walk(&n.Value, ctxType, visit)
384406

385407
case *ast.BadStmt:
386408
case *ast.DeclStmt:
387-
f.walk(n.Decl, "decl", visit)
409+
f.walk(n.Decl, ctxDecl, visit)
388410
case *ast.EmptyStmt:
389411
case *ast.LabeledStmt:
390-
f.walk(n.Stmt, "stmt", visit)
412+
f.walk(n.Stmt, ctxStmt, visit)
391413
case *ast.ExprStmt:
392-
f.walk(&n.X, "expr", visit)
414+
f.walk(&n.X, ctxExpr, visit)
393415
case *ast.SendStmt:
394-
f.walk(&n.Chan, "expr", visit)
395-
f.walk(&n.Value, "expr", visit)
416+
f.walk(&n.Chan, ctxExpr, visit)
417+
f.walk(&n.Value, ctxExpr, visit)
396418
case *ast.IncDecStmt:
397-
f.walk(&n.X, "expr", visit)
419+
f.walk(&n.X, ctxExpr, visit)
398420
case *ast.AssignStmt:
399-
f.walk(n.Lhs, "expr", visit)
421+
f.walk(n.Lhs, ctxExpr, visit)
400422
if len(n.Lhs) == 2 && len(n.Rhs) == 1 {
401-
f.walk(n.Rhs, "as2", visit)
423+
f.walk(n.Rhs, ctxAssign2, visit)
402424
} else {
403-
f.walk(n.Rhs, "expr", visit)
425+
f.walk(n.Rhs, ctxExpr, visit)
404426
}
405427
case *ast.GoStmt:
406-
f.walk(n.Call, "expr", visit)
428+
f.walk(n.Call, ctxExpr, visit)
407429
case *ast.DeferStmt:
408-
f.walk(n.Call, "defer", visit)
430+
f.walk(n.Call, ctxDefer, visit)
409431
case *ast.ReturnStmt:
410-
f.walk(n.Results, "expr", visit)
432+
f.walk(n.Results, ctxExpr, visit)
411433
case *ast.BranchStmt:
412434
case *ast.BlockStmt:
413435
f.walk(n.List, context, visit)
414436
case *ast.IfStmt:
415-
f.walk(n.Init, "stmt", visit)
416-
f.walk(&n.Cond, "expr", visit)
417-
f.walk(n.Body, "stmt", visit)
418-
f.walk(n.Else, "stmt", visit)
437+
f.walk(n.Init, ctxStmt, visit)
438+
f.walk(&n.Cond, ctxExpr, visit)
439+
f.walk(n.Body, ctxStmt, visit)
440+
f.walk(n.Else, ctxStmt, visit)
419441
case *ast.CaseClause:
420-
if context == "typeswitch" {
421-
context = "type"
442+
if context == ctxTypeSwitch {
443+
context = ctxType
422444
} else {
423-
context = "expr"
445+
context = ctxExpr
424446
}
425447
f.walk(n.List, context, visit)
426-
f.walk(n.Body, "stmt", visit)
448+
f.walk(n.Body, ctxStmt, visit)
427449
case *ast.SwitchStmt:
428-
f.walk(n.Init, "stmt", visit)
429-
f.walk(&n.Tag, "expr", visit)
430-
f.walk(n.Body, "switch", visit)
450+
f.walk(n.Init, ctxStmt, visit)
451+
f.walk(&n.Tag, ctxExpr, visit)
452+
f.walk(n.Body, ctxSwitch, visit)
431453
case *ast.TypeSwitchStmt:
432-
f.walk(n.Init, "stmt", visit)
433-
f.walk(n.Assign, "stmt", visit)
434-
f.walk(n.Body, "typeswitch", visit)
454+
f.walk(n.Init, ctxStmt, visit)
455+
f.walk(n.Assign, ctxStmt, visit)
456+
f.walk(n.Body, ctxTypeSwitch, visit)
435457
case *ast.CommClause:
436-
f.walk(n.Comm, "stmt", visit)
437-
f.walk(n.Body, "stmt", visit)
458+
f.walk(n.Comm, ctxStmt, visit)
459+
f.walk(n.Body, ctxStmt, visit)
438460
case *ast.SelectStmt:
439-
f.walk(n.Body, "stmt", visit)
461+
f.walk(n.Body, ctxStmt, visit)
440462
case *ast.ForStmt:
441-
f.walk(n.Init, "stmt", visit)
442-
f.walk(&n.Cond, "expr", visit)
443-
f.walk(n.Post, "stmt", visit)
444-
f.walk(n.Body, "stmt", visit)
463+
f.walk(n.Init, ctxStmt, visit)
464+
f.walk(&n.Cond, ctxExpr, visit)
465+
f.walk(n.Post, ctxStmt, visit)
466+
f.walk(n.Body, ctxStmt, visit)
445467
case *ast.RangeStmt:
446-
f.walk(&n.Key, "expr", visit)
447-
f.walk(&n.Value, "expr", visit)
448-
f.walk(&n.X, "expr", visit)
449-
f.walk(n.Body, "stmt", visit)
468+
f.walk(&n.Key, ctxExpr, visit)
469+
f.walk(&n.Value, ctxExpr, visit)
470+
f.walk(&n.X, ctxExpr, visit)
471+
f.walk(n.Body, ctxStmt, visit)
450472

451473
case *ast.ImportSpec:
452474
case *ast.ValueSpec:
453-
f.walk(&n.Type, "type", visit)
475+
f.walk(&n.Type, ctxType, visit)
454476
if len(n.Names) == 2 && len(n.Values) == 1 {
455-
f.walk(&n.Values[0], "as2", visit)
477+
f.walk(&n.Values[0], ctxAssign2, visit)
456478
} else {
457-
f.walk(n.Values, "expr", visit)
479+
f.walk(n.Values, ctxExpr, visit)
458480
}
459481
case *ast.TypeSpec:
460-
f.walk(&n.Type, "type", visit)
482+
f.walk(&n.Type, ctxType, visit)
461483

462484
case *ast.BadDecl:
463485
case *ast.GenDecl:
464-
f.walk(n.Specs, "spec", visit)
486+
f.walk(n.Specs, ctxSpec, visit)
465487
case *ast.FuncDecl:
466488
if n.Recv != nil {
467-
f.walk(n.Recv, "param", visit)
489+
f.walk(n.Recv, ctxParam, visit)
468490
}
469-
f.walk(n.Type, "type", visit)
491+
f.walk(n.Type, ctxType, visit)
470492
if n.Body != nil {
471-
f.walk(n.Body, "stmt", visit)
493+
f.walk(n.Body, ctxStmt, visit)
472494
}
473495

474496
case *ast.File:
475-
f.walk(n.Decls, "decl", visit)
497+
f.walk(n.Decls, ctxDecl, visit)
476498

477499
case *ast.Package:
478500
for _, file := range n.Files {
479-
f.walk(file, "file", visit)
501+
f.walk(file, ctxFile, visit)
480502
}
481503

482504
case []ast.Decl:

0 commit comments

Comments
 (0)