From f0ebf6e3229d88be4bc8d13b219327a7a073df83 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Mon, 4 Jun 2018 19:10:05 +0000 Subject: [PATCH] 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 Reviewed-on: https://go-review.googlesource.com/115796 From-SVN: r261168 --- gcc/go/gofrontend/MERGE | 2 +- gcc/go/gofrontend/expressions.cc | 10 +++++++--- gcc/go/gofrontend/gogo.cc | 10 +++++++++- 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 618004c..f2ec420 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -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. diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc index 109d6b4..75b8b69 100644 --- a/gcc/go/gofrontend/expressions.cc +++ b/gcc/go/gofrontend/expressions.cc @@ -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()) { diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index 0eac199..6c20a2b 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -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) -- 2.7.4