this->classification_ = TYPE_ERROR;
}
+// Return a string version of this type to use in an error message.
+
+std::string
+Type::message_name() const
+{
+ std::string ret;
+ this->do_message_name(&ret);
+ return ret;
+}
+
// If this is a pointer type, return the type to which it points.
// Otherwise, return NULL.
{
if (rhs->interface_type() != NULL)
reason->assign(_("need explicit conversion"));
- else if (lhs_orig->named_type() != NULL
- && rhs_orig->named_type() != NULL)
+ else
{
- size_t len = (lhs_orig->named_type()->name().length()
- + rhs_orig->named_type()->name().length()
- + 100);
+ const std::string& lhs_name(lhs_orig->message_name());
+ const std::string& rhs_name(rhs_orig->message_name());
+ size_t len = lhs_name.length() + rhs_name.length() + 100;
char* buf = new char[len];
snprintf(buf, len, _("cannot use type %s as type %s"),
- rhs_orig->named_type()->message_name().c_str(),
- lhs_orig->named_type()->message_name().c_str());
+ rhs_name.c_str(), lhs_name.c_str());
reason->assign(buf);
delete[] buf;
}
return this->is_abstract_ == t->is_abstract_;
}
+// Message name.
+
+void
+Integer_type::do_message_name(std::string* ret) const
+{
+ ret->append("<untyped ");
+ if (this->is_byte_)
+ ret->append("byte");
+ else if (this->is_rune_)
+ ret->append("rune");
+ else
+ {
+ if (this->is_unsigned_)
+ ret->push_back('u');
+ if (this->is_abstract_)
+ ret->append("int");
+ else
+ {
+ ret->append("int");
+ char buf[10];
+ snprintf(buf, sizeof buf, "%d", this->bits_);
+ ret->append(buf);
+ }
+ }
+ ret->push_back('>');
+}
+
// Hash code.
unsigned int
return this->is_abstract_ == t->is_abstract_;
}
+// Message name.
+
+void
+Float_type::do_message_name(std::string* ret) const
+{
+ ret->append("<untyped float");
+ if (!this->is_abstract_)
+ {
+ char buf[10];
+ snprintf(buf, sizeof buf, "%d", this->bits_);
+ ret->append(buf);
+ }
+ ret->push_back('>');
+}
+
// Hash code.
unsigned int
return this->is_abstract_ == t->is_abstract_;
}
+// Message name.
+
+void
+Complex_type::do_message_name(std::string* ret) const
+{
+ ret->append("<untyped complex");
+ if (!this->is_abstract_)
+ {
+ char buf[10];
+ snprintf(buf, sizeof buf, "%d", this->bits_);
+ ret->append(buf);
+ }
+ ret->push_back('>');
+}
+
// Hash code.
unsigned int
{ }
protected:
+ void
+ do_message_name(std::string* ret) const
+ { ret->append("<SINK>"); }
+
bool
do_compare_is_identity(Gogo*)
{ return false; }
// Class Function_type.
+// Message name.
+
+void
+Function_type::do_message_name(std::string* ret) const
+{
+ ret->append("func");
+ if (this->receiver_ != NULL)
+ {
+ ret->append(" (receiver ");
+ this->append_message_name(this->receiver_->type(), ret);
+ ret->append(") ");
+ }
+ this->append_signature(ret);
+}
+
+// Append just the signature to RET.
+
+void
+Function_type::append_signature(std::string* ret) const
+{
+ ret->push_back('(');
+ if (this->parameters_ != NULL)
+ {
+ bool first = true;
+ for (Typed_identifier_list::const_iterator p = this->parameters_->begin();
+ p != this->parameters_->end();
+ ++p)
+ {
+ if (first)
+ first = false;
+ else
+ ret->append(", ");
+ this->append_message_name(p->type(), ret);
+ }
+ }
+ ret->push_back(')');
+
+ if (this->results_ != NULL)
+ {
+ if (this->results_->size() == 1)
+ {
+ ret->push_back(' ');
+ this->append_message_name(this->results_->front().type(), ret);
+ }
+ else
+ {
+ ret->append(" (");
+ bool first = true;
+ for (Typed_identifier_list::const_iterator p =
+ this->results_->begin();
+ p != this->results_->end();
+ ++p)
+ {
+ if (first)
+ first = false;
+ else
+ ret->append(", ");
+ this->append_message_name(p->type(), ret);
+ }
+ ret->push_back(')');
+ }
+ }
+}
+
// Traversal.
int
// Class Pointer_type.
+// Message name.
+
+void
+Pointer_type::do_message_name(std::string* ret) const
+{
+ if (this->to_type_->is_void_type())
+ ret->append("unsafe.Pointer");
+ else
+ {
+ ret->push_back('*');
+ this->append_message_name(this->to_type_, ret);
+ }
+}
+
// Traversal.
int
{ }
protected:
+ void
+ do_message_name(std::string* ret) const
+ { ret->append("<call-multiple-result>"); }
+
bool
do_has_pointer() const
{ return false; }
Struct_type::Struct_method_tables Struct_type::struct_method_tables;
+// Message name.
+
+void
+Struct_type::do_message_name(std::string* ret) const
+{
+ if (this->fields_ == NULL || this->fields_->empty())
+ {
+ ret->append("struct{}");
+ return;
+ }
+
+ ret->append("struct {");
+
+ bool first = true;
+ for (Struct_field_list::const_iterator p = this->fields_->begin();
+ p != this->fields_->end();
+ ++p)
+ {
+ if (first)
+ first = false;
+ else
+ ret->append("; ");
+
+ if (!p->is_anonymous())
+ {
+ ret->append(p->field_name());
+ ret->push_back(' ');
+ }
+
+ this->append_message_name(p->type(), ret);
+ }
+
+ ret->append(" }");
+}
+
// Traversal.
int
return false;
}
+// Message name.
+
+void
+Array_type::do_message_name(std::string* ret) const
+{
+ ret->push_back('[');
+ if (!this->is_slice_type())
+ {
+ Numeric_constant nc;
+ if (!this->length_->numeric_constant_value(&nc))
+ ret->append("<unknown length>");
+ else
+ {
+ mpz_t val;
+ if (!nc.to_int(&val))
+ ret->append("<unknown length>");
+ else
+ {
+ char* s = mpz_get_str(NULL, 10, val);
+ ret->append(s);
+ free(s);
+ mpz_clear(val);
+ }
+ }
+ }
+ ret->push_back(']');
+ this->append_message_name(this->element_type_, ret);
+}
+
// Traversal.
int
return zvar;
}
+// Message name.
+
+void
+Map_type::do_message_name(std::string* ret) const
+{
+ ret->append("map[");
+ this->append_message_name(this->key_type_, ret);
+ ret->push_back(']');
+ this->append_message_name(this->val_type_, ret);
+}
+
// Traversal.
int
// Class Channel_type.
+// Message name.
+
+void
+Channel_type::do_message_name(std::string* ret) const
+{
+ if (!this->may_send_)
+ ret->append("<-");
+ ret->append("chan");
+ if (!this->may_receive_)
+ ret->append("<-");
+ ret->push_back(' ');
+ this->append_message_name(this->element_type_, ret);
+}
+
// Verify.
bool
return this->all_methods_ == NULL ? 0 : this->all_methods_->size();
}
+// Message name.
+
+void
+Interface_type::do_message_name(std::string* ret) const
+{
+ const Typed_identifier_list* methods = (this->methods_are_finalized_
+ ? this->all_methods_
+ : this->parse_methods_);
+ if (methods == NULL || methods->empty())
+ {
+ ret->append("interface{}");
+ return;
+ }
+
+ ret->append("interface {");
+
+ bool first = true;
+ for (Typed_identifier_list::const_iterator p = methods->begin();
+ p != methods->end();
+ ++p)
+ {
+ if (first)
+ first = false;
+ else
+ ret->append("; ");
+
+ if (!p->name().empty())
+ ret->append(p->name());
+
+ Function_type* ft = p->type()->function_type();
+ if (ft == NULL)
+ this->append_message_name(p->type(), ret);
+ else
+ ft->append_signature(ret);
+ }
+
+ ret->append(" }");
+}
+
// Traversal.
int
// Return the name of the type to use in an error message.
-std::string
-Named_type::message_name() const
+void
+Named_type::do_message_name(std::string* ret) const
{
- return this->named_object_->message_name();
+ ret->append(this->named_object_->message_name());
}
// Return the base type for this type. We have to be careful about
no->type_declaration_value()->add_existing_method(nom);
}
+// Message name.
+
+void
+Forward_declaration_type::do_message_name(std::string* ret) const
+{
+ if (this->is_defined())
+ this->append_message_name(this->real_type(), ret);
+ else
+ ret->append(this->named_object_->message_name());
+}
+
// Traversal.
int
static Named_type*
make_builtin_named_type(const char* name, Type* type);
+ // Return a string version of this type to use in an error message.
+ std::string
+ message_name() const;
+
// Traverse a type.
static int
traverse(Type*, Traverse*);
// Functions implemented by the child class.
+ // Message name.
+ virtual void
+ do_message_name(std::string*) const = 0;
+
// Traverse the subtypes.
virtual int
do_traverse(Traverse*);
type_descriptor_constructor(Gogo*, int runtime_type_kind, Named_type*,
const Methods*, bool only_value_methods);
+ // For the benefit of child class message name construction.
+ void
+ append_message_name(const Type* type, std::string* ret) const
+ { type->do_message_name(ret); }
+
// For the benefit of child class reflection string generation.
void
append_reflection(const Type* type, Gogo* gogo, std::string* ret) const
{ }
protected:
+ void
+ do_message_name(std::string* ret) const
+ { ret->append("<ERROR>"); }
+
bool
do_compare_is_identity(Gogo*)
{ return false; }
{ }
protected:
+ void
+ do_message_name(std::string* ret) const
+ { ret->append("void"); }
+
bool
do_compare_is_identity(Gogo*)
{ return false; }
{ }
protected:
+ void
+ do_message_name(std::string* ret) const
+ { ret->append("<untyped bool>"); }
+
bool
do_compare_is_identity(Gogo*)
{ return true; }
{ this->is_rune_ = true; }
protected:
+ void
+ do_message_name(std::string* ret) const;
+
bool
do_compare_is_identity(Gogo*)
{ return true; }
is_identical(const Float_type* t) const;
protected:
+ void
+ do_message_name(std::string* ret) const;
+
bool
do_compare_is_identity(Gogo*)
{ return false; }
is_identical(const Complex_type* t) const;
protected:
+ void
+ do_message_name(std::string*) const;
+
bool
do_compare_is_identity(Gogo*)
{ return false; }
{ }
protected:
+ void
+ do_message_name(std::string* ret) const
+ { ret->append("<untyped string>"); }
+
bool
do_has_pointer() const
{ return true; }
is_backend_function_type() const
{ return false; }
+ // Append just the signature of the function type.
+ void
+ append_signature(std::string*) const;
+
protected:
+ void
+ do_message_name(std::string*) const;
+
int
do_traverse(Traverse*);
make_pointer_type_descriptor_type();
protected:
+ void
+ do_message_name(std::string*) const;
+
int
do_traverse(Traverse*);
{ }
protected:
+ void
+ do_message_name(std::string* ret) const
+ { ret->append("<NIL>"); }
+
bool
do_compare_is_identity(Gogo*)
{ return false; }
write_to_c_header(std::ostream&) const;
protected:
+ void
+ do_message_name(std::string*) const;
+
int
do_traverse(Traverse*);
write_equal_function(Gogo*, Named_object* function, Named_type*);
protected:
+ void
+ do_message_name(std::string*) const;
+
int
do_traverse(Traverse* traverse);
static const int bucket_size = 8;
protected:
+ void
+ do_message_name(std::string*) const;
+
int
do_traverse(Traverse*);
select_case_type();
protected:
+ void
+ do_message_name(std::string*) const;
+
int
do_traverse(Traverse* traverse)
{ return Type::traverse(this->element_type_, traverse); }
{ return this->methods_are_finalized_; }
protected:
+ void
+ do_message_name(std::string*) const;
+
int
do_traverse(Traverse*);
const std::string&
name() const;
- // Return the name of the type for an error message. The difference
- // is that if the type is defined in a different package, this will
- // return PACKAGE.NAME.
- std::string
- message_name() const;
-
// Return the underlying type.
Type*
real_type()
convert(Gogo*);
protected:
+ void
+ do_message_name(std::string* ret) const;
+
int
do_traverse(Traverse* traverse)
{ return Type::traverse(this->type_, traverse); }
add_existing_method(Named_object*);
protected:
+ void
+ do_message_name(std::string*) const;
+
int
do_traverse(Traverse* traverse);