diff options
Diffstat (limited to 'gcc/go/gofrontend/expressions.cc')
-rw-r--r-- | gcc/go/gofrontend/expressions.cc | 91 |
1 files changed, 82 insertions, 9 deletions
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 6d484d9..79ed445 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -59,6 +59,67 @@ Expression::traverse_subexpressions(Traverse* traverse) return this->do_traverse(traverse); } +// A traversal used to set the location of subexpressions. + +class Set_location : public Traverse +{ + public: + Set_location(Location loc) + : Traverse(traverse_expressions), + loc_(loc) + { } + + int + expression(Expression** pexpr); + + private: + Location loc_; +}; + +// Set the location of an expression. + +int +Set_location::expression(Expression** pexpr) +{ + // Some expressions are shared or don't have an independent + // location, so we shouldn't change their location. This is the set + // of expressions for which do_copy is just "return this" or + // otherwise does not pass down the location. + switch ((*pexpr)->classification()) + { + case Expression::EXPRESSION_ERROR: + case Expression::EXPRESSION_VAR_REFERENCE: + case Expression::EXPRESSION_ENCLOSED_VAR_REFERENCE: + case Expression::EXPRESSION_STRING: + case Expression::EXPRESSION_FUNC_DESCRIPTOR: + case Expression::EXPRESSION_TYPE: + case Expression::EXPRESSION_BOOLEAN: + case Expression::EXPRESSION_CONST_REFERENCE: + case Expression::EXPRESSION_NIL: + case Expression::EXPRESSION_TYPE_DESCRIPTOR: + case Expression::EXPRESSION_GC_SYMBOL: + case Expression::EXPRESSION_PTRMASK_SYMBOL: + case Expression::EXPRESSION_TYPE_INFO: + case Expression::EXPRESSION_STRUCT_FIELD_OFFSET: + return TRAVERSE_CONTINUE; + default: + break; + } + + (*pexpr)->location_ = this->loc_; + return TRAVERSE_CONTINUE; +} + +// Set the location of an expression and its subexpressions. + +void +Expression::set_location(Location loc) +{ + this->location_ = loc; + Set_location sl(loc); + this->traverse_subexpressions(&sl); +} + // Default implementation for do_traverse for child classes. int @@ -9389,6 +9450,8 @@ Builtin_call_expression::do_is_constant() const if (arg == NULL) return false; Type* arg_type = arg->type(); + if (arg_type->is_error()) + return true; if (arg_type->points_to() != NULL && arg_type->points_to()->array_type() != NULL @@ -9460,6 +9523,8 @@ Builtin_call_expression::do_numeric_constant_value(Numeric_constant* nc) const if (arg == NULL) return false; Type* arg_type = arg->type(); + if (arg_type->is_error()) + return false; if (this->code_ == BUILTIN_LEN && arg_type->is_string_type()) { @@ -9482,17 +9547,25 @@ Builtin_call_expression::do_numeric_constant_value(Numeric_constant* nc) const { if (this->seen_) return false; - Expression* e = arg_type->array_type()->length(); - this->seen_ = true; - bool r = e->numeric_constant_value(nc); - this->seen_ = false; - if (r) + + // We may be replacing this expression with a constant + // during lowering, so verify the type to report any errors. + // It's OK to verify an array type more than once. + arg_type->verify(); + if (!arg_type->is_error()) { - if (!nc->set_type(Type::lookup_integer_type("int"), false, - this->location())) - r = false; + Expression* e = arg_type->array_type()->length(); + this->seen_ = true; + bool r = e->numeric_constant_value(nc); + this->seen_ = false; + if (r) + { + if (!nc->set_type(Type::lookup_integer_type("int"), false, + this->location())) + r = false; + } + return r; } - return r; } } else if (this->code_ == BUILTIN_SIZEOF |