compiler: fix crashes on cyclic var/type references

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

Change-Id: I9e9bfe4413e3ddd7ce611d5164dea36c165dd4c6
Reviewed-on: https://go-review.googlesource.com/115796
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/go/expressions.cc b/go/expressions.cc
index 109d6b4..75b8b69 100644
--- a/go/expressions.cc
+++ b/go/expressions.cc
@@ -8061,9 +8061,13 @@
 	  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())
 	  {
diff --git a/go/gogo.cc b/go/gogo.cc
index 0eac199..6c20a2b 100644
--- a/go/gogo.cc
+++ b/go/gogo.cc
@@ -8258,8 +8258,16 @@
   // 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)