]> Cypherpunks repositories - gostls13.git/commitdiff
go/printer: do not remove parens around composite literals starting with a type name...
authorRobert Griesemer <gri@golang.org>
Mon, 1 Nov 2010 22:08:03 +0000 (15:08 -0700)
committerRobert Griesemer <gri@golang.org>
Mon, 1 Nov 2010 22:08:03 +0000 (15:08 -0700)
(even when they are nested inside an expression).

Fixes #1243.

R=rsc
CC=golang-dev
https://golang.org/cl/2817041

src/pkg/go/printer/nodes.go
src/pkg/go/printer/testdata/statements.golden
src/pkg/go/printer/testdata/statements.input

index 5c3c196b1b5cc56af2789be276004ca8533a8c46..b58277ccf3a72924b00aaf422b3252f6320f73b8 100644 (file)
@@ -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
index 461fd13f95611bc453c88ac703de408dedd4abe5..02ac8a549753fd64cfc0dee48342ba3256d66abe 100644 (file)
@@ -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 {
+       }
 }
 
 
index 5437eb5f19164d2618d75e486ead61e77839e56f..7819820edef0779b32d012da92643081b9930271 100644 (file)
@@ -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) {}
 }