This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[gccgo] Several small fixups
- From: Ian Lance Taylor <iant at google dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 19 Feb 2010 21:02:02 -0800
- Subject: [gccgo] Several small fixups
I committed this patch to the gccgo branch to fix several small
issues.
* Avoid a crash when converting a constant string to an interface.
The code was taking the address of a CONST_DECL.
* Correctly report an attempt to refer to an unexported name. Don't
get confused if the name is local.
* Fix package names in type descriptors.
* Adjust the interface and function type reflection strings to match
the ones generated by 6g. This is just a spacing adjustment, and
avoiding parentheses if there is only one result type.
* Permit converting an unnamed struct with methods to an interface
which requires those methods.
Ian
diff -r bd0100e4882a go/expressions.cc
--- a/go/expressions.cc Sat Feb 13 00:35:21 2010 -0800
+++ b/go/expressions.cc Fri Feb 19 20:53:49 2010 -0800
@@ -297,7 +297,8 @@
// going to copy the value into the interface.
tree make_tmp;
tree object;
- if (TREE_ADDRESSABLE(TREE_TYPE(rhs_tree)) || DECL_P(rhs_tree))
+ if (TREE_ADDRESSABLE(TREE_TYPE(rhs_tree))
+ || (DECL_P(rhs_tree) && TREE_CODE(rhs_tree) != CONST_DECL))
{
make_tmp = NULL_TREE;
object = build_fold_addr_expr(rhs_tree);
@@ -8298,7 +8299,7 @@
Expression* left = this->left_;
if (left->is_type_expression())
return this->lower_method_expression(gogo);
- return Type::bind_field_or_method(left->type(), left, this->name_,
+ return Type::bind_field_or_method(gogo, left->type(), left, this->name_,
this->location());
}
@@ -8393,7 +8394,7 @@
Named_object* vno = gogo->lookup(receiver_name, NULL);
gcc_assert(vno != NULL);
Expression* ve = Expression::make_var_reference(vno, location);
- Expression* bm = Type::bind_field_or_method(nt, ve, name, location);
+ Expression* bm = Type::bind_field_or_method(gogo, nt, ve, name, location);
gcc_assert(bm != NULL && !bm->is_error_expression());
Expression_list* args;
diff -r bd0100e4882a go/gogo.h
--- a/go/gogo.h Sat Feb 13 00:35:21 2010 -0800
+++ b/go/gogo.h Fri Feb 19 20:53:49 2010 -0800
@@ -144,7 +144,7 @@
hidden_name_prefix(const std::string& name)
{
gcc_assert(Gogo::is_hidden_name(name));
- return name.substr(1, name.rfind('.', 1) - 1);
+ return name.substr(1, name.rfind('.') - 1);
}
// Return whether a name is the blank identifier _.
diff -r bd0100e4882a go/types.cc
--- a/go/types.cc Sat Feb 13 00:35:21 2010 -0800
+++ b/go/types.cc Fri Feb 19 20:53:49 2010 -0800
@@ -1868,9 +1868,12 @@
ret->push_back(')');
const Typed_identifier_list* results = this->results();
- if (results != NULL)
- {
- ret->append(" (");
+ if (results != NULL && !results->empty())
+ {
+ if (results->size() == 1)
+ ret->push_back(' ');
+ else
+ ret->append(" (");
for (Typed_identifier_list::const_iterator p = results->begin();
p != results->end();
++p)
@@ -1879,7 +1882,8 @@
ret->append(", ");
this->append_reflection(p->type(), gogo, ret);
}
- ret->push_back(')');
+ if (results->size() > 1)
+ ret->push_back(')');
}
}
@@ -2706,7 +2710,8 @@
// Return whether NAME is an unexported field, for better error reporting.
bool
-Struct_type::is_unexported_local_field(const std::string& name) const
+Struct_type::is_unexported_local_field(Gogo* gogo,
+ const std::string& name) const
{
const Struct_field_list* fields = this->fields_;
if (fields != NULL)
@@ -2717,7 +2722,8 @@
{
const std::string& field_name(pf->field_name());
if (Gogo::is_hidden_name(field_name)
- && name == Gogo::unpack_hidden_name(field_name))
+ && name == Gogo::unpack_hidden_name(field_name)
+ && gogo->pack_hidden_name(name, false) != field_name)
return true;
}
}
@@ -2737,9 +2743,9 @@
// ambiguous.
Method*
-Struct_type::method_function(const std::string& name) const
-{
- return Type::method_function(this->all_methods_, name, NULL);
+Struct_type::method_function(const std::string& name, bool* is_ambiguous) const
+{
+ return Type::method_function(this->all_methods_, name, is_ambiguous);
}
// Get the tree for a struct type.
@@ -4188,7 +4194,7 @@
// reporting.
bool
-Interface_type::is_unexported_method(const std::string& name) const
+Interface_type::is_unexported_method(Gogo* gogo, const std::string& name) const
{
if (this->methods_ == NULL)
return false;
@@ -4198,7 +4204,8 @@
{
const std::string& method_name(p->name());
if (Gogo::is_hidden_name(method_name)
- && name == Gogo::unpack_hidden_name(method_name))
+ && name == Gogo::unpack_hidden_name(method_name)
+ && gogo->pack_hidden_name(name, false) != method_name)
return true;
}
return false;
@@ -4323,6 +4330,7 @@
bool is_pointer = false;
const Named_type* nt = t->named_type();
+ const Struct_type* st = t->struct_type();
// If we start with a named type, we don't dereference it to find
// methods.
if (nt == NULL)
@@ -4334,18 +4342,24 @@
// the type to which it points.
is_pointer = true;
nt = pt->named_type();
- }
- }
-
- // Only named types have methods.
- if (nt == NULL)
+ st = pt->struct_type();
+ }
+ }
+
+ // If we have a named type, get the methods from it rather than from
+ // any struct type.
+ if (nt != NULL)
+ st = NULL;
+
+ // Only named and struct types have methods.
+ if (nt == NULL && st == NULL)
{
if (reason != NULL)
reason->assign(_("type has no methods"));
return false;
}
- if (!nt->has_any_methods())
+ if (nt != NULL ? !nt->has_any_methods() : !st->has_any_methods())
{
if (reason != NULL)
reason->assign(_("type has no methods"));
@@ -4357,7 +4371,9 @@
++p)
{
bool is_ambiguous = false;
- Method* m = nt->method_function(p->name(), &is_ambiguous);
+ Method* m = (nt != NULL
+ ? nt->method_function(p->name(), &is_ambiguous)
+ : st->method_function(p->name(), &is_ambiguous));
if (m == NULL)
{
if (reason != NULL)
@@ -4543,7 +4559,6 @@
ret->append(";");
ret->push_back(' ');
ret->append(Gogo::unpack_hidden_name(p->name()));
- ret->push_back(' ');
std::string sub = p->type()->reflection(gogo);
gcc_assert(sub.compare(0, 4, "func") == 0);
sub = sub.substr(4);
@@ -4967,7 +4982,8 @@
// error reporting.
bool
-Named_type::is_unexported_local_method(const std::string& name) const
+Named_type::is_unexported_local_method(Gogo* gogo,
+ const std::string& name) const
{
Bindings* methods = this->local_methods_;
if (methods != NULL)
@@ -4978,7 +4994,8 @@
++p)
{
if (Gogo::is_hidden_name(p->first)
- && name == Gogo::unpack_hidden_name(p->first))
+ && name == Gogo::unpack_hidden_name(p->first)
+ && gogo->pack_hidden_name(name, false) != p->first)
return true;
}
}
@@ -5882,7 +5899,7 @@
// method, give an appropriate error and return an error expression.
Expression*
-Type::bind_field_or_method(const Type* type, Expression* expr,
+Type::bind_field_or_method(Gogo* gogo, const Type* type, Expression* expr,
const std::string& name,
source_location location)
{
@@ -5920,7 +5937,7 @@
if (nt != NULL)
m = nt->method_function(name, NULL);
else if (st != NULL)
- m = st->method_function(name);
+ m = st->method_function(name, NULL);
else
gcc_unreachable();
gcc_assert(m != NULL);
@@ -5951,7 +5968,8 @@
if (!Gogo::is_hidden_name(name))
is_unexported = false;
else
- is_unexported = Type::is_unexported_field_or_method(type, name);
+ is_unexported = Type::is_unexported_field_or_method(gogo, type,
+ unpacked);
if (is_unexported)
error_at(location, "reference to unexported field or method %qs",
unpacked.c_str());
@@ -6139,20 +6157,21 @@
// Return whether NAME is an unexported field or method for TYPE.
bool
-Type::is_unexported_field_or_method(const Type* type, const std::string& name)
+Type::is_unexported_field_or_method(Gogo* gogo, const Type* type,
+ const std::string& name)
{
type = type->deref();
const Named_type* nt = type->named_type();
- if (nt != NULL && nt->is_unexported_local_method(name))
+ if (nt != NULL && nt->is_unexported_local_method(gogo, name))
return true;
const Interface_type* it = type->interface_type();
- if (it != NULL && it->is_unexported_method(name))
+ if (it != NULL && it->is_unexported_method(gogo, name))
return true;
const Struct_type* st = type->struct_type();
- if (st != NULL && st->is_unexported_local_field(name))
+ if (st != NULL && st->is_unexported_local_field(gogo, name))
return true;
if (st == NULL)
@@ -6170,7 +6189,7 @@
{
Named_type* subtype = pf->type()->deref()->named_type();
gcc_assert(subtype != NULL);
- if (Type::is_unexported_field_or_method(subtype, name))
+ if (Type::is_unexported_field_or_method(gogo, subtype, name))
return true;
}
}
diff -r bd0100e4882a go/types.h
--- a/go/types.h Sat Feb 13 00:35:21 2010 -0800
+++ b/go/types.h Fri Feb 19 20:53:49 2010 -0800
@@ -762,12 +762,12 @@
// Look for field or method NAME for TYPE. Return an expression for
// it, bound to EXPR.
static Expression*
- bind_field_or_method(const Type* type, Expression* expr,
+ bind_field_or_method(Gogo*, const Type* type, Expression* expr,
const std::string& name, source_location);
// Return true if NAME is an unexported field or method of TYPE.
static bool
- is_unexported_field_or_method(const Type*, const std::string&);
+ is_unexported_field_or_method(Gogo*, const Type*, const std::string&);
// This type was passed to the builtin function make. ARGS are the
// arguments passed to make after the type; this may be NULL if
@@ -1770,7 +1770,7 @@
// Return whether NAME is a local field which is not exported. This
// is only used for better error reporting.
bool
- is_unexported_local_field(const std::string& name) const;
+ is_unexported_local_field(Gogo*, const std::string& name) const;
// If this is an unnamed struct, build the complete list of methods,
// including those from anonymous fields, and build methods stubs if
@@ -1791,9 +1791,10 @@
{ return this->all_methods_; }
// Return the method to use for NAME. This returns NULL if there is
- // no such method or if the method is ambiguous.
+ // no such method or if the method is ambiguous. When it returns
+ // NULL, this sets *IS_AMBIGUOUS if the method name is ambiguous.
Method*
- method_function(const std::string& name) const;
+ method_function(const std::string& name, bool* is_ambiguous) const;
// Traverse just the field types of a struct type.
int
@@ -2172,7 +2173,7 @@
// Return whether NAME is a method which is not exported. This is
// only used for better error reporting.
bool
- is_unexported_method(const std::string& name) const;
+ is_unexported_method(Gogo*, const std::string& name) const;
// Import an interface type.
static Interface_type*
@@ -2351,7 +2352,7 @@
// Return whether NAME is a known field or method which is not
// exported. This is only used for better error reporting.
bool
- is_unexported_local_method(const std::string& name) const;
+ is_unexported_local_method(Gogo*, const std::string& name) const;
// Return a pointer to the interface method table for this type for
// the interface INTERFACE.