Skip to content

Commit 09ae7ab

Browse files
authored
Merge pull request #3253 from jrose-apple/ForeignKind
Mark the Dispatch classes as a new kind of "foreign" class. rdar://problem/26850367
2 parents 5da37a5 + 3b6e40c commit 09ae7ab

25 files changed

+304
-101
lines changed

include/swift/AST/Decl.h

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -458,8 +458,8 @@ class alignas(1 << DeclAlignInBits) Decl {
458458
/// This is a value of \c StoredInheritsSuperclassInits.
459459
unsigned InheritsSuperclassInits : 2;
460460

461-
/// Whether this class is "foreign".
462-
unsigned Foreign : 1;
461+
/// \see ClassDecl::ForeignKind
462+
unsigned RawForeignKind : 2;
463463

464464
/// Whether this class contains a destructor decl.
465465
///
@@ -468,7 +468,7 @@ class alignas(1 << DeclAlignInBits) Decl {
468468
/// control inserting the implicit destructor.
469469
unsigned HasDestructorDecl : 1;
470470
};
471-
enum { NumClassDeclBits = NumNominalTypeDeclBits + 7 };
471+
enum { NumClassDeclBits = NumNominalTypeDeclBits + 8 };
472472
static_assert(NumClassDeclBits <= 32, "fits in an unsigned");
473473

474474
class StructDeclBitfields {
@@ -3238,6 +3238,19 @@ class ClassDecl : public NominalTypeDecl {
32383238
ClassDeclBits.RequiresStoredPropertyInits = requiresInits;
32393239
}
32403240

3241+
/// \see getForeignClassKind
3242+
enum class ForeignKind : uint8_t {
3243+
/// A normal Swift or Objective-C class.
3244+
Normal = 0,
3245+
/// An imported Core Foundation type. These are AnyObject-compatible but
3246+
/// do not have runtime metadata.
3247+
CFType,
3248+
/// An imported Objective-C type whose class and metaclass symbols are not
3249+
/// both available at link-time but can be accessed through the Objective-C
3250+
/// runtime.
3251+
RuntimeOnly
3252+
};
3253+
32413254
/// Whether this class is "foreign", meaning that it is implemented
32423255
/// by a runtime that Swift does not have first-class integration
32433256
/// with. This generally means that:
@@ -3248,11 +3261,18 @@ class ClassDecl : public NominalTypeDecl {
32483261
///
32493262
/// We may find ourselves wanting to break this bit into more
32503263
/// precise chunks later.
3251-
bool isForeign() const {
3252-
return ClassDeclBits.Foreign;
3264+
ForeignKind getForeignClassKind() const {
3265+
return static_cast<ForeignKind>(ClassDeclBits.RawForeignKind);
3266+
}
3267+
void setForeignClassKind(ForeignKind kind) {
3268+
ClassDeclBits.RawForeignKind = static_cast<unsigned>(kind);
32533269
}
3254-
void setForeign(bool isForeign = true) {
3255-
ClassDeclBits.Foreign = isForeign;
3270+
3271+
/// Returns true if this class is any kind of "foreign class".
3272+
///
3273+
/// \see getForeignClassKind
3274+
bool isForeign() const {
3275+
return getForeignClassKind() != ForeignKind::Normal;
32563276
}
32573277

32583278
/// Find a method of a class that overrides a given method.
@@ -3295,10 +3315,6 @@ class ClassDecl : public NominalTypeDecl {
32953315
/// the Objective-C runtime.
32963316
StringRef getObjCRuntimeName(llvm::SmallVectorImpl<char> &buffer) const;
32973317

3298-
/// Determine whether the class is only visible to the Objective-C runtime
3299-
/// and not to the linker.
3300-
bool isOnlyObjCRuntimeVisible() const;
3301-
33023318
/// Returns the appropriate kind of entry point to generate for this class,
33033319
/// based on its attributes.
33043320
///

include/swift/AST/DiagnosticsSema.def

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1171,10 +1171,14 @@ NOTE(types_not_equal_requirement,none,
11711171
ERROR(non_class_cannot_conform_to_class_protocol,none,
11721172
"non-class type %0 cannot conform to class protocol %1",
11731173
(Type, Type))
1174-
ERROR(foreign_class_cannot_conform_to_objc_protocol,none,
1174+
ERROR(cf_class_cannot_conform_to_objc_protocol,none,
11751175
"Core Foundation class %0 cannot conform to @objc protocol %1 because "
11761176
"Core Foundation types are not classes in Objective-C",
11771177
(Type, Type))
1178+
ERROR(objc_runtime_visible_cannot_conform_to_objc_protocol,none,
1179+
"class %0 cannot conform to @objc protocol %1 because "
1180+
"the class is only visible via the Objective-C runtime",
1181+
(Type, Type))
11781182
ERROR(protocol_has_missing_requirements,none,
11791183
"type %0 cannot conform to protocol %1 because it has requirements that "
11801184
"cannot be satisfied", (Type, Type))
@@ -1582,8 +1586,11 @@ ERROR(inheritance_from_final_class,none,
15821586
ERROR(inheritance_from_unspecialized_objc_generic_class,none,
15831587
"inheritance from a generic Objective-C class %0 must bind "
15841588
"type parameters of %0 to specific concrete types", (Identifier))
1589+
ERROR(inheritance_from_cf_class,none,
1590+
"cannot inherit from Core Foundation type %0", (Identifier))
15851591
ERROR(inheritance_from_objc_runtime_visible_class,none,
1586-
"inheritance from an Objective-C class %0 only visible via the runtime", (Identifier))
1592+
"cannot inherit from class %0 because it is only visible via the "
1593+
"Objective-C runtime", (Identifier))
15871594

15881595

15891596
// Enums
@@ -2611,8 +2618,6 @@ ERROR(objc_in_extension_context,none,
26112618
"members of constrained extensions cannot be declared @objc", ())
26122619
ERROR(objc_in_generic_extension,none,
26132620
"@objc is not supported within extensions of generic classes", ())
2614-
ERROR(objc_in_objc_runtime_visible,none,
2615-
"@objc is not supported within extensions of classes only visible via the Objective-C runtime", ())
26162621

26172622
ERROR(objc_for_generic_class,none,
26182623
"generic subclasses of '@objc' classes cannot have an explicit '@objc' "
@@ -2733,6 +2738,11 @@ ERROR(objc_invalid_on_failing_init,none,
27332738
"%" OBJC_ATTR_SELECT "0 because 'nil' indicates failure to Objective-C",
27342739
(unsigned))
27352740

2741+
ERROR(objc_in_objc_runtime_visible,none,
2742+
"%0 cannot be %" OBJC_ATTR_SELECT "1 because class %2 is only visible "
2743+
"via the Objective-C runtime",
2744+
(DescriptiveDeclKind, unsigned, Identifier))
2745+
27362746
ERROR(objc_override_method_selector_mismatch,none,
27372747
"Objective-C method has a different selector from the "
27382748
"method it overrides (%0 vs. %1)", (ObjCSelector, ObjCSelector))

include/swift/Serialization/ModuleFormat.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ const uint16_t VERSION_MAJOR = 0;
5353
/// in source control, you should also update the comment to briefly
5454
/// describe what change you made. The content of this comment isn't important;
5555
/// it just ensures a conflict if two people change the module format.
56-
const uint16_t VERSION_MINOR = 251; // Last change: SILFunctionType::isPseudogeneric
56+
const uint16_t VERSION_MINOR = 252; // Last change: remove class's "foreign" field
5757

5858
using DeclID = PointerEmbeddedInt<unsigned, 31>;
5959
using DeclIDField = BCFixed<31>;
@@ -816,7 +816,6 @@ namespace decls_block {
816816
BCFixed<1>, // implicit?
817817
BCFixed<1>, // explicitly objc?
818818
BCFixed<1>, // requires stored property initial values
819-
BCFixed<1>, // foreign
820819
TypeIDField, // superclass
821820
AccessibilityKindField, // accessibility
822821
BCVBR<4>, // number of conformances

lib/AST/Decl.cpp

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2231,7 +2231,7 @@ ClassDecl::ClassDecl(SourceLoc ClassLoc, Identifier Name, SourceLoc NameLoc,
22312231
ClassDeclBits.RequiresStoredPropertyInits = 0;
22322232
ClassDeclBits.InheritsSuperclassInits
22332233
= static_cast<unsigned>(StoredInheritsSuperclassInits::Unchecked);
2234-
ClassDeclBits.Foreign = false;
2234+
ClassDeclBits.RawForeignKind = 0;
22352235
ClassDeclBits.HasDestructorDecl = 0;
22362236
}
22372237

@@ -2398,19 +2398,6 @@ StringRef ClassDecl::getObjCRuntimeName(
23982398
return mangleObjCRuntimeName(this, buffer);
23992399
}
24002400

2401-
bool ClassDecl::isOnlyObjCRuntimeVisible() const {
2402-
auto clangDecl = getClangDecl();
2403-
if (!clangDecl) return false;
2404-
2405-
auto objcClass = dyn_cast<clang::ObjCInterfaceDecl>(clangDecl);
2406-
if (!objcClass) return false;
2407-
2408-
if (auto def = objcClass->getDefinition())
2409-
objcClass = def;
2410-
2411-
return objcClass->hasAttr<clang::ObjCRuntimeVisibleAttr>();
2412-
}
2413-
24142401
ArtificialMainKind ClassDecl::getArtificialMainKind() const {
24152402
if (getAttrs().hasAttribute<UIApplicationMainAttr>())
24162403
return ArtificialMainKind::UIApplicationMain;

lib/ClangImporter/ImportDecl.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1243,7 +1243,7 @@ namespace {
12431243
theClass->setSuperclass(superclass);
12441244
theClass->setCheckedInheritanceClause();
12451245
theClass->setAddedImplicitInitializers(); // suppress all initializers
1246-
theClass->setForeign(true);
1246+
theClass->setForeignClassKind(ClassDecl::ForeignKind::CFType);
12471247
addObjCAttribute(theClass, None);
12481248
Impl.registerExternalDecl(theClass);
12491249

@@ -5660,7 +5660,7 @@ namespace {
56605660
nsObjectTy->getClassOrBoundGenericClass();
56615661

56625662
auto result = createRootClass(nsObjectDecl->getDeclContext());
5663-
result->setForeign(true);
5663+
result->setForeignClassKind(ClassDecl::ForeignKind::RuntimeOnly);
56645664
return result;
56655665
}
56665666

@@ -5731,6 +5731,8 @@ namespace {
57315731

57325732
if (declaredNative)
57335733
markMissingSwiftDecl(result);
5734+
if (decl->getAttr<clang::ObjCRuntimeVisibleAttr>())
5735+
result->setForeignClassKind(ClassDecl::ForeignKind::RuntimeOnly);
57345736

57355737
// If this Objective-C class has a supertype, import it.
57365738
SmallVector<TypeLoc, 4> inheritedTypes;

lib/IRGen/GenCast.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,10 @@ llvm::Value *irgen::emitClassDowncast(IRGenFunction &IGF, llvm::Value *from,
163163
break;
164164
}
165165

166-
// If the destination type is a foreign class or a non-specific
166+
// If the destination type is a CF type or a non-specific
167167
// class-bounded archetype, use the most general cast entrypoint.
168-
} else if (toType.is<ArchetypeType>() || destClass->isForeign()) {
168+
} else if (toType.is<ArchetypeType>() ||
169+
destClass->getForeignClassKind()==ClassDecl::ForeignKind::CFType) {
169170
metadataRef = IGF.emitTypeMetadataRef(toType.getSwiftRValueType());
170171

171172
switch (mode) {

lib/IRGen/GenDecl.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2272,6 +2272,7 @@ Address IRGenModule::getAddrOfObjCClassRef(ClassDecl *theClass) {
22722272
llvm::Constant *IRGenModule::getAddrOfObjCClass(ClassDecl *theClass,
22732273
ForDefinition_t forDefinition) {
22742274
assert(ObjCInterop && "getting address of ObjC class in no-interop mode");
2275+
assert(!theClass->isForeign());
22752276
LinkEntity entity = LinkEntity::forObjCClass(theClass);
22762277
DebugTypeInfo DbgTy(theClass, ObjCClassPtrTy,
22772278
getPointerSize(), getPointerAlignment());
@@ -2285,6 +2286,7 @@ llvm::Constant *IRGenModule::getAddrOfObjCClass(ClassDecl *theClass,
22852286
llvm::Constant *IRGenModule::getAddrOfObjCMetaclass(ClassDecl *theClass,
22862287
ForDefinition_t forDefinition) {
22872288
assert(ObjCInterop && "getting address of ObjC metaclass in no-interop mode");
2289+
assert(!theClass->isForeign());
22882290
LinkEntity entity = LinkEntity::forObjCMetaclass(theClass);
22892291
DebugTypeInfo DbgTy(theClass, ObjCClassPtrTy,
22902292
getPointerSize(), getPointerAlignment());
@@ -2845,7 +2847,7 @@ void IRGenModule::emitExtension(ExtensionDecl *ext) {
28452847

28462848
if (shouldEmitCategory(*this, ext)) {
28472849
assert(origClass && !origClass->isForeign() &&
2848-
"CF types cannot have categories emitted");
2850+
"foreign types cannot have categories emitted");
28492851
llvm::Constant *category = emitCategoryData(*this, ext);
28502852
category = llvm::ConstantExpr::getBitCast(category, Int8PtrTy);
28512853
ObjCCategories.push_back(category);

lib/IRGen/GenMeta.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -292,10 +292,8 @@ llvm::Constant *irgen::tryEmitConstantHeapMetadataRef(IRGenModule &IGM,
292292
if (doesClassMetadataRequireDynamicInitialization(IGM, theDecl))
293293
return nullptr;
294294

295-
// Otherwise, just respect genericity and Objective-C runtime visibility.
296-
} else if ((theDecl->isGenericContext()
297-
&& !isTypeErasedGenericClass(theDecl))
298-
|| theDecl->isOnlyObjCRuntimeVisible()) {
295+
// Otherwise, just respect genericity.
296+
} else if (theDecl->isGenericContext() && !isTypeErasedGenericClass(theDecl)){
299297
return nullptr;
300298
}
301299

@@ -331,13 +329,15 @@ llvm::Value *irgen::emitObjCHeapMetadataRef(IRGenFunction &IGF,
331329
bool allowUninitialized) {
332330
// If the class is visible only through the Objective-C runtime, form the
333331
// appropriate runtime call.
334-
if (theClass->isOnlyObjCRuntimeVisible()) {
332+
if (theClass->getForeignClassKind() == ClassDecl::ForeignKind::RuntimeOnly) {
335333
SmallString<64> scratch;
336334
auto className =
337335
IGF.IGM.getAddrOfGlobalString(theClass->getObjCRuntimeName(scratch));
338336
return IGF.Builder.CreateCall(IGF.IGM.getLookUpClassFn(), className);
339337
}
340338

339+
assert(!theClass->isForeign());
340+
341341
Address classRef = IGF.IGM.getAddrOfObjCClassRef(theClass);
342342
auto classObject = IGF.Builder.CreateLoad(classRef);
343343
if (allowUninitialized) return classObject;

lib/PrintAsObjC/PrintAsObjC.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,8 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
611611
if (auto weakTy = ty->getAs<WeakStorageType>()) {
612612
auto innerTy = weakTy->getReferentType()->getAnyOptionalObjectType();
613613
auto innerClass = innerTy->getClassOrBoundGenericClass();
614-
if ((innerClass && !innerClass->isForeign()) ||
614+
if ((innerClass &&
615+
innerClass->getForeignClassKind()!=ClassDecl::ForeignKind::CFType) ||
615616
(innerTy->isObjCExistentialType() && !isCFTypeRef(innerTy))) {
616617
os << ", weak";
617618
}
@@ -653,7 +654,8 @@ class ObjCPrinter : private DeclVisitor<ObjCPrinter>,
653654
break;
654655
}
655656
} else if ((dyn_cast_or_null<ClassDecl>(nominal) &&
656-
!cast<ClassDecl>(nominal)->isForeign()) ||
657+
cast<ClassDecl>(nominal)->getForeignClassKind() !=
658+
ClassDecl::ForeignKind::CFType) ||
657659
(copyTy->isObjCExistentialType() && !isCFTypeRef(copyTy))) {
658660
os << ", strong";
659661
}
@@ -1617,8 +1619,10 @@ class ModuleWriter {
16171619
}
16181620

16191621
bool forwardDeclare(const ClassDecl *CD) {
1620-
if (!CD->isObjC() || CD->isForeign())
1622+
if (!CD->isObjC() ||
1623+
CD->getForeignClassKind() == ClassDecl::ForeignKind::CFType) {
16211624
return false;
1625+
}
16221626
forwardDeclare(CD, [&]{ os << "@class " << getNameForObjC(CD) << ";\n"; });
16231627
return true;
16241628
}

lib/SIL/SILFunctionType.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -401,18 +401,24 @@ enum class ConventionsKind : uint8_t {
401401

402402
if (clangTy->getPointeeType()->getAs<clang::RecordType>()) {
403403
// CF type as foreign class
404-
if (substTy->getClassOrBoundGenericClass()
405-
&& substTy->getClassOrBoundGenericClass()->isForeign())
404+
if (substTy->getClassOrBoundGenericClass() &&
405+
substTy->getClassOrBoundGenericClass()->getForeignClassKind() ==
406+
ClassDecl::ForeignKind::CFType) {
406407
return false;
408+
}
407409
// swift_newtype-ed CF type as foreign class
408410
if (auto typedefTy = clangTy->getAs<clang::TypedefType>()) {
409411
if (typedefTy->getDecl()->getAttr<clang::SwiftNewtypeAttr>()) {
410412
// Make sure that we actually made the struct during import
411413
if (auto underlyingType =
412414
substTy->getSwiftNewtypeUnderlyingType()) {
413-
if (underlyingType->getClassOrBoundGenericClass() &&
414-
underlyingType->getClassOrBoundGenericClass()->isForeign())
415-
return false;
415+
if (auto underlyingClass =
416+
underlyingType->getClassOrBoundGenericClass()) {
417+
if (underlyingClass->getForeignClassKind() ==
418+
ClassDecl::ForeignKind::CFType) {
419+
return false;
420+
}
421+
}
416422
}
417423
}
418424
}

0 commit comments

Comments
 (0)