diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2013-11-11 17:49:10 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2013-11-11 17:49:10 +0000 |
commit | 64c7b4c0c9bfd876bab126e7bc1861d1a39f1dbe (patch) | |
tree | 8b4f326394f2f25564ed77844fae26c6a03636e8 /gcc/go | |
parent | d368135f692652e33e4f9c7269935613d4e00f14 (diff) | |
download | gcc-64c7b4c0c9bfd876bab126e7bc1861d1a39f1dbe.zip gcc-64c7b4c0c9bfd876bab126e7bc1861d1a39f1dbe.tar.gz gcc-64c7b4c0c9bfd876bab126e7bc1861d1a39f1dbe.tar.bz2 |
compiler: Support Go 1.2 nil checks.
From-SVN: r204679
Diffstat (limited to 'gcc/go')
-rw-r--r-- | gcc/go/gofrontend/expressions.cc | 24 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.h | 17 | ||||
-rw-r--r-- | gcc/go/gofrontend/types.cc | 3 |
3 files changed, 38 insertions, 6 deletions
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index aefb51c..e26bf35 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -3633,7 +3633,8 @@ class Unary_expression : public Expression public: Unary_expression(Operator op, Expression* expr, Location 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. @@ -3719,6 +3720,10 @@ class Unary_expression : public Expression void do_dump_expression(Ast_dump_context*) const; + void + do_issue_nil_check() + { this->issue_nil_check_ = (this->op_ == OPERATOR_MULT); } + private: // The unary operator to apply. Operator op_; @@ -3730,6 +3735,9 @@ class Unary_expression : public Expression bool create_temp_; // The operand. 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 @@ -4107,7 +4115,10 @@ Unary_expression::do_check_types(Gogo*) this->report_error(_("invalid operand for unary %<&%>")); } else - this->expr_->address_taken(this->escapes_); + { + this->expr_->address_taken(this->escapes_); + this->expr_->issue_nil_check(); + } break; case OPERATOR_MULT: @@ -4277,12 +4288,13 @@ Unary_expression::do_get_tree(Translate_context* context) // If we are dereferencing the pointer to a large struct, we // 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. + // 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)); if (!VOID_TYPE_P(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)) expr = save_expr(expr); @@ -10402,6 +10414,10 @@ class Array_index_expression : public Expression do_address_taken(bool escapes) { this->array_->address_taken(escapes); } + void + do_issue_nil_check() + { this->array_->issue_nil_check(); } + tree do_get_tree(Translate_context*); diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index a94330d..47ce4c0 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -613,6 +613,11 @@ class Expression address_taken(bool 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 // according to the order of evaluation rules. This is basically // true of all expressions with side-effects. @@ -742,6 +747,11 @@ class Expression 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 // in order. virtual bool @@ -1721,6 +1731,9 @@ class Index_expression : public Parser_expression void do_dump_expression(Ast_dump_context*) const; + void + do_issue_nil_check() + { this->left_->issue_nil_check(); } private: // The expression being indexed. Expression* left_; @@ -2011,6 +2024,10 @@ class Field_reference_expression : public Expression do_address_taken(bool escapes) { this->expr_->address_taken(escapes); } + void + do_issue_nil_check() + { this->expr_->issue_nil_check(); } + tree do_get_tree(Translate_context*); diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index ea68c43..551e97a 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -8847,8 +8847,7 @@ Type::add_local_methods_for_type(const Named_type* nt, bool is_value_method = (is_embedded_pointer || !Type::method_expects_pointer(no)); Method* m = new Named_method(no, field_indexes, depth, is_value_method, - (needs_stub_method - || (depth > 0 && is_value_method))); + (needs_stub_method || depth > 0)); if (!(*methods)->insert(no->name(), m)) delete m; } |