Commit a1a9c31a by Ian Lance Taylor

compiler: Accept trailing comma after varargs parameter.

Also fix handling of interfaces seen only in a function or
method declaration.

From-SVN: r194492
parent 80928237
...@@ -1764,6 +1764,26 @@ Finalize_methods::type(Type* t) ...@@ -1764,6 +1764,26 @@ Finalize_methods::type(Type* t)
} }
} }
// Finalize the types of all methods that are declared but not
// defined, since we won't see the declarations otherwise.
if (nt->named_object()->package() == NULL
&& nt->local_methods() != NULL)
{
const Bindings* methods = nt->local_methods();
for (Bindings::const_declarations_iterator p =
methods->begin_declarations();
p != methods->end_declarations();
p++)
{
if (p->second->is_function_declaration())
{
Type* mt = p->second->func_declaration_value()->type();
if (Type::traverse(mt, this) == TRAVERSE_EXIT)
return TRAVERSE_EXIT;
}
}
}
return TRAVERSE_SKIP_COMPONENTS; return TRAVERSE_SKIP_COMPONENTS;
} }
...@@ -4491,7 +4511,7 @@ Type_declaration::has_methods() const ...@@ -4491,7 +4511,7 @@ Type_declaration::has_methods() const
void void
Type_declaration::define_methods(Named_type* nt) Type_declaration::define_methods(Named_type* nt)
{ {
for (Methods::const_iterator p = this->methods_.begin(); for (std::vector<Named_object*>::const_iterator p = this->methods_.begin();
p != this->methods_.end(); p != this->methods_.end();
++p) ++p)
nt->add_existing_method(*p); nt->add_existing_method(*p);
...@@ -5230,8 +5250,7 @@ Bindings::traverse(Traverse* traverse, bool is_global) ...@@ -5230,8 +5250,7 @@ Bindings::traverse(Traverse* traverse, bool is_global)
} }
// If we need to traverse types, check the function declarations, // If we need to traverse types, check the function declarations,
// which have types. We don't need to check the type declarations, // which have types. Also check any methods of a type declaration.
// as those are just names.
if ((traverse_mask & e_or_t) != 0) if ((traverse_mask & e_or_t) != 0)
{ {
for (Bindings::const_declarations_iterator p = for (Bindings::const_declarations_iterator p =
...@@ -5246,6 +5265,27 @@ Bindings::traverse(Traverse* traverse, bool is_global) ...@@ -5246,6 +5265,27 @@ Bindings::traverse(Traverse* traverse, bool is_global)
== TRAVERSE_EXIT) == TRAVERSE_EXIT)
return TRAVERSE_EXIT; return TRAVERSE_EXIT;
} }
else if (p->second->is_type_declaration())
{
const std::vector<Named_object*>* methods =
p->second->type_declaration_value()->methods();
for (std::vector<Named_object*>::const_iterator pm =
methods->begin();
pm != methods->end();
pm++)
{
Named_object* no = *pm;
Type *t;
if (no->is_function())
t = no->func_value()->type();
else if (no->is_function_declaration())
t = no->func_declaration_value()->type();
else
continue;
if (Type::traverse(t, traverse) == TRAVERSE_EXIT)
return TRAVERSE_EXIT;
}
}
} }
} }
......
...@@ -37,8 +37,6 @@ class Channel_type; ...@@ -37,8 +37,6 @@ class Channel_type;
class Interface_type; class Interface_type;
class Named_type; class Named_type;
class Forward_declaration_type; class Forward_declaration_type;
class Method;
class Methods;
class Named_object; class Named_object;
class Label; class Label;
class Translate_context; class Translate_context;
...@@ -1738,6 +1736,11 @@ class Type_declaration ...@@ -1738,6 +1736,11 @@ class Type_declaration
bool bool
has_methods() const; has_methods() const;
// Return the methods.
const std::vector<Named_object*>*
methods() const
{ return &this->methods_; }
// Define methods when the real type is known. // Define methods when the real type is known.
void void
define_methods(Named_type*); define_methods(Named_type*);
...@@ -1748,8 +1751,6 @@ class Type_declaration ...@@ -1748,8 +1751,6 @@ class Type_declaration
using_type(); using_type();
private: private:
typedef std::vector<Named_object*> Methods;
// The location of the type declaration. // The location of the type declaration.
Location location_; Location location_;
// If this type is declared in a function, a pointer back to the // If this type is declared in a function, a pointer back to the
...@@ -1758,7 +1759,7 @@ class Type_declaration ...@@ -1758,7 +1759,7 @@ class Type_declaration
// The index of this type in IN_FUNCTION_. // The index of this type in IN_FUNCTION_.
unsigned int in_function_index_; unsigned int in_function_index_;
// Methods defined before the type is defined. // Methods defined before the type is defined.
Methods methods_; std::vector<Named_object*> methods_;
// True if we have issued a warning about a use of this type // True if we have issued a warning about a use of this type
// declaration when it is undefined. // declaration when it is undefined.
bool issued_warning_; bool issued_warning_;
......
...@@ -975,13 +975,13 @@ Parse::parameter_list(bool* is_varargs) ...@@ -975,13 +975,13 @@ Parse::parameter_list(bool* is_varargs)
this->parameter_decl(parameters_have_names, ret, is_varargs, &mix_error); this->parameter_decl(parameters_have_names, ret, is_varargs, &mix_error);
while (this->peek_token()->is_op(OPERATOR_COMMA)) while (this->peek_token()->is_op(OPERATOR_COMMA))
{ {
if (this->advance_token()->is_op(OPERATOR_RPAREN))
break;
if (is_varargs != NULL && *is_varargs) if (is_varargs != NULL && *is_varargs)
{ {
error_at(this->location(), "%<...%> must be last parameter"); error_at(this->location(), "%<...%> must be last parameter");
saw_error = true; saw_error = true;
} }
if (this->advance_token()->is_op(OPERATOR_RPAREN))
break;
this->parameter_decl(parameters_have_names, ret, is_varargs, &mix_error); this->parameter_decl(parameters_have_names, ret, is_varargs, &mix_error);
} }
if (mix_error) if (mix_error)
......
...@@ -6500,6 +6500,24 @@ Type::make_channel_type(bool send, bool receive, Type* element_type) ...@@ -6500,6 +6500,24 @@ Type::make_channel_type(bool send, bool receive, Type* element_type)
// Class Interface_type. // Class Interface_type.
// Return the list of methods.
const Typed_identifier_list*
Interface_type::methods() const
{
go_assert(this->methods_are_finalized_ || saw_errors());
return this->all_methods_;
}
// Return the number of methods.
size_t
Interface_type::method_count() const
{
go_assert(this->methods_are_finalized_ || saw_errors());
return this->all_methods_ == NULL ? 0 : this->all_methods_->size();
}
// Traversal. // Traversal.
int int
...@@ -9630,6 +9648,19 @@ Forward_declaration_type::do_traverse(Traverse* traverse) ...@@ -9630,6 +9648,19 @@ Forward_declaration_type::do_traverse(Traverse* traverse)
return TRAVERSE_CONTINUE; return TRAVERSE_CONTINUE;
} }
// Verify the type.
bool
Forward_declaration_type::do_verify()
{
if (!this->is_defined() && !this->is_nil_constant_as_type())
{
this->warn();
return false;
}
return true;
}
// Get the backend representation for the type. // Get the backend representation for the type.
Btype* Btype*
......
...@@ -2534,19 +2534,11 @@ class Interface_type : public Type ...@@ -2534,19 +2534,11 @@ class Interface_type : public Type
// Return the list of methods. This will return NULL for an empty // Return the list of methods. This will return NULL for an empty
// interface. // interface.
const Typed_identifier_list* const Typed_identifier_list*
methods() const methods() const;
{
go_assert(this->methods_are_finalized_);
return this->all_methods_;
}
// Return the number of methods. // Return the number of methods.
size_t size_t
method_count() const method_count() const;
{
go_assert(this->methods_are_finalized_);
return this->all_methods_ == NULL ? 0 : this->all_methods_->size();
}
// Return the method NAME, or NULL. // Return the method NAME, or NULL.
const Typed_identifier* const Typed_identifier*
...@@ -3024,6 +3016,9 @@ class Forward_declaration_type : public Type ...@@ -3024,6 +3016,9 @@ class Forward_declaration_type : public Type
do_traverse(Traverse* traverse); do_traverse(Traverse* traverse);
bool bool
do_verify();
bool
do_has_pointer() const do_has_pointer() const
{ return this->real_type()->has_pointer(); } { return this->real_type()->has_pointer(); }
......
...@@ -8,7 +8,7 @@ package main ...@@ -8,7 +8,7 @@ package main
func f(x int, y ...int) // ok func f(x int, y ...int) // ok
func g(x int, y float) (...) // ERROR "[.][.][.]" "final argument" func g(x int, y float32) (...) // ERROR "[.][.][.]" "final argument"
func h(x, y ...int) // ERROR "[.][.][.]" func h(x, y ...int) // ERROR "[.][.][.]"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment