Commit 7996924c authored by Robert Griesemer's avatar Robert Griesemer

go/printer: do not remove parens around composite literals starting with a...

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
parent 9384fdc9
...@@ -796,9 +796,15 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, ctxt exprContext, multi ...@@ -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) p.funcBody(x.Body, distance(x.Type.Pos(), p.pos), true, multiLine)
case *ast.ParenExpr: case *ast.ParenExpr:
p.print(token.LPAREN) if _, hasParens := x.X.(*ast.ParenExpr); hasParens {
p.expr0(x.X, reduceDepth(depth), multiLine) // parentheses undo one level of depth // don't print parentheses around an already parenthesized expression
p.print(x.Rparen, token.RPAREN) // 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: case *ast.SelectorExpr:
parts := selectorExprList(expr) parts := selectorExprList(expr)
...@@ -969,16 +975,27 @@ func isTypeName(x ast.Expr) bool { ...@@ -969,16 +975,27 @@ func isTypeName(x ast.Expr) bool {
} }
// TODO(gri): Decide if this should be used more broadly. The printing code func stripParens(x ast.Expr) ast.Expr {
// knows when to insert parentheses for precedence reasons, but if px, strip := x.(*ast.ParenExpr); strip {
// need to be careful to keep them around type expressions. // parentheses must not be stripped if there are any
func stripParens(x ast.Expr, inControlClause bool) ast.Expr { // unparenthesized composite literals starting with
for px, hasParens := x.(*ast.ParenExpr); hasParens; px, hasParens = x.(*ast.ParenExpr) { // a type name
x = px.X ast.Inspect(px.X, func(node interface{}) bool {
if cx, isCompositeLit := x.(*ast.CompositeLit); inControlClause && isCompositeLit && isTypeName(cx.Type) { switch x := node.(type) {
// composite literals inside control clauses need parens if they start with a type name; case *ast.ParenExpr:
// don't strip innermost layer // parentheses protect enclosed composite literals
return px 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 return x
...@@ -991,7 +1008,7 @@ func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, po ...@@ -991,7 +1008,7 @@ func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, po
if init == nil && post == nil { if init == nil && post == nil {
// no semicolons required // no semicolons required
if expr != nil { if expr != nil {
p.expr(stripParens(expr, true), ignoreMultiLine) p.expr(stripParens(expr), ignoreMultiLine)
needsBlank = true needsBlank = true
} }
} else { } else {
...@@ -1002,7 +1019,7 @@ func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, po ...@@ -1002,7 +1019,7 @@ func (p *printer) controlClause(isForStmt bool, init ast.Stmt, expr ast.Expr, po
} }
p.print(token.SEMICOLON, blank) p.print(token.SEMICOLON, blank)
if expr != nil { if expr != nil {
p.expr(stripParens(expr, true), ignoreMultiLine) p.expr(stripParens(expr), ignoreMultiLine)
needsBlank = true needsBlank = true
} }
if isForStmt { if isForStmt {
...@@ -1183,7 +1200,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) { ...@@ -1183,7 +1200,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
p.expr(s.Value, multiLine) p.expr(s.Value, multiLine)
} }
p.print(blank, s.TokPos, s.Tok, blank, token.RANGE, blank) 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.print(blank)
p.block(s.Body, 1) p.block(s.Body, 1)
*multiLine = true *multiLine = true
......
...@@ -209,6 +209,36 @@ func _() { ...@@ -209,6 +209,36 @@ func _() {
for _ = range (T1{T{42}}) { 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 {
}
} }
......
...@@ -146,6 +146,23 @@ func _() { ...@@ -146,6 +146,23 @@ func _() {
switch ; ((((T{})))) {} switch ; ((((T{})))) {}
for _ = range (((T1{T{42}}))) {} 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) {}
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment