74
74
75
75
#include " llvm/ADT/STLExtras.h"
76
76
#include " llvm/ADT/SmallBitVector.h"
77
+ #include " llvm/ADT/SmallSet.h"
77
78
#include " llvm/ADT/SmallString.h"
78
79
#include " llvm/ADT/Statistic.h"
79
80
#include " llvm/ADT/StringExtras.h"
@@ -168,10 +169,6 @@ void ClangImporter::Implementation::makeComputed(AbstractStorageDecl *storage,
168
169
bool importer::recordHasReferenceSemantics (
169
170
const clang::RecordDecl *decl,
170
171
ClangImporter::Implementation *importerImpl) {
171
- if (!isa<clang::CXXRecordDecl>(decl) &&
172
- !importerImpl->SwiftContext .LangOpts .CForeignReferenceTypes )
173
- return false ;
174
-
175
172
// At this point decl might not be fully imported into Swift yet, which
176
173
// means we might not have asked Clang to generate its implicit members, such
177
174
// as copy or move constructors. This would cause CxxRecordSemanticsRequest to
@@ -2670,6 +2667,9 @@ namespace {
2670
2667
}
2671
2668
}
2672
2669
2670
+ // If we need it, add an explicit "deinit" to this type.
2671
+ synthesizer.addExplicitDeinitIfRequired (result, decl);
2672
+
2673
2673
result->setMemberLoader (&Impl, 0 );
2674
2674
return result;
2675
2675
}
@@ -3136,12 +3136,11 @@ namespace {
3136
3136
}
3137
3137
}
3138
3138
3139
- if (auto *ntd = dyn_cast<NominalTypeDecl>(result))
3140
- addExplicitProtocolConformances (ntd, decl);
3141
-
3142
3139
return result;
3143
3140
}
3144
3141
3142
+ using ProtocolSet = llvm::SmallSet<ProtocolDecl *, 4 >;
3143
+
3145
3144
void
3146
3145
addExplicitProtocolConformances (NominalTypeDecl *decl,
3147
3146
const clang::CXXRecordDecl *clangDecl) {
@@ -3156,59 +3155,71 @@ namespace {
3156
3155
if (!clangDecl->hasAttrs ())
3157
3156
return ;
3158
3157
3159
- SmallVector<ValueDecl *, 1 > results;
3160
- auto conformsToAttr =
3161
- llvm::find_if (clangDecl->getAttrs (), [](auto *attr) {
3162
- if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(attr))
3163
- return swiftAttr->getAttribute ().starts_with (" conforms_to:" );
3164
- return false ;
3165
- });
3166
- if (conformsToAttr == clangDecl->getAttrs ().end ())
3167
- return ;
3158
+ ProtocolSet alreadyAdded;
3159
+ llvm::for_each (clangDecl->getAttrs (), [&](auto *attr) {
3160
+ if (auto swiftAttr = dyn_cast<clang::SwiftAttrAttr>(attr)) {
3161
+ if (swiftAttr->getAttribute ().starts_with (" conforms_to:" ))
3162
+ addExplicitProtocolConformance (decl, swiftAttr, alreadyAdded);
3163
+ }
3164
+ });
3165
+ }
3168
3166
3169
- auto conformsToValue = cast<clang::SwiftAttrAttr>(*conformsToAttr)
3170
- ->getAttribute ()
3167
+ void addExplicitProtocolConformance (NominalTypeDecl *decl,
3168
+ clang::SwiftAttrAttr *conformsToAttr,
3169
+ ProtocolSet &alreadyAdded) {
3170
+ auto conformsToValue = conformsToAttr->getAttribute ()
3171
3171
.drop_front (StringRef (" conforms_to:" ).size ())
3172
3172
.str ();
3173
3173
auto names = StringRef (conformsToValue).split (' .' );
3174
3174
auto moduleName = names.first ;
3175
3175
auto protocolName = names.second ;
3176
3176
if (protocolName.empty ()) {
3177
- HeaderLoc attrLoc ((* conformsToAttr) ->getLocation ());
3177
+ HeaderLoc attrLoc (conformsToAttr->getLocation ());
3178
3178
Impl.diagnose (attrLoc, diag::conforms_to_missing_dot, conformsToValue);
3179
3179
return ;
3180
3180
}
3181
3181
3182
3182
auto *mod = Impl.SwiftContext .getModuleByIdentifier (
3183
3183
Impl.SwiftContext .getIdentifier (moduleName));
3184
3184
if (!mod) {
3185
- HeaderLoc attrLoc ((* conformsToAttr) ->getLocation ());
3185
+ HeaderLoc attrLoc (conformsToAttr->getLocation ());
3186
3186
Impl.diagnose (attrLoc, diag::cannot_find_conforms_to_module,
3187
3187
conformsToValue, moduleName);
3188
3188
return ;
3189
3189
}
3190
+
3191
+ SmallVector<ValueDecl *, 1 > results;
3190
3192
mod->lookupValue (Impl.SwiftContext .getIdentifier (protocolName),
3191
3193
NLKind::UnqualifiedLookup, results);
3192
3194
if (results.empty ()) {
3193
- HeaderLoc attrLoc ((* conformsToAttr) ->getLocation ());
3195
+ HeaderLoc attrLoc (conformsToAttr->getLocation ());
3194
3196
Impl.diagnose (attrLoc, diag::cannot_find_conforms_to, protocolName,
3195
3197
moduleName);
3196
3198
return ;
3197
- } else if (results.size () != 1 ) {
3198
- HeaderLoc attrLoc ((*conformsToAttr)->getLocation ());
3199
+ }
3200
+
3201
+ if (results.size () != 1 ) {
3202
+ HeaderLoc attrLoc (conformsToAttr->getLocation ());
3199
3203
Impl.diagnose (attrLoc, diag::conforms_to_ambiguous, protocolName,
3200
3204
moduleName);
3201
3205
return ;
3202
3206
}
3203
3207
3204
3208
auto result = results.front ();
3205
3209
if (auto protocol = dyn_cast<ProtocolDecl>(result)) {
3210
+ auto [_, inserted] = alreadyAdded.insert (protocol);
3211
+ if (!inserted) {
3212
+ HeaderLoc attrLoc (conformsToAttr->getLocation ());
3213
+ Impl.diagnose (attrLoc, diag::redundant_conformance_protocol,
3214
+ decl->getDeclaredInterfaceType (), conformsToValue);
3215
+ }
3216
+
3206
3217
decl->getAttrs ().add (
3207
3218
new (Impl.SwiftContext ) SynthesizedProtocolAttr (protocol, &Impl, false ));
3208
3219
} else {
3209
- HeaderLoc attrLoc ((* conformsToAttr)->getLocation ());
3210
- Impl.diagnose (attrLoc, diag::conforms_to_not_protocol,
3211
- result-> getDescriptiveKind (), result, conformsToValue);
3220
+ HeaderLoc attrLoc ((conformsToAttr)->getLocation ());
3221
+ Impl.diagnose (attrLoc, diag::conforms_to_not_protocol, result,
3222
+ conformsToValue);
3212
3223
}
3213
3224
}
3214
3225
@@ -6511,6 +6522,20 @@ static bool conformsToProtocolInOriginalModule(NominalTypeDecl *nominal,
6511
6522
return false ;
6512
6523
}
6513
6524
6525
+ // / Determine whether the given nominal type was imported with an OptionSet
6526
+ // / conformance.
6527
+ static bool isImportedOptionSet (NominalTypeDecl *nominal) {
6528
+ for (auto attr : nominal->getAttrs ()) {
6529
+ if (auto synthesizedAttr = dyn_cast<SynthesizedProtocolAttr>(attr)) {
6530
+ if (synthesizedAttr->getProtocol ()->isSpecificProtocol (
6531
+ KnownProtocolKind::OptionSet))
6532
+ return true ;
6533
+ }
6534
+ }
6535
+
6536
+ return false ;
6537
+ }
6538
+
6514
6539
Decl *
6515
6540
SwiftDeclConverter::importSwiftNewtype (const clang::TypedefNameDecl *decl,
6516
6541
clang::SwiftNewTypeAttr *newtypeAttr,
@@ -6585,6 +6610,11 @@ SwiftDeclConverter::importSwiftNewtype(const clang::TypedefNameDecl *decl,
6585
6610
addKnown (KnownProtocolKind::RawRepresentable);
6586
6611
addKnown (KnownProtocolKind::SwiftNewtypeWrapper);
6587
6612
6613
+ // If this type was also imported as an OptionSet, include those typealiases.
6614
+ if (isImportedOptionSet (structDecl)) {
6615
+ Impl.addOptionSetTypealiases (structDecl);
6616
+ }
6617
+
6588
6618
// Local function to add a known protocol only when the
6589
6619
// underlying type conforms to it.
6590
6620
auto computedNominal = computedPropertyUnderlyingType->getAnyNominal ();
@@ -6839,8 +6869,6 @@ Decl *SwiftDeclConverter::importEnumCaseAlias(
6839
6869
NominalTypeDecl *
6840
6870
SwiftDeclConverter::importAsOptionSetType (DeclContext *dc, Identifier name,
6841
6871
const clang::EnumDecl *decl) {
6842
- ASTContext &ctx = Impl.SwiftContext ;
6843
-
6844
6872
auto Loc = Impl.importSourceLoc (decl->getLocation ());
6845
6873
6846
6874
// Create a struct with the underlying type as a field.
@@ -6859,10 +6887,7 @@ SwiftDeclConverter::importAsOptionSetType(DeclContext *dc, Identifier name,
6859
6887
6860
6888
synthesizer.makeStructRawValued (structDecl, underlyingType,
6861
6889
{KnownProtocolKind::OptionSet});
6862
- auto selfType = structDecl->getDeclaredInterfaceType ();
6863
- Impl.addSynthesizedTypealias (structDecl, ctx.Id_Element , selfType);
6864
- Impl.addSynthesizedTypealias (structDecl, ctx.Id_ArrayLiteralElement ,
6865
- selfType);
6890
+ Impl.addOptionSetTypealiases (structDecl);
6866
6891
return structDecl;
6867
6892
}
6868
6893
@@ -8760,6 +8785,7 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
8760
8785
8761
8786
std::optional<const clang::SwiftAttrAttr *> seenMainActorAttr;
8762
8787
const clang::SwiftAttrAttr *seenMutabilityAttr = nullptr ;
8788
+ llvm::SmallSet<ProtocolDecl *, 4 > conformancesSeen;
8763
8789
8764
8790
auto importAttrsFromDecl = [&](const clang::NamedDecl *ClangDecl) {
8765
8791
//
@@ -8875,6 +8901,11 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
8875
8901
continue ;
8876
8902
}
8877
8903
8904
+ if (swiftAttr->getAttribute ().starts_with (" conforms_to:" )) {
8905
+ if (auto nominal = dyn_cast<NominalTypeDecl>(MappedDecl))
8906
+ addExplicitProtocolConformance (nominal, swiftAttr, conformancesSeen);
8907
+ }
8908
+
8878
8909
importNontrivialAttribute (MappedDecl, swiftAttr->getAttribute ());
8879
8910
}
8880
8911
@@ -8937,6 +8968,14 @@ ClangImporter::Implementation::importSwiftAttrAttributes(Decl *MappedDecl) {
8937
8968
}
8938
8969
}
8939
8970
8971
+ // Import explicit conformances from C++ base classes.
8972
+ if (auto nominal = dyn_cast<NominalTypeDecl>(MappedDecl)) {
8973
+ if (auto cxxRecordDecl = dyn_cast<clang::CXXRecordDecl>(ClangDecl)) {
8974
+ addExplicitProtocolConformancesFromBases (
8975
+ nominal, cxxRecordDecl, /* isBase=*/ false );
8976
+ }
8977
+ }
8978
+
8940
8979
// Now that we've collected all @Sendable and @_nonSendable attributes, we
8941
8980
// can see if we should synthesize a Sendable conformance.
8942
8981
if (auto nominal = dyn_cast<NominalTypeDecl>(MappedDecl)) {
@@ -9204,6 +9243,100 @@ static bool SwiftifiableCAT(const clang::ASTContext &ctx,
9204
9243
: SwiftifiableCountedByPointerType (swiftType));
9205
9244
}
9206
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
+
9207
9340
void ClangImporter::Implementation::swiftify (AbstractFunctionDecl *MappedDecl) {
9208
9341
if (!SwiftContext.LangOpts .hasFeature (Feature::SafeInteropWrappers))
9209
9342
return ;
0 commit comments