Skip to content

Commit ae5d6fd

Browse files
committed
ClangImporter: Clean up inheritance clause synthesis
There was some duplicate code for adding protocols to inheritance clauses and constructing the SynthesizedProtocolAttrs that indicate a conformance should have a LazyConformanceLoader. Clean this up to make it less error-prone. NFC for now, until further changes land.
1 parent e26949d commit ae5d6fd

File tree

1 file changed

+37
-62
lines changed

1 file changed

+37
-62
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 37 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1212,34 +1212,31 @@ createValueConstructor(ClangImporter::Implementation &Impl,
12121212
return constructor;
12131213
}
12141214

1215-
static void populateInheritedTypes(NominalTypeDecl *nominal,
1216-
ArrayRef<ProtocolDecl *> protocols,
1217-
Type superclass = Type()) {
1215+
/// Add protocol conformances and synthesized protocol attributes
1216+
static void
1217+
populateInheritedTypes(ClangImporter::Implementation &Impl,
1218+
NominalTypeDecl *nominal,
1219+
ArrayRef<KnownProtocolKind> synthesizedProtocolAttrs,
1220+
Type superclass = Type()) {
12181221
SmallVector<TypeLoc, 4> inheritedTypes;
12191222
if (superclass)
12201223
inheritedTypes.push_back(TypeLoc::withoutLoc(superclass));
1221-
inheritedTypes.resize(protocols.size() + (superclass ? 1 : 0));
1222-
for_each(MutableArrayRef<TypeLoc>(inheritedTypes).drop_front(superclass?1:0),
1223-
protocols,
1224-
[](TypeLoc &tl, ProtocolDecl *proto) {
1225-
tl = TypeLoc::withoutLoc(proto->getDeclaredType());
1226-
});
1224+
1225+
for (auto protoKind : synthesizedProtocolAttrs) {
1226+
if (auto *protoDecl = Impl.SwiftContext.getProtocol(protoKind)) {
1227+
auto protoType = protoDecl->getDeclaredType();
1228+
inheritedTypes.push_back(TypeLoc::withoutLoc(protoType));
1229+
}
1230+
}
1231+
12271232
nominal->setInherited(nominal->getASTContext().AllocateCopy(inheritedTypes));
12281233
nominal->setCheckedInheritanceClause();
1229-
}
1230-
1231-
/// Add protocol conformances and synthesized protocol attributes
1232-
static void
1233-
addProtocolsToStruct(ClangImporter::Implementation &Impl,
1234-
StructDecl *structDecl,
1235-
ArrayRef<KnownProtocolKind> synthesizedProtocolAttrs,
1236-
ArrayRef<ProtocolDecl *> protocols) {
1237-
populateInheritedTypes(structDecl, protocols);
12381234

12391235
// Note synthesized protocols
1240-
for (auto kind : synthesizedProtocolAttrs)
1241-
structDecl->getAttrs().add(new (Impl.SwiftContext)
1242-
SynthesizedProtocolAttr(kind, &Impl));
1236+
for (auto kind : synthesizedProtocolAttrs) {
1237+
nominal->getAttrs().add(new (Impl.SwiftContext)
1238+
SynthesizedProtocolAttr(kind, &Impl));
1239+
}
12431240
}
12441241

12451242
/// Add a synthesized typealias to the given nominal type.
@@ -1264,7 +1261,6 @@ static void addSynthesizedTypealias(NominalTypeDecl *nominal, Identifier name,
12641261
/// \param structDecl the struct to make a raw value for
12651262
/// \param underlyingType the type of the raw value
12661263
/// \param synthesizedProtocolAttrs synthesized protocol attributes to add
1267-
/// \param protocols the protocols to make this struct conform to
12681264
/// \param setterAccess the access level of the raw value's setter
12691265
///
12701266
/// This will perform most of the work involved in making a new Swift struct
@@ -1275,11 +1271,11 @@ static void addSynthesizedTypealias(NominalTypeDecl *nominal, Identifier name,
12751271
static void makeStructRawValued(
12761272
ClangImporter::Implementation &Impl, StructDecl *structDecl,
12771273
Type underlyingType, ArrayRef<KnownProtocolKind> synthesizedProtocolAttrs,
1278-
ArrayRef<ProtocolDecl *> protocols,
12791274
MakeStructRawValuedOptions options = getDefaultMakeStructRawValuedOptions(),
12801275
AccessLevel setterAccess = AccessLevel::Private) {
12811276
auto &ctx = Impl.SwiftContext;
1282-
addProtocolsToStruct(Impl, structDecl, synthesizedProtocolAttrs, protocols);
1277+
1278+
populateInheritedTypes(Impl, structDecl, synthesizedProtocolAttrs);
12831279

12841280
// Create a variable to store the underlying value.
12851281
VarDecl *var;
@@ -1356,7 +1352,6 @@ static ConstructorDecl *createRawValueBridgingConstructor(
13561352
/// \param storedUnderlyingType the type of the stored raw value
13571353
/// \param bridgedType the type of the 'rawValue' computed property bridge
13581354
/// \param synthesizedProtocolAttrs synthesized protocol attributes to add
1359-
/// \param protocols the protocols to make this struct conform to
13601355
///
13611356
/// This will perform most of the work involved in making a new Swift struct
13621357
/// be backed by a stored raw value and computed raw value of bridged type.
@@ -1368,9 +1363,10 @@ static void makeStructRawValuedWithBridge(
13681363
ClangImporter::Implementation &Impl, StructDecl *structDecl,
13691364
Type storedUnderlyingType, Type bridgedType,
13701365
ArrayRef<KnownProtocolKind> synthesizedProtocolAttrs,
1371-
ArrayRef<ProtocolDecl *> protocols, bool makeUnlabeledValueInit = false) {
1366+
bool makeUnlabeledValueInit = false) {
13721367
auto &ctx = Impl.SwiftContext;
1373-
addProtocolsToStruct(Impl, structDecl, synthesizedProtocolAttrs, protocols);
1368+
1369+
populateInheritedTypes(Impl, structDecl, synthesizedProtocolAttrs);
13741370

13751371
auto storedVarName = ctx.getIdentifier("_rawValue");
13761372
auto computedVarName = ctx.Id_rawValue;
@@ -2411,7 +2407,6 @@ namespace {
24112407
if (!dc)
24122408
return nullptr;
24132409

2414-
ASTContext &ctx = Impl.SwiftContext;
24152410
auto name = importedName.getDeclName().getBaseIdentifier();
24162411

24172412
// Create the enum declaration and record it.
@@ -2440,19 +2435,14 @@ namespace {
24402435
AccessLevel::Public, Loc, name, Loc, None, nullptr, dc);
24412436
structDecl->computeType();
24422437

2443-
ProtocolDecl *protocols[]
2444-
= {ctx.getProtocol(KnownProtocolKind::RawRepresentable),
2445-
ctx.getProtocol(KnownProtocolKind::Equatable)};
2446-
if (!protocols[0] || !protocols[1])
2447-
return nullptr;
2448-
24492438
auto options = getDefaultMakeStructRawValuedOptions();
24502439
options |= MakeStructRawValuedFlags::MakeUnlabeledValueInit;
24512440
options -= MakeStructRawValuedFlags::IsLet;
24522441
options -= MakeStructRawValuedFlags::IsImplicit;
24532442

24542443
makeStructRawValued(Impl, structDecl, underlyingType,
2455-
{KnownProtocolKind::RawRepresentable}, protocols,
2444+
{KnownProtocolKind::RawRepresentable,
2445+
KnownProtocolKind::Equatable},
24562446
options, /*setterAccess=*/AccessLevel::Public);
24572447

24582448
result = structDecl;
@@ -2495,15 +2485,8 @@ namespace {
24952485
errorWrapper->setAccess(AccessLevel::Public);
24962486

24972487
// Add inheritance clause.
2498-
TypeLoc inheritedTypes[1] = {
2499-
TypeLoc::withoutLoc(bridgedNSError->getDeclaredType())
2500-
};
2501-
errorWrapper->setInherited(C.AllocateCopy(inheritedTypes));
2502-
errorWrapper->setCheckedInheritanceClause();
2503-
2504-
// Set up error conformance to be lazily expanded
2505-
errorWrapper->getAttrs().add(new (C) SynthesizedProtocolAttr(
2506-
KnownProtocolKind::BridgedStoredNSError, &Impl));
2488+
populateInheritedTypes(Impl, errorWrapper,
2489+
{KnownProtocolKind::BridgedStoredNSError});
25072490

25082491
// Create the _nsError member.
25092492
// public let _nsError: NSError
@@ -2565,6 +2548,10 @@ namespace {
25652548
if (errorWrapper) {
25662549
inheritedTypes.push_back(
25672550
TypeLoc::withoutLoc(errorCodeProto->getDeclaredType()));
2551+
2552+
enumDecl->getAttrs().add(new (Impl.SwiftContext)
2553+
SynthesizedProtocolAttr(KnownProtocolKind::ErrorCodeProtocol,
2554+
&Impl));
25682555
}
25692556
enumDecl->setInherited(C.AllocateCopy(inheritedTypes));
25702557
enumDecl->setCheckedInheritanceClause();
@@ -4806,14 +4793,8 @@ SwiftDeclConverter::importCFClassType(const clang::TypedefNameDecl *decl,
48064793
addObjCAttribute(theClass, None);
48074794
Impl.registerExternalDecl(theClass);
48084795

4809-
auto *cfObjectProto =
4810-
Impl.SwiftContext.getProtocol(KnownProtocolKind::CFObject);
4811-
if (cfObjectProto) {
4812-
populateInheritedTypes(theClass, cfObjectProto, superclass);
4813-
auto *attr = new (Impl.SwiftContext) SynthesizedProtocolAttr(
4814-
KnownProtocolKind::CFObject, &Impl);
4815-
theClass->getAttrs().add(attr);
4816-
}
4796+
populateInheritedTypes(Impl, theClass, {KnownProtocolKind::CFObject},
4797+
superclass);
48174798

48184799
// Look for bridging attributes on the clang record. We can
48194800
// just check the most recent redeclaration, which will inherit
@@ -5001,15 +4982,11 @@ SwiftDeclConverter::importSwiftNewtype(const clang::TypedefNameDecl *decl,
50014982

50024983
// Determine the set of protocols to which the synthesized
50034984
// type will conform.
5004-
SmallVector<ProtocolDecl *, 4> protocols;
50054985
SmallVector<KnownProtocolKind, 4> synthesizedProtocols;
50064986

50074987
// Local function to add a known protocol.
50084988
auto addKnown = [&](KnownProtocolKind kind) {
5009-
if (auto proto = ctx.getProtocol(kind)) {
5010-
protocols.push_back(proto);
5011-
synthesizedProtocols.push_back(kind);
5012-
}
4989+
synthesizedProtocols.push_back(kind);
50134990
};
50144991

50154992
// Add conformances that are always available.
@@ -5032,7 +5009,6 @@ SwiftDeclConverter::importSwiftNewtype(const clang::TypedefNameDecl *decl,
50325009
if (conformsToProtocolInOriginalModule(computedNominal, proto,
50335010
Impl.tryLoadFoundationModule(),
50345011
Impl.getTypeResolver())) {
5035-
protocols.push_back(proto);
50365012
synthesizedProtocols.push_back(kind);
50375013
return true;
50385014
}
@@ -5055,13 +5031,13 @@ SwiftDeclConverter::importSwiftNewtype(const clang::TypedefNameDecl *decl,
50555031
options |= MakeStructRawValuedFlags::MakeUnlabeledValueInit;
50565032

50575033
makeStructRawValued(Impl, structDecl, storedUnderlyingType,
5058-
synthesizedProtocols, protocols, options);
5034+
synthesizedProtocols, options);
50595035
} else {
50605036
// We need to make a stored rawValue or storage type, and a
50615037
// computed one of bridged type.
50625038
makeStructRawValuedWithBridge(Impl, structDecl, storedUnderlyingType,
50635039
computedPropertyUnderlyingType,
5064-
synthesizedProtocols, protocols,
5040+
synthesizedProtocols,
50655041
/*makeUnlabeledValueInit=*/unlabeledCtor);
50665042

50675043
if (transferredObjCBridgeable)
@@ -5220,9 +5196,8 @@ SwiftDeclConverter::importAsOptionSetType(DeclContext *dc, Identifier name,
52205196
decl, AccessLevel::Public, Loc, name, Loc, None, nullptr, dc);
52215197
structDecl->computeType();
52225198

5223-
ProtocolDecl *protocols[] = {ctx.getProtocol(KnownProtocolKind::OptionSet)};
52245199
makeStructRawValued(Impl, structDecl, underlyingType,
5225-
{KnownProtocolKind::OptionSet}, protocols);
5200+
{KnownProtocolKind::OptionSet});
52265201
auto selfType = structDecl->getDeclaredInterfaceType();
52275202
addSynthesizedTypealias(structDecl, ctx.Id_Element, selfType);
52285203
addSynthesizedTypealias(structDecl, ctx.Id_ArrayLiteralElement, selfType);

0 commit comments

Comments
 (0)