@@ -3242,24 +3242,37 @@ AssociatedTypeDecl::getOverriddenDecls() const {
3242
3242
return assocTypes;
3243
3243
}
3244
3244
3245
- AssociatedTypeDecl *AssociatedTypeDecl::getAssociatedTypeAnchor () const {
3246
- auto overridden = getOverriddenDecls ();
3245
+ namespace {
3246
+ static AssociatedTypeDecl *getAssociatedTypeAnchor (
3247
+ const AssociatedTypeDecl *ATD,
3248
+ llvm::SmallSet<const AssociatedTypeDecl *, 8 > &searched) {
3249
+ auto overridden = ATD->getOverriddenDecls ();
3247
3250
3248
3251
// If this declaration does not override any other declarations, it's
3249
3252
// the anchor.
3250
- if (overridden.empty ()) return const_cast <AssociatedTypeDecl *>(this );
3253
+ if (overridden.empty ()) return const_cast <AssociatedTypeDecl *>(ATD );
3251
3254
3252
- // Find the best anchor among the anchors of the overridden decls.
3255
+ // Find the best anchor among the anchors of the overridden decls and avoid
3256
+ // reentrancy when erroneous cyclic protocols exist.
3253
3257
AssociatedTypeDecl *bestAnchor = nullptr ;
3254
3258
for (auto assocType : overridden) {
3255
- assert (this != assocType && " AssociatedTypeDecl cannot override itself" );
3256
- auto anchor = assocType->getAssociatedTypeAnchor ();
3257
- if (!bestAnchor || compare (anchor, bestAnchor) < 0 )
3259
+ if (!searched.insert (assocType).second )
3260
+ continue ;
3261
+ auto anchor = getAssociatedTypeAnchor (assocType, searched);
3262
+ if (!anchor)
3263
+ continue ;
3264
+ if (!bestAnchor || AbstractTypeParamDecl::compare (anchor, bestAnchor) < 0 )
3258
3265
bestAnchor = anchor;
3259
3266
}
3260
3267
3261
3268
return bestAnchor;
3262
3269
}
3270
+ };
3271
+
3272
+ AssociatedTypeDecl *AssociatedTypeDecl::getAssociatedTypeAnchor () const {
3273
+ llvm::SmallSet<const AssociatedTypeDecl *, 8 > searched;
3274
+ return ::getAssociatedTypeAnchor (this , searched);
3275
+ }
3263
3276
3264
3277
EnumDecl::EnumDecl (SourceLoc EnumLoc,
3265
3278
Identifier Name, SourceLoc NameLoc,
0 commit comments