Skip to content

Commit f5bc28a

Browse files
ianlancetaylorIan Lance Taylor
authored and
Ian Lance Taylor
committed
compiler: always sort interface parse methods
The exporter relies on sorting interface parse methods. It would sort them as it encountered interface types. However, when an interface type is an element of a struct or array type, the exporter might encounter that interface type before sorting the parse methods. If it then encountered an identical interface type again, it could get confused about whether the two types are identical or not. Fix the problem by always sorting the parse methods in the finalize_methods pass. Also firm up the export type sorting to make sure we never have this kind of confusion again. Doing this revealed that we need to be more careful about sorting in order to handle aliases correctly. Also fix the interface type hash computation to use the right hash value when looking at parse methods rather than all methods. The test case for this is https://go.dev/cl/405759. Fixes golang/go#52841 Change-Id: I6243246148dbd96df8d2f2244516443d9bd6b114 Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/405556 Reviewed-by: Ian Lance Taylor <[email protected]> Reviewed-by: Than McIntosh <[email protected]>
1 parent 6a33e7e commit f5bc28a

File tree

3 files changed

+288
-51
lines changed

3 files changed

+288
-51
lines changed

go/export.cc

+278-37
Original file line numberDiff line numberDiff line change
@@ -360,16 +360,6 @@ Collect_export_references::type(Type* type)
360360
if (type->is_abstract())
361361
return TRAVERSE_SKIP_COMPONENTS;
362362

363-
// For interfaces make sure that embedded methods are sorted, since the
364-
// comparison function we use for indexing types relies on it (this call has
365-
// to happen before the record_type call below).
366-
if (type->classification() == Type::TYPE_INTERFACE)
367-
{
368-
Interface_type* it = type->interface_type();
369-
if (it != NULL)
370-
it->sort_embedded();
371-
}
372-
373363
if (!this->exp_->record_type(type))
374364
{
375365
// We've already seen this type.
@@ -501,6 +491,11 @@ should_export(Named_object* no)
501491
return true;
502492
}
503493

494+
// Compare Typed_identifier_list's.
495+
496+
static int
497+
compare_til(const Typed_identifier_list*, const Typed_identifier_list*);
498+
504499
// A functor to sort Named_object pointers by name.
505500

506501
struct Sort_bindings
@@ -514,10 +509,57 @@ struct Sort_bindings
514509
return true;
515510
if (n2->package() == NULL)
516511
return false;
517-
return n1->package()->pkgpath() < n2->package()->pkgpath();
512+
513+
// Make sure we don't see the same pkgpath twice.
514+
const std::string& p1(n1->package()->pkgpath());
515+
const std::string& p2(n2->package()->pkgpath());
516+
go_assert(p1 != p2);
517+
518+
return p1 < p2;
518519
}
519520

520-
return n1->name() < n2->name();
521+
if (n1->name() != n2->name())
522+
return n1->name() < n2->name();
523+
524+
// We shouldn't see the same name twice, but it can happen for
525+
// nested type names.
526+
527+
go_assert(n1->is_type() && n2->is_type());
528+
529+
unsigned int ind1;
530+
const Named_object* g1 = n1->type_value()->in_function(&ind1);
531+
unsigned int ind2;
532+
const Named_object* g2 = n2->type_value()->in_function(&ind2);
533+
534+
if (g1 == NULL)
535+
{
536+
go_assert(g2 != NULL);
537+
return true;
538+
}
539+
else if (g2 == NULL)
540+
return false;
541+
else if (g1 == g2)
542+
{
543+
go_assert(ind1 != ind2);
544+
return ind1 < ind2;
545+
}
546+
else if ((g1->package() != g2->package()) || (g1->name() != g2->name()))
547+
return Sort_bindings()(g1, g2);
548+
else
549+
{
550+
// This case can happen if g1 or g2 is a method.
551+
if (g1 != NULL && g1->func_value()->is_method())
552+
{
553+
const Typed_identifier* r = g1->func_value()->type()->receiver();
554+
g1 = r->type()->named_type()->named_object();
555+
}
556+
if (g2 != NULL && g2->func_value()->is_method())
557+
{
558+
const Typed_identifier* r = g2->func_value()->type()->receiver();
559+
g2 = r->type()->named_type()->named_object();
560+
}
561+
return Sort_bindings()(g1, g2);
562+
}
521563
}
522564
};
523565

@@ -528,17 +570,20 @@ struct Sort_types
528570
bool
529571
operator()(const Type* t1, const Type* t2) const
530572
{
573+
t1 = t1->forwarded();
574+
t2 = t2->forwarded();
575+
531576
const Named_type* nt1 = t1->named_type();
532577
const Named_type* nt2 = t2->named_type();
533578
if (nt1 != NULL)
534579
{
535-
if (nt2 != NULL)
536-
{
537-
Sort_bindings sb;
538-
return sb(nt1->named_object(), nt2->named_object());
539-
}
540-
else
541-
return true;
580+
if (nt2 != NULL)
581+
{
582+
Sort_bindings sb;
583+
return sb(nt1->named_object(), nt2->named_object());
584+
}
585+
else
586+
return true;
542587
}
543588
else if (nt2 != NULL)
544589
return false;
@@ -549,10 +594,218 @@ struct Sort_types
549594
gogo->type_descriptor_backend_name(t1, NULL, &b1);
550595
Backend_name b2;
551596
gogo->type_descriptor_backend_name(t2, NULL, &b2);
552-
return b1.name() < b2.name();
597+
598+
std::string n1 = b1.name();
599+
std::string n2 = b2.name();
600+
if (n1 != n2)
601+
return n1 < n2;
602+
603+
// We should never see equal types here. If we do, we may not
604+
// generate an identical output file for identical input. But the
605+
// backend names can be equal because we want to treat aliases
606+
// differently while type_descriptor_backend_name does not. In
607+
// that case we need to traverse the type elements.
608+
609+
// t1 == t2 in case std::sort compares elements to themselves.
610+
if (t1 == t2)
611+
return false;
612+
613+
Sort_types sort;
614+
Type_alias_identical identical;
615+
go_assert(!identical(t1, t2));
616+
617+
switch (t1->classification())
618+
{
619+
case Type::TYPE_ERROR:
620+
return false;
621+
622+
case Type::TYPE_VOID:
623+
case Type::TYPE_BOOLEAN:
624+
case Type::TYPE_INTEGER:
625+
case Type::TYPE_FLOAT:
626+
case Type::TYPE_COMPLEX:
627+
case Type::TYPE_STRING:
628+
case Type::TYPE_SINK:
629+
case Type::TYPE_NIL:
630+
case Type::TYPE_CALL_MULTIPLE_RESULT:
631+
case Type::TYPE_NAMED:
632+
case Type::TYPE_FORWARD:
633+
default:
634+
go_unreachable();
635+
636+
case Type::TYPE_FUNCTION:
637+
{
638+
const Function_type* ft1 = t1->function_type();
639+
const Function_type* ft2 = t2->function_type();
640+
const Typed_identifier* r1 = ft1->receiver();
641+
const Typed_identifier* r2 = ft2->receiver();
642+
if (r1 == NULL)
643+
go_assert(r2 == NULL);
644+
else
645+
{
646+
go_assert(r2 != NULL);
647+
const Type* rt1 = r1->type()->forwarded();
648+
const Type* rt2 = r2->type()->forwarded();
649+
if (!identical(rt1, rt2))
650+
return sort(rt1, rt2);
651+
}
652+
653+
const Typed_identifier_list* p1 = ft1->parameters();
654+
const Typed_identifier_list* p2 = ft2->parameters();
655+
if (p1 == NULL || p1->empty())
656+
go_assert(p2 == NULL || p2->empty());
657+
else
658+
{
659+
go_assert(p2 != NULL && !p2->empty());
660+
int i = compare_til(p1, p2);
661+
if (i < 0)
662+
return false;
663+
else if (i > 0)
664+
return true;
665+
}
666+
667+
p1 = ft1->results();
668+
p2 = ft2->results();
669+
if (p1 == NULL || p1->empty())
670+
go_assert(p2 == NULL || p2->empty());
671+
else
672+
{
673+
go_assert(p2 != NULL && !p2->empty());
674+
int i = compare_til(p1, p2);
675+
if (i < 0)
676+
return false;
677+
else if (i > 0)
678+
return true;
679+
}
680+
681+
go_unreachable();
682+
}
683+
684+
case Type::TYPE_POINTER:
685+
{
686+
const Type* p1 = t1->points_to()->forwarded();
687+
const Type* p2 = t2->points_to()->forwarded();
688+
go_assert(!identical(p1, p2));
689+
return sort(p1, p2);
690+
}
691+
692+
case Type::TYPE_STRUCT:
693+
{
694+
const Struct_type* s1 = t1->struct_type();
695+
const Struct_type* s2 = t2->struct_type();
696+
const Struct_field_list* f1 = s1->fields();
697+
const Struct_field_list* f2 = s2->fields();
698+
go_assert(f1 != NULL && f2 != NULL);
699+
Struct_field_list::const_iterator p1 = f1->begin();
700+
Struct_field_list::const_iterator p2 = f2->begin();
701+
for (; p2 != f2->end(); ++p1, ++p2)
702+
{
703+
go_assert(p1 != f1->end());
704+
go_assert(p1->field_name() == p2->field_name());
705+
go_assert(p1->is_anonymous() == p2->is_anonymous());
706+
const Type* ft1 = p1->type()->forwarded();
707+
const Type* ft2 = p2->type()->forwarded();
708+
if (!identical(ft1, ft2))
709+
return sort(ft1, ft2);
710+
}
711+
go_assert(p1 == f1->end());
712+
go_unreachable();
713+
}
714+
715+
case Type::TYPE_ARRAY:
716+
{
717+
const Type* e1 = t1->array_type()->element_type()->forwarded();
718+
const Type* e2 = t2->array_type()->element_type()->forwarded();
719+
go_assert(!identical(e1, e2));
720+
return sort(e1, e2);
721+
}
722+
723+
case Type::TYPE_MAP:
724+
{
725+
const Map_type* m1 = t1->map_type();
726+
const Map_type* m2 = t2->map_type();
727+
const Type* k1 = m1->key_type()->forwarded();
728+
const Type* k2 = m2->key_type()->forwarded();
729+
if (!identical(k1, k2))
730+
return sort(k1, k2);
731+
const Type* v1 = m1->val_type()->forwarded();
732+
const Type* v2 = m2->val_type()->forwarded();
733+
go_assert(!identical(v1, v2));
734+
return sort(v1, v2);
735+
}
736+
737+
case Type::TYPE_CHANNEL:
738+
{
739+
const Type* e1 = t1->channel_type()->element_type()->forwarded();
740+
const Type* e2 = t2->channel_type()->element_type()->forwarded();
741+
go_assert(!identical(e1, e2));
742+
return sort(e1, e2);
743+
}
744+
745+
case Type::TYPE_INTERFACE:
746+
{
747+
const Interface_type* it1 = t1->interface_type();
748+
const Interface_type* it2 = t2->interface_type();
749+
const Typed_identifier_list* m1 = it1->local_methods();
750+
const Typed_identifier_list* m2 = it2->local_methods();
751+
752+
// We know the full method lists are the same, because the
753+
// mangled type names were the same, but here we are looking
754+
// at the local method lists, which include embedded
755+
// interfaces, and we can have an embedded empty interface.
756+
if (m1 == NULL || m1->empty())
757+
{
758+
go_assert(m2 != NULL && !m2->empty());
759+
return true;
760+
}
761+
else if (m2 == NULL || m2->empty())
762+
{
763+
go_assert(m1 != NULL && !m1->empty());
764+
return false;
765+
}
766+
767+
int i = compare_til(m1, m2);
768+
if (i < 0)
769+
return false;
770+
else if (i > 0)
771+
return true;
772+
else
773+
go_unreachable();
774+
}
775+
}
553776
}
554777
};
555778

779+
// Compare Typed_identifier_list's with Sort_types, returning -1, 0, +1.
780+
781+
static int
782+
compare_til(
783+
const Typed_identifier_list* til1,
784+
const Typed_identifier_list* til2)
785+
{
786+
Type_alias_identical identical;
787+
Sort_types sort;
788+
Typed_identifier_list::const_iterator p1 = til1->begin();
789+
Typed_identifier_list::const_iterator p2 = til2->begin();
790+
for (; p2 != til2->end(); ++p1, ++p2)
791+
{
792+
if (p1 == til1->end())
793+
return -1;
794+
const Type* t1 = p1->type()->forwarded();
795+
const Type* t2 = p2->type()->forwarded();
796+
if (!identical(t1, t2))
797+
{
798+
if (sort(t1, t2))
799+
return -1;
800+
else
801+
return +1;
802+
}
803+
}
804+
if (p1 != til1->end())
805+
return +1;
806+
return 0;
807+
}
808+
556809
// Export those identifiers marked for exporting.
557810

558811
void
@@ -714,17 +967,9 @@ bool
714967
Export::record_type(Type* type)
715968
{
716969
type = type->forwarded();
717-
718970
std::pair<Type_refs::iterator, bool> ins =
719971
this->impl_->type_refs.insert(std::make_pair(type, 0));
720-
if (!ins.second)
721-
{
722-
// We've already seen this type.
723-
return false;
724-
}
725-
ins.first->second = 0;
726-
727-
return true;
972+
return ins.second;
728973
}
729974

730975
// Assign the specified type an index.
@@ -733,13 +978,12 @@ void
733978
Export::set_type_index(const Type* type)
734979
{
735980
type = type->forwarded();
736-
std::pair<Type_refs::iterator, bool> ins =
737-
this->impl_->type_refs.insert(std::make_pair(type, 0));
738-
go_assert(!ins.second);
981+
Type_refs::iterator p = this->impl_->type_refs.find(type);
982+
go_assert(p != this->impl_->type_refs.end());
739983
int index = this->type_index_;
740984
++this->type_index_;
741-
go_assert(ins.first->second == 0);
742-
ins.first->second = index;
985+
go_assert(p->second == 0);
986+
p->second = index;
743987
}
744988

745989
// This helper assigns type indices to all types mentioned directly or
@@ -758,9 +1002,6 @@ Export::assign_type_indices(const std::vector<Named_object*>& sorted_exports)
7581002
{
7591003
if (!(*p)->is_type())
7601004
continue;
761-
Interface_type* it = (*p)->type_value()->interface_type();
762-
if (it != NULL)
763-
it->sort_embedded();
7641005
this->record_type((*p)->type_value());
7651006
this->set_type_index((*p)->type_value());
7661007
}

0 commit comments

Comments
 (0)