mirror of git://gcc.gnu.org/git/gcc.git
Fix order in which recursive structs are converted to GENERIC.
From-SVN: r168534
This commit is contained in:
parent
d3ee4aaae7
commit
2e4bc20e51
|
|
@ -3768,6 +3768,19 @@ Struct_type::fill_in_tree(Gogo* gogo, tree type)
|
||||||
return 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.
|
// Initialize struct fields.
|
||||||
|
|
||||||
tree
|
tree
|
||||||
|
|
@ -5977,20 +5990,44 @@ Interface_type::fill_in_tree(Gogo* gogo, tree type)
|
||||||
{
|
{
|
||||||
gcc_assert(this->methods_ != NULL);
|
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.
|
// Build the type of the table of methods.
|
||||||
|
|
||||||
tree method_table = make_node(RECORD_TYPE);
|
tree method_table = make_node(RECORD_TYPE);
|
||||||
|
|
||||||
// The first field is a pointer to the type descriptor.
|
// 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);
|
tree dtype = Type::make_type_descriptor_type()->get_tree(gogo);
|
||||||
dtype = build_pointer_type(build_qualified_type(dtype, TYPE_QUAL_CONST));
|
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;
|
DECL_CONTEXT(field) = method_table;
|
||||||
TYPE_FIELDS(method_table) = field;
|
TYPE_FIELDS(method_table) = field;
|
||||||
|
|
||||||
std::string last_name = "";
|
std::string last_name = "";
|
||||||
tree* pp = &DECL_CHAIN(field);
|
pp = &DECL_CHAIN(field);
|
||||||
for (Typed_identifier_list::const_iterator p = this->methods_->begin();
|
for (Typed_identifier_list::const_iterator p = this->methods_->begin();
|
||||||
p != this->methods_->end();
|
p != this->methods_->end();
|
||||||
++p)
|
++p)
|
||||||
|
|
@ -6010,25 +6047,9 @@ Interface_type::fill_in_tree(Gogo* gogo, tree type)
|
||||||
}
|
}
|
||||||
layout_type(method_table);
|
layout_type(method_table);
|
||||||
|
|
||||||
tree mtype = build_pointer_type(method_table);
|
// Update the type of the __methods field from a generic pointer to
|
||||||
|
// a pointer to the method table.
|
||||||
tree field_trees = NULL_TREE;
|
TREE_TYPE(methods_field) = build_pointer_type(method_table);
|
||||||
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);
|
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
@ -6864,6 +6885,26 @@ Named_type::do_verify()
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -6994,8 +7035,17 @@ Named_type::do_get_tree(Gogo* gogo)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TYPE_STRUCT:
|
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)
|
if (this->named_tree_ != NULL_TREE)
|
||||||
return this->named_tree_;
|
return this->named_tree_;
|
||||||
|
|
||||||
t = make_node(RECORD_TYPE);
|
t = make_node(RECORD_TYPE);
|
||||||
this->named_tree_ = t;
|
this->named_tree_ = t;
|
||||||
t = this->type_->struct_type()->fill_in_tree(gogo, t);
|
t = this->type_->struct_type()->fill_in_tree(gogo, t);
|
||||||
|
|
|
||||||
|
|
@ -1843,7 +1843,8 @@ class Struct_type : public Type
|
||||||
public:
|
public:
|
||||||
Struct_type(Struct_field_list* fields, source_location location)
|
Struct_type(Struct_field_list* fields, source_location location)
|
||||||
: Type(TYPE_STRUCT),
|
: 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
|
// Return the field NAME. This only looks at local fields, not at
|
||||||
|
|
@ -1938,6 +1939,17 @@ class Struct_type : public Type
|
||||||
tree
|
tree
|
||||||
fill_in_tree(Gogo*, 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:
|
protected:
|
||||||
int
|
int
|
||||||
do_traverse(Traverse*);
|
do_traverse(Traverse*);
|
||||||
|
|
@ -1983,6 +1995,16 @@ class Struct_type : public Type
|
||||||
source_location location_;
|
source_location location_;
|
||||||
// If this struct is unnamed, a list of methods.
|
// If this struct is unnamed, a list of methods.
|
||||||
Methods* all_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.
|
// The type of an array.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue