From patchwork Wed Sep 8 00:13:42 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Lance Taylor X-Patchwork-Id: 64082 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 58357B6F01 for ; Wed, 8 Sep 2010 10:14:32 +1000 (EST) Received: (qmail 24498 invoked by alias); 8 Sep 2010 00:14:22 -0000 Received: (qmail 24480 invoked by uid 22791); 8 Sep 2010 00:14:16 -0000 X-SWARE-Spam-Status: No, hits=-2.2 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, SPF_HELO_PASS, TW_CC, TW_FN, T_RP_MATCHES_RCVD, T_TVD_MIME_NO_HEADERS X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (216.239.44.51) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 08 Sep 2010 00:14:05 +0000 Received: from hpaq13.eem.corp.google.com (hpaq13.eem.corp.google.com [172.25.149.13]) by smtp-out.google.com with ESMTP id o880E2Pi020018 for ; Tue, 7 Sep 2010 17:14:02 -0700 Received: from pzk4 (pzk4.prod.google.com [10.243.19.132]) by hpaq13.eem.corp.google.com with ESMTP id o880E0LV026472 for ; Tue, 7 Sep 2010 17:14:00 -0700 Received: by pzk4 with SMTP id 4so3482218pzk.35 for ; Tue, 07 Sep 2010 17:13:59 -0700 (PDT) Received: by 10.142.71.11 with SMTP id t11mr245831wfa.121.1283904839655; Tue, 07 Sep 2010 17:13:59 -0700 (PDT) Received: from coign.google.com ([216.239.45.130]) by mx.google.com with ESMTPS id n35sm6419287wfa.3.2010.09.07.17.13.50 (version=TLSv1/SSLv3 cipher=RC4-MD5); Tue, 07 Sep 2010 17:13:55 -0700 (PDT) From: Ian Lance Taylor To: gcc-patches@gcc.gnu.org, gofrontend-dev@googlegroups.com Subject: [gccgo] Rewrite handling of types that refer to themselves Date: Tue, 07 Sep 2010 17:13:42 -0700 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) MIME-Version: 1.0 X-System-Of-Record: true X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org In Go there are several ways that a type can refer directly to itself, as in type P *P The current code tries to handle all those cases in the various different types implementations. I rewrote it to unify the handling at the place where the self-reference can occur: a named type. This avoids certain obscure cases in which the compiler would otherwise go into an infinite recursive loop. Committed to gccgo branch. Ian diff -r 765edd916c29 go/types.cc --- a/go/types.cc Thu Sep 02 07:49:54 2010 -0700 +++ b/go/types.cc Tue Sep 07 17:04:50 2010 -0700 @@ -787,21 +787,15 @@ return this->tree_; } -// Store an incomplete type tree during construction. - -void -Type::set_incomplete_type_tree(tree incomplete) -{ - gcc_assert(this->tree_ == NULL); - this->tree_ = incomplete; -} - // Return a tree representing a zero initialization for this type. tree Type::get_init_tree(Gogo* gogo, bool is_clear) { - return this->do_init_tree(gogo, is_clear); + tree type_tree = this->get_tree(gogo); + if (type_tree == error_mark_node) + return error_mark_node; + return this->do_get_init_tree(gogo, type_tree, is_clear); } // Any type which supports the builtin make function must implement @@ -921,7 +915,7 @@ { return error_mark_node; } tree - do_init_tree(Gogo*, bool) + do_get_init_tree(Gogo*, tree, bool) { return error_mark_node; } void @@ -959,7 +953,7 @@ { return void_type_node; } tree - do_init_tree(Gogo*, bool) + do_get_init_tree(Gogo*, tree, bool) { gcc_unreachable(); } void @@ -997,8 +991,8 @@ { return boolean_type_node; } tree - do_init_tree(Gogo*, bool is_clear) - { return is_clear ? NULL : boolean_false_node; } + do_get_init_tree(Gogo*, tree type_tree, bool is_clear) + { return is_clear ? NULL : fold_convert(type_tree, boolean_false_node); } void do_type_descriptor_decl(Gogo* gogo, Named_type* name, tree* pdecl); @@ -1167,9 +1161,9 @@ } tree -Integer_type::do_init_tree(Gogo* gogo, bool is_clear) -{ - return is_clear ? NULL : build_int_cst(this->get_tree(gogo), 0); +Integer_type::do_get_init_tree(Gogo*, tree type_tree, bool is_clear) +{ + return is_clear ? NULL : build_int_cst(type_tree, 0); } // The type descriptor for an integer type. Integer types are always @@ -1321,14 +1315,13 @@ } tree -Float_type::do_init_tree(Gogo* gogo, bool is_clear) +Float_type::do_get_init_tree(Gogo*, tree type_tree, bool is_clear) { if (is_clear) return NULL; - tree type = this->get_tree(gogo); REAL_VALUE_TYPE r; - real_from_integer(&r, TYPE_MODE(type), 0, 0, 0); - return build_real(type, r); + real_from_integer(&r, TYPE_MODE(type_tree), 0, 0, 0); + return build_real(type_tree, r); } // The type descriptor for a float type. Float types are always named. @@ -1481,15 +1474,14 @@ // Zero initializer. tree -Complex_type::do_init_tree(Gogo* gogo, bool is_clear) +Complex_type::do_get_init_tree(Gogo*, tree type_tree, bool is_clear) { if (is_clear) return NULL; - tree type = this->get_tree(gogo); REAL_VALUE_TYPE r; - real_from_integer(&r, TYPE_MODE(TREE_TYPE(type)), 0, 0, 0); - return build_complex(type, build_real(TREE_TYPE(type), r), - build_real(TREE_TYPE(type), r)); + real_from_integer(&r, TYPE_MODE(TREE_TYPE(type_tree)), 0, 0, 0); + return build_complex(type_tree, build_real(TREE_TYPE(type_tree), r), + build_real(TREE_TYPE(type_tree), r)); } // The type descriptor for a complex type. Complex types are always @@ -1594,12 +1586,11 @@ // We initialize a string to { NULL, 0 }. tree -String_type::do_init_tree(Gogo* gogo, bool is_clear) +String_type::do_get_init_tree(Gogo*, tree type_tree, bool is_clear) { if (is_clear) return NULL_TREE; - tree type_tree = this->get_tree(gogo); gcc_assert(TREE_CODE(type_tree) == RECORD_TYPE); VEC(constructor_elt, gc)* init = VEC_alloc(constructor_elt, gc, 2); @@ -1700,7 +1691,7 @@ { gcc_unreachable(); } tree - do_init_tree(Gogo*, bool) + do_get_init_tree(Gogo*, tree, bool) { gcc_unreachable(); } void @@ -1979,15 +1970,6 @@ tree Function_type::do_get_tree(Gogo* gogo) { - // A function type can refer to itself indirectly, as in - // type F func() F - // A Go function type is represented as a pointer to a GENERIC - // function. Create a pointer node now and fill it in later. - tree ret = make_node(POINTER_TYPE); - SET_TYPE_MODE(ret, ptr_mode); - layout_type(ret); - this->set_incomplete_type_tree(ret); - tree args = NULL_TREE; tree* pp = &args; @@ -2060,35 +2042,20 @@ if (result == error_mark_node) return error_mark_node; - // A function type whose return type is the function type itself can - // not be handled in GENERIC. Such a type can not be written in C, - // but in Go it looks like "type F func() F". We turn this special - // case into a function which returns a generic pointer. - if (result == ret) - result = ptr_type_node; - tree fntype = build_function_type(result, args); if (fntype == error_mark_node) return fntype; - TREE_TYPE(ret) = fntype; - TYPE_POINTER_TO(fntype) = ret; - if (TYPE_STRUCTURAL_EQUALITY_P(fntype)) - SET_TYPE_STRUCTURAL_EQUALITY(ret); - - return ret; + return build_pointer_type(fntype); } // Functions are initialized to NULL. tree -Function_type::do_init_tree(Gogo* gogo, bool is_clear) +Function_type::do_get_init_tree(Gogo*, tree type_tree, bool is_clear) { if (is_clear) return NULL; - tree type_tree = this->get_tree(gogo); - if (type_tree == error_mark_node) - return error_mark_node; return fold_convert(type_tree, null_pointer_node); } @@ -2411,13 +2378,10 @@ // Initialize a pointer type. tree -Pointer_type::do_init_tree(Gogo* gogo, bool is_clear) +Pointer_type::do_get_init_tree(Gogo*, tree type_tree, bool is_clear) { if (is_clear) return NULL; - tree type_tree = this->get_tree(gogo); - if (type_tree == error_mark_node) - return error_mark_node; return fold_convert(type_tree, null_pointer_node); } @@ -2513,8 +2477,8 @@ { return ptr_type_node; } tree - do_init_tree(Gogo*, bool is_clear) - { return is_clear ? NULL : null_pointer_node; } + do_get_init_tree(Gogo*, tree type_tree, bool is_clear) + { return is_clear ? NULL : fold_convert(type_tree, null_pointer_node); } void do_type_descriptor_decl(Gogo*, Named_type*, tree*) @@ -2560,7 +2524,7 @@ do_get_tree(Gogo*); tree - do_init_tree(Gogo*, bool) + do_get_init_tree(Gogo*, tree, bool) { gcc_unreachable(); } void @@ -3019,11 +2983,16 @@ Struct_type::do_get_tree(Gogo* gogo) { tree type = make_node(RECORD_TYPE); - this->set_incomplete_type_tree(type); - + return this->fill_in_tree(gogo, type); +} + +// Fill in the fields for a struct type. + +tree +Struct_type::fill_in_tree(Gogo* gogo, tree type) +{ tree field_trees = NULL_TREE; tree* pp = &field_trees; - gcc_assert(this->fields_ != NULL); for (Struct_field_list::const_iterator p = this->fields_->begin(); p != this->fields_->end(); ++p) @@ -3050,12 +3019,8 @@ // Initialize struct fields. tree -Struct_type::do_init_tree(Gogo* gogo, bool is_clear) -{ - tree type_tree = this->get_tree(gogo); - if (type_tree == error_mark_node) - return error_mark_node; - +Struct_type::do_get_init_tree(Gogo* gogo, tree type_tree, bool is_clear) +{ if (this->fields_ == NULL || this->fields_->empty()) { if (is_clear) @@ -3550,7 +3515,12 @@ tree Array_type::do_get_tree(Gogo* gogo) { - if (this->length_ != NULL) + if (this->length_ == NULL) + { + tree struct_type = gogo->slice_type_tree(void_type_node); + return this->fill_in_tree(gogo, struct_type); + } + else { tree element_type_tree = this->element_type_->get_tree(gogo); tree length_tree = this->get_length_tree(gogo); @@ -3568,48 +3538,47 @@ return build_array_type(element_type_tree, index_type); } - else - { - // Two different slices of the same element type are really the - // same type. In order to make that valid at the tree level, we - // make sure to return the same struct. - std::pair val(this->element_type_, NULL); - std::pair ins = - Array_type::array_trees.insert(val); - if (!ins.second) - { - // We've already created a tree type for a slice with this - // element type. - gcc_assert(ins.first->second != NULL_TREE); - return ins.first->second; - } - - // A slice type can be recursive, as in "type T []T". Avoid - // infinite recursion by creating the struct first, and then - // filling in the element type. - tree struct_type = gogo->slice_type_tree(void_type_node); - this->set_incomplete_type_tree(struct_type); - ins.first->second = struct_type; - - tree element_type_tree = this->element_type_->get_tree(gogo); - - tree field = TYPE_FIELDS(struct_type); - gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__values") == 0); - gcc_assert(POINTER_TYPE_P(TREE_TYPE(field)) - && TREE_TYPE(TREE_TYPE(field)) == void_type_node); - TREE_TYPE(field) = build_pointer_type(element_type_tree); - - return struct_type; - } +} + +// Fill in the fields for a slice type. This is used for named slice +// types. + +tree +Array_type::fill_in_tree(Gogo* gogo, tree struct_type) +{ + gcc_assert(this->length_ == NULL); + + // Two different slices of the same element type are really the same + // type. In order to make that valid at the tree level, we make + // sure to return the same struct. + std::pair val(this->element_type_, NULL); + std::pair ins = + Array_type::array_trees.insert(val); + if (!ins.second) + { + // We've already created a tree type for a slice with this + // element type. + gcc_assert(ins.first->second != NULL_TREE); + return ins.first->second; + } + + ins.first->second = struct_type; + + tree element_type_tree = this->element_type_->get_tree(gogo); + tree field = TYPE_FIELDS(struct_type); + gcc_assert(strcmp(IDENTIFIER_POINTER(DECL_NAME(field)), "__values") == 0); + gcc_assert(POINTER_TYPE_P(TREE_TYPE(field)) + && TREE_TYPE(TREE_TYPE(field)) == void_type_node); + TREE_TYPE(field) = build_pointer_type(element_type_tree); + + return struct_type; } // Return an initializer for an array type. tree -Array_type::do_init_tree(Gogo* gogo, bool is_clear) -{ - tree type_tree = this->get_tree(gogo); - +Array_type::do_get_init_tree(Gogo* gogo, tree type_tree, bool is_clear) +{ if (this->length_ == NULL) { // Open array. @@ -4170,11 +4139,11 @@ // Initialize a map. tree -Map_type::do_init_tree(Gogo* gogo, bool is_clear) +Map_type::do_get_init_tree(Gogo*, tree type_tree, bool is_clear) { if (is_clear) return NULL; - return fold_convert(this->get_tree(gogo), null_pointer_node); + return fold_convert(type_tree, null_pointer_node); } // Return an expression for a newly allocated map. @@ -4344,11 +4313,11 @@ // Initialize a channel variable. tree -Channel_type::do_init_tree(Gogo* gogo, bool is_clear) +Channel_type::do_get_init_tree(Gogo*, tree type_tree, bool is_clear) { if (is_clear) return NULL; - return fold_convert(this->get_tree(gogo), null_pointer_node); + return fold_convert(type_tree, null_pointer_node); } // Handle the builtin function make for a channel. @@ -4844,14 +4813,13 @@ tree Interface_type::do_get_tree(Gogo* gogo) { - tree dtype = gogo->type_descriptor_type_tree(); - dtype = build_pointer_type(build_qualified_type(dtype, TYPE_QUAL_CONST)); - if (this->methods_ == NULL) { // At the tree level, use the same type for all empty // interfaces. This lets us assign them to each other directly // without triggering GIMPLE type errors. + tree dtype = gogo->type_descriptor_type_tree(); + dtype = build_pointer_type(build_qualified_type(dtype, TYPE_QUAL_CONST)); static tree empty_interface; return Gogo::builtin_struct(&empty_interface, "__go_empty_interface", NULL_TREE, 2, @@ -4861,46 +4829,31 @@ ptr_type_node); } - // Interface types can have methods which refer to the interface - // type itself, so build the type first and then the method table. - tree ret = make_node(RECORD_TYPE); - - tree field_trees = NULL_TREE; - tree* pp = &field_trees; - - // Create the pointer to the method table but don't fill it in yet. - tree mtype = make_node(POINTER_TYPE); - SET_TYPE_MODE(mtype, ptr_mode); - layout_type(mtype); - - tree name_tree = get_identifier("__methods"); - tree field = build_decl(this->location_, FIELD_DECL, name_tree, mtype); - DECL_CONTEXT(field) = ret; - *pp = field; - pp = &TREE_CHAIN(field); - - name_tree = get_identifier("__object"); - field = build_decl(this->location_, FIELD_DECL, name_tree, ptr_type_node); - DECL_CONTEXT(field) = ret; - *pp = field; - - TYPE_FIELDS(ret) = field_trees; - - layout_type(ret); - - this->set_incomplete_type_tree(ret); + return this->fill_in_tree(gogo, make_node(RECORD_TYPE)); +} + +// Fill in the tree for an interface type. This is used for named +// interface types. + +tree +Interface_type::fill_in_tree(Gogo* gogo, tree type) +{ + gcc_assert(this->methods_ != NULL); // 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. - name_tree = get_identifier("__type_descriptor"); - field = build_decl(this->location_, FIELD_DECL, name_tree, dtype); + tree name_tree = get_identifier("__type_descriptor"); + tree dtype = gogo->type_descriptor_type_tree(); + dtype = build_pointer_type(build_qualified_type(dtype, TYPE_QUAL_CONST)); + tree field = build_decl(this->location_, FIELD_DECL, name_tree, dtype); DECL_CONTEXT(field) = method_table; TYPE_FIELDS(method_table) = field; std::string last_name = ""; - pp = &TREE_CHAIN(field); + tree* pp = &TREE_CHAIN(field); for (Typed_identifier_list::const_iterator p = this->methods_->begin(); p != this->methods_->end(); ++p) @@ -4920,25 +4873,37 @@ } layout_type(method_table); - // Finish up the pointer to the method table. - TREE_TYPE(mtype) = method_table; - TYPE_POINTER_TO(method_table) = mtype; - if (TYPE_STRUCTURAL_EQUALITY_P(method_table)) - SET_TYPE_STRUCTURAL_EQUALITY(mtype); - - return ret; + 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 = &TREE_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; } // Initialization value. tree -Interface_type::do_init_tree(Gogo* gogo, bool is_clear) +Interface_type::do_get_init_tree(Gogo*, tree type_tree, bool is_clear) { if (is_clear) return NULL; - tree type_tree = this->get_tree(gogo); - VEC(constructor_elt,gc)* init = VEC_alloc(constructor_elt, gc, 2); for (tree field = TYPE_FIELDS(type_tree); field != NULL_TREE; @@ -5705,32 +5670,127 @@ if (this->is_error_) return error_mark_node; - tree type_tree = this->type_->get_tree(gogo); - if (type_tree != error_mark_node) - { - tree id = this->named_object_->get_id(gogo); - - // If we are looking at a struct, interface, function, channel - // or map, we don't need to make a copy to hold the type. Doing - // this makes it easier for the middle-end to notice when the - // types refer to themselves. - if (TYPE_NAME(type_tree) == NULL - && (this->type_->struct_type() != NULL - || this->type_->interface_type() != NULL - || this->type_->function_type() != NULL - || this->type_->channel_type() != NULL - || this->type_->map_type() != NULL)) - ; + // Go permits types to refer to themselves in various ways. Break + // the recursion here. + tree t; + switch (this->type_->forwarded()->classification()) + { + case TYPE_ERROR: + return error_mark_node; + + case TYPE_VOID: + case TYPE_BOOLEAN: + case TYPE_INTEGER: + case TYPE_FLOAT: + case TYPE_COMPLEX: + case TYPE_STRING: + case TYPE_NIL: + // These types can not refer to themselves. + case TYPE_MAP: + case TYPE_CHANNEL: + // All maps and channels have the same type in GENERIC. + t = this->type_->get_tree(gogo); + if (t == error_mark_node) + return error_mark_node; + // Build a copy to set TYPE_NAME. + t = build_variant_type_copy(t); + break; + + case TYPE_FUNCTION: + case TYPE_POINTER: + if (this->seen_) + { + // GENERIC can't handle a pointer type which points to + // itself. It goes into infinite loops when walking the + // types. + return ptr_type_node; + } + this->seen_ = true; + t = this->type_->get_tree(gogo); + this->seen_ = false; + if (t == error_mark_node) + return error_mark_node; + t = build_variant_type_copy(t); + break; + + case TYPE_STRUCT: + if (this->named_tree_ != NULL_TREE) + return this->named_tree_; + t = make_node(RECORD_TYPE); + this->named_tree_ = t; + this->type_->struct_type()->fill_in_tree(gogo, t); + break; + + case TYPE_ARRAY: + if (!this->is_open_array_type()) + t = this->type_->get_tree(gogo); else { - // Make a copy so that we can set TYPE_NAME. - type_tree = build_variant_type_copy(type_tree); + if (this->named_tree_ != NULL_TREE) + return this->named_tree_; + t = gogo->slice_type_tree(void_type_node); + this->named_tree_ = t; + t = this->type_->array_type()->fill_in_tree(gogo, t); } - - tree decl = build_decl(this->location_, TYPE_DECL, id, type_tree); - TYPE_NAME(type_tree) = decl; - } - return type_tree; + if (t == error_mark_node) + return error_mark_node; + t = build_variant_type_copy(t); + break; + + case TYPE_INTERFACE: + if (this->type_->interface_type()->is_empty()) + { + t = this->type_->get_tree(gogo); + if (t == error_mark_node) + return error_mark_node; + t = build_variant_type_copy(t); + } + else + { + if (this->named_tree_ != NULL_TREE) + return this->named_tree_; + t = make_node(RECORD_TYPE); + this->named_tree_ = t; + t = this->type_->interface_type()->fill_in_tree(gogo, t); + } + break; + + case TYPE_NAMED: + { + // When a named type T1 is defined as another named type T2, + // the definition must simply be "type T1 T2". If the + // definition of T2 may refer to T1, then we must simply + // return the type for T2 here. It's not precisely correct, + // but it's as close as we can get with GENERIC. + bool was_seen = this->seen_; + this->seen_ = true; + t = this->type_->get_tree(gogo); + this->seen_ = was_seen; + if (was_seen) + return t; + if (t == error_mark_node) + return error_mark_node; + t = build_variant_type_copy(t); + } + break; + + case TYPE_FORWARD: + // An undefined forwarding type. Make sure the error is + // emitted. + this->type_->forward_declaration_type()->real_type(); + return error_mark_node; + + default: + case TYPE_SINK: + case TYPE_CALL_MULTIPLE_RESULT: + gcc_unreachable(); + } + + tree id = this->named_object_->get_id(gogo); + tree decl = build_decl(this->location_, TYPE_DECL, id, t); + TYPE_NAME(t) = decl; + + return t; } // Type descriptor decl. diff -r 765edd916c29 go/types.h --- a/go/types.h Thu Sep 02 07:49:54 2010 -0700 +++ b/go/types.h Tue Sep 07 17:04:50 2010 -0700 @@ -799,6 +799,12 @@ tree get_init_tree(Gogo*, bool is_clear); + // Like get_init_tree, but passing in the type to use for the + // initializer. + tree + get_typed_init_tree(Gogo* gogo, tree type_tree, bool is_clear) + { return this->do_get_init_tree(gogo, type_tree, is_clear); } + // Return a tree for a make expression applied to this type. tree make_expression_tree(Translate_context* context, Expression_list* args, @@ -858,7 +864,7 @@ do_get_tree(Gogo*) = 0; virtual tree - do_init_tree(Gogo*, bool) = 0; + do_get_init_tree(Gogo*, tree, bool) = 0; virtual tree do_make_expression_tree(Translate_context*, Expression_list*, @@ -911,10 +917,6 @@ append_mangled_name(const Type* type, Gogo* gogo, std::string* ret) const { type->do_mangled_name(gogo, ret); } - // Store the type tree during construction. - void - set_incomplete_type_tree(tree); - // Incorporate a string into a hash code. static unsigned int hash_string(const std::string&, unsigned int); @@ -1232,7 +1234,7 @@ do_get_tree(Gogo*); tree - do_init_tree(Gogo*, bool); + do_get_init_tree(Gogo*, tree, bool); void do_type_descriptor_decl(Gogo*, Named_type*, tree*); @@ -1308,7 +1310,7 @@ do_get_tree(Gogo*); tree - do_init_tree(Gogo*, bool); + do_get_init_tree(Gogo*, tree, bool); void do_type_descriptor_decl(Gogo*, Named_type*, tree*); @@ -1380,7 +1382,7 @@ do_get_tree(Gogo*); tree - do_init_tree(Gogo*, bool); + do_get_init_tree(Gogo*, tree, bool); void do_type_descriptor_decl(Gogo*, Named_type*, tree*); @@ -1436,7 +1438,7 @@ do_get_tree(Gogo*); tree - do_init_tree(Gogo* gogo, bool); + do_get_init_tree(Gogo* gogo, tree, bool); void do_type_descriptor_decl(Gogo*, Named_type*, tree*); @@ -1549,7 +1551,7 @@ do_get_tree(Gogo*); tree - do_init_tree(Gogo*, bool); + do_get_init_tree(Gogo*, tree, bool); void do_type_descriptor_decl(Gogo*, Named_type*, tree*); @@ -1616,7 +1618,7 @@ do_get_tree(Gogo*); tree - do_init_tree(Gogo*, bool); + do_get_init_tree(Gogo*, tree, bool); void do_type_descriptor_decl(Gogo*, Named_type*, tree*); @@ -1850,6 +1852,10 @@ static Struct_type* do_import(Import*); + // Fill in the fields for a named struct type. + tree + fill_in_tree(Gogo*, tree); + protected: int do_traverse(Traverse*); @@ -1867,7 +1873,7 @@ do_get_tree(Gogo*); tree - do_init_tree(Gogo*, bool); + do_get_init_tree(Gogo*, tree, bool); void do_type_descriptor_decl(Gogo*, Named_type*, tree*); @@ -1939,6 +1945,10 @@ static Array_type* do_import(Import*); + // Fill in the fields for a named slice type. + tree + fill_in_tree(Gogo*, tree); + protected: int do_traverse(Traverse* traverse); @@ -1962,7 +1972,7 @@ do_get_tree(Gogo*); tree - do_init_tree(Gogo*, bool); + do_get_init_tree(Gogo*, tree, bool); tree do_make_expression_tree(Translate_context*, Expression_list*, @@ -2054,7 +2064,7 @@ do_get_tree(Gogo*); tree - do_init_tree(Gogo*, bool); + do_get_init_tree(Gogo*, tree, bool); tree do_make_expression_tree(Translate_context*, Expression_list*, @@ -2135,7 +2145,7 @@ do_get_tree(Gogo*); tree - do_init_tree(Gogo*, bool); + do_get_init_tree(Gogo*, tree, bool); tree do_make_expression_tree(Translate_context*, Expression_list*, @@ -2226,6 +2236,10 @@ static Interface_type* do_import(Import*); + // Fill in the fields for a named interface type. + tree + fill_in_tree(Gogo*, tree); + protected: int do_traverse(Traverse*); @@ -2241,7 +2255,7 @@ do_get_tree(Gogo*); tree - do_init_tree(Gogo* gogo, bool); + do_get_init_tree(Gogo* gogo, tree, bool); void do_type_descriptor_decl(Gogo*, Named_type*, tree*); @@ -2277,7 +2291,8 @@ named_object_(named_object), in_function_(NULL), type_(type), local_methods_(NULL), all_methods_(NULL), interface_method_tables_(NULL), pointer_interface_method_tables_(NULL), - location_(location), is_visible_(true), is_error_(false), seen_(false) + location_(location), named_tree_(NULL), is_visible_(true), + is_error_(false), seen_(false) { } // Return the associated Named_object. This holds the actual name. @@ -2444,8 +2459,8 @@ do_get_tree(Gogo*); tree - do_init_tree(Gogo* gogo, bool is_clear) - { return this->type_->get_init_tree(gogo, is_clear); } + do_get_init_tree(Gogo* gogo, tree type_tree, bool is_clear) + { return this->type_->get_typed_init_tree(gogo, type_tree, is_clear); } tree do_make_expression_tree(Translate_context* context, Expression_list* args, @@ -2492,6 +2507,9 @@ Interface_method_tables* pointer_interface_method_tables_; // The location where this type was defined. source_location location_; + // The tree for this type while converting to GENERIC. This is used + // to avoid endless recursion when a named type refers to itself. + tree named_tree_; // Whether this type is visible. This is false if this type was // created because it was referenced by an imported object, but the // type itself was not exported. This will always be true for types @@ -2567,8 +2585,8 @@ do_get_tree(Gogo* gogo); tree - do_init_tree(Gogo* gogo, bool is_clear) - { return this->base()->get_init_tree(gogo, is_clear); } + do_get_init_tree(Gogo* gogo, tree type_tree, bool is_clear) + { return this->base()->get_typed_init_tree(gogo, type_tree, is_clear); } tree do_make_expression_tree(Translate_context* context, Expression_list* args,