===================================================================
@@ -1,4 +1,4 @@
-0ba4563a4b0dec4c01b90d7b3c9e2ce2cd58a96f
+ea73a80a6047f477d92fccc7de143a3ee1021c65
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
===================================================================
@@ -608,6 +608,9 @@ Export::write_type(const Type* type)
// definition of the type may refer to the named type via a
// pointer.
this->type_refs_[type] = index;
+
+ if (named_type != NULL && named_type->is_alias())
+ this->write_c_string("= ");
}
type->export_type(this);
===================================================================
@@ -108,12 +108,14 @@ Gogo::Gogo(Backend* backend, Linemap* li
uint8_type->integer_type()->set_is_byte();
Named_object* byte_type = Named_object::make_type("byte", NULL, uint8_type,
loc);
+ byte_type->type_value()->set_is_alias();
this->add_named_type(byte_type->type_value());
// "rune" is an alias for "int32".
int32_type->integer_type()->set_is_rune();
Named_object* rune_type = Named_object::make_type("rune", NULL, int32_type,
loc);
+ rune_type->type_value()->set_is_alias();
this->add_named_type(rune_type->type_value());
this->add_named_type(Type::make_named_bool_type());
@@ -1775,6 +1777,10 @@ Gogo::start_function(const std::string&
if (rtype->classification() == Type::TYPE_POINTER)
rtype = rtype->points_to();
+ while (rtype->named_type() != NULL
+ && rtype->named_type()->is_alias())
+ rtype = rtype->named_type()->real_type();
+
if (rtype->is_error_type())
ret = Named_object::make_function(name, NULL, function);
else if (rtype->named_type() != NULL)
@@ -6865,7 +6871,7 @@ Type_declaration::add_method_declaration
return ret;
}
-// Return whether any methods ere defined.
+// Return whether any methods are defined.
bool
Type_declaration::has_methods() const
@@ -6878,6 +6884,36 @@ Type_declaration::has_methods() const
void
Type_declaration::define_methods(Named_type* nt)
{
+ if (this->methods_.empty())
+ return;
+
+ while (nt->is_alias())
+ {
+ Type *t = nt->real_type()->forwarded();
+ if (t->named_type() != NULL)
+ nt = t->named_type();
+ else if (t->forward_declaration_type() != NULL)
+ {
+ Named_object* no = t->forward_declaration_type()->named_object();
+ Type_declaration* td = no->type_declaration_value();
+ td->methods_.insert(td->methods_.end(), this->methods_.begin(),
+ this->methods_.end());
+ this->methods_.clear();
+ return;
+ }
+ else
+ {
+ for (std::vector<Named_object*>::const_iterator p =
+ this->methods_.begin();
+ p != this->methods_.end();
+ ++p)
+ go_error_at((*p)->location(),
+ ("invalid receiver type "
+ "(receiver must be a named type"));
+ return;
+ }
+ }
+
for (std::vector<Named_object*>::const_iterator p = this->methods_.begin();
p != this->methods_.end();
++p)
===================================================================
@@ -737,6 +737,13 @@ Import::read_type()
this->require_c_string(" ");
+ bool is_alias = false;
+ if (this->match_c_string("= "))
+ {
+ stream->advance(2);
+ is_alias = true;
+ }
+
// The package name may follow. This is the name of the package in
// the package clause of that package. The type name will include
// the pkgpath, which may be different.
@@ -810,6 +817,9 @@ Import::read_type()
// This type has not yet been imported.
ntype->clear_is_visible();
+ if (is_alias)
+ ntype->set_is_alias();
+
if (!type->is_undefined() && type->interface_type() != NULL)
this->gogo_->record_interface_type(type->interface_type());
===================================================================
@@ -1515,7 +1515,7 @@ Parse::type_decl()
this->decl(&Parse::type_spec, NULL);
}
-// TypeSpec = identifier Type .
+// TypeSpec = identifier ["="] Type .
void
Parse::type_spec(void*)
@@ -1531,6 +1531,13 @@ Parse::type_spec(void*)
Location location = token->location();
token = this->advance_token();
+ bool is_alias = false;
+ if (token->is_op(OPERATOR_EQ))
+ {
+ is_alias = true;
+ token = this->advance_token();
+ }
+
// The scope of the type name starts at the point where the
// identifier appears in the source code. We implement this by
// declaring the type before we read the type definition.
@@ -1542,13 +1549,13 @@ Parse::type_spec(void*)
}
Type* type;
- if (name == "_" && this->peek_token()->is_keyword(KEYWORD_INTERFACE))
+ if (name == "_" && token->is_keyword(KEYWORD_INTERFACE))
{
// We call Parse::interface_type explicity here because we do not want
// to record an interface with a blank type name.
type = this->interface_type(false);
}
- else if (!this->peek_token()->is_op(OPERATOR_SEMICOLON))
+ else if (!token->is_op(OPERATOR_SEMICOLON))
type = this->type();
else
{
@@ -1579,9 +1586,11 @@ Parse::type_spec(void*)
type = Type::make_error_type();
}
- this->gogo_->define_type(named_type,
- Type::make_named_type(named_type, type,
- location));
+ Named_type* nt = Type::make_named_type(named_type, type, location);
+ if (is_alias)
+ nt->set_is_alias();
+
+ this->gogo_->define_type(named_type, nt);
go_assert(named_type->package() == NULL);
}
else
===================================================================
@@ -328,10 +328,10 @@ Type::are_identical(const Type* t1, cons
t2 = t2->forwarded();
// Ignore aliases for purposes of type identity.
- if (t1->named_type() != NULL && t1->named_type()->is_alias())
- t1 = t1->named_type()->real_type();
- if (t2->named_type() != NULL && t2->named_type()->is_alias())
- t2 = t2->named_type()->real_type();
+ while (t1->named_type() != NULL && t1->named_type()->is_alias())
+ t1 = t1->named_type()->real_type()->forwarded();
+ while (t2->named_type() != NULL && t2->named_type()->is_alias())
+ t2 = t2->named_type()->real_type()->forwarded();
if (t1 == t2)
return true;
@@ -822,6 +822,8 @@ Type::are_convertible(const Type* lhs, c
unsigned int
Type::hash_for_method(Gogo* gogo) const
{
+ if (this->named_type() != NULL && this->named_type()->is_alias())
+ return this->named_type()->real_type()->hash_for_method(gogo);
unsigned int ret = 0;
if (this->classification_ != TYPE_FORWARD)
ret += this->classification_;
@@ -1165,8 +1167,8 @@ Bexpression*
Type::type_descriptor_pointer(Gogo* gogo, Location location)
{
Type* t = this->forwarded();
- if (t->named_type() != NULL && t->named_type()->is_alias())
- t = t->named_type()->real_type();
+ while (t->named_type() != NULL && t->named_type()->is_alias())
+ t = t->named_type()->real_type()->forwarded();
if (t->type_descriptor_var_ == NULL)
{
t->make_type_descriptor_var(gogo);
@@ -1585,6 +1587,9 @@ Type::make_type_descriptor_ptr_type()
bool
Type::needs_specific_type_functions(Gogo* gogo)
{
+ Named_type* nt = this->named_type();
+ if (nt != NULL && nt->is_alias())
+ return false;
if (!this->is_comparable())
return false;
if (!this->compare_is_identity(gogo))
@@ -1593,7 +1598,6 @@ Type::needs_specific_type_functions(Gogo
// We create a few predeclared types for type descriptors; they are
// really just for the backend and don't need hash or equality
// functions.
- Named_type* nt = this->named_type();
if (nt != NULL && Linemap::is_predeclared_location(nt->location()))
return false;
@@ -1634,6 +1638,11 @@ Type::type_functions(Gogo* gogo, Named_t
Function_type* equal_fntype, Named_object** hash_fn,
Named_object** equal_fn)
{
+ // If this loop leaves NAME as NULL, then the type does not have a
+ // name after all.
+ while (name != NULL && name->is_alias())
+ name = name->real_type()->named_type();
+
if (!this->is_comparable())
{
*hash_fn = NULL;
@@ -2164,6 +2173,11 @@ Type::write_named_hash(Gogo* gogo, Named
Location bloc = Linemap::predeclared_location();
Named_type* base_type = name->real_type()->named_type();
+ while (base_type->is_alias())
+ {
+ base_type = base_type->real_type()->named_type();
+ go_assert(base_type != NULL);
+ }
go_assert(base_type != NULL);
// The pointer to the type we are going to hash. This is an
@@ -2371,8 +2385,8 @@ Bexpression*
Type::gc_symbol_pointer(Gogo* gogo)
{
Type* t = this->forwarded();
- if (t->named_type() != NULL && t->named_type()->is_alias())
- t = t->named_type()->real_type();
+ while (t->named_type() != NULL && t->named_type()->is_alias())
+ t = t->named_type()->real_type()->forwarded();
if (t->gc_symbol_var_ == NULL)
{
t->make_gc_symbol_var(gogo);
@@ -4857,7 +4871,10 @@ Struct_field::field_name() const
if (dt->forward_declaration_type() != NULL)
return dt->forward_declaration_type()->name();
else if (dt->named_type() != NULL)
- return dt->named_type()->name();
+ {
+ // Note that this can be an alias name.
+ return dt->named_type()->name();
+ }
else if (t->is_error_type() || dt->is_error_type())
{
static const std::string error_string = "*error*";
@@ -5786,7 +5803,12 @@ Struct_type::do_reflection(Gogo* gogo, s
else
ret->append(Gogo::unpack_hidden_name(p->field_name()));
ret->push_back(' ');
- this->append_reflection(p->type(), gogo, ret);
+ if (p->is_anonymous()
+ && p->type()->named_type() != NULL
+ && p->type()->named_type()->is_alias())
+ p->type()->named_type()->append_reflection_type_name(gogo, true, ret);
+ else
+ this->append_reflection(p->type(), gogo, ret);
if (p->has_tag())
{
@@ -5866,7 +5888,15 @@ Struct_type::do_mangled_name(Gogo* gogo,
ret->append(buf);
ret->append(n);
}
- this->append_mangled_name(p->type(), gogo, ret);
+
+ // For an anonymous field with an alias type, the field name
+ // is the alias name.
+ if (p->is_anonymous()
+ && p->type()->named_type() != NULL
+ && p->type()->named_type()->is_alias())
+ p->type()->named_type()->append_mangled_type_name(gogo, true, ret);
+ else
+ this->append_mangled_name(p->type(), gogo, ret);
if (p->has_tag())
{
const std::string& tag(p->tag());
@@ -9313,18 +9343,6 @@ Named_type::message_name() const
return this->named_object_->message_name();
}
-// Whether this is an alias. There are currently only two aliases so
-// we just recognize them by name.
-
-bool
-Named_type::is_alias() const
-{
- if (!this->is_builtin())
- return false;
- const std::string& name(this->name());
- return name == "byte" || name == "rune";
-}
-
// Return the base type for this type. We have to be careful about
// circular type definitions, which are invalid but may be seen here.
@@ -9384,6 +9402,7 @@ Named_type::named_type_is_comparable(std
Named_object*
Named_type::add_method(const std::string& name, Function* function)
{
+ go_assert(!this->is_alias_);
if (this->local_methods_ == NULL)
this->local_methods_ = new Bindings(NULL);
return this->local_methods_->add_function(name, NULL, function);
@@ -9396,6 +9415,7 @@ Named_type::add_method_declaration(const
Function_type* type,
Location location)
{
+ go_assert(!this->is_alias_);
if (this->local_methods_ == NULL)
this->local_methods_ = new Bindings(NULL);
return this->local_methods_->add_function_declaration(name, package, type,
@@ -9407,6 +9427,7 @@ Named_type::add_method_declaration(const
void
Named_type::add_existing_method(Named_object* no)
{
+ go_assert(!this->is_alias_);
if (this->local_methods_ == NULL)
this->local_methods_ = new Bindings(NULL);
this->local_methods_->add_named_object(no);
@@ -9418,11 +9439,51 @@ Named_type::add_existing_method(Named_ob
Named_object*
Named_type::find_local_method(const std::string& name) const
{
+ if (this->is_error_)
+ return NULL;
+ if (this->is_alias_)
+ {
+ Named_type* nt = this->type_->named_type();
+ if (nt != NULL)
+ {
+ if (this->seen_alias_)
+ return NULL;
+ this->seen_alias_ = true;
+ Named_object* ret = nt->find_local_method(name);
+ this->seen_alias_ = false;
+ return ret;
+ }
+ return NULL;
+ }
if (this->local_methods_ == NULL)
return NULL;
return this->local_methods_->lookup(name);
}
+// Return the list of local methods.
+
+const Bindings*
+Named_type::local_methods() const
+{
+ if (this->is_error_)
+ return NULL;
+ if (this->is_alias_)
+ {
+ Named_type* nt = this->type_->named_type();
+ if (nt != NULL)
+ {
+ if (this->seen_alias_)
+ return NULL;
+ this->seen_alias_ = true;
+ const Bindings* ret = nt->local_methods();
+ this->seen_alias_ = false;
+ return ret;
+ }
+ return NULL;
+ }
+ return this->local_methods_;
+}
+
// Return whether NAME is an unexported field or method, for better
// error reporting.
@@ -9430,6 +9491,22 @@ bool
Named_type::is_unexported_local_method(Gogo* gogo,
const std::string& name) const
{
+ if (this->is_error_)
+ return false;
+ if (this->is_alias_)
+ {
+ Named_type* nt = this->type_->named_type();
+ if (nt != NULL)
+ {
+ if (this->seen_alias_)
+ return false;
+ this->seen_alias_ = true;
+ bool ret = nt->is_unexported_local_method(gogo, name);
+ this->seen_alias_ = false;
+ return ret;
+ }
+ return false;
+ }
Bindings* methods = this->local_methods_;
if (methods != NULL)
{
@@ -9454,6 +9531,8 @@ Named_type::is_unexported_local_method(G
void
Named_type::finalize_methods(Gogo* gogo)
{
+ if (this->is_alias_)
+ return;
if (this->all_methods_ != NULL)
return;
@@ -9474,6 +9553,56 @@ Named_type::finalize_methods(Gogo* gogo)
Type::finalize_methods(gogo, this, this->location_, &this->all_methods_);
}
+// Return whether this type has any methods.
+
+bool
+Named_type::has_any_methods() const
+{
+ if (this->is_error_)
+ return false;
+ if (this->is_alias_)
+ {
+ if (this->type_->named_type() != NULL)
+ {
+ if (this->seen_alias_)
+ return false;
+ this->seen_alias_ = true;
+ bool ret = this->type_->named_type()->has_any_methods();
+ this->seen_alias_ = false;
+ return ret;
+ }
+ if (this->type_->struct_type() != NULL)
+ return this->type_->struct_type()->has_any_methods();
+ return false;
+ }
+ return this->all_methods_ != NULL;
+}
+
+// Return the methods for this type.
+
+const Methods*
+Named_type::methods() const
+{
+ if (this->is_error_)
+ return NULL;
+ if (this->is_alias_)
+ {
+ if (this->type_->named_type() != NULL)
+ {
+ if (this->seen_alias_)
+ return NULL;
+ this->seen_alias_ = true;
+ const Methods* ret = this->type_->named_type()->methods();
+ this->seen_alias_ = false;
+ return ret;
+ }
+ if (this->type_->struct_type() != NULL)
+ return this->type_->struct_type()->methods();
+ return NULL;
+ }
+ return this->all_methods_;
+}
+
// Return the method NAME, or NULL if there isn't one or if it is
// ambiguous. Set *IS_AMBIGUOUS if the method exists but is
// ambiguous.
@@ -9481,6 +9610,26 @@ Named_type::finalize_methods(Gogo* gogo)
Method*
Named_type::method_function(const std::string& name, bool* is_ambiguous) const
{
+ if (this->is_error_)
+ return NULL;
+ if (this->is_alias_)
+ {
+ if (is_ambiguous != NULL)
+ *is_ambiguous = false;
+ if (this->type_->named_type() != NULL)
+ {
+ if (this->seen_alias_)
+ return NULL;
+ this->seen_alias_ = true;
+ Named_type* nt = this->type_->named_type();
+ Method* ret = nt->method_function(name, is_ambiguous);
+ this->seen_alias_ = false;
+ return ret;
+ }
+ if (this->type_->struct_type() != NULL)
+ return this->type_->struct_type()->method_function(name, is_ambiguous);
+ return NULL;
+ }
return Type::method_function(this->all_methods_, name, is_ambiguous);
}
@@ -9491,6 +9640,25 @@ Named_type::method_function(const std::s
Expression*
Named_type::interface_method_table(Interface_type* interface, bool is_pointer)
{
+ if (this->is_error_)
+ return Expression::make_error(this->location_);
+ if (this->is_alias_)
+ {
+ if (this->type_->named_type() != NULL)
+ {
+ if (this->seen_alias_)
+ return Expression::make_error(this->location_);
+ this->seen_alias_ = true;
+ Named_type* nt = this->type_->named_type();
+ Expression* ret = nt->interface_method_table(interface, is_pointer);
+ this->seen_alias_ = false;
+ return ret;
+ }
+ if (this->type_->struct_type() != NULL)
+ return this->type_->struct_type()->interface_method_table(interface,
+ is_pointer);
+ go_unreachable();
+ }
return Type::interface_method_table(this, interface, is_pointer,
&this->interface_method_tables_,
&this->pointer_interface_method_tables_);
@@ -9609,6 +9777,55 @@ Find_type_use::type(Type* type)
return TRAVERSE_CONTINUE;
}
+// Look for a circular reference of an alias.
+
+class Find_alias : public Traverse
+{
+ public:
+ Find_alias(Named_type* find_type)
+ : Traverse(traverse_types),
+ find_type_(find_type), found_(false)
+ { }
+
+ // Whether we found the type.
+ bool
+ found() const
+ { return this->found_; }
+
+ protected:
+ int
+ type(Type*);
+
+ private:
+ // The type we are looking for.
+ Named_type* find_type_;
+ // Whether we found the type.
+ bool found_;
+};
+
+int
+Find_alias::type(Type* type)
+{
+ Named_type* nt = type->named_type();
+ if (nt != NULL)
+ {
+ if (nt == this->find_type_)
+ {
+ this->found_ = true;
+ return TRAVERSE_EXIT;
+ }
+
+ // We started from `type T1 = T2`, where T1 is find_type_ and T2
+ // is, perhaps indirectly, the parameter TYPE. If TYPE is not
+ // an alias itself, it's OK if whatever T2 is defined as refers
+ // to T1.
+ if (!nt->is_alias())
+ return TRAVERSE_SKIP_COMPONENTS;
+ }
+
+ return TRAVERSE_CONTINUE;
+}
+
// Verify that a named type does not refer to itself.
bool
@@ -9618,6 +9835,22 @@ Named_type::do_verify()
return true;
this->is_verified_ = true;
+ if (this->is_error_)
+ return false;
+
+ if (this->is_alias_)
+ {
+ Find_alias find(this);
+ Type::traverse(this->type_, &find);
+ if (find.found())
+ {
+ go_error_at(this->location_, "invalid recursive alias %qs",
+ this->message_name().c_str());
+ this->is_error_ = true;
+ return false;
+ }
+ }
+
Find_type_use find(this);
Type::traverse(this->type_, &find);
if (find.found())
@@ -9718,8 +9951,11 @@ Named_type::do_needs_key_update()
unsigned int
Named_type::do_hash_for_method(Gogo* gogo) const
{
- if (this->is_alias())
- return this->type_->named_type()->do_hash_for_method(gogo);
+ if (this->is_error_)
+ return 0;
+
+ // Aliases are handled in Type::hash_for_method.
+ go_assert(!this->is_alias_);
const std::string& name(this->named_object()->name());
unsigned int ret = Type::hash_string(name, 0);
@@ -10089,8 +10325,17 @@ Named_type::do_get_backend(Gogo* gogo)
Expression*
Named_type::do_type_descriptor(Gogo* gogo, Named_type* name)
{
- if (name == NULL && this->is_alias())
- return this->type_->type_descriptor(gogo, this->type_);
+ if (this->is_error_)
+ return Expression::make_error(this->location_);
+ if (name == NULL && this->is_alias_)
+ {
+ if (this->seen_alias_)
+ return Expression::make_error(this->location_);
+ this->seen_alias_ = true;
+ Expression* ret = this->type_->type_descriptor(gogo, NULL);
+ this->seen_alias_ = false;
+ return ret;
+ }
// If NAME is not NULL, then we don't really want the type
// descriptor for this type; we want the descriptor for the
@@ -10106,9 +10351,25 @@ Named_type::do_type_descriptor(Gogo* gog
void
Named_type::do_reflection(Gogo* gogo, std::string* ret) const
{
- if (this->is_alias())
+ this->append_reflection_type_name(gogo, false, ret);
+}
+
+// Add to the reflection string. For an alias we normally use the
+// real name, but if USE_ALIAS is true we use the alias name itself.
+
+void
+Named_type::append_reflection_type_name(Gogo* gogo, bool use_alias,
+ std::string* ret) const
+{
+ if (this->is_error_)
+ return;
+ if (this->is_alias_ && !use_alias)
{
+ if (this->seen_alias_)
+ return;
+ this->seen_alias_ = true;
this->append_reflection(this->type_, gogo, ret);
+ this->seen_alias_ = false;
return;
}
if (!this->is_builtin())
@@ -10173,9 +10434,25 @@ Named_type::do_gc_symbol(Gogo* gogo, Exp
void
Named_type::do_mangled_name(Gogo* gogo, std::string* ret) const
{
- if (this->is_alias())
+ this->append_mangled_type_name(gogo, false, ret);
+}
+
+// Get the mangled name. For an alias we normally get the real name,
+// but if USE_ALIAS is true we use the alias name itself.
+
+void
+Named_type::append_mangled_type_name(Gogo* gogo, bool use_alias,
+ std::string* ret) const
+{
+ if (this->is_error_)
+ return;
+ if (this->is_alias_ && !use_alias)
{
+ if (this->seen_alias_)
+ return;
+ this->seen_alias_ = true;
this->append_mangled_name(this->type_, gogo, ret);
+ this->seen_alias_ = false;
return;
}
Named_object* no = this->named_object_;
@@ -11392,7 +11669,7 @@ Forward_declaration_type::do_type_descri
if (name != NULL)
return this->named_type_descriptor(gogo, t, name);
else
- return Expression::make_type_descriptor(t, ploc);
+ return Expression::make_error(this->named_object_->location());
}
}
===================================================================
@@ -3061,10 +3061,10 @@ class Named_type : public Type
type_(type), local_methods_(NULL), all_methods_(NULL),
interface_method_tables_(NULL), pointer_interface_method_tables_(NULL),
location_(location), named_btype_(NULL), dependencies_(),
- is_visible_(true), is_error_(false), is_placeholder_(false),
- is_converted_(false), is_circular_(false), is_verified_(false),
- seen_(false), seen_in_compare_is_identity_(false),
- seen_in_get_backend_(false)
+ is_alias_(false), is_visible_(true), is_error_(false),
+ is_placeholder_(false), is_converted_(false), is_circular_(false),
+ is_verified_(false), seen_(false), seen_in_compare_is_identity_(false),
+ seen_in_get_backend_(false), seen_alias_(false)
{ }
// Return the associated Named_object. This holds the actual name.
@@ -3082,6 +3082,17 @@ class Named_type : public Type
set_named_object(Named_object* no)
{ this->named_object_ = no; }
+ // Whether this is an alias (type T1 = T2) rather than an ordinary
+ // named type (type T1 T2).
+ bool
+ is_alias() const
+ { return this->is_alias_; }
+
+ // Record that this type is an alias.
+ void
+ set_is_alias()
+ { this->is_alias_ = true; }
+
// Return the function in which this type is defined. This will
// return NULL for a type defined in global scope.
const Named_object*
@@ -3143,11 +3154,6 @@ class Named_type : public Type
is_builtin() const
{ return Linemap::is_predeclared_location(this->location_); }
- // Whether this is an alias. There are currently two aliases: byte
- // and rune.
- bool
- is_alias() const;
-
// Whether this named type is valid. A recursive named type is invalid.
bool
is_valid() const
@@ -3195,8 +3201,7 @@ class Named_type : public Type
// Return the list of local methods.
const Bindings*
- local_methods() const
- { return this->local_methods_; }
+ local_methods() const;
// Build the complete list of methods, including those from
// anonymous fields, and build method stubs if needed.
@@ -3206,14 +3211,12 @@ class Named_type : public Type
// Return whether this type has any methods. This should only be
// called after the finalize_methods pass.
bool
- has_any_methods() const
- { return this->all_methods_ != NULL; }
+ has_any_methods() const;
// Return the methods for this type. This should only be called
// after the finalized_methods pass.
const Methods*
- methods() const
- { return this->all_methods_; }
+ methods() const;
// Return the method to use for NAME. This returns NULL if there is
// no such method or if the method is ambiguous. When it returns
@@ -3246,6 +3249,16 @@ class Named_type : public Type
is_named_backend_type_size_known() const
{ return this->named_btype_ != NULL && !this->is_placeholder_; }
+ // Add to the reflection string as for Type::append_reflection, but
+ // if USE_ALIAS use the alias name rather than the alias target.
+ void
+ append_reflection_type_name(Gogo*, bool use_alias, std::string*) const;
+
+ // Append the mangled type name as for Type::append_mangled_name,
+ // but if USE_ALIAS use the alias name rather than the alias target.
+ void
+ append_mangled_type_name(Gogo*, bool use_alias, std::string*) const;
+
// Export the type.
void
export_named_type(Export*, const std::string& name) const;
@@ -3340,6 +3353,8 @@ class Named_type : public Type
// where we can't convert S2 to the backend representation unless we
// have converted S1.
std::vector<Named_type*> dependencies_;
+ // Whether this is an alias type.
+ bool is_alias_;
// 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
@@ -3367,6 +3382,8 @@ class Named_type : public Type
bool seen_in_compare_is_identity_;
// Like seen_, but used only by do_get_backend.
bool seen_in_get_backend_;
+ // Like seen_, but used when resolving aliases.
+ mutable bool seen_alias_;
};
// A forward declaration. This handles a type which has been declared