imported_init_fns_(),
unique_prefix_(),
unique_prefix_specified_(false),
- interface_types_()
+ interface_types_(),
+ named_types_are_converted_(false)
{
const source_location loc = BUILTINS_LOCATION;
else if (!type->is_method())
{
ret = this->package_->bindings()->add_function(*pname, NULL, function);
- if (!ret->is_function())
+ if (!ret->is_function() || ret->func_value() != function)
{
- // Redefinition error.
- ret = Named_object::make_function(name, NULL, function);
+ // Redefinition error. Invent a name to avoid knockon
+ // errors.
+ static int redefinition_count;
+ char buf[30];
+ snprintf(buf, sizeof buf, ".$redefined%d", redefinition_count);
+ ++redefinition_count;
+ ret = this->package_->bindings()->add_function(buf, NULL, function);
}
}
else
int
Verify_types::type(Type* t)
{
- // Don't verify types defined in other packages.
- Named_type* nt = t->named_type();
- if (nt != NULL && nt->named_object()->package() != NULL)
- return TRAVERSE_SKIP_COMPONENTS;
-
if (!t->verify())
return TRAVERSE_SKIP_COMPONENTS;
return TRAVERSE_CONTINUE;
{
public:
Lower_parse_tree(Gogo* gogo, Named_object* function)
- : Traverse(traverse_constants
+ : Traverse(traverse_variables
+ | traverse_constants
| traverse_functions
| traverse_statements
| traverse_expressions),
gogo_(gogo), function_(function), iota_value_(-1)
{ }
+ int
+ variable(Named_object*);
+
int
constant(Named_object*, bool);
int iota_value_;
};
+// Lower variables. We handle variables specially to break loops in
+// which a variable initialization expression refers to itself. The
+// loop breaking is in lower_init_expression.
+
+int
+Lower_parse_tree::variable(Named_object* no)
+{
+ if (no->is_variable())
+ no->var_value()->lower_init_expression(this->gogo_, this->function_);
+ return TRAVERSE_CONTINUE;
+}
+
// Lower constants. We handle constants specially so that we can set
// the right value for the predeclared constant iota. This works in
// conjunction with the way we lower Const_expression objects.
const std::string& new_receiver_name(orig_fntype->receiver()->name());
Named_object* new_rec_no = new_bindings->lookup_local(new_receiver_name);
- gcc_assert(new_rec_no != NULL
- && new_rec_no->is_variable()
- && new_rec_no->var_value()->is_receiver());
- new_rec_no->var_value()->set_is_not_receiver();
+ if (new_rec_no == NULL)
+ gcc_assert(saw_errors());
+ else
+ {
+ gcc_assert(new_rec_no->is_variable()
+ && new_rec_no->var_value()->is_receiver());
+ new_rec_no->var_value()->set_is_not_receiver();
+ }
}
// Because we flipped blocks but not types, the can_recover
this->package_->bindings());
}
+// Find the blocks in order to convert named types defined in blocks.
+
+class Convert_named_types : public Traverse
+{
+ public:
+ Convert_named_types(Gogo* gogo)
+ : Traverse(traverse_blocks),
+ gogo_(gogo)
+ { }
+
+ protected:
+ int
+ block(Block* block);
+
+ private:
+ Gogo* gogo_;
+};
+
+int
+Convert_named_types::block(Block* block)
+{
+ this->gogo_->convert_named_types_in_bindings(block->bindings());
+ return TRAVERSE_CONTINUE;
+}
+
+// Convert all named types to the backend representation. Since named
+// types can refer to other types, this needs to be done in the right
+// sequence, which is handled by Named_type::convert. Here we arrange
+// to call that for each named type.
+
+void
+Gogo::convert_named_types()
+{
+ this->convert_named_types_in_bindings(this->globals_);
+ for (Packages::iterator p = this->packages_.begin();
+ p != this->packages_.end();
+ ++p)
+ {
+ Package* package = p->second;
+ this->convert_named_types_in_bindings(package->bindings());
+ }
+
+ Convert_named_types cnt(this);
+ this->traverse(&cnt);
+
+ // Make all the builtin named types used for type descriptors, and
+ // then convert them. They will only be written out if they are
+ // needed.
+ Type::make_type_descriptor_type();
+ Type::make_type_descriptor_ptr_type();
+ Function_type::make_function_type_descriptor_type();
+ Pointer_type::make_pointer_type_descriptor_type();
+ Struct_type::make_struct_type_descriptor_type();
+ Array_type::make_array_type_descriptor_type();
+ Array_type::make_slice_type_descriptor_type();
+ Map_type::make_map_type_descriptor_type();
+ Channel_type::make_chan_type_descriptor_type();
+ Interface_type::make_interface_type_descriptor_type();
+ Type::convert_builtin_named_types(this);
+
+ this->named_types_are_converted_ = true;
+}
+
+// Convert all names types in a set of bindings.
+
+void
+Gogo::convert_named_types_in_bindings(Bindings* bindings)
+{
+ for (Bindings::const_definitions_iterator p = bindings->begin_definitions();
+ p != bindings->end_definitions();
+ ++p)
+ {
+ if ((*p)->is_type())
+ (*p)->type_value()->convert(this);
+ }
+}
+
// Class Function.
Function::Function(Function_type* type, Function* enclosing, Block* block,
}
Result_variable* result = new Result_variable(p->type(), this, index);
Named_object* no = block->bindings()->add_result_variable(name, result);
- this->named_results_->push_back(no);
+ if (no->is_result_variable())
+ this->named_results_->push_back(no);
}
}