compiler: Parse receiver as a single parameter.
authorIan Lance Taylor <ian@gcc.gnu.org>
Thu, 16 Oct 2014 17:17:16 +0000 (17:17 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Thu, 16 Oct 2014 17:17:16 +0000 (17:17 +0000)
Fixes issue 8288.

From-SVN: r216340

gcc/go/gofrontend/parse.cc
gcc/go/gofrontend/parse.h

index d77f462..b24de60 100644 (file)
@@ -974,7 +974,8 @@ Parse::parameter_list(bool* is_varargs)
     }
 
   bool mix_error = false;
-  this->parameter_decl(parameters_have_names, ret, is_varargs, &mix_error);
+  this->parameter_decl(parameters_have_names, ret, is_varargs, &mix_error,
+                      &saw_error);
   while (this->peek_token()->is_op(OPERATOR_COMMA))
     {
       if (this->advance_token()->is_op(OPERATOR_RPAREN))
@@ -984,7 +985,8 @@ Parse::parameter_list(bool* is_varargs)
          error_at(this->location(), "%<...%> must be last parameter");
          saw_error = true;
        }
-      this->parameter_decl(parameters_have_names, ret, is_varargs, &mix_error);
+      this->parameter_decl(parameters_have_names, ret, is_varargs, &mix_error,
+                          &saw_error);
     }
   if (mix_error)
     {
@@ -1005,7 +1007,8 @@ void
 Parse::parameter_decl(bool parameters_have_names,
                      Typed_identifier_list* til,
                      bool* is_varargs,
-                     bool* mix_error)
+                     bool* mix_error,
+                     bool* saw_error)
 {
   if (!parameters_have_names)
     {
@@ -1047,6 +1050,8 @@ Parse::parameter_decl(bool parameters_have_names,
        }
       if (!type->is_error_type())
        til->push_back(Typed_identifier("", type, location));
+      else
+       *saw_error = true;
     }
   else
     {
@@ -1063,9 +1068,15 @@ Parse::parameter_decl(bool parameters_have_names,
       else
        {
          if (is_varargs == NULL)
-           error_at(this->location(), "invalid use of %<...%>");
+           {
+             error_at(this->location(), "invalid use of %<...%>");
+             *saw_error = true;
+           }
          else if (new_count > orig_count + 1)
-           error_at(this->location(), "%<...%> only permits one name");
+           {
+             error_at(this->location(), "%<...%> only permits one name");
+             *saw_error = true;
+           }
          else
            *is_varargs = true;
          this->advance_token();
@@ -2310,103 +2321,27 @@ Parse::function_decl(bool saw_nointerface)
     }
 }
 
-// Receiver     = "(" [ identifier ] [ "*" ] BaseTypeName ")" .
-// BaseTypeName = identifier .
+// Receiver = Parameters .
 
 Typed_identifier*
 Parse::receiver()
 {
-  go_assert(this->peek_token()->is_op(OPERATOR_LPAREN));
-
-  std::string name;
-  const Token* token = this->advance_token();
-  Location location = token->location();
-  if (!token->is_op(OPERATOR_MULT))
-    {
-      if (!token->is_identifier())
-       {
-         error_at(this->location(), "method has no receiver");
-         this->gogo_->mark_locals_used();
-         while (!token->is_eof() && !token->is_op(OPERATOR_RPAREN))
-           token = this->advance_token();
-         if (!token->is_eof())
-           this->advance_token();
-         return NULL;
-       }
-      name = token->identifier();
-      bool is_exported = token->is_identifier_exported();
-      token = this->advance_token();
-      if (!token->is_op(OPERATOR_DOT) && !token->is_op(OPERATOR_RPAREN))
-       {
-         // An identifier followed by something other than a dot or a
-         // right parenthesis must be a receiver name followed by a
-         // type.
-         name = this->gogo_->pack_hidden_name(name, is_exported);
-       }
-      else
-       {
-         // This must be a type name.
-         this->unget_token(Token::make_identifier_token(name, is_exported,
-                                                        location));
-         token = this->peek_token();
-         name.clear();
-       }
-    }
-
-  // Here the receiver name is in NAME (it is empty if the receiver is
-  // unnamed) and TOKEN is the first token in the type.
-
-  bool is_pointer = false;
-  if (token->is_op(OPERATOR_MULT))
-    {
-      is_pointer = true;
-      token = this->advance_token();
-    }
-
-  if (!token->is_identifier())
+  Location location = this->location();
+  Typed_identifier_list* til;
+  if (!this->parameters(&til, NULL))
+    return NULL;
+  else if (til == NULL || til->empty())
     {
-      error_at(this->location(), "expected receiver name or type");
-      this->gogo_->mark_locals_used();
-      int c = token->is_op(OPERATOR_LPAREN) ? 1 : 0;
-      while (!token->is_eof())
-       {
-         token = this->advance_token();
-         if (token->is_op(OPERATOR_LPAREN))
-           ++c;
-         else if (token->is_op(OPERATOR_RPAREN))
-           {
-             if (c == 0)
-               break;
-             --c;
-           }
-       }
-      if (!token->is_eof())
-       this->advance_token();
+      error_at(location, "method has no receiver");
       return NULL;
     }
-
-  Type* type = this->type_name(true);
-
-  if (is_pointer && !type->is_error_type())
-    type = Type::make_pointer_type(type);
-
-  if (this->peek_token()->is_op(OPERATOR_RPAREN))
-    this->advance_token();
-  else
+  else if (til->size() > 1)
     {
-      if (this->peek_token()->is_op(OPERATOR_COMMA))
-       error_at(this->location(), "method has multiple receivers");
-      else
-       error_at(this->location(), "expected %<)%>");
-      this->gogo_->mark_locals_used();
-      while (!token->is_eof() && !token->is_op(OPERATOR_RPAREN))
-       token = this->advance_token();
-      if (!token->is_eof())
-       this->advance_token();
+      error_at(location, "method has multiple receivers");
       return NULL;
     }
-
-  return new Typed_identifier(name, type, location);
+  else
+    return &til->front();
 }
 
 // Operand    = Literal | QualifiedIdent | MethodExpr | "(" Expression ")" .
index 3a7bbd5..86698a1 100644 (file)
@@ -179,7 +179,7 @@ class Parse
   Function_type* signature(Typed_identifier*, Location);
   bool parameters(Typed_identifier_list**, bool* is_varargs);
   Typed_identifier_list* parameter_list(bool* is_varargs);
-  void parameter_decl(bool, Typed_identifier_list*, bool*, bool*);
+  void parameter_decl(bool, Typed_identifier_list*, bool*, bool*, bool*);
   bool result(Typed_identifier_list**);
   Location block();
   Type* interface_type();