Check for duplicate parameter/result names.
From-SVN: r179010
This commit is contained in:
parent
40ebf57b67
commit
458692b00c
3 changed files with 45 additions and 3 deletions
|
@ -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:
|
||||
|
|
|
@ -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(¶ms, &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();
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue