compiler: use correct location for iota errors
authorIan Lance Taylor <iant@golang.org>
Sun, 6 Dec 2020 05:16:13 +0000 (21:16 -0800)
committerIan Lance Taylor <iant@golang.org>
Tue, 8 Dec 2020 18:22:12 +0000 (10:22 -0800)
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
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/expressions.h
gcc/go/gofrontend/parse.cc

index d4c8e30d1b4288a33a48f66b52ac3d965f6b4494..619f1c001f08cf9448e63ab7b154b5efbe55f096 100644 (file)
@@ -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.
index 6d484d9a33995e1de0a6ba4a4452995b19410dad..79ed44510a9a9ff75572ec998cf4649557c498f5 100644 (file)
@@ -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
index 259eeb6027e8d8e5af66ca2fb0e35613020d933e..712f6870211088f4fd275a560a1776285fdc01b8 100644 (file)
@@ -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
index b1925ed8ccceaec8edde381248fe4738c6a8f532..a4740cfad0e302a961498e8066739cfdd3c5bc12 100644 (file)
@@ -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
     {