diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-03-01 10:06:45 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-03-01 10:06:45 +0000 |
commit | a79ad0b39b356a82b01dcc061d52b506bdf631e9 (patch) | |
tree | f75386ffb541630f9a5648bddd8e39156373c57b /gcc/go | |
parent | ee584ef105d93fbf5b26c76ff37371b58bb3da72 (diff) | |
download | gcc-a79ad0b39b356a82b01dcc061d52b506bdf631e9.tar.gz |
2012-03-01 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 184686 using svnmerge
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@184689 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/go')
-rw-r--r-- | gcc/go/ChangeLog | 11 | ||||
-rw-r--r-- | gcc/go/go-gcc.cc | 8 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.cc | 111 | ||||
-rw-r--r-- | gcc/go/gofrontend/parse.cc | 5 | ||||
-rw-r--r-- | gcc/go/gofrontend/statements.cc | 4 | ||||
-rw-r--r-- | gcc/go/gofrontend/types.cc | 24 | ||||
-rw-r--r-- | gcc/go/gofrontend/types.h | 3 |
7 files changed, 106 insertions, 60 deletions
diff --git a/gcc/go/ChangeLog b/gcc/go/ChangeLog index eb2638fd54d..8b8e90c4b68 100644 --- a/gcc/go/ChangeLog +++ b/gcc/go/ChangeLog @@ -1,3 +1,14 @@ +2012-02-29 Ian Lance Taylor <iant@google.com> + + * go-gcc.cc (class Gcc_tree): Add set_tree method. + (set_placeholder_pointer_type): When setting to a pointer to + error, set to error_mark_node. + +2012-02-23 Richard Guenther <rguenther@suse.de> + + * go-gcc.cc (Gcc_backend::placeholder_pointer_type): Use + build_distinct_type_copy. + 2012-02-17 Ian Lance Taylor <iant@google.com> * Make-lang.in (go/import.o): Add dependency on $(GO_LEX_H). diff --git a/gcc/go/go-gcc.cc b/gcc/go/go-gcc.cc index e6967a830e1..a19bb894a99 100644 --- a/gcc/go/go-gcc.cc +++ b/gcc/go/go-gcc.cc @@ -56,6 +56,10 @@ class Gcc_tree get_tree() const { return this->t_; } + void + set_tree(tree t) + { this->t_ = t; } + private: tree t_; }; @@ -602,7 +606,7 @@ Btype* Gcc_backend::placeholder_pointer_type(const std::string& name, Location location, bool) { - tree ret = build_variant_type_copy(ptr_type_node); + tree ret = build_distinct_type_copy(ptr_type_node); if (!name.empty()) { tree decl = build_decl(location.gcc_location(), TYPE_DECL, @@ -626,7 +630,7 @@ Gcc_backend::set_placeholder_pointer_type(Btype* placeholder, tree tt = to_type->get_tree(); if (tt == error_mark_node) { - TREE_TYPE(pt) = tt; + placeholder->set_tree(error_mark_node); return false; } gcc_assert(TREE_CODE(tt) == POINTER_TYPE); diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 638cacbe2c9..a2097e002eb 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -3942,10 +3942,6 @@ Unsafe_type_conversion_expression::do_get_tree(Translate_context* context) go_assert(et->map_type() != NULL); else if (t->channel_type() != NULL) go_assert(et->channel_type() != NULL); - else if (t->points_to() != NULL && t->points_to()->channel_type() != NULL) - go_assert((et->points_to() != NULL - && et->points_to()->channel_type() != NULL) - || et->is_nil_type()); else if (t->points_to() != NULL) go_assert(et->points_to() != NULL || et->is_nil_type()); else if (et->is_unsafe_pointer_type()) @@ -4304,14 +4300,23 @@ Unary_expression::eval_integer(Operator op, Type* utype, mpz_t uval, mpz_t val, unsigned HOST_WIDE_INT* phwi = new unsigned HOST_WIDE_INT[count]; memset(phwi, 0, count * sizeof(HOST_WIDE_INT)); + size_t obits = utype->integer_type()->bits(); + + if (!utype->integer_type()->is_unsigned() + && mpz_sgn(uval) < 0) + { + mpz_t adj; + mpz_init_set_ui(adj, 1); + mpz_mul_2exp(adj, adj, obits); + mpz_add(uval, uval, adj); + mpz_clear(adj); + } + size_t ecount; mpz_export(phwi, &ecount, -1, sizeof(HOST_WIDE_INT), 0, 0, uval); go_assert(ecount <= count); // Trim down to the number of words required by the type. - size_t obits = utype->integer_type()->bits(); - if (!utype->integer_type()->is_unsigned()) - ++obits; size_t ocount = ((obits + HOST_BITS_PER_WIDE_INT - 1) / HOST_BITS_PER_WIDE_INT); go_assert(ocount <= count); @@ -4326,6 +4331,16 @@ Unary_expression::eval_integer(Operator op, Type* utype, mpz_t uval, mpz_t val, mpz_import(val, ocount, -1, sizeof(HOST_WIDE_INT), 0, 0, phwi); + if (!utype->integer_type()->is_unsigned() + && mpz_tstbit(val, obits - 1)) + { + mpz_t adj; + mpz_init_set_ui(adj, 1); + mpz_mul_2exp(adj, adj, obits); + mpz_sub(val, val, adj); + mpz_clear(adj); + } + delete[] phwi; } return Integer_expression::check_constant(val, utype, location); @@ -4690,29 +4705,33 @@ Unary_expression::do_get_tree(Translate_context* context) // need to check for nil. We don't bother to check for small // structs because we expect the system to crash on a nil // pointer dereference. - HOST_WIDE_INT s = int_size_in_bytes(TREE_TYPE(TREE_TYPE(expr))); - if (s == -1 || s >= 4096) + tree target_type_tree = TREE_TYPE(TREE_TYPE(expr)); + if (!VOID_TYPE_P(target_type_tree)) { - if (!DECL_P(expr)) - expr = save_expr(expr); - tree compare = fold_build2_loc(loc.gcc_location(), EQ_EXPR, - boolean_type_node, - expr, - fold_convert(TREE_TYPE(expr), - null_pointer_node)); - tree crash = Gogo::runtime_error(RUNTIME_ERROR_NIL_DEREFERENCE, - loc); - expr = fold_build2_loc(loc.gcc_location(), COMPOUND_EXPR, - TREE_TYPE(expr), build3(COND_EXPR, - void_type_node, - compare, crash, - NULL_TREE), - expr); + HOST_WIDE_INT s = int_size_in_bytes(target_type_tree); + if (s == -1 || s >= 4096) + { + if (!DECL_P(expr)) + expr = save_expr(expr); + tree compare = fold_build2_loc(loc.gcc_location(), EQ_EXPR, + boolean_type_node, + expr, + fold_convert(TREE_TYPE(expr), + null_pointer_node)); + tree crash = Gogo::runtime_error(RUNTIME_ERROR_NIL_DEREFERENCE, + loc); + expr = fold_build2_loc(loc.gcc_location(), COMPOUND_EXPR, + TREE_TYPE(expr), build3(COND_EXPR, + void_type_node, + compare, crash, + NULL_TREE), + expr); + } } // If the type of EXPR is a recursive pointer type, then we // need to insert a cast before indirecting. - if (TREE_TYPE(TREE_TYPE(expr)) == ptr_type_node) + if (VOID_TYPE_P(target_type_tree)) { Type* pt = this->expr_->type()->points_to(); tree ind = type_to_tree(pt->get_backend(context->gogo())); @@ -8502,6 +8521,7 @@ Builtin_call_expression::do_check_types(Gogo*) case BUILTIN_INVALID: case BUILTIN_NEW: case BUILTIN_MAKE: + case BUILTIN_DELETE: return; case BUILTIN_LEN: @@ -8670,13 +8690,17 @@ Builtin_call_expression::do_check_types(Gogo*) this->report_error(_("too many arguments")); break; } + if (args->front()->type()->is_error() + || args->back()->type()->is_error()) + break; + + Array_type* at = args->front()->type()->array_type(); + Type* e = at->element_type(); // The language permits appending a string to a []byte, as a // special case. if (args->back()->type()->is_string_type()) { - const Array_type* at = args->front()->type()->array_type(); - const Type* e = at->element_type()->forwarded(); if (e->integer_type() != NULL && e->integer_type()->is_byte()) break; } @@ -8685,8 +8709,7 @@ Builtin_call_expression::do_check_types(Gogo*) // 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); + Type* arg2_type = Type::make_array_type(e, NULL); std::string reason; if (!Type::are_assignable(arg2_type, args->back()->type(), &reason)) { @@ -8982,7 +9005,10 @@ Builtin_call_expression::do_get_tree(Translate_context* context) fnname = "__go_print_slice"; } else - go_unreachable(); + { + go_assert(saw_errors()); + return error_mark_node; + } tree call = Gogo::call_builtin(pfndecl, location, @@ -9665,8 +9691,11 @@ Call_expression::result_count() const Temporary_statement* Call_expression::result(size_t i) const { - go_assert(this->results_ != NULL - && this->results_->size() > i); + if (this->results_ == NULL || this->results_->size() <= i) + { + go_assert(saw_errors()); + return NULL; + } return (*this->results_)[i]; } @@ -10153,6 +10182,11 @@ Call_expression::set_results(Translate_context* context, tree call_tree) go_assert(field != NULL_TREE); Temporary_statement* temp = this->result(i); + if (temp == NULL) + { + go_assert(saw_errors()); + return error_mark_node; + } Temporary_reference_expression* ref = Expression::make_temporary_reference(temp, loc); ref->set_is_lvalue(); @@ -10332,8 +10366,17 @@ tree Call_result_expression::do_get_tree(Translate_context* context) { Call_expression* ce = this->call_->call_expression(); - go_assert(ce != NULL); + if (ce == NULL) + { + go_assert(this->call_->is_error_expression()); + return error_mark_node; + } Temporary_statement* ts = ce->result(this->index_); + if (ts == NULL) + { + go_assert(saw_errors()); + return error_mark_node; + } Expression* ref = Expression::make_temporary_reference(ts, this->location()); return ref->get_tree(context); } @@ -13839,7 +13882,7 @@ tree Heap_composite_expression::do_get_tree(Translate_context* context) { tree expr_tree = this->expr_->get_tree(context); - if (expr_tree == error_mark_node) + if (expr_tree == error_mark_node || TREE_TYPE(expr_tree) == error_mark_node) return error_mark_node; tree expr_size = TYPE_SIZE_UNIT(TREE_TYPE(expr_tree)); go_assert(TREE_CODE(expr_size) == INTEGER_CST); diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc index df28d2baf4b..1a9c153a578 100644 --- a/gcc/go/gofrontend/parse.cc +++ b/gcc/go/gofrontend/parse.cc @@ -3948,8 +3948,9 @@ Parse::return_stat() ++p) { Named_object* no = this->gogo_->lookup((*p)->name(), NULL); - go_assert(no != NULL); - if (!no->is_result_variable()) + if (no == NULL) + go_assert(saw_errors()); + else if (!no->is_result_variable()) error_at(location, "%qs is shadowed during return", (*p)->message_name().c_str()); } diff --git a/gcc/go/gofrontend/statements.cc b/gcc/go/gofrontend/statements.cc index e55dc74b3b7..65c64c5e906 100644 --- a/gcc/go/gofrontend/statements.cc +++ b/gcc/go/gofrontend/statements.cc @@ -1013,7 +1013,7 @@ Tuple_assignment_statement::do_lower(Gogo*, Named_object*, Block* enclosing, b->add_statement(s); ++ptemp; } - go_assert(ptemp == temps.end()); + go_assert(ptemp == temps.end() || saw_errors()); return Statement::make_block_statement(b, loc); } @@ -3452,7 +3452,7 @@ Case_clauses::Case_clause::get_backend(Translate_context* context, { // Value was already present. error_at(this->location_, "duplicate case in switch"); - continue; + e = Expression::make_error(this->location_); } tree case_tree = e->get_tree(context); diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index a2064bb6eea..6abe21d2522 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -4116,7 +4116,6 @@ Struct_type::do_verify() 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) @@ -4126,7 +4125,6 @@ Struct_type::do_verify() { error_at(p->location(), "struct field type is incomplete"); p->set_type(Type::make_error_type()); - ret = false; } else if (p->is_anonymous()) { @@ -4134,19 +4132,17 @@ Struct_type::do_verify() { 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. @@ -5206,10 +5202,7 @@ bool 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; } @@ -5899,10 +5892,7 @@ Map_type::do_verify() { // 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; } @@ -7885,7 +7875,6 @@ Named_type::do_verify() 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 = @@ -7899,12 +7888,9 @@ Named_type::do_verify() 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; diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h index 72c42ebb4ba..3fe80488a49 100644 --- a/gcc/go/gofrontend/types.h +++ b/gcc/go/gofrontend/types.h @@ -510,7 +510,8 @@ class Type // Verify the type. This is called after parsing, and verifies that // types are complete and meet the language requirements. This - // returns false if the type is invalid. + // returns false if the type is invalid and we should not continue + // traversing it. bool verify() { return this->do_verify(); } |