Commit 64c7b4c0 by Ian Lance Taylor

compiler: Support Go 1.2 nil checks.

From-SVN: r204679
parent d368135f
...@@ -3633,7 +3633,8 @@ class Unary_expression : public Expression ...@@ -3633,7 +3633,8 @@ class Unary_expression : public Expression
public: public:
Unary_expression(Operator op, Expression* expr, Location location) Unary_expression(Operator op, Expression* expr, Location location)
: Expression(EXPRESSION_UNARY, location), : Expression(EXPRESSION_UNARY, location),
op_(op), escapes_(true), create_temp_(false), expr_(expr) op_(op), escapes_(true), create_temp_(false), expr_(expr),
issue_nil_check_(false)
{ } { }
// Return the operator. // Return the operator.
...@@ -3719,6 +3720,10 @@ class Unary_expression : public Expression ...@@ -3719,6 +3720,10 @@ class Unary_expression : public Expression
void void
do_dump_expression(Ast_dump_context*) const; do_dump_expression(Ast_dump_context*) const;
void
do_issue_nil_check()
{ this->issue_nil_check_ = (this->op_ == OPERATOR_MULT); }
private: private:
// The unary operator to apply. // The unary operator to apply.
Operator op_; Operator op_;
...@@ -3730,6 +3735,9 @@ class Unary_expression : public Expression ...@@ -3730,6 +3735,9 @@ class Unary_expression : public Expression
bool create_temp_; bool create_temp_;
// The operand. // The operand.
Expression* expr_; Expression* expr_;
// Whether or not to issue a nil check for this expression if its address
// is being taken.
bool issue_nil_check_;
}; };
// If we are taking the address of a composite literal, and the // If we are taking the address of a composite literal, and the
...@@ -4107,7 +4115,10 @@ Unary_expression::do_check_types(Gogo*) ...@@ -4107,7 +4115,10 @@ Unary_expression::do_check_types(Gogo*)
this->report_error(_("invalid operand for unary %<&%>")); this->report_error(_("invalid operand for unary %<&%>"));
} }
else else
this->expr_->address_taken(this->escapes_); {
this->expr_->address_taken(this->escapes_);
this->expr_->issue_nil_check();
}
break; break;
case OPERATOR_MULT: case OPERATOR_MULT:
...@@ -4277,12 +4288,13 @@ Unary_expression::do_get_tree(Translate_context* context) ...@@ -4277,12 +4288,13 @@ Unary_expression::do_get_tree(Translate_context* context)
// If we are dereferencing the pointer to a large struct, we // If we are dereferencing the pointer to a large struct, we
// need to check for nil. We don't bother to check for small // need to check for nil. We don't bother to check for small
// structs because we expect the system to crash on a nil // structs because we expect the system to crash on a nil
// pointer dereference. // pointer dereference. However, if we know the address of this
// expression is being taken, we must always check for nil.
tree target_type_tree = TREE_TYPE(TREE_TYPE(expr)); tree target_type_tree = TREE_TYPE(TREE_TYPE(expr));
if (!VOID_TYPE_P(target_type_tree)) if (!VOID_TYPE_P(target_type_tree))
{ {
HOST_WIDE_INT s = int_size_in_bytes(target_type_tree); HOST_WIDE_INT s = int_size_in_bytes(target_type_tree);
if (s == -1 || s >= 4096) if (s == -1 || s >= 4096 || this->issue_nil_check_)
{ {
if (!DECL_P(expr)) if (!DECL_P(expr))
expr = save_expr(expr); expr = save_expr(expr);
...@@ -10402,6 +10414,10 @@ class Array_index_expression : public Expression ...@@ -10402,6 +10414,10 @@ class Array_index_expression : public Expression
do_address_taken(bool escapes) do_address_taken(bool escapes)
{ this->array_->address_taken(escapes); } { this->array_->address_taken(escapes); }
void
do_issue_nil_check()
{ this->array_->issue_nil_check(); }
tree tree
do_get_tree(Translate_context*); do_get_tree(Translate_context*);
......
...@@ -613,6 +613,11 @@ class Expression ...@@ -613,6 +613,11 @@ class Expression
address_taken(bool escapes) address_taken(bool escapes)
{ this->do_address_taken(escapes); } { this->do_address_taken(escapes); }
// Note that a nil check must be issued for this expression.
void
issue_nil_check()
{ this->do_issue_nil_check(); }
// Return whether this expression must be evaluated in order // Return whether this expression must be evaluated in order
// according to the order of evaluation rules. This is basically // according to the order of evaluation rules. This is basically
// true of all expressions with side-effects. // true of all expressions with side-effects.
...@@ -742,6 +747,11 @@ class Expression ...@@ -742,6 +747,11 @@ class Expression
do_address_taken(bool) do_address_taken(bool)
{ } { }
// Child class implements issuing a nil check if the address is taken.
virtual void
do_issue_nil_check()
{ }
// Child class implements whether this expression must be evaluated // Child class implements whether this expression must be evaluated
// in order. // in order.
virtual bool virtual bool
...@@ -1721,6 +1731,9 @@ class Index_expression : public Parser_expression ...@@ -1721,6 +1731,9 @@ class Index_expression : public Parser_expression
void void
do_dump_expression(Ast_dump_context*) const; do_dump_expression(Ast_dump_context*) const;
void
do_issue_nil_check()
{ this->left_->issue_nil_check(); }
private: private:
// The expression being indexed. // The expression being indexed.
Expression* left_; Expression* left_;
...@@ -2011,6 +2024,10 @@ class Field_reference_expression : public Expression ...@@ -2011,6 +2024,10 @@ class Field_reference_expression : public Expression
do_address_taken(bool escapes) do_address_taken(bool escapes)
{ this->expr_->address_taken(escapes); } { this->expr_->address_taken(escapes); }
void
do_issue_nil_check()
{ this->expr_->issue_nil_check(); }
tree tree
do_get_tree(Translate_context*); do_get_tree(Translate_context*);
......
...@@ -8847,8 +8847,7 @@ Type::add_local_methods_for_type(const Named_type* nt, ...@@ -8847,8 +8847,7 @@ Type::add_local_methods_for_type(const Named_type* nt,
bool is_value_method = (is_embedded_pointer bool is_value_method = (is_embedded_pointer
|| !Type::method_expects_pointer(no)); || !Type::method_expects_pointer(no));
Method* m = new Named_method(no, field_indexes, depth, is_value_method, Method* m = new Named_method(no, field_indexes, depth, is_value_method,
(needs_stub_method (needs_stub_method || depth > 0));
|| (depth > 0 && is_value_method)));
if (!(*methods)->insert(no->name(), m)) if (!(*methods)->insert(no->name(), m))
delete m; delete m;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment