@@ -3150,98 +3150,9 @@ namespace {
31503150 }
31513151 }
31523152
3153- if (auto *ntd = dyn_cast<NominalTypeDecl>(result))
3154- addExplicitProtocolConformances (ntd, decl);
3155-
31563153 return result;
31573154 }
31583155
3159- using ProtocolSet = llvm::SmallSet<ProtocolDecl *, 4 >;
3160-
3161- void
3162- addExplicitProtocolConformances (NominalTypeDecl *decl,
3163- const clang::CXXRecordDecl *clangDecl) {
3164- if (clangDecl->isCompleteDefinition ()) {
3165- // Propagate conforms_to attribute from public base classes.
3166- for (auto base : clangDecl->bases ()) {
3167- if (base.getAccessSpecifier () != clang::AccessSpecifier::AS_public)
3168- continue ;
3169- if (auto *baseClangDecl = base.getType ()->getAsCXXRecordDecl ())
3170- addExplicitProtocolConformances (decl, baseClangDecl);
3171- }
3172- }
3173-
3174- if (!clangDecl->hasAttrs ())
3175- return ;
3176-
3177- ProtocolSet alreadyAdded;
3178- llvm::for_each (clangDecl->getAttrs (), [&](auto *attr) {
3179- if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(attr)) {
3180- if (swiftAttr->getAttribute ().starts_with (" conforms_to:" ))
3181- addExplicitProtocolConformance (decl, swiftAttr, alreadyAdded);
3182- }
3183- });
3184- }
3185-
3186- void addExplicitProtocolConformance (NominalTypeDecl *decl,
3187- clang::SwiftAttrAttr *conformsToAttr,
3188- ProtocolSet &alreadyAdded) {
3189- auto conformsToValue = conformsToAttr->getAttribute ()
3190- .drop_front (StringRef (" conforms_to:" ).size ())
3191- .str ();
3192- auto names = StringRef (conformsToValue).split (' .' );
3193- auto moduleName = names.first ;
3194- auto protocolName = names.second ;
3195- if (protocolName.empty ()) {
3196- HeaderLoc attrLoc (conformsToAttr->getLocation ());
3197- Impl.diagnose (attrLoc, diag::conforms_to_missing_dot, conformsToValue);
3198- return ;
3199- }
3200-
3201- auto *mod = Impl.SwiftContext .getModuleByIdentifier (
3202- Impl.SwiftContext .getIdentifier (moduleName));
3203- if (!mod) {
3204- HeaderLoc attrLoc (conformsToAttr->getLocation ());
3205- Impl.diagnose (attrLoc, diag::cannot_find_conforms_to_module,
3206- conformsToValue, moduleName);
3207- return ;
3208- }
3209-
3210- SmallVector<ValueDecl *, 1 > results;
3211- mod->lookupValue (Impl.SwiftContext .getIdentifier (protocolName),
3212- NLKind::UnqualifiedLookup, results);
3213- if (results.empty ()) {
3214- HeaderLoc attrLoc (conformsToAttr->getLocation ());
3215- Impl.diagnose (attrLoc, diag::cannot_find_conforms_to, protocolName,
3216- moduleName);
3217- return ;
3218- }
3219-
3220- if (results.size () != 1 ) {
3221- HeaderLoc attrLoc (conformsToAttr->getLocation ());
3222- Impl.diagnose (attrLoc, diag::conforms_to_ambiguous, protocolName,
3223- moduleName);
3224- return ;
3225- }
3226-
3227- auto result = results.front ();
3228- if (auto protocol = dyn_cast<ProtocolDecl>(result)) {
3229- auto [_, inserted] = alreadyAdded.insert (protocol);
3230- if (!inserted) {
3231- HeaderLoc attrLoc (conformsToAttr->getLocation ());
3232- Impl.diagnose (attrLoc, diag::redundant_conformance_protocol,
3233- decl->getDeclaredInterfaceType (), conformsToValue);
3234- }
3235-
3236- decl->getAttrs ().add (
3237- new (Impl.SwiftContext ) SynthesizedProtocolAttr (protocol, &Impl, false ));
3238- } else {
3239- HeaderLoc attrLoc ((conformsToAttr)->getLocation ());
3240- Impl.diagnose (attrLoc, diag::conforms_to_not_protocol, result,
3241- conformsToValue);
3242- }
3243- }
3244-
32453156 bool isSpecializationDepthGreaterThan (
32463157 const clang::ClassTemplateSpecializationDecl *decl, unsigned maxDepth) {
32473158 for (auto arg : decl->getTemplateArgs ().asArray ()) {
@@ -6633,6 +6544,20 @@ static bool conformsToProtocolInOriginalModule(NominalTypeDecl *nominal,
66336544 return false ;
66346545}
66356546
6547+ // / Determine whether the given nominal type was imported with an OptionSet
6548+ // / conformance.
6549+ static bool isImportedOptionSet (NominalTypeDecl *nominal) {
6550+ for (auto attr : nominal->getAttrs ()) {
6551+ if (auto synthesizedAttr = dyn_cast<SynthesizedProtocolAttr>(attr)) {
6552+ if (synthesizedAttr->getProtocol ()->isSpecificProtocol (
6553+ KnownProtocolKind::OptionSet))
6554+ return true ;
6555+ }
6556+ }
6557+
6558+ return false ;
6559+ }
6560+
66366561Decl *
66376562SwiftDeclConverter::importSwiftNewtype (const clang::TypedefNameDecl *decl,
66386563 clang::SwiftNewTypeAttr *newtypeAttr,
@@ -6707,6 +6632,11 @@ SwiftDeclConverter::importSwiftNewtype(const clang::TypedefNameDecl *decl,
67076632 addKnown (KnownProtocolKind::RawRepresentable);
67086633 addKnown (KnownProtocolKind::SwiftNewtypeWrapper);
67096634
6635+ // If this type was also imported as an OptionSet, include those typealiases.
6636+ if (isImportedOptionSet (structDecl)) {
6637+ Impl.addOptionSetTypealiases (structDecl);
6638+ }
6639+
67106640 // Local function to add a known protocol only when the
67116641 // underlying type conforms to it.
67126642 auto computedNominal = computedPropertyUnderlyingType->getAnyNominal ();
@@ -6961,8 +6891,6 @@ Decl *SwiftDeclConverter::importEnumCaseAlias(
69616891NominalTypeDecl *
69626892SwiftDeclConverter::importAsOptionSetType (DeclContext *dc, Identifier name,
69636893 const clang::EnumDecl *decl) {
6964- ASTContext &ctx = Impl.SwiftContext ;
6965-
69666894 auto Loc = Impl.importSourceLoc (decl->getLocation ());
69676895
69686896 // Create a struct with the underlying type as a field.
@@ -6981,10 +6909,7 @@ SwiftDeclConverter::importAsOptionSetType(DeclContext *dc, Identifier name,
69816909
69826910 synthesizer.makeStructRawValued (structDecl, underlyingType,
69836911 {KnownProtocolKind::OptionSet});
6984- auto selfType = structDecl->getDeclaredInterfaceType ();
6985- Impl.addSynthesizedTypealias (structDecl, ctx.Id_Element , selfType);
6986- Impl.addSynthesizedTypealias (structDecl, ctx.Id_ArrayLiteralElement ,
6987- selfType);
6912+ Impl.addOptionSetTypealiases (structDecl);
69886913 return structDecl;
69896914}
69906915
@@ -8882,6 +8807,7 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
88828807
88838808 std::optional<const clang::SwiftAttrAttr *> seenMainActorAttr;
88848809 const clang::SwiftAttrAttr *seenMutabilityAttr = nullptr ;
8810+ llvm::SmallSet<ProtocolDecl *, 4 > conformancesSeen;
88858811
88868812 auto importAttrsFromDecl = [&](const clang::NamedDecl *ClangDecl) {
88878813 //
@@ -8997,6 +8923,11 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
89978923 continue ;
89988924 }
89998925
8926+ if (swiftAttr->getAttribute ().starts_with (" conforms_to:" )) {
8927+ if (auto nominal = dyn_cast<NominalTypeDecl>(MappedDecl))
8928+ addExplicitProtocolConformance (nominal, swiftAttr, conformancesSeen);
8929+ }
8930+
90008931 importNontrivialAttribute (MappedDecl, swiftAttr->getAttribute ());
90018932 }
90028933
@@ -9059,6 +8990,14 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
90598990 }
90608991 }
90618992
8993+ // Import explicit conformances from C++ base classes.
8994+ if (auto nominal = dyn_cast<NominalTypeDecl>(MappedDecl)) {
8995+ if (auto cxxRecordDecl = dyn_cast<clang::CXXRecordDecl>(ClangDecl)) {
8996+ addExplicitProtocolConformancesFromBases (
8997+ nominal, cxxRecordDecl, /* isBase=*/ false );
8998+ }
8999+ }
9000+
90629001 // Now that we've collected all @Sendable and @_nonSendable attributes, we
90639002 // can see if we should synthesize a Sendable conformance.
90649003 if (auto nominal = dyn_cast<NominalTypeDecl>(MappedDecl)) {
@@ -9327,6 +9266,102 @@ struct UnaliasedInstantiationVisitor
93279266};
93289267} // namespace
93299268
9269+
9270+
9271+ void ClangImporter::Implementation::addExplicitProtocolConformance (
9272+ NominalTypeDecl *decl,
9273+ clang::SwiftAttrAttr *conformsToAttr,
9274+ llvm::SmallSet<ProtocolDecl *, 4 > &alreadyAdded) {
9275+ auto conformsToValue = conformsToAttr->getAttribute ()
9276+ .drop_front (StringRef (" conforms_to:" ).size ())
9277+ .str ();
9278+ auto names = StringRef (conformsToValue).split (' .' );
9279+ auto moduleName = names.first ;
9280+ auto protocolName = names.second ;
9281+ if (protocolName.empty ()) {
9282+ HeaderLoc attrLoc (conformsToAttr->getLocation ());
9283+ diagnose (attrLoc, diag::conforms_to_missing_dot, conformsToValue);
9284+ return ;
9285+ }
9286+
9287+ auto *mod = SwiftContext.getModuleByIdentifier (
9288+ SwiftContext.getIdentifier (moduleName));
9289+ if (!mod) {
9290+ HeaderLoc attrLoc (conformsToAttr->getLocation ());
9291+ diagnose (attrLoc, diag::cannot_find_conforms_to_module,
9292+ conformsToValue, moduleName);
9293+ return ;
9294+ }
9295+
9296+ SmallVector<ValueDecl *, 1 > results;
9297+ mod->lookupValue (SwiftContext.getIdentifier (protocolName),
9298+ NLKind::UnqualifiedLookup, results);
9299+ if (results.empty ()) {
9300+ HeaderLoc attrLoc (conformsToAttr->getLocation ());
9301+ diagnose (attrLoc, diag::cannot_find_conforms_to, protocolName,
9302+ moduleName);
9303+ return ;
9304+ }
9305+
9306+ if (results.size () != 1 ) {
9307+ HeaderLoc attrLoc (conformsToAttr->getLocation ());
9308+ diagnose (attrLoc, diag::conforms_to_ambiguous, protocolName,
9309+ moduleName);
9310+ return ;
9311+ }
9312+
9313+ auto result = results.front ();
9314+ if (auto protocol = dyn_cast<ProtocolDecl>(result)) {
9315+ auto [_, inserted] = alreadyAdded.insert (protocol);
9316+ if (!inserted) {
9317+ HeaderLoc attrLoc (conformsToAttr->getLocation ());
9318+ diagnose (attrLoc, diag::redundant_conformance_protocol,
9319+ decl->getDeclaredInterfaceType (), conformsToValue);
9320+ }
9321+
9322+ decl->getAttrs ().add (
9323+ new (SwiftContext) SynthesizedProtocolAttr (protocol, this , false ));
9324+ } else {
9325+ HeaderLoc attrLoc ((conformsToAttr)->getLocation ());
9326+ diagnose (attrLoc, diag::conforms_to_not_protocol, result,
9327+ conformsToValue);
9328+ }
9329+ }
9330+
9331+ void ClangImporter::Implementation::addExplicitProtocolConformancesFromBases (
9332+ NominalTypeDecl *nominal,
9333+ const clang::CXXRecordDecl *cxxRecordDecl,
9334+ bool isBase) {
9335+ if (cxxRecordDecl->isCompleteDefinition ()) {
9336+ // Propagate conforms_to attribute from public base classes.
9337+ for (auto base : cxxRecordDecl->bases ()) {
9338+ if (base.getAccessSpecifier () != clang::AccessSpecifier::AS_public)
9339+ continue ;
9340+ if (auto *baseClangDecl = base.getType ()->getAsCXXRecordDecl ())
9341+ addExplicitProtocolConformancesFromBases (nominal, baseClangDecl,
9342+ /* isBase=*/ true );
9343+ }
9344+ }
9345+
9346+ if (isBase && cxxRecordDecl->hasAttrs ()) {
9347+ llvm::SmallSet<ProtocolDecl *, 4 > alreadyAdded;
9348+ llvm::for_each (cxxRecordDecl->getAttrs (), [&](auto *attr) {
9349+ if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(attr)) {
9350+ if (swiftAttr->getAttribute ().starts_with (" conforms_to:" ))
9351+ addExplicitProtocolConformance (nominal, swiftAttr, alreadyAdded);
9352+ }
9353+ });
9354+ }
9355+ }
9356+
9357+ void ClangImporter::Implementation::addOptionSetTypealiases (
9358+ NominalTypeDecl *nominal) {
9359+ auto selfType = nominal->getDeclaredInterfaceType ();
9360+ addSynthesizedTypealias (nominal, SwiftContext.Id_Element , selfType);
9361+ addSynthesizedTypealias (nominal, SwiftContext.Id_ArrayLiteralElement ,
9362+ selfType);
9363+ }
9364+
93309365void ClangImporter::Implementation::swiftify (AbstractFunctionDecl *MappedDecl) {
93319366 if (!SwiftContext.LangOpts .hasFeature (Feature::SafeInteropWrappers))
93329367 return ;
0 commit comments