From f1b6e17b3f753980527721aa8e949d2481b2560b Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sat, 5 Dec 2020 21:16:13 -0800 Subject: [PATCH] compiler: use correct location for iota errors Also check for valid array length when reducing len/cap to a constant. For golang/go#8183 Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/275654 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/expressions.cc | 91 ++++++++++++++++++++++++++++++++++++---- gcc/go/gofrontend/expressions.h | 10 +++++ gcc/go/gofrontend/parse.cc | 7 +++- 4 files changed, 99 insertions(+), 11 deletions(-) diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index d4c8e30..619f1c0 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -1,4 +1,4 @@ -3363fc239f642d3c3fb9a138d2833985d85dc083 +f4069d94a25893afc9f2fcf641359366f3ede017 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. 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 diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h index 259eeb6..712f687 100644 --- a/gcc/go/gofrontend/expressions.h +++ b/gcc/go/gofrontend/expressions.h @@ -549,6 +549,16 @@ class Expression location() const { return this->location_; } + // Set the location of an expression and all its subexpressions. + // This is used for const declarations where the expression is + // copied from an earlier declaration. + void + set_location(Location loc); + + // For set_location. This should really be a local class in + // Expression, but it needs types defined in gogo.h. + friend class Set_location; + // Return whether this is a constant expression. bool is_constant() const diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc index b1925ed..a4740cf 100644 --- a/gcc/go/gofrontend/parse.cc +++ b/gcc/go/gofrontend/parse.cc @@ -1442,6 +1442,7 @@ Parse::const_decl() void Parse::const_spec(int iota, Type** last_type, Expression_list** last_expr_list) { + Location loc = this->location(); Typed_identifier_list til; this->identifier_list(&til); @@ -1466,7 +1467,11 @@ Parse::const_spec(int iota, Type** last_type, Expression_list** last_expr_list) for (Expression_list::const_iterator p = (*last_expr_list)->begin(); p != (*last_expr_list)->end(); ++p) - expr_list->push_back((*p)->copy()); + { + Expression* copy = (*p)->copy(); + copy->set_location(loc); + expr_list->push_back(copy); + } } else { -- 2.7.4