compiler: fix crashes on cyclic var/type references
authorIan Lance Taylor <ian@gcc.gnu.org>
Mon, 4 Jun 2018 19:10:05 +0000 (19:10 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Mon, 4 Jun 2018 19:10:05 +0000 (19:10 +0000)
    This patch fixes type traversal to avoid compiler crashes for test
    cases where a type T includes an expression that refers back to the
    type without actually explicitly mentioning T. Examples include

      var x [uintptr(unsafe.Sizeof(&x))]byte
      var a [len(a)]int

    The fix involves expanding the set of types that the traversal code
    "remembers" (to avoid cycles) to include array types, and introducing an
    additional guard in Builtin_call_expression::do_is_constant to catch
    cyclic type constructs.

    Fixes golang/go#25299
    Fixes golang/go#25679
    Fixes golang/go#25315
    Fixes golang/go#25680

    Reviewed-on: https://go-review.googlesource.com/115796

From-SVN: r261168

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/gogo.cc

index 618004c6d8d084d5f03d56e812135aa03ccb955d..f2ec42058fcab45f5119be6dcff91e283a120dee 100644 (file)
@@ -1,4 +1,4 @@
-79eca4fd642724d89e9bec8f79889451f6632a46
+8e74a218e11ef6eaaf7014a3ad1cd0b13359c607
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index 109d6b469316e37feef221b7e625984ee205cc72..75b8b69383cea162d7b9a55f02d0c86c6f992f89 100644 (file)
@@ -8061,9 +8061,13 @@ Builtin_call_expression::do_is_constant() const
          arg_type = arg_type->points_to();
 
        if (arg_type->array_type() != NULL
-           && arg_type->array_type()->length() != NULL
-           && Builtin_call_expression::array_len_is_constant(arg))
-         return true;
+           && arg_type->array_type()->length() != NULL)
+          {
+           this->seen_ = true;
+           bool ret = Builtin_call_expression::array_len_is_constant(arg);
+           this->seen_ = false;
+           return ret;
+          }
 
        if (this->code_ == BUILTIN_LEN && arg_type->is_string_type())
          {
index 0eac1993402f776f1c300358a84db99c757e313d..6c20a2b9a45c1da8be7cd5b2b3e675bf61d5e7a4 100644 (file)
@@ -8258,8 +8258,16 @@ Traverse::remember_type(const Type* type)
   // We mostly only have to remember named types.  But it turns out
   // that an interface type can refer to itself without using a name
   // by relying on interface inheritance, as in
-  // type I interface { F() interface{I} }
+  //
+  //         type I interface { F() interface{I} }
+  //
+  // Similarly it is possible for array types to refer to themselves
+  // without a name, e.g.
+  //
+  //         var x [uintptr(unsafe.Sizeof(&x))]byte
+  //
   if (type->classification() != Type::TYPE_NAMED
+      && type->classification() != Type::TYPE_ARRAY
       && type->classification() != Type::TYPE_INTERFACE)
     return false;
   if (this->types_seen_ == NULL)