aboutsummaryrefslogtreecommitdiff
path: root/gcc/go/gofrontend
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-01-06 01:35:19 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-01-06 01:35:19 +0000
commit2e4bc20e5107fbf05555ca34d4d6664835845729 (patch)
tree9db74ecffec3a6d70f53bc522036a91c803d7ffd /gcc/go/gofrontend
parentd3ee4aaae70586c4ee4adfb258703c8362d04eb6 (diff)
downloadgcc-2e4bc20e5107fbf05555ca34d4d6664835845729.zip
gcc-2e4bc20e5107fbf05555ca34d4d6664835845729.tar.gz
gcc-2e4bc20e5107fbf05555ca34d4d6664835845729.tar.bz2
Fix order in which recursive structs are converted to GENERIC.
From-SVN: r168534
Diffstat (limited to 'gcc/go/gofrontend')
-rw-r--r--gcc/go/gofrontend/types.cc94
-rw-r--r--gcc/go/gofrontend/types.h24
2 files changed, 95 insertions, 23 deletions
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index a8faa35..8bb2b72 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -3768,6 +3768,19 @@ Struct_type::fill_in_tree(Gogo* gogo, tree type)
return type;
}
+// Make sure that all structs which must be converted to the backend
+// representation before this one are in fact converted.
+
+void
+Struct_type::convert_prerequisites(Gogo* gogo)
+{
+ for (std::vector<Named_type*>::const_iterator p
+ = this->prerequisites_.begin();
+ p != this->prerequisites_.end();
+ ++p)
+ (*p)->get_tree(gogo);
+}
+
// Initialize struct fields.
tree
@@ -5977,20 +5990,44 @@ Interface_type::fill_in_tree(Gogo* gogo, tree type)
{
gcc_assert(this->methods_ != NULL);
+ // Because the methods may refer to the interface type itself, we
+ // need to build the interface type first, and then update the
+ // method pointer later.
+
+ tree field_trees = NULL_TREE;
+ tree* pp = &field_trees;
+
+ tree name_tree = get_identifier("__methods");
+ tree methods_field = build_decl(this->location_, FIELD_DECL, name_tree,
+ ptr_type_node);
+ DECL_CONTEXT(methods_field) = type;
+ *pp = methods_field;
+ pp = &DECL_CHAIN(methods_field);
+
+ name_tree = get_identifier("__object");
+ tree field = build_decl(this->location_, FIELD_DECL, name_tree,
+ ptr_type_node);
+ DECL_CONTEXT(field) = type;
+ *pp = field;
+
+ TYPE_FIELDS(type) = field_trees;
+
+ layout_type(type);
+
// Build the type of the table of methods.
tree method_table = make_node(RECORD_TYPE);
// The first field is a pointer to the type descriptor.
- tree name_tree = get_identifier("__type_descriptor");
+ name_tree = get_identifier("__type_descriptor");
tree dtype = Type::make_type_descriptor_type()->get_tree(gogo);
dtype = build_pointer_type(build_qualified_type(dtype, TYPE_QUAL_CONST));
- tree field = build_decl(this->location_, FIELD_DECL, name_tree, dtype);
+ field = build_decl(this->location_, FIELD_DECL, name_tree, dtype);
DECL_CONTEXT(field) = method_table;
TYPE_FIELDS(method_table) = field;
std::string last_name = "";
- tree* pp = &DECL_CHAIN(field);
+ pp = &DECL_CHAIN(field);
for (Typed_identifier_list::const_iterator p = this->methods_->begin();
p != this->methods_->end();
++p)
@@ -6010,25 +6047,9 @@ Interface_type::fill_in_tree(Gogo* gogo, tree type)
}
layout_type(method_table);
- tree mtype = build_pointer_type(method_table);
-
- tree field_trees = NULL_TREE;
- pp = &field_trees;
-
- name_tree = get_identifier("__methods");
- field = build_decl(this->location_, FIELD_DECL, name_tree, mtype);
- DECL_CONTEXT(field) = type;
- *pp = field;
- pp = &DECL_CHAIN(field);
-
- name_tree = get_identifier("__object");
- field = build_decl(this->location_, FIELD_DECL, name_tree, ptr_type_node);
- DECL_CONTEXT(field) = type;
- *pp = field;
-
- TYPE_FIELDS(type) = field_trees;
-
- layout_type(type);
+ // Update the type of the __methods field from a generic pointer to
+ // a pointer to the method table.
+ TREE_TYPE(methods_field) = build_pointer_type(method_table);
return type;
}
@@ -6864,6 +6885,26 @@ Named_type::do_verify()
return false;
}
+ // If this is a struct, then if any of the fields of the struct
+ // themselves have struct type, then this struct must be converted
+ // to the backend representation before the field's type is
+ // converted. That may seem backward, but it works because if the
+ // field's type refers to this one, e.g., via a pointer, then the
+ // conversion process will pick up the half-built struct and do the
+ // right thing.
+ if (this->struct_type() != NULL)
+ {
+ const Struct_field_list* fields = this->struct_type()->fields();
+ for (Struct_field_list::const_iterator p = fields->begin();
+ p != fields->end();
+ ++p)
+ {
+ Struct_type* st = p->type()->struct_type();
+ if (st != NULL)
+ st->add_prerequisite(this);
+ }
+ }
+
return true;
}
@@ -6994,8 +7035,17 @@ Named_type::do_get_tree(Gogo* gogo)
break;
case TYPE_STRUCT:
+ // If there are structs which must be converted first, do them.
+ if (this->seen_ == 0)
+ {
+ ++this->seen_;
+ this->type_->struct_type()->convert_prerequisites(gogo);
+ --this->seen_;
+ }
+
if (this->named_tree_ != NULL_TREE)
return this->named_tree_;
+
t = make_node(RECORD_TYPE);
this->named_tree_ = t;
t = this->type_->struct_type()->fill_in_tree(gogo, t);
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h
index cecf106..a8d8a0b 100644
--- a/gcc/go/gofrontend/types.h
+++ b/gcc/go/gofrontend/types.h
@@ -1843,7 +1843,8 @@ class Struct_type : public Type
public:
Struct_type(Struct_field_list* fields, source_location location)
: Type(TYPE_STRUCT),
- fields_(fields), location_(location), all_methods_(NULL)
+ fields_(fields), location_(location), all_methods_(NULL),
+ prerequisites_()
{ }
// Return the field NAME. This only looks at local fields, not at
@@ -1938,6 +1939,17 @@ class Struct_type : public Type
tree
fill_in_tree(Gogo*, tree);
+ // Note that a struct must be converted to the backend
+ // representation before we convert this struct.
+ void
+ add_prerequisite(Named_type* nt)
+ { this->prerequisites_.push_back(nt); }
+
+ // If there are any structs which must be converted to the backend
+ // representation before this one, convert them.
+ void
+ convert_prerequisites(Gogo*);
+
protected:
int
do_traverse(Traverse*);
@@ -1983,6 +1995,16 @@ class Struct_type : public Type
source_location location_;
// If this struct is unnamed, a list of methods.
Methods* all_methods_;
+ // A list of structs which must be converted to the backend
+ // representation before this struct can be converted. This is for
+ // cases like
+ // type S1 { p *S2 }
+ // type S2 { s S1 }
+ // where we must start converting S2 before we start converting S1.
+ // That is because we can fully convert S1 before S2 is complete,
+ // but we can not fully convert S2 before S1 is complete. If we
+ // start converting S1 first, we won't be able to convert S2.
+ std::vector<Named_type*> prerequisites_;
};
// The type of an array.