1
2
3
4
5
6
7 package types2
8
9 import (
10 "cmd/compile/internal/syntax"
11 "go/constant"
12 "sort"
13 )
14
15 func (check *Checker) funcBody(decl *declInfo, name string, sig *Signature, body *syntax.BlockStmt, iota constant.Value) {
16 if check.conf.IgnoreFuncBodies {
17 panic("function body not ignored")
18 }
19
20 if check.conf.Trace {
21 check.trace(body.Pos(), "--- %s: %s", name, sig)
22 defer func() {
23 check.trace(syntax.EndPos(body), "--- <end>")
24 }()
25 }
26
27
28 sig.scope.pos = body.Pos()
29 sig.scope.end = syntax.EndPos(body)
30
31
32
33 defer func(env environment, indent int) {
34 check.environment = env
35 check.indent = indent
36 }(check.environment, check.indent)
37 check.environment = environment{
38 decl: decl,
39 scope: sig.scope,
40 iota: iota,
41 sig: sig,
42 }
43 check.indent = 0
44
45 check.stmtList(0, body.List)
46
47 if check.hasLabel && !check.conf.IgnoreLabels {
48 check.labels(body)
49 }
50
51 if sig.results.Len() > 0 && !check.isTerminating(body, "") {
52 check.error(body.Rbrace, "missing return")
53 }
54
55
56
57 check.usage(sig.scope)
58 }
59
60 func (check *Checker) usage(scope *Scope) {
61 var unused []*Var
62 for name, elem := range scope.elems {
63 elem = resolve(name, elem)
64 if v, _ := elem.(*Var); v != nil && !v.used {
65 unused = append(unused, v)
66 }
67 }
68 sort.Slice(unused, func(i, j int) bool {
69 return unused[i].pos.Cmp(unused[j].pos) < 0
70 })
71 for _, v := range unused {
72 check.softErrorf(v.pos, "%s declared but not used", v.name)
73 }
74
75 for _, scope := range scope.children {
76
77
78 if !scope.isFunc {
79 check.usage(scope)
80 }
81 }
82 }
83
84
85
86
87
88 type stmtContext uint
89
90 const (
91
92 breakOk stmtContext = 1 << iota
93 continueOk
94 fallthroughOk
95
96
97 finalSwitchCase
98 )
99
100 func (check *Checker) simpleStmt(s syntax.Stmt) {
101 if s != nil {
102 check.stmt(0, s)
103 }
104 }
105
106 func trimTrailingEmptyStmts(list []syntax.Stmt) []syntax.Stmt {
107 for i := len(list); i > 0; i-- {
108 if _, ok := list[i-1].(*syntax.EmptyStmt); !ok {
109 return list[:i]
110 }
111 }
112 return nil
113 }
114
115 func (check *Checker) stmtList(ctxt stmtContext, list []syntax.Stmt) {
116 ok := ctxt&fallthroughOk != 0
117 inner := ctxt &^ fallthroughOk
118 list = trimTrailingEmptyStmts(list)
119 for i, s := range list {
120 inner := inner
121 if ok && i+1 == len(list) {
122 inner |= fallthroughOk
123 }
124 check.stmt(inner, s)
125 }
126 }
127
128 func (check *Checker) multipleSwitchDefaults(list []*syntax.CaseClause) {
129 var first *syntax.CaseClause
130 for _, c := range list {
131 if c.Cases == nil {
132 if first != nil {
133 check.errorf(c, "multiple defaults (first at %s)", first.Pos())
134
135 } else {
136 first = c
137 }
138 }
139 }
140 }
141
142 func (check *Checker) multipleSelectDefaults(list []*syntax.CommClause) {
143 var first *syntax.CommClause
144 for _, c := range list {
145 if c.Comm == nil {
146 if first != nil {
147 check.errorf(c, "multiple defaults (first at %s)", first.Pos())
148
149 } else {
150 first = c
151 }
152 }
153 }
154 }
155
156 func (check *Checker) openScope(node syntax.Node, comment string) {
157 check.openScopeUntil(node, syntax.EndPos(node), comment)
158 }
159
160 func (check *Checker) openScopeUntil(node syntax.Node, end syntax.Pos, comment string) {
161 scope := NewScope(check.scope, node.Pos(), end, comment)
162 check.recordScope(node, scope)
163 check.scope = scope
164 }
165
166 func (check *Checker) closeScope() {
167 check.scope = check.scope.Parent()
168 }
169
170 func (check *Checker) suspendedCall(keyword string, call *syntax.CallExpr) {
171 var x operand
172 var msg string
173 switch check.rawExpr(&x, call, nil, false) {
174 case conversion:
175 msg = "requires function call, not conversion"
176 case expression:
177 msg = "discards result of"
178 case statement:
179 return
180 default:
181 unreachable()
182 }
183 check.errorf(&x, "%s %s %s", keyword, msg, &x)
184 }
185
186
187 func goVal(val constant.Value) interface{} {
188
189 if val == nil {
190 return nil
191 }
192
193
194
195
196 switch val.Kind() {
197 case constant.Int:
198 if x, ok := constant.Int64Val(val); ok {
199 return x
200 }
201 if x, ok := constant.Uint64Val(val); ok {
202 return x
203 }
204 case constant.Float:
205 if x, ok := constant.Float64Val(val); ok {
206 return x
207 }
208 case constant.String:
209 return constant.StringVal(val)
210 }
211 return nil
212 }
213
214
215
216
217
218
219
220 type (
221 valueMap map[interface{}][]valueType
222 valueType struct {
223 pos syntax.Pos
224 typ Type
225 }
226 )
227
228 func (check *Checker) caseValues(x *operand, values []syntax.Expr, seen valueMap) {
229 L:
230 for _, e := range values {
231 var v operand
232 check.expr(&v, e)
233 if x.mode == invalid || v.mode == invalid {
234 continue L
235 }
236 check.convertUntyped(&v, x.typ)
237 if v.mode == invalid {
238 continue L
239 }
240
241 res := v
242 check.comparison(&res, x, syntax.Eql, true)
243 if res.mode == invalid {
244 continue L
245 }
246 if v.mode != constant_ {
247 continue L
248 }
249
250 if val := goVal(v.val); val != nil {
251
252
253 for _, vt := range seen[val] {
254 if Identical(v.typ, vt.typ) {
255 var err error_
256 err.errorf(&v, "duplicate case %s in expression switch", &v)
257 err.errorf(vt.pos, "previous case")
258 check.report(&err)
259 continue L
260 }
261 }
262 seen[val] = append(seen[val], valueType{v.Pos(), v.typ})
263 }
264 }
265 }
266
267
268 func (check *Checker) isNil(e syntax.Expr) bool {
269
270 if name, _ := unparen(e).(*syntax.Name); name != nil {
271 _, ok := check.lookup(name.Value).(*Nil)
272 return ok
273 }
274 return false
275 }
276
277
278 func (check *Checker) caseTypes(x *operand, types []syntax.Expr, seen map[Type]syntax.Expr) (T Type) {
279 var dummy operand
280 L:
281 for _, e := range types {
282
283 if check.isNil(e) {
284 T = nil
285 check.expr(&dummy, e)
286 } else {
287 T = check.varType(e)
288 if T == Typ[Invalid] {
289 continue L
290 }
291 }
292
293
294 for t, other := range seen {
295 if T == nil && t == nil || T != nil && t != nil && Identical(T, t) {
296
297 Ts := "nil"
298 if T != nil {
299 Ts = TypeString(T, check.qualifier)
300 }
301 var err error_
302 err.errorf(e, "duplicate case %s in type switch", Ts)
303 err.errorf(other, "previous case")
304 check.report(&err)
305 continue L
306 }
307 }
308 seen[T] = e
309 if x != nil && T != nil {
310 check.typeAssertion(e, x, T, true)
311 }
312 }
313 return
314 }
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358 func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) {
359
360 if debug {
361 defer func(scope *Scope) {
362
363 if p := recover(); p != nil {
364 panic(p)
365 }
366 assert(scope == check.scope)
367 }(check.scope)
368 }
369
370
371 defer check.processDelayed(len(check.delayed))
372
373 inner := ctxt &^ (fallthroughOk | finalSwitchCase)
374 switch s := s.(type) {
375 case *syntax.EmptyStmt:
376
377
378 case *syntax.DeclStmt:
379 check.declStmt(s.DeclList)
380
381 case *syntax.LabeledStmt:
382 check.hasLabel = true
383 check.stmt(ctxt, s.Stmt)
384
385 case *syntax.ExprStmt:
386
387
388
389 var x operand
390 kind := check.rawExpr(&x, s.X, nil, false)
391 var msg string
392 switch x.mode {
393 default:
394 if kind == statement {
395 return
396 }
397 msg = "is not used"
398 case builtin:
399 msg = "must be called"
400 case typexpr:
401 msg = "is not an expression"
402 }
403 check.errorf(&x, "%s %s", &x, msg)
404
405 case *syntax.SendStmt:
406 var ch, val operand
407 check.expr(&ch, s.Chan)
408 check.expr(&val, s.Value)
409 if ch.mode == invalid || val.mode == invalid {
410 return
411 }
412 u := coreType(ch.typ)
413 if u == nil {
414 check.errorf(s, invalidOp+"cannot send to %s: no core type", &ch)
415 return
416 }
417 uch, _ := u.(*Chan)
418 if uch == nil {
419 check.errorf(s, invalidOp+"cannot send to non-channel %s", &ch)
420 return
421 }
422 if uch.dir == RecvOnly {
423 check.errorf(s, invalidOp+"cannot send to receive-only channel %s", &ch)
424 return
425 }
426 check.assignment(&val, uch.elem, "send")
427
428 case *syntax.AssignStmt:
429 lhs := unpackExpr(s.Lhs)
430 if s.Rhs == nil {
431
432 if len(lhs) != 1 {
433 check.errorf(s, invalidAST+"%s%s requires one operand", s.Op, s.Op)
434 return
435 }
436 var x operand
437 check.expr(&x, lhs[0])
438 if x.mode == invalid {
439 return
440 }
441 if !allNumeric(x.typ) {
442 check.errorf(lhs[0], invalidOp+"%s%s%s (non-numeric type %s)", lhs[0], s.Op, s.Op, x.typ)
443 return
444 }
445 check.assignVar(lhs[0], &x)
446 return
447 }
448
449 rhs := unpackExpr(s.Rhs)
450 switch s.Op {
451 case 0:
452 check.assignVars(lhs, rhs)
453 return
454 case syntax.Def:
455 check.shortVarDecl(s.Pos(), lhs, rhs)
456 return
457 }
458
459
460 if len(lhs) != 1 || len(rhs) != 1 {
461 check.errorf(s, "assignment operation %s requires single-valued expressions", s.Op)
462 return
463 }
464
465 var x operand
466 check.binary(&x, nil, lhs[0], rhs[0], s.Op)
467 check.assignVar(lhs[0], &x)
468
469 case *syntax.CallStmt:
470 kind := "go"
471 if s.Tok == syntax.Defer {
472 kind = "defer"
473 }
474 check.suspendedCall(kind, s.Call)
475
476 case *syntax.ReturnStmt:
477 res := check.sig.results
478
479
480 results := unpackExpr(s.Results)
481 if len(results) == 0 && res.Len() > 0 && res.vars[0].name != "" {
482
483
484
485 for _, obj := range res.vars {
486 if alt := check.lookup(obj.name); alt != nil && alt != obj {
487 var err error_
488 err.errorf(s, "result parameter %s not in scope at return", obj.name)
489 err.errorf(alt, "inner declaration of %s", obj)
490 check.report(&err)
491
492 }
493 }
494 } else {
495 var lhs []*Var
496 if res.Len() > 0 {
497 lhs = res.vars
498 }
499 check.initVars(lhs, results, s)
500 }
501
502 case *syntax.BranchStmt:
503 if s.Label != nil {
504 check.hasLabel = true
505 break
506 }
507 switch s.Tok {
508 case syntax.Break:
509 if ctxt&breakOk == 0 {
510 if check.conf.CompilerErrorMessages {
511 check.error(s, "break is not in a loop, switch, or select statement")
512 } else {
513 check.error(s, "break not in for, switch, or select statement")
514 }
515 }
516 case syntax.Continue:
517 if ctxt&continueOk == 0 {
518 if check.conf.CompilerErrorMessages {
519 check.error(s, "continue is not in a loop")
520 } else {
521 check.error(s, "continue not in for statement")
522 }
523 }
524 case syntax.Fallthrough:
525 if ctxt&fallthroughOk == 0 {
526 msg := "fallthrough statement out of place"
527 if ctxt&finalSwitchCase != 0 {
528 msg = "cannot fallthrough final case in switch"
529 }
530 check.error(s, msg)
531 }
532 case syntax.Goto:
533
534 fallthrough
535 default:
536 check.errorf(s, invalidAST+"branch statement: %s", s.Tok)
537 }
538
539 case *syntax.BlockStmt:
540 check.openScope(s, "block")
541 defer check.closeScope()
542
543 check.stmtList(inner, s.List)
544
545 case *syntax.IfStmt:
546 check.openScope(s, "if")
547 defer check.closeScope()
548
549 check.simpleStmt(s.Init)
550 var x operand
551 check.expr(&x, s.Cond)
552 if x.mode != invalid && !allBoolean(x.typ) {
553 check.error(s.Cond, "non-boolean condition in if statement")
554 }
555 check.stmt(inner, s.Then)
556
557
558 switch s.Else.(type) {
559 case nil:
560
561 case *syntax.IfStmt, *syntax.BlockStmt:
562 check.stmt(inner, s.Else)
563 default:
564 check.error(s.Else, "invalid else branch in if statement")
565 }
566
567 case *syntax.SwitchStmt:
568 inner |= breakOk
569 check.openScope(s, "switch")
570 defer check.closeScope()
571
572 check.simpleStmt(s.Init)
573
574 if g, _ := s.Tag.(*syntax.TypeSwitchGuard); g != nil {
575 check.typeSwitchStmt(inner, s, g)
576 } else {
577 check.switchStmt(inner, s)
578 }
579
580 case *syntax.SelectStmt:
581 inner |= breakOk
582
583 check.multipleSelectDefaults(s.Body)
584
585 for i, clause := range s.Body {
586 if clause == nil {
587 continue
588 }
589
590
591 valid := false
592 var rhs syntax.Expr
593 switch s := clause.Comm.(type) {
594 case nil, *syntax.SendStmt:
595 valid = true
596 case *syntax.AssignStmt:
597 if _, ok := s.Rhs.(*syntax.ListExpr); !ok {
598 rhs = s.Rhs
599 }
600 case *syntax.ExprStmt:
601 rhs = s.X
602 }
603
604
605 if rhs != nil {
606 if x, _ := unparen(rhs).(*syntax.Operation); x != nil && x.Y == nil && x.Op == syntax.Recv {
607 valid = true
608 }
609 }
610
611 if !valid {
612 check.error(clause.Comm, "select case must be send or receive (possibly with assignment)")
613 continue
614 }
615 end := s.Rbrace
616 if i+1 < len(s.Body) {
617 end = s.Body[i+1].Pos()
618 }
619 check.openScopeUntil(clause, end, "case")
620 if clause.Comm != nil {
621 check.stmt(inner, clause.Comm)
622 }
623 check.stmtList(inner, clause.Body)
624 check.closeScope()
625 }
626
627 case *syntax.ForStmt:
628 inner |= breakOk | continueOk
629
630 if rclause, _ := s.Init.(*syntax.RangeClause); rclause != nil {
631 check.rangeStmt(inner, s, rclause)
632 break
633 }
634
635 check.openScope(s, "for")
636 defer check.closeScope()
637
638 check.simpleStmt(s.Init)
639 if s.Cond != nil {
640 var x operand
641 check.expr(&x, s.Cond)
642 if x.mode != invalid && !allBoolean(x.typ) {
643 check.error(s.Cond, "non-boolean condition in for statement")
644 }
645 }
646 check.simpleStmt(s.Post)
647
648
649 if s, _ := s.Post.(*syntax.AssignStmt); s != nil && s.Op == syntax.Def {
650
651 check.use(s.Lhs)
652 }
653 check.stmt(inner, s.Body)
654
655 default:
656 check.error(s, "invalid statement")
657 }
658 }
659
660 func (check *Checker) switchStmt(inner stmtContext, s *syntax.SwitchStmt) {
661
662
663 var x operand
664 if s.Tag != nil {
665 check.expr(&x, s.Tag)
666
667
668 check.assignment(&x, nil, "switch expression")
669 if x.mode != invalid && !Comparable(x.typ) && !hasNil(x.typ) {
670 check.errorf(&x, "cannot switch on %s (%s is not comparable)", &x, x.typ)
671 x.mode = invalid
672 }
673 } else {
674
675
676 x.mode = constant_
677 x.typ = Typ[Bool]
678 x.val = constant.MakeBool(true)
679
680 pos := s.Rbrace
681 if len(s.Body) > 0 {
682 pos = s.Body[0].Pos()
683 }
684 x.expr = syntax.NewName(pos, "true")
685 }
686
687 check.multipleSwitchDefaults(s.Body)
688
689 seen := make(valueMap)
690 for i, clause := range s.Body {
691 if clause == nil {
692 check.error(clause, invalidAST+"incorrect expression switch case")
693 continue
694 }
695 end := s.Rbrace
696 inner := inner
697 if i+1 < len(s.Body) {
698 end = s.Body[i+1].Pos()
699 inner |= fallthroughOk
700 } else {
701 inner |= finalSwitchCase
702 }
703 check.caseValues(&x, unpackExpr(clause.Cases), seen)
704 check.openScopeUntil(clause, end, "case")
705 check.stmtList(inner, clause.Body)
706 check.closeScope()
707 }
708 }
709
710 func (check *Checker) typeSwitchStmt(inner stmtContext, s *syntax.SwitchStmt, guard *syntax.TypeSwitchGuard) {
711
712
713
714
715
716
717
718
719 lhs := guard.Lhs
720 if lhs != nil {
721 if lhs.Value == "_" {
722
723 check.softErrorf(lhs, "no new variable on left side of :=")
724 lhs = nil
725 } else {
726 check.recordDef(lhs, nil)
727 }
728 }
729
730
731 var x operand
732 check.expr(&x, guard.X)
733 if x.mode == invalid {
734 return
735 }
736
737
738 var sx *operand
739 if isTypeParam(x.typ) {
740 check.errorf(&x, "cannot use type switch on type parameter value %s", &x)
741 } else {
742 if _, ok := under(x.typ).(*Interface); ok {
743 sx = &x
744 } else {
745 check.errorf(&x, "%s is not an interface", &x)
746 }
747 }
748
749 check.multipleSwitchDefaults(s.Body)
750
751 var lhsVars []*Var
752 seen := make(map[Type]syntax.Expr)
753 for i, clause := range s.Body {
754 if clause == nil {
755 check.error(s, invalidAST+"incorrect type switch case")
756 continue
757 }
758 end := s.Rbrace
759 if i+1 < len(s.Body) {
760 end = s.Body[i+1].Pos()
761 }
762
763 cases := unpackExpr(clause.Cases)
764 T := check.caseTypes(sx, cases, seen)
765 check.openScopeUntil(clause, end, "case")
766
767 if lhs != nil {
768
769
770
771
772
773 if len(cases) != 1 || T == nil {
774 T = x.typ
775 }
776 obj := NewVar(lhs.Pos(), check.pkg, lhs.Value, T)
777
778
779 scopePos := clause.Pos()
780 if n := len(cases); n > 0 {
781 scopePos = syntax.EndPos(cases[n-1])
782 }
783 check.declare(check.scope, nil, obj, scopePos)
784 check.recordImplicit(clause, obj)
785
786
787
788 lhsVars = append(lhsVars, obj)
789 }
790 check.stmtList(inner, clause.Body)
791 check.closeScope()
792 }
793
794
795
796
797
798 if lhs != nil {
799 var used bool
800 for _, v := range lhsVars {
801 if v.used {
802 used = true
803 }
804 v.used = true
805 }
806 if !used {
807 check.softErrorf(lhs, "%s declared but not used", lhs.Value)
808 }
809 }
810 }
811
812 func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *syntax.RangeClause) {
813
814 sKey := rclause.Lhs
815 var sValue, sExtra syntax.Expr
816 if p, _ := sKey.(*syntax.ListExpr); p != nil {
817 if len(p.ElemList) < 2 {
818 check.error(s, invalidAST+"invalid lhs in range clause")
819 return
820 }
821
822 sKey = p.ElemList[0]
823 sValue = p.ElemList[1]
824 if len(p.ElemList) > 2 {
825
826 sExtra = p.ElemList[2]
827 }
828 }
829
830
831 var x operand
832 check.expr(&x, rclause.X)
833
834
835 var key, val Type
836 if x.mode != invalid {
837
838 var cause string
839 u := coreType(x.typ)
840 if t, _ := u.(*Chan); t != nil {
841 if sValue != nil {
842 check.softErrorf(sValue, "range over %s permits only one iteration variable", &x)
843
844 }
845 if t.dir == SendOnly {
846 cause = "receive from send-only channel"
847 }
848 } else {
849 if sExtra != nil {
850 check.softErrorf(sExtra, "range clause permits at most two iteration variables")
851
852 }
853 if u == nil {
854 cause = check.sprintf("%s has no core type", x.typ)
855 }
856 }
857 key, val = rangeKeyVal(u)
858 if key == nil || cause != "" {
859 if cause == "" {
860 check.softErrorf(&x, "cannot range over %s", &x)
861 } else {
862 check.softErrorf(&x, "cannot range over %s (%s)", &x, cause)
863 }
864
865 }
866 }
867
868
869
870 check.openScope(s, "range")
871 defer check.closeScope()
872
873
874
875
876
877 lhs := [2]syntax.Expr{sKey, sValue}
878 rhs := [2]Type{key, val}
879
880 if rclause.Def {
881
882 var vars []*Var
883 for i, lhs := range lhs {
884 if lhs == nil {
885 continue
886 }
887
888
889 var obj *Var
890 if ident, _ := lhs.(*syntax.Name); ident != nil {
891
892 name := ident.Value
893 obj = NewVar(ident.Pos(), check.pkg, name, nil)
894 check.recordDef(ident, obj)
895
896 if name != "_" {
897 vars = append(vars, obj)
898 }
899 } else {
900 check.errorf(lhs, "cannot declare %s", lhs)
901 obj = NewVar(lhs.Pos(), check.pkg, "_", nil)
902 }
903
904
905 if typ := rhs[i]; typ != nil {
906 x.mode = value
907 x.expr = lhs
908 x.typ = typ
909 check.initVar(obj, &x, "range clause")
910 } else {
911 obj.typ = Typ[Invalid]
912 obj.used = true
913 }
914 }
915
916
917 if len(vars) > 0 {
918 scopePos := s.Body.Pos()
919 for _, obj := range vars {
920 check.declare(check.scope, nil , obj, scopePos)
921 }
922 } else {
923 check.error(s, "no new variables on left side of :=")
924 }
925 } else {
926
927 for i, lhs := range lhs {
928 if lhs == nil {
929 continue
930 }
931 if typ := rhs[i]; typ != nil {
932 x.mode = value
933 x.expr = lhs
934 x.typ = typ
935 check.assignVar(lhs, &x)
936 }
937 }
938 }
939
940 check.stmt(inner, s.Body)
941 }
942
943
944
945
946 func rangeKeyVal(typ Type) (key, val Type) {
947 switch typ := arrayPtrDeref(typ).(type) {
948 case *Basic:
949 if isString(typ) {
950 return Typ[Int], universeRune
951 }
952 case *Array:
953 return Typ[Int], typ.elem
954 case *Slice:
955 return Typ[Int], typ.elem
956 case *Map:
957 return typ.key, typ.elem
958 case *Chan:
959 return typ.elem, Typ[Invalid]
960 }
961 return
962 }
963
View as plain text