diff options
author | Ian Lance Taylor <iant@golang.org> | 2020-12-05 21:16:13 -0800 |
---|---|---|
committer | Ian Lance Taylor <iant@golang.org> | 2020-12-08 10:22:12 -0800 |
commit | f1b6e17b3f753980527721aa8e949d2481b2560b (patch) | |
tree | 1d9071fcfcbf9832e58b86f14812d4d017cdb654 | |
parent | f41dd93ade24f22f8cd1863129ab20c821000134 (diff) | |
download | gcc-f1b6e17b3f753980527721aa8e949d2481b2560b.zip gcc-f1b6e17b3f753980527721aa8e949d2481b2560b.tar.gz gcc-f1b6e17b3f753980527721aa8e949d2481b2560b.tar.bz2 |
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
-rw-r--r-- | gcc/go/gofrontend/MERGE | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.cc | 91 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.h | 10 | ||||
-rw-r--r-- | 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 { |