p != fields->end();
++p)
{
+ if (Gogo::is_sink_name(p->field_name()))
+ continue;
+
if (!p->type()->is_comparable())
{
if (reason != NULL)
std::string* reason)
{
// Do some checks first. Make sure the types are defined.
- if (rhs != NULL
- && rhs->forwarded()->forward_declaration_type() == NULL
- && rhs->is_void_type())
+ if (rhs != NULL && !rhs->is_undefined())
{
- if (reason != NULL)
- *reason = "non-value used as value";
- return false;
+ if (rhs->is_void_type())
+ {
+ if (reason != NULL)
+ *reason = "non-value used as value";
+ return false;
+ }
+ if (rhs->is_call_multiple_result_type())
+ {
+ if (reason != NULL)
+ reason->assign(_("multiple value function call in "
+ "single value context"));
+ return false;
+ }
}
- if (lhs != NULL && lhs->forwarded()->forward_declaration_type() == NULL)
+ if (lhs != NULL && !lhs->is_undefined())
{
// Any value may be assigned to the blank identifier.
if (lhs->is_sink_type())
// All fields of a struct must be exported, or the assignment
// must be in the same package.
- if (check_hidden_fields
- && rhs != NULL
- && rhs->forwarded()->forward_declaration_type() == NULL)
+ if (check_hidden_fields && rhs != NULL && !rhs->is_undefined())
{
if (lhs->has_hidden_fields(NULL, reason)
|| rhs->has_hidden_fields(NULL, reason))
{
if (rhs->interface_type() != NULL)
reason->assign(_("need explicit conversion"));
- else if (rhs->is_call_multiple_result_type())
- reason->assign(_("multiple value function call in "
- "single value context"));
else if (lhs->named_type() != NULL && rhs->named_type() != NULL)
{
size_t len = (lhs->named_type()->name().length()
return "__go_td_" + this->mangled_name(gogo);
Named_object* no = nt->named_object();
- const Named_object* in_function = nt->in_function();
+ unsigned int index;
+ const Named_object* in_function = nt->in_function(&index);
std::string ret = "__go_tdn_";
if (nt->is_builtin())
go_assert(in_function == NULL);
else
{
- const std::string& unique_prefix(no->package() == NULL
- ? gogo->unique_prefix()
- : no->package()->unique_prefix());
- const std::string& package_name(no->package() == NULL
- ? gogo->package_name()
- : no->package()->name());
- ret.append(unique_prefix);
- ret.append(1, '.');
- ret.append(package_name);
+ const std::string& pkgpath(no->package() == NULL
+ ? gogo->pkgpath_symbol()
+ : no->package()->pkgpath_symbol());
+ ret.append(pkgpath);
ret.append(1, '.');
if (in_function != NULL)
{
ret.append(Gogo::unpack_hidden_name(in_function->name()));
ret.append(1, '.');
+ if (index > 0)
+ {
+ char buf[30];
+ snprintf(buf, sizeof buf, "%u", index);
+ ret.append(buf);
+ ret.append(1, '.');
+ }
}
}
- ret.append(no->name());
+
+ // FIXME: This adds in pkgpath twice for hidden symbols, which is
+ // pointless.
+ const std::string& name(no->name());
+ if (!Gogo::is_hidden_name(name))
+ ret.append(name);
+ else
+ {
+ ret.append(1, '.');
+ ret.append(Gogo::pkgpath_for_symbol(Gogo::hidden_name_pkgpath(name)));
+ ret.append(1, '.');
+ ret.append(Gogo::unpack_hidden_name(name));
+ }
+
return ret;
}
{
// This name is already hidden or not as appropriate.
base_name = name->name();
- const Named_object* in_function = name->in_function();
+ unsigned int index;
+ const Named_object* in_function = name->in_function(&index);
if (in_function != NULL)
- base_name += '$' + in_function->name();
+ {
+ base_name += '$' + Gogo::unpack_hidden_name(in_function->name());
+ if (index > 0)
+ {
+ char buf[30];
+ snprintf(buf, sizeof buf, "%u", index);
+ base_name += '$';
+ base_name += buf;
+ }
+ }
}
std::string hash_name = base_name + "$hash";
std::string equal_name = base_name + "$equal";
{
Location bloc = Linemap::predeclared_location();
+ if (gogo->specific_type_functions_are_written())
+ {
+ go_assert(saw_errors());
+ return;
+ }
+
Named_object* hash_fn = gogo->start_function(hash_name, hash_fntype, false,
bloc);
gogo->start_block(bloc);
else
{
const Package* package = no->package();
- const std::string& unique_prefix(package == NULL
- ? gogo->unique_prefix()
- : package->unique_prefix());
- const std::string& package_name(package == NULL
- ? gogo->package_name()
- : package->name());
- n.assign(unique_prefix);
- n.append(1, '.');
- n.append(package_name);
- if (name->in_function() != NULL)
+ const std::string& pkgpath(package == NULL
+ ? gogo->pkgpath()
+ : package->pkgpath());
+ n.assign(pkgpath);
+ unsigned int index;
+ const Named_object* in_function = name->in_function(&index);
+ if (in_function != NULL)
{
n.append(1, '.');
- n.append(Gogo::unpack_hidden_name(name->in_function()->name()));
+ n.append(Gogo::unpack_hidden_name(in_function->name()));
+ if (index > 0)
+ {
+ char buf[30];
+ snprintf(buf, sizeof buf, "%u", index);
+ n.append(1, '.');
+ n.append(buf);
+ }
}
s = Expression::make_string(n, bloc);
vals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
vals->push_back(Expression::make_nil(bloc));
else
{
- s = Expression::make_string(Gogo::hidden_name_prefix(method_name), bloc);
+ s = Expression::make_string(Gogo::hidden_name_pkgpath(method_name),
+ bloc);
vals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
}
return true;
else
{
+ Numeric_constant nc;
+ if (!at->length()->numeric_constant_value(&nc))
+ return false;
mpz_t ival;
- mpz_init(ival);
- Type* dummy;
- bool length_known = at->length()->integer_constant_value(true,
- ival,
- &dummy);
- mpz_clear(ival);
- if (!length_known)
+ if (!nc.to_int(&ival))
return false;
+ mpz_clear(ival);
return at->element_type()->is_backend_type_size_known(gogo);
}
}
// A redeclaration of a function is required to use the same names
// for the receiver and parameters.
if (this->receiver() != NULL
- && this->receiver()->name() != t->receiver()->name()
- && this->receiver()->name() != Import::import_marker
- && t->receiver()->name() != Import::import_marker)
+ && this->receiver()->name() != t->receiver()->name())
{
if (reason != NULL)
*reason = "receiver name changed";
p2 != parms2->end();
++p2, ++p1)
{
- if (p1->name() != p2->name()
- && p1->name() != Import::import_marker
- && p2->name() != Import::import_marker)
+ if (p1->name() != p2->name())
{
if (reason != NULL)
*reason = "parameter name changed";
res2 != results2->end();
++res2, ++res1)
{
- if (res1->name() != res2->name()
- && res1->name() != Import::import_marker
- && res2->name() != Import::import_marker)
+ if (res1->name() != res2->name())
{
if (reason != NULL)
*reason = "result name changed";
first = false;
else
exp->write_c_string(", ");
+ exp->write_name(p->name());
+ exp->write_c_string(" ");
if (!is_varargs || p + 1 != this->parameters_->end())
exp->write_type(p->type());
else
if (results != NULL)
{
exp->write_c_string(" ");
- if (results->size() == 1)
+ if (results->size() == 1 && results->begin()->name().empty())
exp->write_type(results->begin()->type());
else
{
first = false;
else
exp->write_c_string(", ");
+ exp->write_name(p->name());
+ exp->write_c_string(" ");
exp->write_type(p->type());
}
exp->write_c_string(")");
parameters = new Typed_identifier_list();
while (true)
{
+ std::string name = imp->read_name();
+ imp->require_c_string(" ");
+
if (imp->match_c_string("..."))
{
imp->advance(3);
Type* ptype = imp->read_type();
if (is_varargs)
ptype = Type::make_array_type(ptype, NULL);
- parameters->push_back(Typed_identifier(Import::import_marker,
- ptype, imp->location()));
+ parameters->push_back(Typed_identifier(name, ptype,
+ imp->location()));
if (imp->peek_char() != ',')
break;
go_assert(!is_varargs);
if (imp->peek_char() != '(')
{
Type* rtype = imp->read_type();
- results->push_back(Typed_identifier(Import::import_marker, rtype,
- imp->location()));
+ results->push_back(Typed_identifier("", rtype, imp->location()));
}
else
{
imp->advance(1);
while (true)
{
+ std::string name = imp->read_name();
+ imp->require_c_string(" ");
Type* rtype = imp->read_type();
- results->push_back(Typed_identifier(Import::import_marker,
- rtype, imp->location()));
+ results->push_back(Typed_identifier(name, rtype,
+ imp->location()));
if (imp->peek_char() != ',')
break;
imp->require_c_string(", ");
go_assert(!this->is_method());
Typed_identifier* receiver = new Typed_identifier("", receiver_type,
this->location_);
- return Type::make_function_type(receiver, this->parameters_,
- this->results_, this->location_);
+ Function_type* ret = Type::make_function_type(receiver, this->parameters_,
+ this->results_,
+ this->location_);
+ if (this->is_varargs_)
+ ret->set_is_varargs();
+ return ret;
}
// Make a function type.
Struct_field_list* fields = this->fields_;
if (fields == NULL)
return true;
- bool ret = true;
for (Struct_field_list::iterator p = fields->begin();
p != fields->end();
++p)
{
error_at(p->location(), "struct field type is incomplete");
p->set_type(Type::make_error_type());
- ret = false;
}
else if (p->is_anonymous())
{
{
error_at(p->location(), "embedded type may not be a pointer");
p->set_type(Type::make_error_type());
- return false;
}
- if (t->points_to() != NULL
- && t->points_to()->interface_type() != NULL)
+ else if (t->points_to() != NULL
+ && t->points_to()->interface_type() != NULL)
{
error_at(p->location(),
"embedded type may not be pointer to interface");
p->set_type(Type::make_error_type());
- return false;
}
}
}
- return ret;
+ return true;
}
// Whether this contains a pointer.
pf != fields->end();
++pf)
{
+ if (Gogo::is_sink_name(pf->field_name()))
+ return false;
+
if (!pf->type()->compare_is_identity(gogo))
return false;
fvals->push_back(Expression::make_nil(bloc));
else
{
- std::string n = Gogo::hidden_name_prefix(pf->field_name());
+ std::string n = Gogo::hidden_name_pkgpath(pf->field_name());
Expression* s = Expression::make_string(n, bloc);
fvals->push_back(Expression::make_unary(OPERATOR_AND, s, bloc));
}
pf != fields->end();
++pf)
{
+ if (Gogo::is_sink_name(pf->field_name()))
+ continue;
+
if (first)
first = false;
else
pf != fields->end();
++pf, ++field_index)
{
+ if (Gogo::is_sink_name(pf->field_name()))
+ continue;
+
// Compare one field in both P1 and P2.
Expression* f1 = Expression::make_temporary_reference(p1, bloc);
f1 = Expression::make_unary(OPERATOR_MULT, f1, bloc);
// Try to determine the lengths. If we can't, assume the arrays
// are not identical.
bool ret = false;
- mpz_t v1;
- mpz_init(v1);
- Type* type1;
- mpz_t v2;
- mpz_init(v2);
- Type* type2;
- if (l1->integer_constant_value(true, v1, &type1)
- && l2->integer_constant_value(true, v2, &type2))
- ret = mpz_cmp(v1, v2) == 0;
- mpz_clear(v1);
- mpz_clear(v2);
+ Numeric_constant nc1, nc2;
+ if (l1->numeric_constant_value(&nc1)
+ && l2->numeric_constant_value(&nc2))
+ {
+ mpz_t v1;
+ if (nc1.to_int(&v1))
+ {
+ mpz_t v2;
+ if (nc2.to_int(&v2))
+ {
+ ret = mpz_cmp(v1, v2) == 0;
+ mpz_clear(v2);
+ }
+ mpz_clear(v1);
+ }
+ }
return ret;
}
return false;
}
- mpz_t val;
- mpz_init(val);
- Type* vt;
- if (!this->length_->integer_constant_value(true, val, &vt))
+ Numeric_constant nc;
+ if (!this->length_->numeric_constant_value(&nc))
{
- mpfr_t fval;
- mpfr_init(fval);
- if (!this->length_->float_constant_value(fval, &vt))
- {
- if (this->length_->type()->integer_type() != NULL
- || this->length_->type()->float_type() != NULL)
- error_at(this->length_->location(),
- "array bound is not constant");
- else
- error_at(this->length_->location(),
- "array bound is not numeric");
- mpfr_clear(fval);
- mpz_clear(val);
- return false;
- }
- if (!mpfr_integer_p(fval))
- {
- error_at(this->length_->location(),
- "array bound truncated to integer");
- mpfr_clear(fval);
- mpz_clear(val);
- return false;
- }
- mpz_init(val);
- mpfr_get_z(val, fval, GMP_RNDN);
- mpfr_clear(fval);
+ if (this->length_->type()->integer_type() != NULL
+ || this->length_->type()->float_type() != NULL)
+ error_at(this->length_->location(), "array bound is not constant");
+ else
+ error_at(this->length_->location(), "array bound is not numeric");
+ return false;
}
- if (mpz_sgn(val) < 0)
+ unsigned long val;
+ switch (nc.to_unsigned_long(&val))
{
+ case Numeric_constant::NC_UL_VALID:
+ break;
+ case Numeric_constant::NC_UL_NOTINT:
+ error_at(this->length_->location(), "array bound truncated to integer");
+ return false;
+ case Numeric_constant::NC_UL_NEGATIVE:
error_at(this->length_->location(), "negative array bound");
- mpz_clear(val);
return false;
+ case Numeric_constant::NC_UL_BIG:
+ error_at(this->length_->location(), "array bound overflows");
+ return false;
+ default:
+ go_unreachable();
}
Type* int_type = Type::lookup_integer_type("int");
- int tbits = int_type->integer_type()->bits();
- int vbits = mpz_sizeinbase(val, 2);
- if (vbits + 1 > tbits)
+ unsigned int tbits = int_type->integer_type()->bits();
+ if (sizeof(val) <= tbits * 8
+ && val >> (tbits - 1) != 0)
{
error_at(this->length_->location(), "array bound overflows");
- mpz_clear(val);
return false;
}
- mpz_clear(val);
-
return true;
}
Array_type::do_verify()
{
if (!this->verify_length())
- {
- this->length_ = Expression::make_error(this->length_->location());
- return false;
- }
+ this->length_ = Expression::make_error(this->length_->location());
return true;
}
go_assert(this->length_ != NULL);
if (this->length_tree_ == NULL_TREE)
{
+ Numeric_constant nc;
mpz_t val;
- mpz_init(val);
- Type* t;
- if (this->length_->integer_constant_value(true, val, &t))
+ if (this->length_->numeric_constant_value(&nc) && nc.to_int(&val))
{
+ if (mpz_sgn(val) < 0)
+ {
+ this->length_tree_ = error_mark_node;
+ return this->length_tree_;
+ }
+ Type* t = nc.type();
if (t == NULL)
t = Type::lookup_integer_type("int");
else if (t->is_abstract())
}
else
{
- mpz_clear(val);
-
// Make up a translation context for the array length
// expression. FIXME: This won't work in general.
Translate_context context(gogo, NULL, NULL, NULL);
ret->push_back('[');
if (this->length_ != NULL)
{
- mpz_t val;
- mpz_init(val);
- Type* type;
- if (!this->length_->integer_constant_value(true, val, &type))
- error_at(this->length_->location(),
- "array length must be integer constant expression");
- else if (mpz_cmp_si(val, 0) < 0)
- error_at(this->length_->location(), "array length is negative");
- else if (mpz_cmp_ui(val, mpz_get_ui(val)) != 0)
- error_at(this->length_->location(), "array length is too large");
+ Numeric_constant nc;
+ unsigned long val;
+ if (!this->length_->numeric_constant_value(&nc)
+ || nc.to_unsigned_long(&val) != Numeric_constant::NC_UL_VALID)
+ error_at(this->length_->location(), "invalid array length");
else
{
char buf[50];
- snprintf(buf, sizeof buf, "%lu", mpz_get_ui(val));
+ snprintf(buf, sizeof buf, "%lu", val);
ret->append(buf);
}
- mpz_clear(val);
}
ret->push_back(']');
this->append_mangled_name(this->element_type_, gogo, ret);
if (this->length_ != NULL)
{
- mpz_t val;
- mpz_init(val);
- Type* type;
- if (!this->length_->integer_constant_value(true, val, &type))
- error_at(this->length_->location(),
- "array length must be integer constant expression");
- else if (mpz_cmp_si(val, 0) < 0)
- error_at(this->length_->location(), "array length is negative");
- else if (mpz_cmp_ui(val, mpz_get_ui(val)) != 0)
- error_at(this->length_->location(), "array size is too large");
+ Numeric_constant nc;
+ unsigned long val;
+ if (!this->length_->numeric_constant_value(&nc)
+ || nc.to_unsigned_long(&val) != Numeric_constant::NC_UL_VALID)
+ error_at(this->length_->location(), "invalid array length");
else
{
char buf[50];
- snprintf(buf, sizeof buf, "%lu", mpz_get_ui(val));
+ snprintf(buf, sizeof buf, "%lu", val);
ret->append(buf);
}
- mpz_clear(val);
}
ret->push_back('e');
}
{
// The runtime support uses "map[void]void".
if (!this->key_type_->is_comparable() && !this->key_type_->is_void_type())
- {
- error_at(this->location_, "invalid map key type");
- return false;
- }
+ error_at(this->location_, "invalid map key type");
return true;
}
}
Named_type* nt = t->named_type();
- if (nt != NULL)
+ if (nt != NULL && it->parse_methods_ != NULL)
{
std::vector<Named_type*>::const_iterator q;
for (q = seen.begin(); q != seen.end(); ++q)
Interface_type::is_identical(const Interface_type* t,
bool errors_are_identical) const
{
- go_assert(this->methods_are_finalized_ && t->methods_are_finalized_);
+ // If methods have not been finalized, then we are asking whether
+ // func redeclarations are the same. This is an error, so for
+ // simplicity we say they are never the same.
+ if (!this->methods_are_finalized_ || !t->methods_are_finalized_)
+ return false;
// We require the same methods with the same types. The methods
// have already been sorted.
std::string n = Gogo::message_name(p->name());
size_t len = 100 + n.length();
char* buf = new char[len];
- snprintf(buf, len, _("method %s%s%s requires a pointer"),
+ snprintf(buf, len,
+ _("method %s%s%s requires a pointer receiver"),
open_quote, n.c_str(), close_quote);
reason->assign(buf);
delete[] buf;
p != type->methods()->end();
++p, ++i)
{
+ // The type of the method in Go only includes the parameters.
+ // The actual method also has a receiver, which is always a
+ // pointer. We need to add that pointer type here in order to
+ // generate the correct type for the backend.
+ Function_type* ft = p->type()->function_type();
+ go_assert(ft->receiver() == NULL);
+
+ const Typed_identifier_list* params = ft->parameters();
+ Typed_identifier_list* mparams = new Typed_identifier_list();
+ if (params != NULL)
+ mparams->reserve(params->size() + 1);
+ Type* vt = Type::make_pointer_type(Type::make_void_type());
+ mparams->push_back(Typed_identifier("", vt, ft->location()));
+ if (params != NULL)
+ {
+ for (Typed_identifier_list::const_iterator pp = params->begin();
+ pp != params->end();
+ ++pp)
+ mparams->push_back(*pp);
+ }
+
+ Typed_identifier_list* mresults = (ft->results() == NULL
+ ? NULL
+ : ft->results()->copy());
+ Function_type* mft = Type::make_function_type(NULL, mparams, mresults,
+ ft->location());
+
mfields[i].name = Gogo::unpack_hidden_name(p->name());
mfields[i].btype = (use_placeholder
- ? p->type()->get_backend_placeholder(gogo)
- : p->type()->get_backend(gogo));
+ ? mft->get_backend_placeholder(gogo)
+ : mft->get_backend(gogo));
mfields[i].location = loc;
// Sanity check: the names should be sorted.
go_assert(p->name() > last_name);
mvals->push_back(Expression::make_nil(bloc));
else
{
- s = Gogo::hidden_name_prefix(pm->name());
+ s = Gogo::hidden_name_pkgpath(pm->name());
e = Expression::make_string(s, bloc);
mvals->push_back(Expression::make_unary(OPERATOR_AND, e, bloc));
}
{
if (!Gogo::is_hidden_name(p->name()))
ret->append(p->name());
+ else if (gogo->pkgpath_from_option())
+ ret->append(p->name().substr(1));
else
{
- // This matches what the gc compiler does.
- std::string prefix = Gogo::hidden_name_prefix(p->name());
- ret->append(prefix.substr(prefix.find('.') + 1));
+ // If no -fgo-pkgpath option, backward compatibility
+ // for how this used to work before -fgo-pkgpath was
+ // introduced.
+ std::string pkgpath = Gogo::hidden_name_pkgpath(p->name());
+ ret->append(pkgpath.substr(pkgpath.find('.') + 1));
ret->push_back('.');
ret->append(Gogo::unpack_hidden_name(p->name()));
}
{
if (pm->name().empty())
{
- exp->write_c_string("$ ");
+ exp->write_c_string("? ");
exp->write_type(pm->type());
}
else
first = false;
else
exp->write_c_string(", ");
+ exp->write_name(pp->name());
+ exp->write_c_string(" ");
if (!is_varargs || pp + 1 != parameters->end())
exp->write_type(pp->type());
else
if (results != NULL)
{
exp->write_c_string(" ");
- if (results->size() == 1)
+ if (results->size() == 1 && results->begin()->name().empty())
exp->write_type(results->begin()->type());
else
{
first = false;
else
exp->write_c_string(", ");
+ exp->write_name(p->name());
+ exp->write_c_string(" ");
exp->write_type(p->type());
}
exp->write_c_string(")");
{
std::string name = imp->read_identifier();
- if (name == "$")
+ if (name == "?")
{
imp->require_c_string(" ");
Type* t = imp->read_type();
parameters = new Typed_identifier_list;
while (true)
{
+ std::string name = imp->read_name();
+ imp->require_c_string(" ");
+
if (imp->match_c_string("..."))
{
imp->advance(3);
Type* ptype = imp->read_type();
if (is_varargs)
ptype = Type::make_array_type(ptype, NULL);
- parameters->push_back(Typed_identifier(Import::import_marker,
- ptype, imp->location()));
+ parameters->push_back(Typed_identifier(name, ptype,
+ imp->location()));
if (imp->peek_char() != ',')
break;
go_assert(!is_varargs);
if (imp->peek_char() != '(')
{
Type* rtype = imp->read_type();
- results->push_back(Typed_identifier(Import::import_marker,
- rtype, imp->location()));
+ results->push_back(Typed_identifier("", rtype, imp->location()));
}
else
{
imp->advance(1);
while (true)
{
+ std::string name = imp->read_name();
+ imp->require_c_string(" ");
Type* rtype = imp->read_type();
- results->push_back(Typed_identifier(Import::import_marker,
- rtype, imp->location()));
+ results->push_back(Typed_identifier(name, rtype,
+ imp->location()));
if (imp->peek_char() != ',')
break;
imp->require_c_string(", ");
bool
Named_type::do_verify()
{
+ if (this->is_verified_)
+ return true;
+ this->is_verified_ = true;
+
Find_type_use find(this);
Type::traverse(this->type_, &find);
if (find.found())
if (this->local_methods_ != NULL)
{
Struct_type* st = this->type_->struct_type();
- bool found_dup = false;
if (st != NULL)
{
for (Bindings::const_declarations_iterator p =
error_at(p->second->location(),
"method %qs redeclares struct field name",
Gogo::message_name(name).c_str());
- found_dup = true;
}
}
}
- if (found_dup)
- return false;
}
return true;
// where we are going to be comparing named types for equality. In
// other cases, which are cases where the runtime is going to
// compare hash codes to see if the types are the same, we need to
- // include the package prefix and name in the hash.
+ // include the pkgpath in the hash.
if (gogo != NULL && !Gogo::is_hidden_name(name) && !this->is_builtin())
{
const Package* package = this->named_object()->package();
if (package == NULL)
- {
- ret = Type::hash_string(gogo->unique_prefix(), ret);
- ret = Type::hash_string(gogo->package_name(), ret);
- }
+ ret = Type::hash_string(gogo->pkgpath(), ret);
else
- {
- ret = Type::hash_string(package->unique_prefix(), ret);
- ret = Type::hash_string(package->name(), ret);
- }
+ ret = Type::hash_string(package->pkgpath(), ret);
}
return ret;
this->create_placeholder(gogo);
+ // If we are called to turn unsafe.Sizeof into a constant, we may
+ // not have verified the type yet. We have to make sure it is
+ // verified, since that sets the list of dependencies.
+ this->verify();
+
// Convert all the dependencies. If they refer indirectly back to
// this type, they will pick up the intermediate tree we just
// created.
}
if (!this->is_builtin())
{
+ // We handle -fgo-prefix and -fgo-pkgpath differently here for
+ // compatibility with how the compiler worked before
+ // -fgo-pkgpath was introduced. When -fgo-pkgpath is specified,
+ // we use it to make a unique reflection string, so that the
+ // type canonicalization in the reflect package will work. In
+ // order to be compatible with the gc compiler, we put tabs into
+ // the package path, so that the reflect methods can discard it.
const Package* package = this->named_object_->package();
- if (package != NULL)
- ret->append(package->name());
- else
- ret->append(gogo->package_name());
+ if (gogo->pkgpath_from_option())
+ {
+ ret->push_back('\t');
+ ret->append(package != NULL
+ ? package->pkgpath_symbol()
+ : gogo->pkgpath_symbol());
+ ret->push_back('\t');
+ }
+ ret->append(package != NULL
+ ? package->package_name()
+ : gogo->package_name());
ret->push_back('.');
}
if (this->in_function_ != NULL)
{
ret->append(Gogo::unpack_hidden_name(this->in_function_->name()));
ret->push_back('$');
+ if (this->in_function_index_ > 0)
+ {
+ char buf[30];
+ snprintf(buf, sizeof buf, "%u", this->in_function_index_);
+ ret->append(buf);
+ ret->push_back('$');
+ }
}
ret->append(Gogo::unpack_hidden_name(this->named_object_->name()));
}
go_assert(this->in_function_ == NULL);
else
{
- const std::string& unique_prefix(no->package() == NULL
- ? gogo->unique_prefix()
- : no->package()->unique_prefix());
- const std::string& package_name(no->package() == NULL
- ? gogo->package_name()
- : no->package()->name());
- name = unique_prefix;
- name.append(1, '.');
- name.append(package_name);
+ const std::string& pkgpath(no->package() == NULL
+ ? gogo->pkgpath_symbol()
+ : no->package()->pkgpath_symbol());
+ name = pkgpath;
name.append(1, '.');
if (this->in_function_ != NULL)
{
name.append(Gogo::unpack_hidden_name(this->in_function_->name()));
name.append(1, '$');
+ if (this->in_function_index_ > 0)
+ {
+ char buf[30];
+ snprintf(buf, sizeof buf, "%u", this->in_function_index_);
+ name.append(buf);
+ name.append(1, '$');
+ }
}
}
name.append(Gogo::unpack_hidden_name(no->name()));
Gogo::message_name(name).c_str(), ambig1.c_str(),
ambig2.c_str());
else if (found_pointer_method)
- error_at(location, "method requires a pointer");
+ error_at(location, "method requires a pointer receiver");
else if (nt == NULL && st == NULL && it == NULL)
error_at(location,
("reference to field %qs in object which "
const Named_object* no = this->named_object();
std::string name;
if (no->package() == NULL)
- name = gogo->package_name();
+ name = gogo->pkgpath_symbol();
else
- name = no->package()->name();
+ name = no->package()->pkgpath_symbol();
name += '.';
name += Gogo::unpack_hidden_name(no->name());
char buf[20];