aboutsummaryrefslogtreecommitdiff
path: root/gcc/go/gofrontend/types.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/go/gofrontend/types.cc')
-rw-r--r--gcc/go/gofrontend/types.cc47
1 files changed, 44 insertions, 3 deletions
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index ca5f5121d36..4d923733667 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -1057,6 +1057,8 @@ Type::get_backend_placeholder(Gogo* gogo)
{
Location loc = Linemap::unknown_location();
bt = gogo->backend()->placeholder_pointer_type("", loc, false);
+ Pointer_type* pt = this->convert<Pointer_type, TYPE_POINTER>();
+ Type::placeholder_pointers.push_back(pt);
}
break;
@@ -5516,14 +5518,22 @@ Pointer_type::do_import(Import* imp)
return Type::make_pointer_type(to);
}
+// Cache of pointer types. Key is "to" type, value is pointer type
+// that points to key.
+
+Type::Pointer_type_table Type::pointer_types;
+
+// A list of placeholder pointer types. We keep this so we can ensure
+// they are finalized.
+
+std::vector<Pointer_type*> Type::placeholder_pointers;
+
// Make a pointer type.
Pointer_type*
Type::make_pointer_type(Type* to_type)
{
- typedef Unordered_map(Type*, Pointer_type*) Hashtable;
- static Hashtable pointer_types;
- Hashtable::const_iterator p = pointer_types.find(to_type);
+ Pointer_type_table::const_iterator p = pointer_types.find(to_type);
if (p != pointer_types.end())
return p->second;
Pointer_type* ret = new Pointer_type(to_type);
@@ -5531,6 +5541,37 @@ Type::make_pointer_type(Type* to_type)
return ret;
}
+// This helper is invoked immediately after named types have been
+// converted, to clean up any unresolved pointer types remaining in
+// the pointer type cache.
+//
+// The motivation for this routine: occasionally the compiler creates
+// some specific pointer type as part of a lowering operation (ex:
+// pointer-to-void), then Type::backend_type_size() is invoked on the
+// type (which creates a Btype placeholder for it), that placeholder
+// passed somewhere along the line to the back end, but since there is
+// no reference to the type in user code, there is never a call to
+// Type::finish_backend for the type (hence the Btype remains as an
+// unresolved placeholder). Calling this routine will clean up such
+// instances.
+
+void
+Type::finish_pointer_types(Gogo* gogo)
+{
+ // We don't use begin() and end() because it is possible to add new
+ // placeholder pointer types as we finalized existing ones.
+ for (size_t i = 0; i < Type::placeholder_pointers.size(); i++)
+ {
+ Pointer_type* pt = Type::placeholder_pointers[i];
+ Type_btypes::iterator tbti = Type::type_btypes.find(pt);
+ if (tbti != Type::type_btypes.end() && tbti->second.is_placeholder)
+ {
+ pt->finish_backend(gogo, tbti->second.btype);
+ tbti->second.is_placeholder = false;
+ }
+ }
+}
+
// The nil type. We use a special type for nil because it is not the
// same as any other type. In C term nil has type void*, but there is
// no such type in Go.