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