@@ -429,8 +429,13 @@ void ClangImporter::Implementation::addSynthesizedProtocolAttrs(
429
429
auto &ctx = nominal->getASTContext ();
430
430
431
431
for (auto kind : synthesizedProtocolAttrs) {
432
- nominal->getAttrs ().add (
433
- new (ctx) SynthesizedProtocolAttr (kind, this , isUnchecked));
432
+ // This is unfortunately not an error because some test use mock protocols.
433
+ // If those tests were updated, we could assert that
434
+ // ctx.getProtocol(kind) != nulltpr which would be nice.
435
+ if (auto proto = ctx.getProtocol (kind))
436
+ nominal->getAttrs ().add (
437
+ new (ctx) SynthesizedProtocolAttr (ctx.getProtocol (kind), this ,
438
+ isUnchecked));
434
439
}
435
440
}
436
441
@@ -2611,23 +2616,72 @@ namespace {
2611
2616
}
2612
2617
2613
2618
auto result = VisitRecordDecl (decl);
2619
+ if (!result)
2620
+ return nullptr ;
2614
2621
2615
- if (auto classDecl = dyn_cast_or_null <ClassDecl>(result))
2622
+ if (auto classDecl = dyn_cast <ClassDecl>(result))
2616
2623
validateForeignReferenceType (decl, classDecl);
2617
2624
2618
2625
// If this module is declared as a C++ module, try to synthesize
2619
2626
// conformances to Swift protocols from the Cxx module.
2620
2627
auto clangModule = decl->getOwningModule ();
2621
2628
if (clangModule && requiresCPlusPlus (clangModule)) {
2622
- if (auto structDecl = dyn_cast_or_null<NominalTypeDecl>(result)) {
2623
- conformToCxxIteratorIfNeeded (Impl, structDecl, decl);
2624
- conformToCxxSequenceIfNeeded (Impl, structDecl, decl);
2625
- }
2629
+ auto nominalDecl = cast<NominalTypeDecl>(result);
2630
+ conformToCxxIteratorIfNeeded (Impl, nominalDecl, decl);
2631
+ conformToCxxSequenceIfNeeded (Impl, nominalDecl, decl);
2626
2632
}
2627
2633
2634
+ addExplicitProtocolConformances (cast<NominalTypeDecl>(result));
2635
+
2628
2636
return result;
2629
2637
}
2630
2638
2639
+ void addExplicitProtocolConformances (NominalTypeDecl *decl) {
2640
+ auto clangDecl = decl->getClangDecl ();
2641
+
2642
+ if (!clangDecl->hasAttrs ())
2643
+ return ;
2644
+
2645
+ SmallVector<ValueDecl *, 1 > results;
2646
+ auto conformsToAttr =
2647
+ llvm::find_if (clangDecl->getAttrs (), [](auto *attr) {
2648
+ if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(attr))
2649
+ return swiftAttr->getAttribute ().startswith (" conforms_to:" );
2650
+ return false ;
2651
+ });
2652
+ if (conformsToAttr == clangDecl->getAttrs ().end ())
2653
+ return ;
2654
+
2655
+ auto name = cast<clang::SwiftAttrAttr>(*conformsToAttr)
2656
+ ->getAttribute ()
2657
+ .drop_front (StringRef (" conforms_to:" ).size ())
2658
+ .str ();
2659
+
2660
+ for (auto &module : Impl.SwiftContext .getLoadedModules ()) {
2661
+ module .second ->lookupValue (Impl.SwiftContext .getIdentifier (name),
2662
+ NLKind::UnqualifiedLookup, results);
2663
+ }
2664
+
2665
+ if (results.empty ()) {
2666
+ HeaderLoc attrLoc ((*conformsToAttr)->getLocation ());
2667
+ Impl.diagnose (attrLoc, diag::cannot_find_conforms_to, name);
2668
+ return ;
2669
+ } else if (results.size () != 1 ) {
2670
+ HeaderLoc attrLoc ((*conformsToAttr)->getLocation ());
2671
+ Impl.diagnose (attrLoc, diag::conforms_to_ambiguous, name);
2672
+ return ;
2673
+ }
2674
+
2675
+ auto result = results.front ();
2676
+ if (auto protocol = dyn_cast<ProtocolDecl>(result)) {
2677
+ decl->getAttrs ().add (
2678
+ new (Impl.SwiftContext ) SynthesizedProtocolAttr (protocol, &Impl, false ));
2679
+ } else {
2680
+ HeaderLoc attrLoc ((*conformsToAttr)->getLocation ());
2681
+ Impl.diagnose (attrLoc, diag::conforms_to_not_protocol, name);
2682
+ }
2683
+ }
2684
+
2631
2685
bool isSpecializationDepthGreaterThan (
2632
2686
const clang::ClassTemplateSpecializationDecl *decl, unsigned maxDepth) {
2633
2687
for (auto arg : decl->getTemplateArgs ().asArray ()) {
@@ -5126,10 +5180,11 @@ static bool conformsToProtocolInOriginalModule(NominalTypeDecl *nominal,
5126
5180
if (inheritanceListContainsProtocol (nominal, proto))
5127
5181
return true ;
5128
5182
5129
- for (auto attr : nominal->getAttrs ().getAttributes <SynthesizedProtocolAttr>())
5130
- if (auto *otherProto = ctx.getProtocol (attr->getProtocolKind ()))
5131
- if (otherProto == proto || otherProto->inheritsFrom (proto))
5132
- return true ;
5183
+ for (auto attr : nominal->getAttrs ().getAttributes <SynthesizedProtocolAttr>()) {
5184
+ auto *otherProto = attr->getProtocol ();
5185
+ if (otherProto == proto || otherProto->inheritsFrom (proto))
5186
+ return true ;
5187
+ }
5133
5188
5134
5189
// Only consider extensions from the original module...or from an overlay
5135
5190
// or the Swift half of a mixed-source framework.
0 commit comments