Commit f0ebf6e3 by Ian Lance Taylor

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
parent e68086c4
79eca4fd642724d89e9bec8f79889451f6632a46 8e74a218e11ef6eaaf7014a3ad1cd0b13359c607
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
...@@ -8061,9 +8061,13 @@ Builtin_call_expression::do_is_constant() const ...@@ -8061,9 +8061,13 @@ Builtin_call_expression::do_is_constant() const
arg_type = arg_type->points_to(); arg_type = arg_type->points_to();
if (arg_type->array_type() != NULL if (arg_type->array_type() != NULL
&& arg_type->array_type()->length() != NULL && arg_type->array_type()->length() != NULL)
&& Builtin_call_expression::array_len_is_constant(arg)) {
return true; 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()) if (this->code_ == BUILTIN_LEN && arg_type->is_string_type())
{ {
......
...@@ -8258,8 +8258,16 @@ Traverse::remember_type(const Type* type) ...@@ -8258,8 +8258,16 @@ Traverse::remember_type(const Type* type)
// We mostly only have to remember named types. But it turns out // We mostly only have to remember named types. But it turns out
// that an interface type can refer to itself without using a name // that an interface type can refer to itself without using a name
// by relying on interface inheritance, as in // 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 if (type->classification() != Type::TYPE_NAMED
&& type->classification() != Type::TYPE_ARRAY
&& type->classification() != Type::TYPE_INTERFACE) && type->classification() != Type::TYPE_INTERFACE)
return false; return false;
if (this->types_seen_ == NULL) if (this->types_seen_ == NULL)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment