aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-09-20 16:46:46 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-09-20 16:46:46 +0000
commit458692b00c947e500d42d2704c3a38604ee6b451 (patch)
treef418101b123973bea669d8eed9ad229dbf0a64be /gcc
parent40ebf57b67ae30304a7c12fcbac885a8eb6463ce (diff)
downloadgcc-458692b00c947e500d42d2704c3a38604ee6b451.zip
gcc-458692b00c947e500d42d2704c3a38604ee6b451.tar.gz
gcc-458692b00c947e500d42d2704c3a38604ee6b451.tar.bz2
Check for duplicate parameter/result names.
From-SVN: r179010
Diffstat (limited to 'gcc')
-rw-r--r--gcc/go/gofrontend/gogo.cc6
-rw-r--r--gcc/go/gofrontend/parse.cc38
-rw-r--r--gcc/go/gofrontend/parse.h4
3 files changed, 45 insertions, 3 deletions
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index 221826b..be7592b 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -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:
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc
index 06281db..29f4c69 100644
--- a/gcc/go/gofrontend/parse.cc
+++ b/gcc/go/gofrontend/parse.cc
@@ -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();
diff --git a/gcc/go/gofrontend/parse.h b/gcc/go/gofrontend/parse.h
index f072fd3..0da86fb 100644
--- a/gcc/go/gofrontend/parse.h
+++ b/gcc/go/gofrontend/parse.h
@@ -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);