@@ -3132,82 +3132,9 @@ namespace {
31323132 }
31333133 }
31343134
3135- if (auto *ntd = dyn_cast<NominalTypeDecl>(result))
3136- addExplicitProtocolConformances (ntd, decl);
3137-
31383135 return result;
31393136 }
31403137
3141- void
3142- addExplicitProtocolConformances (NominalTypeDecl *decl,
3143- const clang::CXXRecordDecl *clangDecl) {
3144- // Propagate conforms_to attribute from public base classes.
3145- for (auto base : clangDecl->bases ()) {
3146- if (base.getAccessSpecifier () != clang::AccessSpecifier::AS_public)
3147- continue ;
3148- if (auto *baseClangDecl = base.getType ()->getAsCXXRecordDecl ())
3149- addExplicitProtocolConformances (decl, baseClangDecl);
3150- }
3151-
3152- if (!clangDecl->hasAttrs ())
3153- return ;
3154-
3155- SmallVector<ValueDecl *, 1 > results;
3156- auto conformsToAttr =
3157- llvm::find_if (clangDecl->getAttrs (), [](auto *attr) {
3158- if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(attr))
3159- return swiftAttr->getAttribute ().starts_with (" conforms_to:" );
3160- return false ;
3161- });
3162- if (conformsToAttr == clangDecl->getAttrs ().end ())
3163- return ;
3164-
3165- auto conformsToValue = cast<clang::SwiftAttrAttr>(*conformsToAttr)
3166- ->getAttribute ()
3167- .drop_front (StringRef (" conforms_to:" ).size ())
3168- .str ();
3169- auto names = StringRef (conformsToValue).split (' .' );
3170- auto moduleName = names.first ;
3171- auto protocolName = names.second ;
3172- if (protocolName.empty ()) {
3173- HeaderLoc attrLoc ((*conformsToAttr)->getLocation ());
3174- Impl.diagnose (attrLoc, diag::conforms_to_missing_dot, conformsToValue);
3175- return ;
3176- }
3177-
3178- auto *mod = Impl.SwiftContext .getModuleByIdentifier (
3179- Impl.SwiftContext .getIdentifier (moduleName));
3180- if (!mod) {
3181- HeaderLoc attrLoc ((*conformsToAttr)->getLocation ());
3182- Impl.diagnose (attrLoc, diag::cannot_find_conforms_to_module,
3183- conformsToValue, moduleName);
3184- return ;
3185- }
3186- mod->lookupValue (Impl.SwiftContext .getIdentifier (protocolName),
3187- NLKind::UnqualifiedLookup, results);
3188- if (results.empty ()) {
3189- HeaderLoc attrLoc ((*conformsToAttr)->getLocation ());
3190- Impl.diagnose (attrLoc, diag::cannot_find_conforms_to, protocolName,
3191- moduleName);
3192- return ;
3193- } else if (results.size () != 1 ) {
3194- HeaderLoc attrLoc ((*conformsToAttr)->getLocation ());
3195- Impl.diagnose (attrLoc, diag::conforms_to_ambiguous, protocolName,
3196- moduleName);
3197- return ;
3198- }
3199-
3200- auto result = results.front ();
3201- if (auto protocol = dyn_cast<ProtocolDecl>(result)) {
3202- decl->getAttrs ().add (
3203- new (Impl.SwiftContext ) SynthesizedProtocolAttr (protocol, &Impl, false ));
3204- } else {
3205- HeaderLoc attrLoc ((*conformsToAttr)->getLocation ());
3206- Impl.diagnose (attrLoc, diag::conforms_to_not_protocol,
3207- result->getDescriptiveKind (), result, conformsToValue);
3208- }
3209- }
3210-
32113138 bool isSpecializationDepthGreaterThan (
32123139 const clang::ClassTemplateSpecializationDecl *decl, unsigned maxDepth) {
32133140 for (auto arg : decl->getTemplateArgs ().asArray ()) {
@@ -6507,6 +6434,20 @@ static bool conformsToProtocolInOriginalModule(NominalTypeDecl *nominal,
65076434 return false ;
65086435}
65096436
6437+ // / Determine whether the given nominal type was imported with an OptionSet
6438+ // / conformance.
6439+ static bool isImportedOptionSet (NominalTypeDecl *nominal) {
6440+ for (auto attr : nominal->getAttrs ()) {
6441+ if (auto synthesizedAttr = dyn_cast<SynthesizedProtocolAttr>(attr)) {
6442+ if (synthesizedAttr->getProtocol ()->isSpecificProtocol (
6443+ KnownProtocolKind::OptionSet))
6444+ return true ;
6445+ }
6446+ }
6447+
6448+ return false ;
6449+ }
6450+
65106451Decl *
65116452SwiftDeclConverter::importSwiftNewtype (const clang::TypedefNameDecl *decl,
65126453 clang::SwiftNewTypeAttr *newtypeAttr,
@@ -6581,6 +6522,11 @@ SwiftDeclConverter::importSwiftNewtype(const clang::TypedefNameDecl *decl,
65816522 addKnown (KnownProtocolKind::RawRepresentable);
65826523 addKnown (KnownProtocolKind::SwiftNewtypeWrapper);
65836524
6525+ // If this type was also imported as an OptionSet, include those typealiases.
6526+ if (isImportedOptionSet (structDecl)) {
6527+ Impl.addOptionSetTypealiases (structDecl);
6528+ }
6529+
65846530 // Local function to add a known protocol only when the
65856531 // underlying type conforms to it.
65866532 auto computedNominal = computedPropertyUnderlyingType->getAnyNominal ();
@@ -6835,8 +6781,6 @@ Decl *SwiftDeclConverter::importEnumCaseAlias(
68356781NominalTypeDecl *
68366782SwiftDeclConverter::importAsOptionSetType (DeclContext *dc, Identifier name,
68376783 const clang::EnumDecl *decl) {
6838- ASTContext &ctx = Impl.SwiftContext ;
6839-
68406784 auto Loc = Impl.importSourceLoc (decl->getLocation ());
68416785
68426786 // Create a struct with the underlying type as a field.
@@ -6855,10 +6799,7 @@ SwiftDeclConverter::importAsOptionSetType(DeclContext *dc, Identifier name,
68556799
68566800 synthesizer.makeStructRawValued (structDecl, underlyingType,
68576801 {KnownProtocolKind::OptionSet});
6858- auto selfType = structDecl->getDeclaredInterfaceType ();
6859- Impl.addSynthesizedTypealias (structDecl, ctx.Id_Element , selfType);
6860- Impl.addSynthesizedTypealias (structDecl, ctx.Id_ArrayLiteralElement ,
6861- selfType);
6802+ Impl.addOptionSetTypealiases (structDecl);
68626803 return structDecl;
68636804}
68646805
@@ -8756,6 +8697,7 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
87568697
87578698 std::optional<const clang::SwiftAttrAttr *> seenMainActorAttr;
87588699 const clang::SwiftAttrAttr *seenMutabilityAttr = nullptr ;
8700+ llvm::SmallSet<ProtocolDecl *, 4 > conformancesSeen;
87598701
87608702 auto importAttrsFromDecl = [&](const clang::NamedDecl *ClangDecl) {
87618703 //
@@ -8871,6 +8813,11 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
88718813 continue ;
88728814 }
88738815
8816+ if (swiftAttr->getAttribute ().starts_with (" conforms_to:" )) {
8817+ if (auto nominal = dyn_cast<NominalTypeDecl>(MappedDecl))
8818+ addExplicitProtocolConformance (nominal, swiftAttr, conformancesSeen);
8819+ }
8820+
88748821 importNontrivialAttribute (MappedDecl, swiftAttr->getAttribute ());
88758822 }
88768823
@@ -8933,6 +8880,14 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
89338880 }
89348881 }
89358882
8883+ // Import explicit conformances from C++ base classes.
8884+ if (auto nominal = dyn_cast<NominalTypeDecl>(MappedDecl)) {
8885+ if (auto cxxRecordDecl = dyn_cast<clang::CXXRecordDecl>(ClangDecl)) {
8886+ addExplicitProtocolConformancesFromBases (
8887+ nominal, cxxRecordDecl, /* isBase=*/ false );
8888+ }
8889+ }
8890+
89368891 // Now that we've collected all @Sendable and @_nonSendable attributes, we
89378892 // can see if we should synthesize a Sendable conformance.
89388893 if (auto nominal = dyn_cast<NominalTypeDecl>(MappedDecl)) {
@@ -9200,6 +9155,100 @@ static bool SwiftifiableCAT(const clang::ASTContext &ctx,
92009155 : SwiftifiableCountedByPointerType (swiftType));
92019156}
92029157
9158+ void ClangImporter::Implementation::addExplicitProtocolConformance (
9159+ NominalTypeDecl *decl,
9160+ clang::SwiftAttrAttr *conformsToAttr,
9161+ llvm::SmallSet<ProtocolDecl *, 4 > &alreadyAdded) {
9162+ auto conformsToValue = conformsToAttr->getAttribute ()
9163+ .drop_front (StringRef (" conforms_to:" ).size ())
9164+ .str ();
9165+ auto names = StringRef (conformsToValue).split (' .' );
9166+ auto moduleName = names.first ;
9167+ auto protocolName = names.second ;
9168+ if (protocolName.empty ()) {
9169+ HeaderLoc attrLoc (conformsToAttr->getLocation ());
9170+ diagnose (attrLoc, diag::conforms_to_missing_dot, conformsToValue);
9171+ return ;
9172+ }
9173+
9174+ auto *mod = SwiftContext.getModuleByIdentifier (
9175+ SwiftContext.getIdentifier (moduleName));
9176+ if (!mod) {
9177+ HeaderLoc attrLoc (conformsToAttr->getLocation ());
9178+ diagnose (attrLoc, diag::cannot_find_conforms_to_module,
9179+ conformsToValue, moduleName);
9180+ return ;
9181+ }
9182+
9183+ SmallVector<ValueDecl *, 1 > results;
9184+ mod->lookupValue (SwiftContext.getIdentifier (protocolName),
9185+ NLKind::UnqualifiedLookup, results);
9186+ if (results.empty ()) {
9187+ HeaderLoc attrLoc (conformsToAttr->getLocation ());
9188+ diagnose (attrLoc, diag::cannot_find_conforms_to, protocolName,
9189+ moduleName);
9190+ return ;
9191+ }
9192+
9193+ if (results.size () != 1 ) {
9194+ HeaderLoc attrLoc (conformsToAttr->getLocation ());
9195+ diagnose (attrLoc, diag::conforms_to_ambiguous, protocolName,
9196+ moduleName);
9197+ return ;
9198+ }
9199+
9200+ auto result = results.front ();
9201+ if (auto protocol = dyn_cast<ProtocolDecl>(result)) {
9202+ auto [_, inserted] = alreadyAdded.insert (protocol);
9203+ if (!inserted) {
9204+ HeaderLoc attrLoc (conformsToAttr->getLocation ());
9205+ diagnose (attrLoc, diag::redundant_conformance_protocol,
9206+ decl->getDeclaredInterfaceType (), conformsToValue);
9207+ }
9208+
9209+ decl->getAttrs ().add (
9210+ new (SwiftContext) SynthesizedProtocolAttr (protocol, this , false ));
9211+ } else {
9212+ HeaderLoc attrLoc ((conformsToAttr)->getLocation ());
9213+ diagnose (attrLoc, diag::conforms_to_not_protocol, result,
9214+ conformsToValue);
9215+ }
9216+ }
9217+
9218+ void ClangImporter::Implementation::addExplicitProtocolConformancesFromBases (
9219+ NominalTypeDecl *nominal,
9220+ const clang::CXXRecordDecl *cxxRecordDecl,
9221+ bool isBase) {
9222+ if (cxxRecordDecl->isCompleteDefinition ()) {
9223+ // Propagate conforms_to attribute from public base classes.
9224+ for (auto base : cxxRecordDecl->bases ()) {
9225+ if (base.getAccessSpecifier () != clang::AccessSpecifier::AS_public)
9226+ continue ;
9227+ if (auto *baseClangDecl = base.getType ()->getAsCXXRecordDecl ())
9228+ addExplicitProtocolConformancesFromBases (nominal, baseClangDecl,
9229+ /* isBase=*/ true );
9230+ }
9231+ }
9232+
9233+ if (isBase && cxxRecordDecl->hasAttrs ()) {
9234+ llvm::SmallSet<ProtocolDecl *, 4 > alreadyAdded;
9235+ llvm::for_each (cxxRecordDecl->getAttrs (), [&](auto *attr) {
9236+ if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(attr)) {
9237+ if (swiftAttr->getAttribute ().starts_with (" conforms_to:" ))
9238+ addExplicitProtocolConformance (nominal, swiftAttr, alreadyAdded);
9239+ }
9240+ });
9241+ }
9242+ }
9243+
9244+ void ClangImporter::Implementation::addOptionSetTypealiases (
9245+ NominalTypeDecl *nominal) {
9246+ auto selfType = nominal->getDeclaredInterfaceType ();
9247+ addSynthesizedTypealias (nominal, SwiftContext.Id_Element , selfType);
9248+ addSynthesizedTypealias (nominal, SwiftContext.Id_ArrayLiteralElement ,
9249+ selfType);
9250+ }
9251+
92039252void ClangImporter::Implementation::swiftify (AbstractFunctionDecl *MappedDecl) {
92049253 if (!SwiftContext.LangOpts .hasFeature (Feature::SafeInteropWrappers))
92059254 return ;
0 commit comments