Fix bug with multiple results returning structs with invalid sizes.
authorian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 13 May 2011 22:34:56 +0000 (22:34 +0000)
committerian <ian@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 13 May 2011 22:34:56 +0000 (22:34 +0000)
* 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
gcc/go/go-gcc.cc
gcc/go/gofrontend/backend.h
gcc/go/gofrontend/gogo.cc
gcc/go/gofrontend/types.cc
gcc/go/gofrontend/types.h

index 63a47c1..79e68be 100644 (file)
@@ -1,3 +1,9 @@
+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>
 
        * go-gcc.cc (Gcc_backend::local_variable): Add is_address_taken
index 49f574a..a024e19 100644 (file)
@@ -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);
 }
 
index fa158be..e2dde9a 100644 (file)
@@ -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
index c7b847f..ba3e9df 100644 (file)
@@ -2599,6 +2599,8 @@ Gogo::convert_named_types()
 
   Runtime::convert_types(this);
 
+  Function_type::convert_types(this);
+
   this->named_types_are_converted_ = true;
 }
 
index fdaf888..e33b349 100644 (file)
@@ -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;
 
index 74dad7b..913266b 100644 (file)
@@ -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<std::pair<Function_type*, Btype*> > 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_;