OSDN Git Service

Fix typo in error message.
[pf3gnuchains/gcc-fork.git] / gcc / go / gofrontend / parse.cc
index 06281db..b91bfbd 100644 (file)
@@ -335,10 +335,17 @@ Parse::type_name(bool issue_error)
   bool ok = true;
   if (named_object == NULL)
     {
-      if (package != NULL)
-       ok = false;
-      else
+      if (package == NULL)
        named_object = this->gogo_->add_unknown_name(name, location);
+      else
+       {
+         const std::string& packname(package->package_value()->name());
+         error_at(location, "reference to undefined identifier %<%s.%s%>",
+                  Gogo::message_name(packname).c_str(),
+                  Gogo::message_name(name).c_str());
+         issue_error = false;
+         ok = false;
+       }
     }
   else if (named_object->is_type())
     {
@@ -677,6 +684,32 @@ Parse::channel_type()
   return Type::make_channel_type(send, receive, element_type);
 }
 
+// Give an error for a duplicate parameter or receiver name.
+
+void
+Parse::check_signature_names(const Typed_identifier_list* params,
+                            Parse::Names* names)
+{
+  for (Typed_identifier_list::const_iterator p = params->begin();
+       p != params->end();
+       ++p)
+    {
+      if (p->name().empty() || Gogo::is_sink_name(p->name()))
+       continue;
+      std::pair<std::string, const Typed_identifier*> val =
+       std::make_pair(p->name(), &*p);
+      std::pair<Parse::Names::iterator, bool> ins = names->insert(val);
+      if (!ins.second)
+       {
+         error_at(p->location(), "redefinition of %qs",
+                  Gogo::message_name(p->name()).c_str());
+         inform(ins.first->second->location(),
+                "previous definition of %qs was here",
+                Gogo::message_name(p->name()).c_str());
+       }
+    }
+}
+
 // Signature      = Parameters [ Result ] .
 
 // RECEIVER is the receiver if there is one, or NULL.  LOCATION is the
@@ -691,18 +724,24 @@ Parse::signature(Typed_identifier* receiver, source_location location)
   Typed_identifier_list* params;
   bool params_ok = this->parameters(&params, &is_varargs);
 
-  Typed_identifier_list* result = NULL;
+  Typed_identifier_list* results = NULL;
   if (this->peek_token()->is_op(OPERATOR_LPAREN)
       || this->type_may_start_here())
     {
-      if (!this->result(&result))
+      if (!this->result(&results))
        return NULL;
     }
 
   if (!params_ok)
     return NULL;
 
-  Function_type* ret = Type::make_function_type(receiver, params, result,
+  Parse::Names names;
+  if (params != NULL)
+    this->check_signature_names(params, &names);
+  if (results != NULL)
+    this->check_signature_names(results, &names);
+
+  Function_type* ret = Type::make_function_type(receiver, params, results,
                                                location);
   if (is_varargs)
     ret->set_is_varargs();
@@ -3781,7 +3820,8 @@ Parse::return_stat()
   this->gogo_->add_statement(Statement::make_return_statement(vals, location));
 }
 
-// IfStmt    = "if" [ SimpleStmt ";" ] Expression Block [ "else" Statement ] .
+// IfStmt = "if" [ SimpleStmt ";" ] Expression Block
+//          [ "else" ( IfStmt | Block ) ] .
 
 void
 Parse::if_stat()
@@ -3851,10 +3891,17 @@ Parse::if_stat()
   Block* else_block = NULL;
   if (this->peek_token()->is_keyword(KEYWORD_ELSE))
     {
-      this->advance_token();
-      // We create a block to gather the statement.
       this->gogo_->start_block(this->location());
-      this->statement(NULL);
+      const Token* token = this->advance_token();
+      if (token->is_keyword(KEYWORD_IF))
+       this->if_stat();
+      else if (token->is_op(OPERATOR_LCURLY))
+       this->block();
+      else
+       {
+         error_at(this->location(), "expected %<if%> or %<{%>");
+         this->statement(NULL);
+       }
       else_block = this->gogo_->finish_block(this->location());
     }
 
@@ -4882,7 +4929,7 @@ Parse::break_stat()
        {
          // If there is a label with this name, mark it as used to
          // avoid a useless error about an unused label.
-         this->gogo_->add_label_reference(token->identifier());
+         this->gogo_->add_label_reference(token->identifier(), 0, false);
 
          error_at(token->location(), "invalid break label %qs",
                   Gogo::message_name(token->identifier()).c_str());
@@ -4937,7 +4984,7 @@ Parse::continue_stat()
        {
          // If there is a label with this name, mark it as used to
          // avoid a useless error about an unused label.
-         this->gogo_->add_label_reference(token->identifier());
+         this->gogo_->add_label_reference(token->identifier(), 0, false);
 
          error_at(token->location(), "invalid continue label %qs",
                   Gogo::message_name(token->identifier()).c_str());
@@ -4971,7 +5018,8 @@ Parse::goto_stat()
     error_at(this->location(), "expected label for goto");
   else
     {
-      Label* label = this->gogo_->add_label_reference(token->identifier());
+      Label* label = this->gogo_->add_label_reference(token->identifier(),
+                                                     location, true);
       Statement* s = Statement::make_goto_statement(label, location);
       this->gogo_->add_statement(s);
       this->advance_token();