summaryrefslogtreecommitdiff
path: root/gcc/go
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2012-03-01 10:06:45 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2012-03-01 10:06:45 +0000
commita79ad0b39b356a82b01dcc061d52b506bdf631e9 (patch)
treef75386ffb541630f9a5648bddd8e39156373c57b /gcc/go
parentee584ef105d93fbf5b26c76ff37371b58bb3da72 (diff)
downloadgcc-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/ChangeLog11
-rw-r--r--gcc/go/go-gcc.cc8
-rw-r--r--gcc/go/gofrontend/expressions.cc111
-rw-r--r--gcc/go/gofrontend/parse.cc5
-rw-r--r--gcc/go/gofrontend/statements.cc4
-rw-r--r--gcc/go/gofrontend/types.cc24
-rw-r--r--gcc/go/gofrontend/types.h3
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(); }