Commit 26793fb5 by Ian Lance Taylor Committed by Ian Lance Taylor

Fix bug with multiple results returning structs with invalid sizes.

	* go-gcc.cc (Gcc_backend::function_type): When building a struct
	for multiple results, check that all fields types have a size.
	(Gcc_backend::placeholder_pointer_type): Permit name to be empty.

From-SVN: r173742
parent b8f2ad7c
2011-05-13 Ian Lance Taylor <iant@google.com>
* go-gcc.cc (Gcc_backend::function_type): When building a struct
for multiple results, check that all fields types have a size.
(Gcc_backend::placeholder_pointer_type): Permit name to be empty.
2011-05-12 Ian Lance Taylor <iant@google.com> 2011-05-12 Ian Lance Taylor <iant@google.com>
* go-gcc.cc (Gcc_backend::local_variable): Add is_address_taken * go-gcc.cc (Gcc_backend::local_variable): Add is_address_taken
......
...@@ -465,6 +465,7 @@ Gcc_backend::function_type(const Btyped_identifier& receiver, ...@@ -465,6 +465,7 @@ Gcc_backend::function_type(const Btyped_identifier& receiver,
tree field_type_tree = p->btype->get_tree(); tree field_type_tree = p->btype->get_tree();
if (field_type_tree == error_mark_node) if (field_type_tree == error_mark_node)
return this->error_type(); return this->error_type();
gcc_assert(TYPE_SIZE(field_type_tree) != NULL_TREE);
tree field = build_decl(location, FIELD_DECL, name_tree, tree field = build_decl(location, FIELD_DECL, name_tree,
field_type_tree); field_type_tree);
DECL_CONTEXT(field) = result; DECL_CONTEXT(field) = result;
...@@ -573,10 +574,13 @@ Gcc_backend::placeholder_pointer_type(const std::string& name, ...@@ -573,10 +574,13 @@ Gcc_backend::placeholder_pointer_type(const std::string& name,
source_location location, bool) source_location location, bool)
{ {
tree ret = build_variant_type_copy(ptr_type_node); tree ret = build_variant_type_copy(ptr_type_node);
tree decl = build_decl(location, TYPE_DECL, if (!name.empty())
get_identifier_from_string(name), {
ret); tree decl = build_decl(location, TYPE_DECL,
TYPE_NAME(ret) = decl; get_identifier_from_string(name),
ret);
TYPE_NAME(ret) = decl;
}
return this->make_type(ret); return this->make_type(ret);
} }
......
...@@ -113,7 +113,9 @@ class Backend ...@@ -113,7 +113,9 @@ class Backend
// Create a placeholder pointer type. This is used for a named // Create a placeholder pointer type. This is used for a named
// pointer type, since in Go a pointer type may refer to itself. // pointer type, since in Go a pointer type may refer to itself.
// NAME is the name of the type, and the location is where the named // NAME is the name of the type, and the location is where the named
// type is defined. FOR_FUNCTION is true if this is for a Go // type is defined. This function is also used for unnamed function
// types with multiple results, in which case the type has no name
// and NAME will be empty. FOR_FUNCTION is true if this is for a Go
// function type, which corresponds to a C/C++ pointer to function // function type, which corresponds to a C/C++ pointer to function
// type. The return value will later be passed as the first // type. The return value will later be passed as the first
// parameter to set_placeholder_pointer_type or // parameter to set_placeholder_pointer_type or
......
...@@ -2599,6 +2599,8 @@ Gogo::convert_named_types() ...@@ -2599,6 +2599,8 @@ Gogo::convert_named_types()
Runtime::convert_types(this); Runtime::convert_types(this);
Function_type::convert_types(this);
this->named_types_are_converted_ = true; this->named_types_are_converted_ = true;
} }
......
...@@ -831,7 +831,8 @@ Type::check_int_value(Expression* e, const char* errmsg, ...@@ -831,7 +831,8 @@ Type::check_int_value(Expression* e, const char* errmsg,
return false; return false;
} }
// A hash table mapping unnamed types to trees. // A hash table mapping unnamed types to the backend representation of
// those types.
Type::Type_btypes Type::type_btypes; Type::Type_btypes Type::type_btypes;
...@@ -2588,10 +2589,10 @@ Function_type::do_hash_for_method(Gogo* gogo) const ...@@ -2588,10 +2589,10 @@ Function_type::do_hash_for_method(Gogo* gogo) const
return ret; return ret;
} }
// Get the tree for a function type. // Get the backend representation for a function type.
Btype* Btype*
Function_type::do_get_backend(Gogo* gogo) Function_type::get_function_backend(Gogo* gogo)
{ {
Backend::Btyped_identifier breceiver; Backend::Btyped_identifier breceiver;
if (this->receiver_ != NULL) if (this->receiver_ != NULL)
...@@ -2643,6 +2644,46 @@ Function_type::do_get_backend(Gogo* gogo) ...@@ -2643,6 +2644,46 @@ Function_type::do_get_backend(Gogo* gogo)
this->location()); this->location());
} }
// A hash table mapping function types to their backend placeholders.
Function_type::Placeholders Function_type::placeholders;
// Get the backend representation for a function type. If we are
// still converting types, and this types has multiple results, return
// a placeholder instead. We do this because for multiple results we
// build a struct, and we need to make sure that all the types in the
// struct are valid before we create the struct.
Btype*
Function_type::do_get_backend(Gogo* gogo)
{
if (!gogo->named_types_are_converted()
&& this->results_ != NULL
&& this->results_->size() > 1)
{
Btype* placeholder =
gogo->backend()->placeholder_pointer_type("", this->location(), true);
Function_type::placeholders.push_back(std::make_pair(this, placeholder));
return placeholder;
}
return this->get_function_backend(gogo);
}
// Convert function types after all named types are converted.
void
Function_type::convert_types(Gogo* gogo)
{
for (Placeholders::const_iterator p = Function_type::placeholders.begin();
p != Function_type::placeholders.end();
++p)
{
Btype* bt = p->first->get_function_backend(gogo);
if (!gogo->backend()->set_placeholder_function_type(p->second, bt))
go_assert(saw_errors());
}
}
// Functions are initialized to NULL. // Functions are initialized to NULL.
tree tree
...@@ -7236,7 +7277,7 @@ Named_type::do_get_backend(Gogo* gogo) ...@@ -7236,7 +7277,7 @@ Named_type::do_get_backend(Gogo* gogo)
--this->seen_; --this->seen_;
if (this->is_circular_) if (this->is_circular_)
bt1 = gogo->backend()->circular_pointer_type(bt, true); bt1 = gogo->backend()->circular_pointer_type(bt, true);
if (!gogo->backend()->set_placeholder_pointer_type(bt, bt1)) if (!gogo->backend()->set_placeholder_function_type(bt, bt1))
bt = gogo->backend()->error_type(); bt = gogo->backend()->error_type();
return bt; return bt;
......
...@@ -1628,6 +1628,10 @@ class Function_type : public Type ...@@ -1628,6 +1628,10 @@ class Function_type : public Type
Function_type* Function_type*
copy_with_receiver(Type*) const; copy_with_receiver(Type*) const;
// Finishing converting function types.
static void
convert_types(Gogo*);
static Type* static Type*
make_function_type_descriptor_type(); make_function_type_descriptor_type();
...@@ -1666,6 +1670,16 @@ class Function_type : public Type ...@@ -1666,6 +1670,16 @@ class Function_type : public Type
type_descriptor_params(Type*, const Typed_identifier*, type_descriptor_params(Type*, const Typed_identifier*,
const Typed_identifier_list*); const Typed_identifier_list*);
Btype*
get_function_backend(Gogo*);
// A list of function types with multiple results and their
// placeholder backend representations, used to postpone building
// the structs we use for multiple results until all types are
// converted.
typedef std::vector<std::pair<Function_type*, Btype*> > Placeholders;
static Placeholders placeholders;
// The receiver name and type. This will be NULL for a normal // The receiver name and type. This will be NULL for a normal
// function, non-NULL for a method. // function, non-NULL for a method.
Typed_identifier* receiver_; Typed_identifier* receiver_;
......
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