Patchwork [gccgo] Do not permit parenthesized types in composite literals

login
register
mail settings
Submitter Ian Taylor
Date Sept. 8, 2010, 9:28 p.m.
Message ID <mcr7hivhqlt.fsf@google.com>
Download mbox | patch
Permalink /patch/64228/
State New
Headers show

Comments

Ian Taylor - Sept. 8, 2010, 9:28 p.m.
In order to avoid a parsing ambiguity, Go prohibits parenthesized types
with composite literals.  Otherwise cases like
    if (S) {}
are ambiguous, because the condition of the if statement could be either
(S) or (S){}.  The language requires that an extra set of parentheses be
used if the latter case is intended.  For simplicity, the language was
changed to simply prohibit a parenthesized type when used with a
composite literal.  This change implements that in gccgo.  Committed to
gccgo branch.

Ian

Patch

diff -r 6b9674bf9b5c go/parse.cc
--- a/go/parse.cc	Wed Sep 08 14:19:56 2010 -0700
+++ b/go/parse.cc	Wed Sep 08 14:21:59 2010 -0700
@@ -2513,11 +2513,15 @@ 
 Parse::primary_expr(bool may_be_sink, bool may_be_composite_lit,
 		    bool* is_type_switch)
 {
+  source_location start_loc = this->location();
+  bool is_parenthesized = this->peek_token()->is_op(OPERATOR_LPAREN);
+
   Expression* ret = this->operand(may_be_sink);
 
   // An unknown name followed by a curly brace must be a composite
   // literal, and the unknown name must be a type.
   if (may_be_composite_lit
+      && !is_parenthesized
       && ret->unknown_expression() != NULL
       && this->peek_token()->is_op(OPERATOR_LCURLY))
     {
@@ -2528,11 +2532,16 @@ 
 
   // We handle composite literals and type casts here, as it is the
   // easiest way to handle types which are in parentheses, as in
-  // "((([]int))){1}".
+  // "((uint))(1)".
   if (ret->is_type_expression())
     {
       if (this->peek_token()->is_op(OPERATOR_LCURLY))
-	ret = this->composite_lit(ret->type(), ret->location());
+	{
+	  if (is_parenthesized)
+	    error_at(start_loc,
+		     "cannot parenthesize type in composite literal");
+	  ret = this->composite_lit(ret->type(), ret->location());
+	}
       else if (this->peek_token()->is_op(OPERATOR_LPAREN))
 	{
 	  source_location loc = this->location();