Skip to content

Commit bd26c57

Browse files
committed
Merge branch 'master' into net-url-testparseerrors-fix-again
2 parents 53beeb5 + c302785 commit bd26c57

File tree

14 files changed

+1834
-122
lines changed

14 files changed

+1834
-122
lines changed

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

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ package gc
66

77
import (
88
"cmd/compile/internal/types"
9+
"cmd/internal/src"
10+
"fmt"
911
"math/big"
1012
"strings"
1113
)
@@ -1397,28 +1399,30 @@ func hascallchan(n *Node) bool {
13971399

13981400
// A constSet represents a set of Go constant expressions.
13991401
type constSet struct {
1400-
m map[constSetKey]*Node
1402+
m map[constSetKey]src.XPos
14011403
}
14021404

14031405
type constSetKey struct {
14041406
typ *types.Type
14051407
val interface{}
14061408
}
14071409

1408-
// add adds constant expressions to s. If a constant expression of
1409-
// equal value and identical type has already been added, then that
1410-
// type expression is returned. Otherwise, add returns nil.
1410+
// add adds constant expression n to s. If a constant expression of
1411+
// equal value and identical type has already been added, then add
1412+
// reports an error about the duplicate value.
14111413
//
1412-
// add also returns nil if n is not a Go constant expression.
1414+
// pos provides position information for where expression n occured
1415+
// (in case n does not have its own position information). what and
1416+
// where are used in the error message.
14131417
//
14141418
// n must not be an untyped constant.
1415-
func (s *constSet) add(n *Node) *Node {
1419+
func (s *constSet) add(pos src.XPos, n *Node, what, where string) {
14161420
if n.Op == OCONVIFACE && n.Implicit() {
14171421
n = n.Left
14181422
}
14191423

14201424
if !n.isGoConst() {
1421-
return nil
1425+
return
14221426
}
14231427
if n.Type.IsUntyped() {
14241428
Fatalf("%v is untyped", n)
@@ -1448,12 +1452,32 @@ func (s *constSet) add(n *Node) *Node {
14481452
}
14491453
k := constSetKey{typ, n.Val().Interface()}
14501454

1455+
if hasUniquePos(n) {
1456+
pos = n.Pos
1457+
}
1458+
14511459
if s.m == nil {
1452-
s.m = make(map[constSetKey]*Node)
1460+
s.m = make(map[constSetKey]src.XPos)
14531461
}
1454-
old, dup := s.m[k]
1455-
if !dup {
1456-
s.m[k] = n
1462+
1463+
if prevPos, isDup := s.m[k]; isDup {
1464+
yyerrorl(pos, "duplicate %s %s in %s\n\tprevious %s at %v",
1465+
what, nodeAndVal(n), where,
1466+
what, linestr(prevPos))
1467+
} else {
1468+
s.m[k] = pos
14571469
}
1458-
return old
1470+
}
1471+
1472+
// nodeAndVal reports both an expression and its constant value, if
1473+
// the latter is non-obvious.
1474+
//
1475+
// TODO(mdempsky): This could probably be a fmt.go flag.
1476+
func nodeAndVal(n *Node) string {
1477+
show := n.String()
1478+
val := n.Val().Interface()
1479+
if s := fmt.Sprintf("%#v", val); show != s {
1480+
show += " (value " + s + ")"
1481+
}
1482+
return show
14591483
}

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

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -194,30 +194,37 @@ func Fatalf(fmt_ string, args ...interface{}) {
194194
errorexit()
195195
}
196196

197-
func setlineno(n *Node) src.XPos {
198-
lno := lineno
199-
if n != nil {
200-
switch n.Op {
201-
case ONAME, OPACK:
202-
break
203-
204-
case OLITERAL, OTYPE:
205-
if n.Sym != nil {
206-
break
207-
}
208-
fallthrough
197+
// hasUniquePos reports whether n has a unique position that can be
198+
// used for reporting error messages.
199+
//
200+
// It's primarily used to distinguish references to named objects,
201+
// whose Pos will point back to their declaration position rather than
202+
// their usage position.
203+
func hasUniquePos(n *Node) bool {
204+
switch n.Op {
205+
case ONAME, OPACK:
206+
return false
207+
case OLITERAL, OTYPE:
208+
if n.Sym != nil {
209+
return false
210+
}
211+
}
209212

210-
default:
211-
lineno = n.Pos
212-
if !lineno.IsKnown() {
213-
if Debug['K'] != 0 {
214-
Warn("setlineno: unknown position (line 0)")
215-
}
216-
lineno = lno
217-
}
213+
if !n.Pos.IsKnown() {
214+
if Debug['K'] != 0 {
215+
Warn("setlineno: unknown position (line 0)")
218216
}
217+
return false
219218
}
220219

220+
return true
221+
}
222+
223+
func setlineno(n *Node) src.XPos {
224+
lno := lineno
225+
if n != nil && hasUniquePos(n) {
226+
lineno = n.Pos
227+
}
221228
return lno
222229
}
223230

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

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package gc
66

77
import (
88
"cmd/compile/internal/types"
9-
"fmt"
109
"sort"
1110
)
1211

@@ -641,23 +640,11 @@ func checkDupExprCases(exprname *Node, clauses []*Node) {
641640
continue
642641
}
643642

644-
if prev := cs.add(n); prev != nil {
645-
yyerrorl(ncase.Pos, "duplicate case %s in switch\n\tprevious case at %v",
646-
nodeAndVal(n), prev.Line())
647-
}
643+
cs.add(ncase.Pos, n, "case", "switch")
648644
}
649645
}
650646
}
651647

652-
func nodeAndVal(n *Node) string {
653-
show := n.String()
654-
val := n.Val().Interface()
655-
if s := fmt.Sprintf("%#v", val); show != s {
656-
show += " (value " + s + ")"
657-
}
658-
return show
659-
}
660-
661648
// walk generates an AST that implements sw,
662649
// where sw is a type switch.
663650
// The AST is generally of the form of a linear

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2911,9 +2911,7 @@ func typecheckcomplit(n *Node) (res *Node) {
29112911
r = typecheck(r, ctxExpr)
29122912
r = defaultlit(r, t.Key())
29132913
l.Left = assignconv(r, t.Key(), "map key")
2914-
if cs.add(l.Left) != nil {
2915-
yyerror("duplicate key %v in map literal", l.Left)
2916-
}
2914+
cs.add(lineno, l.Left, "key", "map literal")
29172915

29182916
r = l.Right
29192917
pushtype(r, t.Elem())

src/cmd/compile/internal/ssa/gen/generic.rules

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1733,6 +1733,12 @@
17331733
(Eq(8|16|32|64) s:(Sub(8|16|32|64) x y) (Const(8|16|32|64) [0])) && s.Uses == 1 -> (Eq(8|16|32|64) x y)
17341734
(Neq(8|16|32|64) s:(Sub(8|16|32|64) x y) (Const(8|16|32|64) [0])) && s.Uses == 1 -> (Neq(8|16|32|64) x y)
17351735

1736+
// Optimize bitsets
1737+
(Eq(8|16|32|64) (And(8|16|32|64) <t> x (Const(8|16|32|64) <t> [y])) (Const(8|16|32|64) <t> [y])) && isPowerOfTwo(y)
1738+
-> (Neq(8|16|32|64) (And(8|16|32|64) <t> x (Const(8|16|32|64) <t> [y])) (Const(8|16|32|64) <t> [0]))
1739+
(Neq(8|16|32|64) (And(8|16|32|64) <t> x (Const(8|16|32|64) <t> [y])) (Const(8|16|32|64) <t> [y])) && isPowerOfTwo(y)
1740+
-> (Eq(8|16|32|64) (And(8|16|32|64) <t> x (Const(8|16|32|64) <t> [y])) (Const(8|16|32|64) <t> [0]))
1741+
17361742
// Reassociate expressions involving
17371743
// constants such that constants come first,
17381744
// exposing obvious constant-folding opportunities.

0 commit comments

Comments
 (0)