Check for duplicate parameter/result names.
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 20 Sep 2011 16:46:46 +0000 (16:46 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 20 Sep 2011 16:46:46 +0000 (16:46 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@179010 138bc75d-0d04-0410-961f-82ee72b054a4

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

index 221826b..be7592b 100644 (file)
@@ -4482,6 +4482,12 @@ Bindings::new_definition(Named_object* old_object, Named_object* new_object)
 
     case Named_object::NAMED_OBJECT_VAR:
     case Named_object::NAMED_OBJECT_RESULT_VAR:
+      // We have already given an error in the parser for cases where
+      // one parameter or result variable redeclares another one.
+      if ((new_object->is_variable()
+          && new_object->var_value()->is_parameter())
+         || new_object->is_result_variable())
+       return old_object;
       break;
 
     case Named_object::NAMED_OBJECT_SINK:
index 06281db..29f4c69 100644 (file)
@@ -677,6 +677,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 +717,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();
index f072fd3..0da86fb 100644 (file)
@@ -131,6 +131,9 @@ class Parse
   // A set of Enclosing_var entries.
   typedef std::set<Enclosing_var, Enclosing_var_comparison> Enclosing_vars;
 
+  // Used to detect duplicate parameter/result names.
+  typedef std::map<std::string, const Typed_identifier*> Names;
+
   // Peek at the current token from the lexer.
   const Token*
   peek_token();
@@ -165,6 +168,7 @@ class Parse
   void field_decl(Struct_field_list*);
   Type* pointer_type();
   Type* channel_type();
+  void check_signature_names(const Typed_identifier_list*, Names*);
   Function_type* signature(Typed_identifier*, source_location);
   bool parameters(Typed_identifier_list**, bool* is_varargs);
   Typed_identifier_list* parameter_list(bool* is_varargs);