summaryrefslogtreecommitdiff
path: root/gcc/go/gofrontend
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2012-02-03 09:24:10 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2012-02-03 09:24:10 +0000
commita68d233ff64d692c5376bf8fc84c6edb4a17e6a7 (patch)
tree31998253493902e174563585be32c732f581fbe8 /gcc/go/gofrontend
parentef91be55fa1a0f1f2e3a483c39a8768c1a4c1e58 (diff)
downloadgcc-a68d233ff64d692c5376bf8fc84c6edb4a17e6a7.tar.gz
2012-02-03 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 183862 using svnmerge git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@183866 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/go/gofrontend')
-rw-r--r--gcc/go/gofrontend/expressions.cc80
-rw-r--r--gcc/go/gofrontend/gogo.cc7
-rw-r--r--gcc/go/gofrontend/gogo.h4
-rw-r--r--gcc/go/gofrontend/import.cc29
-rw-r--r--gcc/go/gofrontend/parse.cc39
-rw-r--r--gcc/go/gofrontend/types.cc6
-rw-r--r--gcc/go/gofrontend/types.h2
7 files changed, 116 insertions, 51 deletions
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 5563dde7032..f906b2206ea 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -7657,7 +7657,10 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
this->set_is_error();
return this;
}
- this->lower_varargs(gogo, function, inserter, slice_type, 2);
+ Type* element_type = slice_type->array_type()->element_type();
+ this->lower_varargs(gogo, function, inserter,
+ Type::make_array_type(element_type, NULL),
+ 2);
}
break;
@@ -8624,16 +8627,20 @@ Builtin_call_expression::do_check_types(Gogo*)
break;
}
+ // The language says that the second argument must be
+ // assignable to a slice of the element type of the first
+ // argument. We already know the first argument is a slice
+ // type.
+ Array_type* at = args->front()->type()->array_type();
+ Type* arg2_type = Type::make_array_type(at->element_type(), NULL);
std::string reason;
- if (!Type::are_assignable(args->front()->type(), args->back()->type(),
- &reason))
+ if (!Type::are_assignable(arg2_type, args->back()->type(), &reason))
{
if (reason.empty())
- this->report_error(_("arguments 1 and 2 have different types"));
+ this->report_error(_("argument 2 has invalid type"));
else
{
- error_at(this->location(),
- "arguments 1 and 2 have different types (%s)",
+ error_at(this->location(), "argument 2 has invalid type (%s)",
reason.c_str());
this->set_is_error();
}
@@ -10642,11 +10649,28 @@ Array_index_expression::do_get_tree(Translate_context* context)
if (array_type->length() == NULL && !DECL_P(array_tree))
array_tree = save_expr(array_tree);
- tree length_tree = array_type->length_tree(gogo, array_tree);
- if (length_tree == error_mark_node)
- return error_mark_node;
- length_tree = save_expr(length_tree);
- tree length_type = TREE_TYPE(length_tree);
+
+ tree length_tree = NULL_TREE;
+ if (this->end_ == NULL || this->end_->is_nil_expression())
+ {
+ length_tree = array_type->length_tree(gogo, array_tree);
+ if (length_tree == error_mark_node)
+ return error_mark_node;
+ length_tree = save_expr(length_tree);
+ }
+
+ tree capacity_tree = NULL_TREE;
+ if (this->end_ != NULL)
+ {
+ capacity_tree = array_type->capacity_tree(gogo, array_tree);
+ if (capacity_tree == error_mark_node)
+ return error_mark_node;
+ capacity_tree = save_expr(capacity_tree);
+ }
+
+ tree length_type = (length_tree != NULL_TREE
+ ? TREE_TYPE(length_tree)
+ : TREE_TYPE(capacity_tree));
tree bad_index = boolean_false_node;
@@ -10669,7 +10693,9 @@ Array_index_expression::do_get_tree(Translate_context* context)
? GE_EXPR
: GT_EXPR),
boolean_type_node, start_tree,
- length_tree));
+ (this->end_ == NULL
+ ? length_tree
+ : capacity_tree)));
int code = (array_type->length() != NULL
? (this->end_ == NULL
@@ -10716,12 +10742,6 @@ Array_index_expression::do_get_tree(Translate_context* context)
// Array slice.
- tree capacity_tree = array_type->capacity_tree(gogo, array_tree);
- if (capacity_tree == error_mark_node)
- return error_mark_node;
- capacity_tree = fold_convert_loc(loc.gcc_location(), length_type,
- capacity_tree);
-
tree end_tree;
if (this->end_->is_nil_expression())
end_tree = length_tree;
@@ -10740,7 +10760,6 @@ Array_index_expression::do_get_tree(Translate_context* context)
end_tree = fold_convert_loc(loc.gcc_location(), length_type, end_tree);
- capacity_tree = save_expr(capacity_tree);
tree bad_end = fold_build2_loc(loc.gcc_location(), TRUTH_OR_EXPR,
boolean_type_node,
fold_build2_loc(loc.gcc_location(),
@@ -11704,10 +11723,21 @@ Selector_expression::lower_method_expression(Gogo* gogo)
const Typed_identifier_list* method_parameters = method_type->parameters();
if (method_parameters != NULL)
{
+ int i = 0;
for (Typed_identifier_list::const_iterator p = method_parameters->begin();
p != method_parameters->end();
- ++p)
- parameters->push_back(*p);
+ ++p, ++i)
+ {
+ if (!p->name().empty() && p->name() != Import::import_marker)
+ parameters->push_back(*p);
+ else
+ {
+ char buf[20];
+ snprintf(buf, sizeof buf, "$param%d", i);
+ parameters->push_back(Typed_identifier(buf, p->type(),
+ p->location()));
+ }
+ }
}
const Typed_identifier_list* method_results = method_type->results();
@@ -11767,14 +11797,14 @@ Selector_expression::lower_method_expression(Gogo* gogo)
}
Expression_list* args;
- if (method_parameters == NULL)
+ if (parameters->size() <= 1)
args = NULL;
else
{
args = new Expression_list();
- for (Typed_identifier_list::const_iterator p = method_parameters->begin();
- p != method_parameters->end();
- ++p)
+ Typed_identifier_list::const_iterator p = parameters->begin();
+ ++p;
+ for (; p != parameters->end(); ++p)
{
vno = gogo->lookup(p->name(), NULL);
go_assert(vno != NULL);
diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc
index c65e47f6745..fafd04fe18e 100644
--- a/gcc/go/gofrontend/gogo.cc
+++ b/gcc/go/gofrontend/gogo.cc
@@ -880,7 +880,7 @@ Gogo::declare_function(const std::string& name, Function_type* type,
else if (rtype->forward_declaration_type() != NULL)
{
Forward_declaration_type* ftype = rtype->forward_declaration_type();
- return ftype->add_method_declaration(name, type, location);
+ return ftype->add_method_declaration(name, NULL, type, location);
}
else
go_unreachable();
@@ -4325,11 +4325,12 @@ Type_declaration::add_method(const std::string& name, Function* function)
Named_object*
Type_declaration::add_method_declaration(const std::string& name,
+ Package* package,
Function_type* type,
Location location)
{
- Named_object* ret = Named_object::make_function_declaration(name, NULL, type,
- location);
+ Named_object* ret = Named_object::make_function_declaration(name, package,
+ type, location);
this->methods_.push_back(ret);
return ret;
}
diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h
index 2231e5dba5b..008c8a09872 100644
--- a/gcc/go/gofrontend/gogo.h
+++ b/gcc/go/gofrontend/gogo.h
@@ -1621,8 +1621,8 @@ class Type_declaration
// Add a method declaration to this type.
Named_object*
- add_method_declaration(const std::string& name, Function_type* type,
- Location location);
+ add_method_declaration(const std::string& name, Package*,
+ Function_type* type, Location location);
// Return whether any methods were defined.
bool
diff --git a/gcc/go/gofrontend/import.cc b/gcc/go/gofrontend/import.cc
index de7edc91e2e..44ffda61fba 100644
--- a/gcc/go/gofrontend/import.cc
+++ b/gcc/go/gofrontend/import.cc
@@ -441,12 +441,29 @@ Import::import_func(Package* package)
Named_object* no;
if (fntype->is_method())
{
- Type* rtype = receiver->type()->deref();
+ Type* rtype = receiver->type();
+
+ // We may still be reading the definition of RTYPE, so we have
+ // to be careful to avoid calling base or convert. If RTYPE is
+ // a named type or a forward declaration, then we know that it
+ // is not a pointer, because we are reading a method on RTYPE
+ // and named pointers can't have methods.
+
+ if (rtype->classification() == Type::TYPE_POINTER)
+ rtype = rtype->points_to();
+
if (rtype->is_error_type())
return NULL;
- Named_type* named_rtype = rtype->named_type();
- go_assert(named_rtype != NULL);
- no = named_rtype->add_method_declaration(name, package, fntype, loc);
+ else if (rtype->named_type() != NULL)
+ no = rtype->named_type()->add_method_declaration(name, package, fntype,
+ loc);
+ else if (rtype->forward_declaration_type() != NULL)
+ no = rtype->forward_declaration_type()->add_method_declaration(name,
+ package,
+ fntype,
+ loc);
+ else
+ go_unreachable();
}
else
{
@@ -647,8 +664,8 @@ Import::read_type()
{
// We have seen this type before. FIXME: it would be a good
// idea to check that the two imported types are identical,
- // but we have not finalized the methds yet, which means
- // that we can nt reliably compare interface types.
+ // but we have not finalized the methods yet, which means
+ // that we can not reliably compare interface types.
type = no->type_value();
// Don't change the visibility of the existing type.
diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc
index 06faeb61e58..10abfc036c3 100644
--- a/gcc/go/gofrontend/parse.cc
+++ b/gcc/go/gofrontend/parse.cc
@@ -4311,9 +4311,16 @@ Parse::type_switch_body(Label* label, const Type_switch& type_switch,
Named_object* switch_no = NULL;
if (!type_switch.name.empty())
{
- Variable* switch_var = new Variable(NULL, type_switch.expr, false, false,
- false, type_switch.location);
- switch_no = this->gogo_->add_variable(type_switch.name, switch_var);
+ if (Gogo::is_sink_name(type_switch.name))
+ error_at(type_switch.location,
+ "no new variables on left side of %<:=%>");
+ else
+ {
+ Variable* switch_var = new Variable(NULL, type_switch.expr, false,
+ false, false,
+ type_switch.location);
+ switch_no = this->gogo_->add_variable(type_switch.name, switch_var);
+ }
}
Type_switch_statement* statement =
@@ -4640,9 +4647,14 @@ Parse::send_or_recv_stmt(bool* is_send, Expression** channel, Expression** val,
if (token->is_op(OPERATOR_COLONEQ))
{
// case rv := <-c:
- if (!this->advance_token()->is_op(OPERATOR_CHANOP))
+ this->advance_token();
+ Expression* e = this->expression(PRECEDENCE_NORMAL, false, false,
+ NULL);
+ Receive_expression* re = e->receive_expression();
+ if (re == NULL)
{
- error_at(this->location(), "expected %<<-%>");
+ if (!e->is_error_expression())
+ error_at(this->location(), "expected receive expression");
return false;
}
if (recv_var == "_")
@@ -4653,8 +4665,7 @@ Parse::send_or_recv_stmt(bool* is_send, Expression** channel, Expression** val,
}
*is_send = false;
*varname = gogo->pack_hidden_name(recv_var, is_rv_exported);
- this->advance_token();
- *channel = this->expression(PRECEDENCE_NORMAL, false, true, NULL);
+ *channel = re->channel();
return true;
}
else if (token->is_op(OPERATOR_COMMA))
@@ -4671,9 +4682,15 @@ Parse::send_or_recv_stmt(bool* is_send, Expression** channel, Expression** val,
if (token->is_op(OPERATOR_COLONEQ))
{
// case rv, rc := <-c:
- if (!this->advance_token()->is_op(OPERATOR_CHANOP))
+ this->advance_token();
+ Expression* e = this->expression(PRECEDENCE_NORMAL, false,
+ false, NULL);
+ Receive_expression* re = e->receive_expression();
+ if (re == NULL)
{
- error_at(this->location(), "expected %<<-%>");
+ if (!e->is_error_expression())
+ error_at(this->location(),
+ "expected receive expression");
return false;
}
if (recv_var == "_" && recv_closed == "_")
@@ -4689,9 +4706,7 @@ Parse::send_or_recv_stmt(bool* is_send, Expression** channel, Expression** val,
if (recv_closed != "_")
*closedname = gogo->pack_hidden_name(recv_closed,
is_rc_exported);
- this->advance_token();
- *channel = this->expression(PRECEDENCE_NORMAL, false, true,
- NULL);
+ *channel = re->channel();
return true;
}
diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc
index 525d33ad8e5..0bbe3c5b7ca 100644
--- a/gcc/go/gofrontend/types.cc
+++ b/gcc/go/gofrontend/types.cc
@@ -5416,7 +5416,8 @@ tree
Array_type::capacity_tree(Gogo* gogo, tree array)
{
if (this->length_ != NULL)
- return omit_one_operand(sizetype, this->get_length_tree(gogo), array);
+ return omit_one_operand(integer_type_node, this->get_length_tree(gogo),
+ array);
// This is an open array. We need to read the capacity field.
@@ -9115,6 +9116,7 @@ Forward_declaration_type::add_method(const std::string& name,
Named_object*
Forward_declaration_type::add_method_declaration(const std::string& name,
+ Package* package,
Function_type* type,
Location location)
{
@@ -9122,7 +9124,7 @@ Forward_declaration_type::add_method_declaration(const std::string& name,
if (no->is_unknown())
no->declare_as_type();
Type_declaration* td = no->type_declaration_value();
- return td->add_method_declaration(name, type, location);
+ return td->add_method_declaration(name, package, type, location);
}
// Traversal.
diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h
index 4e45b991b57..4398ef1e639 100644
--- a/gcc/go/gofrontend/types.h
+++ b/gcc/go/gofrontend/types.h
@@ -2937,7 +2937,7 @@ class Forward_declaration_type : public Type
// Add a method declaration to this type.
Named_object*
- add_method_declaration(const std::string& name, Function_type*,
+ add_method_declaration(const std::string& name, Package*, Function_type*,
Location);
protected: