Commit ee0c35be authored by Robert Griesemer's avatar Robert Griesemer

go/printer: fix a couple of hidden crashes that become

visible only when enabling internal debug mode:
- in rare cases expression depth can underflow
- when printing a single labeled statement, indentation
  may underflow if not setup correctly

R=rsc
CC=golang-dev
https://golang.org/cl/484041
parent f7c27b9a
...@@ -562,6 +562,15 @@ func diffPrec(expr ast.Expr, prec int) int { ...@@ -562,6 +562,15 @@ func diffPrec(expr ast.Expr, prec int) int {
} }
func reduceDepth(depth int) int {
depth--
if depth < 1 {
depth = 1
}
return depth
}
// Format the binary expression: decide the cutoff and then format. // Format the binary expression: decide the cutoff and then format.
// Let's call depth == 1 Normal mode, and depth > 1 Compact mode. // Let's call depth == 1 Normal mode, and depth > 1 Compact mode.
// (Algorithm suggestion by Russ Cox.) // (Algorithm suggestion by Russ Cox.)
...@@ -604,7 +613,7 @@ func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int, multiL ...@@ -604,7 +613,7 @@ func (p *printer) binaryExpr(x *ast.BinaryExpr, prec1, cutoff, depth int, multiL
// Note: The parser inserts an ast.ParenExpr node; thus this case // Note: The parser inserts an ast.ParenExpr node; thus this case
// can only occur if the AST is created in a different way. // can only occur if the AST is created in a different way.
p.print(token.LPAREN) p.print(token.LPAREN)
p.expr0(x, depth-1, multiLine) // parentheses undo one level of depth p.expr0(x, reduceDepth(depth), multiLine) // parentheses undo one level of depth
p.print(token.RPAREN) p.print(token.RPAREN)
return return
} }
...@@ -707,7 +716,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, ctxt exprContext, multi ...@@ -707,7 +716,7 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, ctxt exprContext, multi
case *ast.ParenExpr: case *ast.ParenExpr:
p.print(token.LPAREN) p.print(token.LPAREN)
p.expr0(x.X, depth-1, multiLine) // parentheses undo one level of depth p.expr0(x.X, reduceDepth(depth), multiLine) // parentheses undo one level of depth
p.print(x.Rparen, token.RPAREN) p.print(x.Rparen, token.RPAREN)
case *ast.SelectorExpr: case *ast.SelectorExpr:
......
...@@ -1002,6 +1002,11 @@ func (cfg *Config) Fprint(output io.Writer, node interface{}) (int, os.Error) { ...@@ -1002,6 +1002,11 @@ func (cfg *Config) Fprint(output io.Writer, node interface{}) (int, os.Error) {
p.expr(n, ignoreMultiLine) p.expr(n, ignoreMultiLine)
case ast.Stmt: case ast.Stmt:
p.useNodeComments = true p.useNodeComments = true
// A labeled statement will un-indent to position the
// label. Set indent to 1 so we don't get indent "underflow".
if _, labeledStmt := n.(*ast.LabeledStmt); labeledStmt {
p.indent = 1
}
p.stmt(n, ignoreMultiLine) p.stmt(n, ignoreMultiLine)
case ast.Decl: case ast.Decl:
p.useNodeComments = true p.useNodeComments = true
......
...@@ -20,6 +20,7 @@ var ( ...@@ -20,6 +20,7 @@ var (
func _() { func _() {
// no spaces around simple or parenthesized expressions // no spaces around simple or parenthesized expressions
_ = (a + 0)
_ = a + b _ = a + b
_ = a + b + c _ = a + b + c
_ = a + b - c _ = a + b - c
......
...@@ -20,6 +20,7 @@ var ( ...@@ -20,6 +20,7 @@ var (
func _() { func _() {
// no spaces around simple or parenthesized expressions // no spaces around simple or parenthesized expressions
_ = (a+0)
_ = a+b _ = a+b
_ = a+b+c _ = a+b+c
_ = a+b-c _ = a+b-c
......
...@@ -20,6 +20,7 @@ var ( ...@@ -20,6 +20,7 @@ var (
func _() { func _() {
// no spaces around simple or parenthesized expressions // no spaces around simple or parenthesized expressions
_ = (a + 0)
_ = a + b _ = a + b
_ = a + b + c _ = a + b + c
_ = a + b - c _ = a + b - c
......
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