@@ -3152,98 +3152,9 @@ namespace {
31523152 }
31533153 }
31543154
3155- if (auto *ntd = dyn_cast<NominalTypeDecl>(result))
3156- addExplicitProtocolConformances (ntd, decl);
3157-
31583155 return result;
31593156 }
31603157
3161- using ProtocolSet = llvm::SmallSet<ProtocolDecl *, 4 >;
3162-
3163- void
3164- addExplicitProtocolConformances (NominalTypeDecl *decl,
3165- const clang::CXXRecordDecl *clangDecl) {
3166- if (clangDecl->isCompleteDefinition ()) {
3167- // Propagate conforms_to attribute from public base classes.
3168- for (auto base : clangDecl->bases ()) {
3169- if (base.getAccessSpecifier () != clang::AccessSpecifier::AS_public)
3170- continue ;
3171- if (auto *baseClangDecl = base.getType ()->getAsCXXRecordDecl ())
3172- addExplicitProtocolConformances (decl, baseClangDecl);
3173- }
3174- }
3175-
3176- if (!clangDecl->hasAttrs ())
3177- return ;
3178-
3179- ProtocolSet alreadyAdded;
3180- llvm::for_each (clangDecl->getAttrs (), [&](auto *attr) {
3181- if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(attr)) {
3182- if (swiftAttr->getAttribute ().starts_with (" conforms_to:" ))
3183- addExplicitProtocolConformance (decl, swiftAttr, alreadyAdded);
3184- }
3185- });
3186- }
3187-
3188- void addExplicitProtocolConformance (NominalTypeDecl *decl,
3189- clang::SwiftAttrAttr *conformsToAttr,
3190- ProtocolSet &alreadyAdded) {
3191- auto conformsToValue = conformsToAttr->getAttribute ()
3192- .drop_front (StringRef (" conforms_to:" ).size ())
3193- .str ();
3194- auto names = StringRef (conformsToValue).split (' .' );
3195- auto moduleName = names.first ;
3196- auto protocolName = names.second ;
3197- if (protocolName.empty ()) {
3198- HeaderLoc attrLoc (conformsToAttr->getLocation ());
3199- Impl.diagnose (attrLoc, diag::conforms_to_missing_dot, conformsToValue);
3200- return ;
3201- }
3202-
3203- auto *mod = Impl.SwiftContext .getModuleByIdentifier (
3204- Impl.SwiftContext .getIdentifier (moduleName));
3205- if (!mod) {
3206- HeaderLoc attrLoc (conformsToAttr->getLocation ());
3207- Impl.diagnose (attrLoc, diag::cannot_find_conforms_to_module,
3208- conformsToValue, moduleName);
3209- return ;
3210- }
3211-
3212- SmallVector<ValueDecl *, 1 > results;
3213- mod->lookupValue (Impl.SwiftContext .getIdentifier (protocolName),
3214- NLKind::UnqualifiedLookup, results);
3215- if (results.empty ()) {
3216- HeaderLoc attrLoc (conformsToAttr->getLocation ());
3217- Impl.diagnose (attrLoc, diag::cannot_find_conforms_to, protocolName,
3218- moduleName);
3219- return ;
3220- }
3221-
3222- if (results.size () != 1 ) {
3223- HeaderLoc attrLoc (conformsToAttr->getLocation ());
3224- Impl.diagnose (attrLoc, diag::conforms_to_ambiguous, protocolName,
3225- moduleName);
3226- return ;
3227- }
3228-
3229- auto result = results.front ();
3230- if (auto protocol = dyn_cast<ProtocolDecl>(result)) {
3231- auto [_, inserted] = alreadyAdded.insert (protocol);
3232- if (!inserted) {
3233- HeaderLoc attrLoc (conformsToAttr->getLocation ());
3234- Impl.diagnose (attrLoc, diag::redundant_conformance_protocol,
3235- decl->getDeclaredInterfaceType (), conformsToValue);
3236- }
3237-
3238- decl->getAttrs ().add (
3239- new (Impl.SwiftContext ) SynthesizedProtocolAttr (protocol, &Impl, false ));
3240- } else {
3241- HeaderLoc attrLoc ((conformsToAttr)->getLocation ());
3242- Impl.diagnose (attrLoc, diag::conforms_to_not_protocol, result,
3243- conformsToValue);
3244- }
3245- }
3246-
32473158 bool isSpecializationDepthGreaterThan (
32483159 const clang::ClassTemplateSpecializationDecl *decl, unsigned maxDepth) {
32493160 for (auto arg : decl->getTemplateArgs ().asArray ()) {
@@ -6608,6 +6519,20 @@ static bool conformsToProtocolInOriginalModule(NominalTypeDecl *nominal,
66086519 return false ;
66096520}
66106521
6522+ // / Determine whether the given nominal type was imported with an OptionSet
6523+ // / conformance.
6524+ static bool isImportedOptionSet (NominalTypeDecl *nominal) {
6525+ for (auto attr : nominal->getAttrs ()) {
6526+ if (auto synthesizedAttr = dyn_cast<SynthesizedProtocolAttr>(attr)) {
6527+ if (synthesizedAttr->getProtocol ()->isSpecificProtocol (
6528+ KnownProtocolKind::OptionSet))
6529+ return true ;
6530+ }
6531+ }
6532+
6533+ return false ;
6534+ }
6535+
66116536Decl *
66126537SwiftDeclConverter::importSwiftNewtype (const clang::TypedefNameDecl *decl,
66136538 clang::SwiftNewTypeAttr *newtypeAttr,
@@ -6682,6 +6607,11 @@ SwiftDeclConverter::importSwiftNewtype(const clang::TypedefNameDecl *decl,
66826607 addKnown (KnownProtocolKind::RawRepresentable);
66836608 addKnown (KnownProtocolKind::SwiftNewtypeWrapper);
66846609
6610+ // If this type was also imported as an OptionSet, include those typealiases.
6611+ if (isImportedOptionSet (structDecl)) {
6612+ Impl.addOptionSetTypealiases (structDecl);
6613+ }
6614+
66856615 // Local function to add a known protocol only when the
66866616 // underlying type conforms to it.
66876617 auto computedNominal = computedPropertyUnderlyingType->getAnyNominal ();
@@ -6936,8 +6866,6 @@ Decl *SwiftDeclConverter::importEnumCaseAlias(
69366866NominalTypeDecl *
69376867SwiftDeclConverter::importAsOptionSetType (DeclContext *dc, Identifier name,
69386868 const clang::EnumDecl *decl) {
6939- ASTContext &ctx = Impl.SwiftContext ;
6940-
69416869 auto Loc = Impl.importSourceLoc (decl->getLocation ());
69426870
69436871 // Create a struct with the underlying type as a field.
@@ -6956,10 +6884,7 @@ SwiftDeclConverter::importAsOptionSetType(DeclContext *dc, Identifier name,
69566884
69576885 synthesizer.makeStructRawValued (structDecl, underlyingType,
69586886 {KnownProtocolKind::OptionSet});
6959- auto selfType = structDecl->getDeclaredInterfaceType ();
6960- Impl.addSynthesizedTypealias (structDecl, ctx.Id_Element , selfType);
6961- Impl.addSynthesizedTypealias (structDecl, ctx.Id_ArrayLiteralElement ,
6962- selfType);
6887+ Impl.addOptionSetTypealiases (structDecl);
69636888 return structDecl;
69646889}
69656890
@@ -8857,6 +8782,7 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
88578782
88588783 std::optional<const clang::SwiftAttrAttr *> seenMainActorAttr;
88598784 const clang::SwiftAttrAttr *seenMutabilityAttr = nullptr ;
8785+ llvm::SmallSet<ProtocolDecl *, 4 > conformancesSeen;
88608786
88618787 auto importAttrsFromDecl = [&](const clang::NamedDecl *ClangDecl) {
88628788 //
@@ -8972,6 +8898,11 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
89728898 continue ;
89738899 }
89748900
8901+ if (swiftAttr->getAttribute ().starts_with (" conforms_to:" )) {
8902+ if (auto nominal = dyn_cast<NominalTypeDecl>(MappedDecl))
8903+ addExplicitProtocolConformance (nominal, swiftAttr, conformancesSeen);
8904+ }
8905+
89758906 importNontrivialAttribute (MappedDecl, swiftAttr->getAttribute ());
89768907 }
89778908
@@ -9034,6 +8965,14 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
90348965 }
90358966 }
90368967
8968+ // Import explicit conformances from C++ base classes.
8969+ if (auto nominal = dyn_cast<NominalTypeDecl>(MappedDecl)) {
8970+ if (auto cxxRecordDecl = dyn_cast<clang::CXXRecordDecl>(ClangDecl)) {
8971+ addExplicitProtocolConformancesFromBases (
8972+ nominal, cxxRecordDecl, /* isBase=*/ false );
8973+ }
8974+ }
8975+
90378976 // Now that we've collected all @Sendable and @_nonSendable attributes, we
90388977 // can see if we should synthesize a Sendable conformance.
90398978 if (auto nominal = dyn_cast<NominalTypeDecl>(MappedDecl)) {
@@ -9302,6 +9241,102 @@ struct UnaliasedInstantiationVisitor
93029241};
93039242} // namespace
93049243
9244+
9245+
9246+ void ClangImporter::Implementation::addExplicitProtocolConformance (
9247+ NominalTypeDecl *decl,
9248+ clang::SwiftAttrAttr *conformsToAttr,
9249+ llvm::SmallSet<ProtocolDecl *, 4 > &alreadyAdded) {
9250+ auto conformsToValue = conformsToAttr->getAttribute ()
9251+ .drop_front (StringRef (" conforms_to:" ).size ())
9252+ .str ();
9253+ auto names = StringRef (conformsToValue).split (' .' );
9254+ auto moduleName = names.first ;
9255+ auto protocolName = names.second ;
9256+ if (protocolName.empty ()) {
9257+ HeaderLoc attrLoc (conformsToAttr->getLocation ());
9258+ diagnose (attrLoc, diag::conforms_to_missing_dot, conformsToValue);
9259+ return ;
9260+ }
9261+
9262+ auto *mod = SwiftContext.getModuleByIdentifier (
9263+ SwiftContext.getIdentifier (moduleName));
9264+ if (!mod) {
9265+ HeaderLoc attrLoc (conformsToAttr->getLocation ());
9266+ diagnose (attrLoc, diag::cannot_find_conforms_to_module,
9267+ conformsToValue, moduleName);
9268+ return ;
9269+ }
9270+
9271+ SmallVector<ValueDecl *, 1 > results;
9272+ mod->lookupValue (SwiftContext.getIdentifier (protocolName),
9273+ NLKind::UnqualifiedLookup, results);
9274+ if (results.empty ()) {
9275+ HeaderLoc attrLoc (conformsToAttr->getLocation ());
9276+ diagnose (attrLoc, diag::cannot_find_conforms_to, protocolName,
9277+ moduleName);
9278+ return ;
9279+ }
9280+
9281+ if (results.size () != 1 ) {
9282+ HeaderLoc attrLoc (conformsToAttr->getLocation ());
9283+ diagnose (attrLoc, diag::conforms_to_ambiguous, protocolName,
9284+ moduleName);
9285+ return ;
9286+ }
9287+
9288+ auto result = results.front ();
9289+ if (auto protocol = dyn_cast<ProtocolDecl>(result)) {
9290+ auto [_, inserted] = alreadyAdded.insert (protocol);
9291+ if (!inserted) {
9292+ HeaderLoc attrLoc (conformsToAttr->getLocation ());
9293+ diagnose (attrLoc, diag::redundant_conformance_protocol,
9294+ decl->getDeclaredInterfaceType (), conformsToValue);
9295+ }
9296+
9297+ decl->getAttrs ().add (
9298+ new (SwiftContext) SynthesizedProtocolAttr (protocol, this , false ));
9299+ } else {
9300+ HeaderLoc attrLoc ((conformsToAttr)->getLocation ());
9301+ diagnose (attrLoc, diag::conforms_to_not_protocol, result,
9302+ conformsToValue);
9303+ }
9304+ }
9305+
9306+ void ClangImporter::Implementation::addExplicitProtocolConformancesFromBases (
9307+ NominalTypeDecl *nominal,
9308+ const clang::CXXRecordDecl *cxxRecordDecl,
9309+ bool isBase) {
9310+ if (cxxRecordDecl->isCompleteDefinition ()) {
9311+ // Propagate conforms_to attribute from public base classes.
9312+ for (auto base : cxxRecordDecl->bases ()) {
9313+ if (base.getAccessSpecifier () != clang::AccessSpecifier::AS_public)
9314+ continue ;
9315+ if (auto *baseClangDecl = base.getType ()->getAsCXXRecordDecl ())
9316+ addExplicitProtocolConformancesFromBases (nominal, baseClangDecl,
9317+ /* isBase=*/ true );
9318+ }
9319+ }
9320+
9321+ if (isBase && cxxRecordDecl->hasAttrs ()) {
9322+ llvm::SmallSet<ProtocolDecl *, 4 > alreadyAdded;
9323+ llvm::for_each (cxxRecordDecl->getAttrs (), [&](auto *attr) {
9324+ if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(attr)) {
9325+ if (swiftAttr->getAttribute ().starts_with (" conforms_to:" ))
9326+ addExplicitProtocolConformance (nominal, swiftAttr, alreadyAdded);
9327+ }
9328+ });
9329+ }
9330+ }
9331+
9332+ void ClangImporter::Implementation::addOptionSetTypealiases (
9333+ NominalTypeDecl *nominal) {
9334+ auto selfType = nominal->getDeclaredInterfaceType ();
9335+ addSynthesizedTypealias (nominal, SwiftContext.Id_Element , selfType);
9336+ addSynthesizedTypealias (nominal, SwiftContext.Id_ArrayLiteralElement ,
9337+ selfType);
9338+ }
9339+
93059340void ClangImporter::Implementation::swiftify (AbstractFunctionDecl *MappedDecl) {
93069341 if (!SwiftContext.LangOpts .hasFeature (Feature::SafeInteropWrappers))
93079342 return ;
0 commit comments