Skip to content

Commit 4d2739a

Browse files
committed
Initial support for @_objcImpl stored properties
No runtime tests yet.
1 parent 7247782 commit 4d2739a

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/ClangImporter/ClangImporter.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5221,6 +5221,13 @@ Decl *Decl::getImplementedObjCDecl() const {
52215221
.interfaceDecl;
52225222
}
52235223

5224+
DeclContext *DeclContext::getImplementedObjCContext() const {
5225+
if (auto ED = dyn_cast<ExtensionDecl>(this))
5226+
if (auto impl = dyn_cast_or_null<DeclContext>(ED->getImplementedObjCDecl()))
5227+
return impl;
5228+
return const_cast<DeclContext *>(this);
5229+
}
5230+
52245231
Decl *Decl::getObjCImplementationDecl() const {
52255232
if (!hasClangNode())
52265233
// This *is* the implementation, if it has one.

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
@@ -3291,7 +3291,8 @@ class SILVerifier : public SILVerifierBase<SILVerifier> {
32913291
F.getResilienceExpansion()),
32923292
"cannot access storage of resilient class");
32933293

3294-
require(EI->getField()->getDeclContext() == cd,
3294+
require(EI->getField()->getDeclContext() ==
3295+
cd->getImplementationContext()->getAsGenericContext(),
32953296
"ref_element_addr field must be a member of the class");
32963297

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

lib/SILGen/SILGenType.cpp

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

12391239
/// Emit SIL functions for all the members of the extension.
12401240
void emitExtension(ExtensionDecl *e) {
1241+
// Arguably, we should divert to SILGenType::emitType() here if it's an
1242+
// @_objcImplementation extension, but we don't actually need to do any of
1243+
// the stuff that it currently does.
1244+
12411245
for (Decl *member : e->getABIMembers())
12421246
visit(member);
12431247

@@ -1313,6 +1317,17 @@ class SILGenExtension : public TypeMemberVisitor<SILGenExtension> {
13131317

13141318
void visitVarDecl(VarDecl *vd) {
13151319
if (vd->hasStorage()) {
1320+
if (!vd->isStatic()) {
1321+
// Is this a stored property of an @_objcImplementation extension?
1322+
auto ed = cast<ExtensionDecl>(vd->getDeclContext());
1323+
if (auto cd =
1324+
dyn_cast_or_null<ClassDecl>(ed->getImplementedObjCDecl())) {
1325+
// Act as though we declared it on the class.
1326+
SILGenType(SGM, cd).visitVarDecl(vd);
1327+
return;
1328+
}
1329+
}
1330+
13161331
bool hasDidSetOrWillSetDynamicReplacement =
13171332
vd->hasDidSetOrWillSetDynamicReplacement();
13181333
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)