compiler: traverse method declarations

We were not consistently traversing method declarations, which appear
if there is a method without a body.  The gc compiler rejects that
case, but gofrontend currently permits it.  Maybe that should change,
but not today.

This avoids a compiler crash if there are method declarations
with types that require specific functions.  I didn't bother
with a test case because a program with method declarations is
almost certainly invalid anyhow.

Fixes PR go/117891

Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/633495
This commit is contained in:
Ian Lance Taylor 2024-12-03 20:25:47 -08:00
parent 2576dd68a6
commit 9a53561075
2 changed files with 30 additions and 22 deletions

View file

@ -1,4 +1,4 @@
dfe585bf82380630697e96c249de825c5f655afe
f4956f807f1a33e406cf1b3bf3479a9ac1c1015a
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.

View file

@ -3592,26 +3592,6 @@ Finalize_methods::type(Type* t)
}
}
// Finalize the types of all methods that are declared but not
// defined, since we won't see the declarations otherwise.
if (nt->named_object()->package() == NULL
&& nt->local_methods() != NULL)
{
const Bindings* methods = nt->local_methods();
for (Bindings::const_declarations_iterator p =
methods->begin_declarations();
p != methods->end_declarations();
p++)
{
if (p->second->is_function_declaration())
{
Type* mt = p->second->func_declaration_value()->type();
if (Type::traverse(mt, this) == TRAVERSE_EXIT)
return TRAVERSE_EXIT;
}
}
}
return TRAVERSE_SKIP_COMPONENTS;
}
@ -8790,7 +8770,35 @@ Named_object::traverse(Traverse* traverse, bool is_global)
case Named_object::NAMED_OBJECT_TYPE:
if ((traverse_mask & e_or_t) != 0)
t = Type::traverse(this->type_value(), traverse);
{
t = Type::traverse(this->type_value(), traverse);
if (t == TRAVERSE_EXIT)
return TRAVERSE_EXIT;
// Traverse the types of any local methods that are declared
// but not defined. We will see defined methods as
// NAMED_OBJECT_FUNC, but we won't see methods that are only
// declared.
if (this->package_ == NULL
&& this->type_value()->named_type()->local_methods() != NULL)
{
const Bindings* methods =
this->type_value()->named_type()->local_methods();
for (Bindings::const_declarations_iterator p =
methods->begin_declarations();
p != methods->end_declarations();
++p)
{
if (p->second->is_function_declaration())
{
Type* mt = p->second->func_declaration_value()->type();
if (Type::traverse(mt, traverse) == TRAVERSE_EXIT)
return TRAVERSE_EXIT;
}
}
}
}
break;
case Named_object::NAMED_OBJECT_PACKAGE: