@@ -3150,98 +3150,9 @@ namespace {
3150
3150
}
3151
3151
}
3152
3152
3153
- if (auto *ntd = dyn_cast<NominalTypeDecl>(result))
3154
- addExplicitProtocolConformances (ntd, decl);
3155
-
3156
3153
return result;
3157
3154
}
3158
3155
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
-
3245
3156
bool isSpecializationDepthGreaterThan (
3246
3157
const clang::ClassTemplateSpecializationDecl *decl, unsigned maxDepth) {
3247
3158
for (auto arg : decl->getTemplateArgs ().asArray ()) {
@@ -6633,6 +6544,20 @@ static bool conformsToProtocolInOriginalModule(NominalTypeDecl *nominal,
6633
6544
return false ;
6634
6545
}
6635
6546
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
+
6636
6561
Decl *
6637
6562
SwiftDeclConverter::importSwiftNewtype (const clang::TypedefNameDecl *decl,
6638
6563
clang::SwiftNewTypeAttr *newtypeAttr,
@@ -6707,6 +6632,11 @@ SwiftDeclConverter::importSwiftNewtype(const clang::TypedefNameDecl *decl,
6707
6632
addKnown (KnownProtocolKind::RawRepresentable);
6708
6633
addKnown (KnownProtocolKind::SwiftNewtypeWrapper);
6709
6634
6635
+ // If this type was also imported as an OptionSet, include those typealiases.
6636
+ if (isImportedOptionSet (structDecl)) {
6637
+ Impl.addOptionSetTypealiases (structDecl);
6638
+ }
6639
+
6710
6640
// Local function to add a known protocol only when the
6711
6641
// underlying type conforms to it.
6712
6642
auto computedNominal = computedPropertyUnderlyingType->getAnyNominal ();
@@ -6961,8 +6891,6 @@ Decl *SwiftDeclConverter::importEnumCaseAlias(
6961
6891
NominalTypeDecl *
6962
6892
SwiftDeclConverter::importAsOptionSetType (DeclContext *dc, Identifier name,
6963
6893
const clang::EnumDecl *decl) {
6964
- ASTContext &ctx = Impl.SwiftContext ;
6965
-
6966
6894
auto Loc = Impl.importSourceLoc (decl->getLocation ());
6967
6895
6968
6896
// Create a struct with the underlying type as a field.
@@ -6981,10 +6909,7 @@ SwiftDeclConverter::importAsOptionSetType(DeclContext *dc, Identifier name,
6981
6909
6982
6910
synthesizer.makeStructRawValued (structDecl, underlyingType,
6983
6911
{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);
6988
6913
return structDecl;
6989
6914
}
6990
6915
@@ -8882,6 +8807,7 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
8882
8807
8883
8808
std::optional<const clang::SwiftAttrAttr *> seenMainActorAttr;
8884
8809
const clang::SwiftAttrAttr *seenMutabilityAttr = nullptr ;
8810
+ llvm::SmallSet<ProtocolDecl *, 4 > conformancesSeen;
8885
8811
8886
8812
auto importAttrsFromDecl = [&](const clang::NamedDecl *ClangDecl) {
8887
8813
//
@@ -8997,6 +8923,11 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
8997
8923
continue ;
8998
8924
}
8999
8925
8926
+ if (swiftAttr->getAttribute ().starts_with (" conforms_to:" )) {
8927
+ if (auto nominal = dyn_cast<NominalTypeDecl>(MappedDecl))
8928
+ addExplicitProtocolConformance (nominal, swiftAttr, conformancesSeen);
8929
+ }
8930
+
9000
8931
importNontrivialAttribute (MappedDecl, swiftAttr->getAttribute ());
9001
8932
}
9002
8933
@@ -9059,6 +8990,14 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
9059
8990
}
9060
8991
}
9061
8992
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
+
9062
9001
// Now that we've collected all @Sendable and @_nonSendable attributes, we
9063
9002
// can see if we should synthesize a Sendable conformance.
9064
9003
if (auto nominal = dyn_cast<NominalTypeDecl>(MappedDecl)) {
@@ -9327,6 +9266,102 @@ struct UnaliasedInstantiationVisitor
9327
9266
};
9328
9267
} // namespace
9329
9268
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
+
9330
9365
void ClangImporter::Implementation::swiftify (AbstractFunctionDecl *MappedDecl) {
9331
9366
if (!SwiftContext.LangOpts .hasFeature (Feature::SafeInteropWrappers))
9332
9367
return ;
0 commit comments