diff --git a/src/cmd/compile/internal/gc/swt.go b/src/cmd/compile/internal/gc/swt.go index cab0a3d219..98efedc084 100644 --- a/src/cmd/compile/internal/gc/swt.go +++ b/src/cmd/compile/internal/gc/swt.go @@ -600,18 +600,21 @@ func (s *exprSwitch) checkDupCases(cc []caseClause) { if !s.exprname.Type.IsInterface() { seen := make(map[interface{}]*Node) for _, c := range cc { - // Can't check for duplicates that aren't constants, per the spec. Issue 15896. - // Don't check for duplicate bools. Although the spec allows it, - // (1) the compiler hasn't checked it in the past, so compatibility mandates it, and - // (2) it would disallow useful things like - // case GOARCH == "arm" && GOARM == "5": - // case GOARCH == "arm": - // which would both evaluate to false for non-ARM compiles. - if ct := consttype(c.node.Left); ct < 0 || ct == CTBOOL { - continue - } - if c.node.Left != nil { + switch { + case c.node.Left != nil: // Single constant. + + // Can't check for duplicates that aren't constants, per the spec. Issue 15896. + // Don't check for duplicate bools. Although the spec allows it, + // (1) the compiler hasn't checked it in the past, so compatibility mandates it, and + // (2) it would disallow useful things like + // case GOARCH == "arm" && GOARM == "5": + // case GOARCH == "arm": + // which would both evaluate to false for non-ARM compiles. + if ct := consttype(c.node.Left); ct < 0 || ct == CTBOOL { + continue + } + val := c.node.Left.Val().Interface() prev, dup := seen[val] if !dup { @@ -619,10 +622,9 @@ func (s *exprSwitch) checkDupCases(cc []caseClause) { continue } setlineno(c.node) - yyerror("duplicate case %v in switch\n\tprevious case at %v", prev.Left, prev.Line()) - continue - } - if c.node.List.Len() == 2 { + yyerror("duplicate case %#v in switch\n\tprevious case at %v", val, prev.Line()) + + case c.node.List.Len() == 2: // Range of integers. low := c.node.List.Index(0).Int64() high := c.node.List.Index(1).Int64() @@ -633,11 +635,12 @@ func (s *exprSwitch) checkDupCases(cc []caseClause) { continue } setlineno(c.node) - yyerror("duplicate case %v in switch\n\tprevious case at %v", prev.Left, prev.Line()) + yyerror("duplicate case %d in switch\n\tprevious case at %v", i, prev.Line()) } - continue + + default: + Fatalf("bad caseClause node in checkDupCases: %v", c.node) } - Fatalf("bad caseClause node in checkDupCases: %v", c.node) } return } diff --git a/test/switch5.go b/test/switch5.go index 54a11b5c9a..5ca53ba724 100644 --- a/test/switch5.go +++ b/test/switch5.go @@ -90,3 +90,12 @@ func f6() int { } return 2 } + +// Ensure duplicates in ranges are detected (issue #17517). +func f7(a int) { + switch a { + case 0: + case 0, 1: // ERROR "duplicate case 0" + case 1, 2, 3, 4: // ERROR "duplicate case 1" + } +}