aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2018-06-04 19:10:05 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2018-06-04 19:10:05 +0000
commitf0ebf6e3229d88be4bc8d13b219327a7a073df83 (patch)
treebac6ab9a7cb11017d4e4ab53577eebb573d2e3dc /gcc
parente68086c43226ee8ada8ac71365f571a3d3ad2a0a (diff)
downloadgcc-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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/expressions.cc10
-rw-r--r--gcc/go/gofrontend/gogo.cc10
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)