diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2018-06-04 19:10:05 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2018-06-04 19:10:05 +0000 |
commit | f0ebf6e3229d88be4bc8d13b219327a7a073df83 (patch) | |
tree | bac6ab9a7cb11017d4e4ab53577eebb573d2e3dc | |
parent | e68086c43226ee8ada8ac71365f571a3d3ad2a0a (diff) | |
download | gcc-f0ebf6e3229d88be4bc8d13b219327a7a073df83.zip gcc-f0ebf6e3229d88be4bc8d13b219327a7a073df83.tar.gz gcc-f0ebf6e3229d88be4bc8d13b219327a7a073df83.tar.bz2 |
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
-rw-r--r-- | gcc/go/gofrontend/MERGE | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/expressions.cc | 10 | ||||
-rw-r--r-- | 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) |