diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-02-03 09:24:10 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-02-03 09:24:10 +0000 |
commit | a68d233ff64d692c5376bf8fc84c6edb4a17e6a7 (patch) | |
tree | 31998253493902e174563585be32c732f581fbe8 /gcc/go/gofrontend | |
parent | ef91be55fa1a0f1f2e3a483c39a8768c1a4c1e58 (diff) | |
download | gcc-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.cc | 80 | ||||
-rw-r--r-- | gcc/go/gofrontend/gogo.cc | 7 | ||||
-rw-r--r-- | gcc/go/gofrontend/gogo.h | 4 | ||||
-rw-r--r-- | gcc/go/gofrontend/import.cc | 29 | ||||
-rw-r--r-- | gcc/go/gofrontend/parse.cc | 39 | ||||
-rw-r--r-- | gcc/go/gofrontend/types.cc | 6 | ||||
-rw-r--r-- | gcc/go/gofrontend/types.h | 2 |
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: |