@@ -3132,82 +3132,9 @@ namespace {
3132
3132
}
3133
3133
}
3134
3134
3135
- if (auto *ntd = dyn_cast<NominalTypeDecl>(result))
3136
- addExplicitProtocolConformances (ntd, decl);
3137
-
3138
3135
return result;
3139
3136
}
3140
3137
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
-
3211
3138
bool isSpecializationDepthGreaterThan (
3212
3139
const clang::ClassTemplateSpecializationDecl *decl, unsigned maxDepth) {
3213
3140
for (auto arg : decl->getTemplateArgs ().asArray ()) {
@@ -6507,6 +6434,20 @@ static bool conformsToProtocolInOriginalModule(NominalTypeDecl *nominal,
6507
6434
return false ;
6508
6435
}
6509
6436
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
+
6510
6451
Decl *
6511
6452
SwiftDeclConverter::importSwiftNewtype (const clang::TypedefNameDecl *decl,
6512
6453
clang::SwiftNewTypeAttr *newtypeAttr,
@@ -6581,6 +6522,11 @@ SwiftDeclConverter::importSwiftNewtype(const clang::TypedefNameDecl *decl,
6581
6522
addKnown (KnownProtocolKind::RawRepresentable);
6582
6523
addKnown (KnownProtocolKind::SwiftNewtypeWrapper);
6583
6524
6525
+ // If this type was also imported as an OptionSet, include those typealiases.
6526
+ if (isImportedOptionSet (structDecl)) {
6527
+ Impl.addOptionSetTypealiases (structDecl);
6528
+ }
6529
+
6584
6530
// Local function to add a known protocol only when the
6585
6531
// underlying type conforms to it.
6586
6532
auto computedNominal = computedPropertyUnderlyingType->getAnyNominal ();
@@ -6835,8 +6781,6 @@ Decl *SwiftDeclConverter::importEnumCaseAlias(
6835
6781
NominalTypeDecl *
6836
6782
SwiftDeclConverter::importAsOptionSetType (DeclContext *dc, Identifier name,
6837
6783
const clang::EnumDecl *decl) {
6838
- ASTContext &ctx = Impl.SwiftContext ;
6839
-
6840
6784
auto Loc = Impl.importSourceLoc (decl->getLocation ());
6841
6785
6842
6786
// Create a struct with the underlying type as a field.
@@ -6855,10 +6799,7 @@ SwiftDeclConverter::importAsOptionSetType(DeclContext *dc, Identifier name,
6855
6799
6856
6800
synthesizer.makeStructRawValued (structDecl, underlyingType,
6857
6801
{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);
6862
6803
return structDecl;
6863
6804
}
6864
6805
@@ -8756,6 +8697,7 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
8756
8697
8757
8698
std::optional<const clang::SwiftAttrAttr *> seenMainActorAttr;
8758
8699
const clang::SwiftAttrAttr *seenMutabilityAttr = nullptr ;
8700
+ llvm::SmallSet<ProtocolDecl *, 4 > conformancesSeen;
8759
8701
8760
8702
auto importAttrsFromDecl = [&](const clang::NamedDecl *ClangDecl) {
8761
8703
//
@@ -8871,6 +8813,11 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
8871
8813
continue ;
8872
8814
}
8873
8815
8816
+ if (swiftAttr->getAttribute ().starts_with (" conforms_to:" )) {
8817
+ if (auto nominal = dyn_cast<NominalTypeDecl>(MappedDecl))
8818
+ addExplicitProtocolConformance (nominal, swiftAttr, conformancesSeen);
8819
+ }
8820
+
8874
8821
importNontrivialAttribute (MappedDecl, swiftAttr->getAttribute ());
8875
8822
}
8876
8823
@@ -8933,6 +8880,14 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
8933
8880
}
8934
8881
}
8935
8882
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
+
8936
8891
// Now that we've collected all @Sendable and @_nonSendable attributes, we
8937
8892
// can see if we should synthesize a Sendable conformance.
8938
8893
if (auto nominal = dyn_cast<NominalTypeDecl>(MappedDecl)) {
@@ -9200,6 +9155,100 @@ static bool SwiftifiableCAT(const clang::ASTContext &ctx,
9200
9155
: SwiftifiableCountedByPointerType (swiftType));
9201
9156
}
9202
9157
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
+
9203
9252
void ClangImporter::Implementation::swiftify (AbstractFunctionDecl *MappedDecl) {
9204
9253
if (!SwiftContext.LangOpts .hasFeature (Feature::SafeInteropWrappers))
9205
9254
return ;
0 commit comments