aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2010-11-01 15:08:03 -0700
committerRobert Griesemer <gri@golang.org>2010-11-01 15:08:03 -0700
commit7996924c89a22efa3603fa6c181ea26aeccbdbd3 (patch)
tree28e32cdf9d60934b96607eefa599ccb40c9480d8
parent9384fdc96aca890c11ff964738f4c9a9bb6ac8dd (diff)
downloadgo-7996924c89a22efa3603fa6c181ea26aeccbdbd3.tar.gz
go-7996924c89a22efa3603fa6c181ea26aeccbdbd3.zip
go/printer: do not remove parens around composite literals starting with a type name in control clauses
(even when they are nested inside an expression). Fixes #1243. R=rsc CC=golang-dev https://golang.org/cl/2817041
-rw-r--r--src/pkg/go/printer/nodes.go49
-rw-r--r--src/pkg/go/printer/testdata/statements.golden30
-rw-r--r--src/pkg/go/printer/testdata/statements.input17
3 files changed, 80 insertions, 16 deletions
diff --git a/src/pkg/go/printer/nodes.go b/src/pkg/go/printer/nodes.go
index 5c3c196b1b..b58277ccf3 100644
--- a/src/pkg/go/printer/nodes.go
+++ b/src/pkg/go/printer/nodes.go
@@ -796,9 +796,15 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, ctxt exprContext, multi
p.funcBody(x.Body, distance(x.Type.Pos(), p.pos), true, multiLine)
case *ast.ParenExpr:
- p.print(token.LPAREN)
- p.expr0(x.X, reduceDepth(depth), multiLine) // parentheses undo one level of depth
- p.print(x.Rparen, token.RPAREN)
+ if _, hasParens := x.X.(*ast.ParenExpr); hasParens {
+ // don't print parentheses around an already parenthesized expression
+ // TODO(gri) consider making this more general and incorporate precedence levels
+ p.expr0(x.X, reduceDepth(depth), multiLine) // parentheses undo one level of depth
+ } else {
+ p.print(token.LPAREN)
+ p.expr0(x.X, reduceDepth(depth), multiLine) // parentheses undo one level of depth
+ p.print(x.Rparen, token.RPAREN)
+ }
case *ast.SelectorExpr:
parts := selectorExprList(expr)
@@ -969,16 +975,27 @@ func isTypeName(x ast.Expr) bool {
}
-// TODO(gri): Decide if this should be used more broadly. The printing code
-// knows when to insert parentheses for precedence reasons, but
-// need to be careful to keep them around type expressions.
-func stripParens(x ast.Expr, inControlClause bool) ast.Expr {
- for px, hasParens := x.(*ast.ParenExpr); hasParens; px, hasParens = x.(*ast.ParenExpr) {
- x = px.X
- if cx, isCompositeLit := x.(*ast.CompositeLit); inControlClause && isCompositeLit && isTypeName(cx.Type) {
- // composite literals inside control clauses need parens if they start with a type name;
- // don't strip innermost layer
- return px
+func stripParens(x ast.Expr) ast.Expr {
+ if px, strip := x.(*ast.ParenExpr); strip {
+ // parentheses must not be stripped if there are any
+ // unparenthesized composite literals starting with
+ // a type name
+ ast.Inspect(px.X, func(node interface{}) bool {
+ switch x := node.(type) {
+ case *ast.ParenExpr:
+ // parentheses protect enclosed composite literals
+ return false
+ case *ast.CompositeLit:
+ if isTypeName(x.Type) {
+ strip = false // do not strip parentheses
+ }
+ return false
+ }
+ // in all other cases, keep inspecting
+ return true
+ })
+ if strip {
+ return stripParens(px.X)
}
}
return x
@@ -991,7 +1008,7 @@ func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, po
if init == nil && post == nil {
// no semicolons required
if expr != nil {
- p.expr(stripParens(expr, true), ignoreMultiLine)
+ p.expr(stripParens(expr), ignoreMultiLine)
needsBlank = true
}
} else {
@@ -1002,7 +1019,7 @@ func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, po
}
p.print(token.SEMICOLON, blank)
if expr != nil {
- p.expr(stripParens(expr, true), ignoreMultiLine)
+ p.expr(stripParens(expr), ignoreMultiLine)
needsBlank = true
}
if isForStmt {
@@ -1183,7 +1200,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
p.expr(s.Value, multiLine)
}
p.print(blank, s.TokPos, s.Tok, blank, token.RANGE, blank)
- p.expr(stripParens(s.X, true), multiLine)
+ p.expr(stripParens(s.X), multiLine)
p.print(blank)
p.block(s.Body, 1)
*multiLine = true
diff --git a/src/pkg/go/printer/testdata/statements.golden b/src/pkg/go/printer/testdata/statements.golden
index 461fd13f95..02ac8a5497 100644
--- a/src/pkg/go/printer/testdata/statements.golden
+++ b/src/pkg/go/printer/testdata/statements.golden
@@ -209,6 +209,36 @@ func _() {
for _ = range (T1{T{42}}) {
}
+
+ if x == (T{42}[0]) {
+ }
+ if (x == T{42}[0]) {
+ }
+ if x == (T{42}[0]) {
+ }
+ if x == (T{42}[0]) {
+ }
+ if x == (T{42}[0]) {
+ }
+ if x == a+b*(T{42}[0]) {
+ }
+ if (x == a+b*T{42}[0]) {
+ }
+ if x == a+b*(T{42}[0]) {
+ }
+ if x == a+(b * (T{42}[0])) {
+ }
+ if x == a+b*(T{42}[0]) {
+ }
+ if (a + b*(T{42}[0])) == x {
+ }
+ if (a + b*(T{42}[0])) == x {
+ }
+
+ if struct{ x bool }{false}.x {
+ }
+ if struct{ x bool }{false}.x == false {
+ }
}
diff --git a/src/pkg/go/printer/testdata/statements.input b/src/pkg/go/printer/testdata/statements.input
index 5437eb5f19..7819820ede 100644
--- a/src/pkg/go/printer/testdata/statements.input
+++ b/src/pkg/go/printer/testdata/statements.input
@@ -146,6 +146,23 @@ func _() {
switch ; ((((T{})))) {}
for _ = range (((T1{T{42}}))) {}
+
+ if x == (T{42}[0]) {}
+ if (x == T{42}[0]) {}
+ if (x == (T{42}[0])) {}
+ if (x == (((T{42}[0])))) {}
+ if (((x == (T{42}[0])))) {}
+ if x == a + b*(T{42}[0]) {}
+ if (x == a + b*T{42}[0]) {}
+ if (x == a + b*(T{42}[0])) {}
+ if (x == a + ((b * (T{42}[0])))) {}
+ if (((x == a + b * (T{42}[0])))) {}
+ if (((a + b * (T{42}[0])) == x)) {}
+ if (((a + b * (T{42}[0])))) == x {}
+
+ if (struct{x bool}{false}.x) {}
+ if (struct{x bool}{false}.x) == false {}
+ if (struct{x bool}{false}.x == false) {}
}