@@ -3152,98 +3152,9 @@ namespace {
3152
3152
}
3153
3153
}
3154
3154
3155
- if (auto *ntd = dyn_cast<NominalTypeDecl>(result))
3156
- addExplicitProtocolConformances (ntd, decl);
3157
-
3158
3155
return result;
3159
3156
}
3160
3157
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
-
3247
3158
bool isSpecializationDepthGreaterThan (
3248
3159
const clang::ClassTemplateSpecializationDecl *decl, unsigned maxDepth) {
3249
3160
for (auto arg : decl->getTemplateArgs ().asArray ()) {
@@ -6608,6 +6519,20 @@ static bool conformsToProtocolInOriginalModule(NominalTypeDecl *nominal,
6608
6519
return false ;
6609
6520
}
6610
6521
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
+
6611
6536
Decl *
6612
6537
SwiftDeclConverter::importSwiftNewtype (const clang::TypedefNameDecl *decl,
6613
6538
clang::SwiftNewTypeAttr *newtypeAttr,
@@ -6682,6 +6607,11 @@ SwiftDeclConverter::importSwiftNewtype(const clang::TypedefNameDecl *decl,
6682
6607
addKnown (KnownProtocolKind::RawRepresentable);
6683
6608
addKnown (KnownProtocolKind::SwiftNewtypeWrapper);
6684
6609
6610
+ // If this type was also imported as an OptionSet, include those typealiases.
6611
+ if (isImportedOptionSet (structDecl)) {
6612
+ Impl.addOptionSetTypealiases (structDecl);
6613
+ }
6614
+
6685
6615
// Local function to add a known protocol only when the
6686
6616
// underlying type conforms to it.
6687
6617
auto computedNominal = computedPropertyUnderlyingType->getAnyNominal ();
@@ -6936,8 +6866,6 @@ Decl *SwiftDeclConverter::importEnumCaseAlias(
6936
6866
NominalTypeDecl *
6937
6867
SwiftDeclConverter::importAsOptionSetType (DeclContext *dc, Identifier name,
6938
6868
const clang::EnumDecl *decl) {
6939
- ASTContext &ctx = Impl.SwiftContext ;
6940
-
6941
6869
auto Loc = Impl.importSourceLoc (decl->getLocation ());
6942
6870
6943
6871
// Create a struct with the underlying type as a field.
@@ -6956,10 +6884,7 @@ SwiftDeclConverter::importAsOptionSetType(DeclContext *dc, Identifier name,
6956
6884
6957
6885
synthesizer.makeStructRawValued (structDecl, underlyingType,
6958
6886
{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);
6963
6888
return structDecl;
6964
6889
}
6965
6890
@@ -8857,6 +8782,7 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
8857
8782
8858
8783
std::optional<const clang::SwiftAttrAttr *> seenMainActorAttr;
8859
8784
const clang::SwiftAttrAttr *seenMutabilityAttr = nullptr ;
8785
+ llvm::SmallSet<ProtocolDecl *, 4 > conformancesSeen;
8860
8786
8861
8787
auto importAttrsFromDecl = [&](const clang::NamedDecl *ClangDecl) {
8862
8788
//
@@ -8972,6 +8898,11 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
8972
8898
continue ;
8973
8899
}
8974
8900
8901
+ if (swiftAttr->getAttribute ().starts_with (" conforms_to:" )) {
8902
+ if (auto nominal = dyn_cast<NominalTypeDecl>(MappedDecl))
8903
+ addExplicitProtocolConformance (nominal, swiftAttr, conformancesSeen);
8904
+ }
8905
+
8975
8906
importNontrivialAttribute (MappedDecl, swiftAttr->getAttribute ());
8976
8907
}
8977
8908
@@ -9034,6 +8965,14 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
9034
8965
}
9035
8966
}
9036
8967
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
+
9037
8976
// Now that we've collected all @Sendable and @_nonSendable attributes, we
9038
8977
// can see if we should synthesize a Sendable conformance.
9039
8978
if (auto nominal = dyn_cast<NominalTypeDecl>(MappedDecl)) {
@@ -9302,6 +9241,102 @@ struct UnaliasedInstantiationVisitor
9302
9241
};
9303
9242
} // namespace
9304
9243
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
+
9305
9340
void ClangImporter::Implementation::swiftify (AbstractFunctionDecl *MappedDecl) {
9306
9341
if (!SwiftContext.LangOpts .hasFeature (Feature::SafeInteropWrappers))
9307
9342
return ;
0 commit comments