From f16348a4bd142258cc1ce31ab8450308b6d8b234 Mon Sep 17 00:00:00 2001 From: ian Date: Fri, 13 May 2011 22:34:56 +0000 Subject: [PATCH] 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@173742 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/go/ChangeLog | 6 ++++++ gcc/go/go-gcc.cc | 12 +++++++---- gcc/go/gofrontend/backend.h | 4 +++- gcc/go/gofrontend/gogo.cc | 2 ++ gcc/go/gofrontend/types.cc | 49 +++++++++++++++++++++++++++++++++++++++++---- gcc/go/gofrontend/types.h | 14 +++++++++++++ 6 files changed, 78 insertions(+), 9 deletions(-) diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog index 63a47c1efcd..79e68be55ad 100644 --- a/gcc/go/ChangeLog +++ b/gcc/go/ChangeLog @@ -1,3 +1,9 @@ +2011-05-13 Ian Lance Taylor + + * 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 * go-gcc.cc (Gcc_backend::local_variable): Add is_address_taken diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc index 49f574a58fd..a024e197132 100644 --- a/gcc/go/go-gcc.cc +++ b/gcc/go/go-gcc.cc @@ -465,6 +465,7 @@ Gcc_backend::function_type(const Btyped_identifier& receiver, tree field_type_tree = p->btype->get_tree(); if (field_type_tree == error_mark_node) return this->error_type(); + gcc_assert(TYPE_SIZE(field_type_tree) != NULL_TREE); tree field = build_decl(location, FIELD_DECL, name_tree, field_type_tree); DECL_CONTEXT(field) = result; @@ -573,10 +574,13 @@ Gcc_backend::placeholder_pointer_type(const std::string& name, source_location location, bool) { tree ret = build_variant_type_copy(ptr_type_node); - tree decl = build_decl(location, TYPE_DECL, - get_identifier_from_string(name), - ret); - TYPE_NAME(ret) = decl; + if (!name.empty()) + { + tree decl = build_decl(location, TYPE_DECL, + get_identifier_from_string(name), + ret); + TYPE_NAME(ret) = decl; + } return this->make_type(ret); } diff --git a/gcc/go/gofrontend/backend.h b/gcc/go/gofrontend/backend.h index fa158be5ad1..e2dde9a08e6 100644 --- a/gcc/go/gofrontend/backend.h +++ b/gcc/go/gofrontend/backend.h @@ -113,7 +113,9 @@ class Backend // Create a placeholder pointer type. This is used for a named // 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 - // 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 // type. The return value will later be passed as the first // parameter to set_placeholder_pointer_type or diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index c7b847fb4d1..ba3e9df0c2a 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -2599,6 +2599,8 @@ Gogo::convert_named_types() Runtime::convert_types(this); + Function_type::convert_types(this); + this->named_types_are_converted_ = true; } diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index fdaf8881a17..e33b349b3c1 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -831,7 +831,8 @@ Type::check_int_value(Expression* e, const char* errmsg, 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; @@ -2588,10 +2589,10 @@ Function_type::do_hash_for_method(Gogo* gogo) const return ret; } -// Get the tree for a function type. +// Get the backend representation for a function type. Btype* -Function_type::do_get_backend(Gogo* gogo) +Function_type::get_function_backend(Gogo* gogo) { Backend::Btyped_identifier breceiver; if (this->receiver_ != NULL) @@ -2643,6 +2644,46 @@ Function_type::do_get_backend(Gogo* gogo) 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. tree @@ -7236,7 +7277,7 @@ Named_type::do_get_backend(Gogo* gogo) --this->seen_; if (this->is_circular_) 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(); return bt; diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h index 74dad7b09bd..913266b784c 100644 --- a/gcc/go/gofrontend/types.h +++ b/gcc/go/gofrontend/types.h @@ -1628,6 +1628,10 @@ class Function_type : public Type Function_type* copy_with_receiver(Type*) const; + // Finishing converting function types. + static void + convert_types(Gogo*); + static Type* make_function_type_descriptor_type(); @@ -1666,6 +1670,16 @@ class Function_type : public Type type_descriptor_params(Type*, const Typed_identifier*, 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 > Placeholders; + static Placeholders placeholders; + // The receiver name and type. This will be NULL for a normal // function, non-NULL for a method. Typed_identifier* receiver_; -- 2.11.4.GIT