aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@golang.org>2023-10-20 10:25:04 -0700
committerIan Lance Taylor <iant@golang.org>2024-02-05 11:26:01 -0800
commite86066a71e684065fae6910b9e2aaf37d7177e01 (patch)
tree29aabb316dd7b27d2a03276f7e7ef380b209a8f2
parent51f8ac3341078303e81e72d9013698a31c5ddd29 (diff)
downloadgcc-e86066a71e684065fae6910b9e2aaf37d7177e01.zip
gcc-e86066a71e684065fae6910b9e2aaf37d7177e01.tar.gz
gcc-e86066a71e684065fae6910b9e2aaf37d7177e01.tar.bz2
compiler: add Type::message_name
As we move toward generics, the error messages need to be able to refer to types in a readable manner. Add that capability, and use it today in AST dumps. Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/536716
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/ast-dump.cc9
-rw-r--r--gcc/go/gofrontend/types.cc310
-rw-r--r--gcc/go/gofrontend/types.h79
4 files changed, 375 insertions, 25 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index 429904a..ec7e2ab 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-8c056e335cecec67d1d223a329b7ba4dac778a65
+1cb83a415e86ab4de0d436d277377d8fc060cb61
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/gcc/go/gofrontend/ast-dump.cc b/gcc/go/gofrontend/ast-dump.cc
index eca0bf1..12f49e6 100644
--- a/gcc/go/gofrontend/ast-dump.cc
+++ b/gcc/go/gofrontend/ast-dump.cc
@@ -223,14 +223,7 @@ Ast_dump_context::dump_type(const Type* t)
if (t == NULL)
this->ostream() << "(nil type)";
else
- // FIXME: write a type pretty printer instead of
- // using mangled names.
- if (this->gogo_ != NULL)
- {
- Backend_name bname;
- t->backend_name(this->gogo_, &bname);
- this->ostream() << "(" << bname.name() << ")";
- }
+ this->ostream() << "(" << t->message_name() << ")";
}
// Dump a textual representation of a block to the
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index b349ad1..a39cfbf 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -270,6 +270,16 @@ Type::set_is_error()
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.
@@ -742,16 +752,14 @@ Type::are_assignable(const Type* lhs, const Type* rhs, std::string* reason)
{
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;
}
@@ -4244,6 +4252,33 @@ Integer_type::is_identical(const Integer_type* t) const
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
@@ -4382,6 +4417,21 @@ Float_type::is_identical(const Float_type* t) const
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
@@ -4496,6 +4546,21 @@ Complex_type::is_identical(const Complex_type *t) const
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
@@ -4661,6 +4726,10 @@ class Sink_type : public Type
{ }
protected:
+ void
+ do_message_name(std::string* ret) const
+ { ret->append("<SINK>"); }
+
bool
do_compare_is_identity(Gogo*)
{ return false; }
@@ -4696,6 +4765,70 @@ Type::make_sink_type()
// 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
@@ -5548,6 +5681,20 @@ Type::make_backend_function_type(Typed_identifier* receiver,
// 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
@@ -5764,6 +5911,10 @@ class Call_multiple_result_type : public Type
{ }
protected:
+ void
+ do_message_name(std::string* ret) const
+ { ret->append("<call-multiple-result>"); }
+
bool
do_has_pointer() const
{ return false; }
@@ -5940,6 +6091,41 @@ Struct_type::Identical_structs Struct_type::identical_structs;
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
@@ -7344,6 +7530,35 @@ Array_type::is_identical(const Array_type* t, int flags) const
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
@@ -8249,6 +8464,17 @@ Map_type::backend_zero_value(Gogo* gogo)
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
@@ -8803,6 +9029,20 @@ Type::make_map_type(Type* key_type, Type* val_type, Location location)
// 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
@@ -9053,6 +9293,45 @@ Interface_type::method_count() const
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
@@ -10295,10 +10574,10 @@ Named_type::name() const
// 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
@@ -12819,6 +13098,17 @@ Forward_declaration_type::add_existing_method(Named_object* nom)
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
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h
index 3dd3279..cbc7ce0 100644
--- a/gcc/go/gofrontend/types.h
+++ b/gcc/go/gofrontend/types.h
@@ -575,6 +575,10 @@ class Type
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*);
@@ -1095,6 +1099,10 @@ class Type
// 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*);
@@ -1195,6 +1203,11 @@ class Type
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
@@ -1656,6 +1669,10 @@ class Error_type : public Type
{ }
protected:
+ void
+ do_message_name(std::string* ret) const
+ { ret->append("<ERROR>"); }
+
bool
do_compare_is_identity(Gogo*)
{ return false; }
@@ -1683,6 +1700,10 @@ class Void_type : public Type
{ }
protected:
+ void
+ do_message_name(std::string* ret) const
+ { ret->append("void"); }
+
bool
do_compare_is_identity(Gogo*)
{ return false; }
@@ -1712,6 +1733,10 @@ class Boolean_type : public Type
{ }
protected:
+ void
+ do_message_name(std::string* ret) const
+ { ret->append("<untyped bool>"); }
+
bool
do_compare_is_identity(Gogo*)
{ return true; }
@@ -1797,6 +1822,9 @@ class Integer_type : public Type
{ this->is_rune_ = true; }
protected:
+ void
+ do_message_name(std::string* ret) const;
+
bool
do_compare_is_identity(Gogo*)
{ return true; }
@@ -1874,6 +1902,9 @@ class Float_type : public Type
is_identical(const Float_type* t) const;
protected:
+ void
+ do_message_name(std::string* ret) const;
+
bool
do_compare_is_identity(Gogo*)
{ return false; }
@@ -1952,6 +1983,9 @@ class Complex_type : public Type
is_identical(const Complex_type* t) const;
protected:
+ void
+ do_message_name(std::string*) const;
+
bool
do_compare_is_identity(Gogo*)
{ return false; }
@@ -2009,6 +2043,10 @@ class String_type : public Type
{ }
protected:
+ void
+ do_message_name(std::string* ret) const
+ { ret->append("<untyped string>"); }
+
bool
do_has_pointer() const
{ return true; }
@@ -2166,7 +2204,14 @@ class Function_type : public Type
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*);
@@ -2293,6 +2338,9 @@ class Pointer_type : public Type
make_pointer_type_descriptor_type();
protected:
+ void
+ do_message_name(std::string*) const;
+
int
do_traverse(Traverse*);
@@ -2346,6 +2394,10 @@ class Nil_type : public Type
{ }
protected:
+ void
+ do_message_name(std::string* ret) const
+ { ret->append("<NIL>"); }
+
bool
do_compare_is_identity(Gogo*)
{ return false; }
@@ -2671,6 +2723,9 @@ class Struct_type : public Type
write_to_c_header(std::ostream&) const;
protected:
+ void
+ do_message_name(std::string*) const;
+
int
do_traverse(Traverse*);
@@ -2851,6 +2906,9 @@ class Array_type : public Type
write_equal_function(Gogo*, Named_object* function, Named_type*);
protected:
+ void
+ do_message_name(std::string*) const;
+
int
do_traverse(Traverse* traverse);
@@ -2999,6 +3057,9 @@ class Map_type : public Type
static const int bucket_size = 8;
protected:
+ void
+ do_message_name(std::string*) const;
+
int
do_traverse(Traverse*);
@@ -3118,6 +3179,9 @@ class Channel_type : public Type
select_case_type();
protected:
+ void
+ do_message_name(std::string*) const;
+
int
do_traverse(Traverse* traverse)
{ return Type::traverse(this->element_type_, traverse); }
@@ -3273,6 +3337,9 @@ class Interface_type : public Type
{ return this->methods_are_finalized_; }
protected:
+ void
+ do_message_name(std::string*) const;
+
int
do_traverse(Traverse*);
@@ -3450,12 +3517,6 @@ class Named_type : public Type
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()
@@ -3599,6 +3660,9 @@ class Named_type : public Type
convert(Gogo*);
protected:
+ void
+ do_message_name(std::string* ret) const;
+
int
do_traverse(Traverse* traverse)
{ return Type::traverse(this->type_, traverse); }
@@ -3758,6 +3822,9 @@ class Forward_declaration_type : public Type
add_existing_method(Named_object*);
protected:
+ void
+ do_message_name(std::string*) const;
+
int
do_traverse(Traverse* traverse);