Skip to content

Commit 97bf476

Browse files
committed
Initial support for @_objcImpl stored properties
No runtime tests yet.
1 parent 6f726fd commit 97bf476

File tree

10 files changed

+70
-15
lines changed

10 files changed

+70
-15
lines changed

include/swift/AST/DeclContext.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -507,6 +507,11 @@ class alignas(1 << DeclContextAlignInBits) DeclContext
507507
LLVM_READONLY
508508
DeclContext *getModuleScopeContext() const;
509509

510+
/// If this DeclContext is an \c \@_objcImplementation extension, returns the
511+
/// \c DeclContext for the Objective-C declaration it implements. Otherwise
512+
/// returns \c this.
513+
DeclContext *getImplementedObjCContext() const;
514+
510515
/// Returns the source file that contains this context, or null if this
511516
/// is not within a source file.
512517
LLVM_READONLY

lib/AST/DeclContext.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,13 @@ DeclContext *DeclContext::getModuleScopeContext() const {
303303
}
304304
}
305305

306+
DeclContext *DeclContext::getImplementedObjCContext() const {
307+
if (auto ED = dyn_cast<ExtensionDecl>(this))
308+
if (auto impl = dyn_cast_or_null<DeclContext>(ED->getImplementedObjCDecl()))
309+
return impl;
310+
return const_cast<DeclContext *>(this);
311+
}
312+
306313
void DeclContext::getSeparatelyImportedOverlays(
307314
ModuleDecl *declaring, SmallVectorImpl<ModuleDecl *> &overlays) const {
308315
if (auto SF = getParentSourceFile())

lib/IRGen/GenClass.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,8 @@ namespace {
223223
bool superclass) {
224224
if (theClass->hasClangNode() && !theClass->isForeignReferenceType()) {
225225
Options |= ClassMetadataFlags::ClassHasObjCAncestry;
226-
return;
226+
if (!theClass->getObjCImplementationDecl())
227+
return;
227228
}
228229

229230
if (theClass->isNativeNSObjectSubclass()) {

lib/IRGen/GenMeta.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3833,6 +3833,9 @@ namespace {
38333833
: super(IGM, theClass, builder, fieldLayout) {}
38343834

38353835
void addFieldOffset(VarDecl *var) {
3836+
if (FieldLayout.hasObjCImplementation())
3837+
return;
3838+
38363839
addFixedFieldOffset(IGM, B, var, [](DeclContext *dc) {
38373840
return dc->getDeclaredTypeInContext();
38383841
});
@@ -3869,12 +3872,18 @@ namespace {
38693872
: super(IGM, theClass, builder, fieldLayout) {}
38703873

38713874
void addFieldOffset(VarDecl *var) {
3875+
if (FieldLayout.hasObjCImplementation())
3876+
return;
3877+
38723878
// Field offsets are either copied from the superclass or calculated
38733879
// at runtime.
38743880
B.addInt(IGM.SizeTy, 0);
38753881
}
38763882

38773883
void addFieldOffsetPlaceholders(MissingMemberDecl *placeholder) {
3884+
if (FieldLayout.hasObjCImplementation())
3885+
return;
3886+
38783887
for (unsigned i = 0,
38793888
e = placeholder->getNumberOfFieldOffsetVectorEntries();
38803889
i < e; ++i) {
@@ -4334,6 +4343,9 @@ namespace {
43344343
}
43354344

43364345
void addFieldOffset(VarDecl *var) {
4346+
if (FieldLayout.hasObjCImplementation())
4347+
return;
4348+
43374349
addFixedFieldOffset(IGM, B, var, [&](DeclContext *dc) {
43384350
return dc->mapTypeIntoContext(type);
43394351
});

lib/IRGen/Linking.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,8 @@ SILLinkage LinkEntity::getLinkage(ForDefinition_t forDefinition) const {
703703
auto linkage = getDeclLinkage(varDecl);
704704

705705
// Classes with resilient storage don't expose field offset symbols.
706-
if (cast<ClassDecl>(varDecl->getDeclContext())->isResilient()) {
706+
auto implContext = varDecl->getDeclContext()->getImplementedObjCContext();
707+
if (cast<ClassDecl>(implContext)->isResilient()) {
707708
assert(linkage != FormalLinkage::PublicNonUnique &&
708709
"Cannot have a resilient class with non-unique linkage");
709710

lib/IRGen/MetadataLayout.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,8 @@ ClassMetadataLayout::ClassMetadataLayout(IRGenModule &IGM, ClassDecl *decl)
366366
}
367367

368368
void addFieldOffset(VarDecl *field) {
369-
assert(IsInTargetFields == (field->getDeclContext() == Target));
369+
assert(IsInTargetFields ==
370+
(field->getDeclContext()->getImplementedObjCContext() == Target));
370371
if (IsInTargetFields) {
371372
++Layout.NumImmediateMembers;
372373
Layout.FieldOffsets.try_emplace(field, getNextOffset());
@@ -382,7 +383,7 @@ ClassMetadataLayout::ClassMetadataLayout(IRGenModule &IGM, ClassDecl *decl)
382383
}
383384

384385
void addFieldOffsetPlaceholders(MissingMemberDecl *placeholder) {
385-
if (placeholder->getDeclContext() == Target) {
386+
if (placeholder->getDeclContext()->getImplementedObjCContext() == Target) {
386387
Layout.NumImmediateMembers +=
387388
placeholder->getNumberOfFieldOffsetVectorEntries();
388389
}

lib/SIL/Verifier/SILVerifier.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3282,7 +3282,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
32823282
F.getResilienceExpansion()),
32833283
"cannot access storage of resilient class");
32843284

3285-
require(EI->getField()->getDeclContext() == cd,
3285+
require(EI->getField()->getDeclContext() ==
3286+
cd->getImplementationContext()->getAsGenericContext(),
32863287
"ref_element_addr field must be a member of the class");
32873288

32883289
if (EI->getModule().getStage() != SILStage::Lowered) {

lib/SILGen/SILGenType.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1230,6 +1230,10 @@ class SILGenExtension : public TypeMemberVisitor<SILGenExtension> {
12301230

12311231
/// Emit SIL functions for all the members of the extension.
12321232
void emitExtension(ExtensionDecl *e) {
1233+
// Arguably, we should divert to SILGenType::emitType() here if it's an
1234+
// @_objcImplementation extension, but we don't actually need to do any of
1235+
// the stuff that it currently does.
1236+
12331237
for (Decl *member : e->getABIMembers())
12341238
visit(member);
12351239

@@ -1305,6 +1309,17 @@ class SILGenExtension : public TypeMemberVisitor<SILGenExtension> {
13051309

13061310
void visitVarDecl(VarDecl *vd) {
13071311
if (vd->hasStorage()) {
1312+
if (!vd->isStatic()) {
1313+
// Is this a stored property of an @_objcImplementation extension?
1314+
auto ed = cast<ExtensionDecl>(vd->getDeclContext());
1315+
if (auto cd =
1316+
dyn_cast_or_null<ClassDecl>(ed->getImplementedObjCDecl())) {
1317+
// Act as though we declared it on the class.
1318+
SILGenType(SGM, cd).visitVarDecl(vd);
1319+
return;
1320+
}
1321+
}
1322+
13081323
bool hasDidSetOrWillSetDynamicReplacement =
13091324
vd->hasDidSetOrWillSetDynamicReplacement();
13101325
assert((vd->isStatic() || hasDidSetOrWillSetDynamicReplacement) &&

test/IRGen/Inputs/objc_implementation.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
@interface ImplClass: NSObject
44

5+
@property (assign) int implProperty;
6+
57
- (void)mainMethod:(int)param;
68

79
@end

0 commit comments

Comments
 (0)