Skip to content

Commit 2a80bdc

Browse files
authored
Merge pull request #75081 from beccadax/objcimpl-enable-6.0
2 parents fa753d7 + 5a7456f commit 2a80bdc

File tree

71 files changed

+2622
-561
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+2622
-561
lines changed

include/swift/AST/Attr.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2422,6 +2422,9 @@ class DocumentationAttr: public DeclAttribute {
24222422

24232423
class ObjCImplementationAttr final : public DeclAttribute {
24242424
public:
2425+
/// Name of the category being implemented. This should only be used with
2426+
/// the early adopter \@\_objcImplementation syntax, but we support it there
2427+
/// for backwards compatibility.
24252428
Identifier CategoryName;
24262429

24272430
ObjCImplementationAttr(Identifier CategoryName, SourceLoc AtLoc,

include/swift/AST/Decl.h

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1025,6 +1025,10 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
10251025
/// Returns the source range of the declaration including its attributes.
10261026
SourceRange getSourceRangeIncludingAttrs() const;
10271027

1028+
/// Retrieve the location at which we should insert a new attribute or
1029+
/// modifier.
1030+
SourceLoc getAttributeInsertionLoc(bool forModifier) const;
1031+
10281032
using ImportAccessLevel = std::optional<AttributedImport<ImportedModule>>;
10291033

10301034
/// Returns the import that may restrict the access to this decl
@@ -1916,11 +1920,6 @@ class ExtensionDecl final : public GenericContext, public Decl,
19161920
/// extended type?
19171921
bool isAddingConformanceToInvertible() const;
19181922

1919-
/// Returns the name of the category specified by the \c \@_objcImplementation
1920-
/// attribute, or \c None if the name is invalid or
1921-
/// \c isObjCImplementation() is false.
1922-
std::optional<Identifier> getCategoryNameForObjCImplementation() const;
1923-
19241923
/// If this extension represents an imported Objective-C category, returns the
19251924
/// category's name. Otherwise returns the empty identifier.
19261925
Identifier getObjCCategoryName() const;
@@ -3181,10 +3180,6 @@ class ValueDecl : public Decl {
31813180
/// can't be "static" or are in a context where "static" doesn't make sense.
31823181
bool isStatic() const;
31833182

3184-
/// Retrieve the location at which we should insert a new attribute or
3185-
/// modifier.
3186-
SourceLoc getAttributeInsertionLoc(bool forModifier) const;
3187-
31883183
static bool classof(const Decl *D) {
31893184
return D->getKind() >= DeclKind::First_ValueDecl &&
31903185
D->getKind() <= DeclKind::Last_ValueDecl;
@@ -4215,6 +4210,12 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
42154210
/// Retrieve the set of extensions of this type.
42164211
ExtensionRange getExtensions();
42174212

4213+
/// Retrieve the extension most recently added to this type. Helpful to
4214+
/// determine if an extension has been added.
4215+
ExtensionDecl *getLastExtension() const {
4216+
return LastExtension;
4217+
}
4218+
42184219
/// Special-behaviour flags passed to lookupDirect()
42194220
enum class LookupDirectFlags {
42204221
/// Whether to include @_implements members.
@@ -5080,6 +5081,11 @@ class ClassDecl final : public NominalTypeDecl {
50805081
llvm::TinyPtrVector<Decl *>
50815082
getImportedObjCCategory(Identifier name) const;
50825083

5084+
/// Return a map of category names to extensions with that category name,
5085+
/// whether imported or otherwise.
5086+
llvm::DenseMap<Identifier, llvm::TinyPtrVector<ExtensionDecl *>>
5087+
getObjCCategoryNameMap();
5088+
50835089
// Implement isa/cast/dyncast/etc.
50845090
static bool classof(const Decl *D) {
50855091
return D->getKind() == DeclKind::Class;

include/swift/AST/DiagnosticsClangImporter.def

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,12 +136,10 @@ WARNING(api_pattern_attr_ignored, none,
136136
(StringRef, StringRef))
137137

138138
ERROR(objc_implementation_two_impls, none,
139-
"duplicate implementation of Objective-C %select{|category %0 on }0"
140-
"%kind1",
141-
(Identifier, Decl *))
142-
139+
"duplicate implementation of imported %kind0",
140+
(Decl *))
143141
NOTE(previous_objc_implementation, none,
144-
"previously implemented by extension here", ())
142+
"previously implemented here", ())
145143

146144
NOTE(macro_not_imported_unsupported_operator, none, "operator not supported in macro arithmetic", ())
147145
NOTE(macro_not_imported_unsupported_named_operator, none, "operator '%0' not supported in macro arithmetic", (StringRef))

include/swift/AST/DiagnosticsIRGen.def

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,5 +69,16 @@ NOTE(layout_strings_blocked,none,
6969
"Layout string value witnesses have been disabled for module '%0' "
7070
"through block list entry", (StringRef))
7171

72+
ERROR(attr_objc_implementation_resilient_property_not_supported, none,
73+
"'@implementation' does not support stored properties whose size can "
74+
"change due to library evolution; store this value in an object or 'any' "
75+
"type",
76+
())
77+
ERROR(attr_objc_implementation_resilient_property_deployment_target, none,
78+
"'@implementation' on %0 %1 does not support stored properties whose "
79+
"size can change due to library evolution; raise the minimum deployment "
80+
"target to %0 %2 or store this value in an object or 'any' type",
81+
(StringRef, const llvm::VersionTuple, const llvm::VersionTuple))
82+
7283
#define UNDEFINE_DIAGNOSTIC_MACROS
7384
#include "DefineDiagnosticMacros.h"

include/swift/AST/DiagnosticsSema.def

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,9 @@ ERROR(expr_selector_not_objc,none,
763763
NOTE(make_decl_objc,none,
764764
"add '@objc' to expose this %0 to Objective-C",
765765
(DescriptiveDeclKind))
766+
NOTE(make_decl_objc_for_implementation,none,
767+
"add '@objc' to implement an Objective-C %0",
768+
(DescriptiveDeclKind))
766769

767770
// Selectors-as-string-literals.
768771
WARNING(selector_literal_invalid,none,
@@ -1760,21 +1763,17 @@ WARNING(objc_implementation_early_spelling_deprecated,none,
17601763
ERROR(attr_objc_implementation_must_be_unconditional,none,
17611764
"only unconditional extensions can implement an Objective-C '@interface'",
17621765
())
1763-
ERROR(attr_objc_implementation_must_extend_class,none,
1764-
"cannot mark extension of %kind0 with '@_objcImplementation'; it is not "
1765-
"an imported Objective-C class",
1766-
(ValueDecl *))
17671766
ERROR(attr_objc_implementation_must_be_imported,none,
1768-
"'@_objcImplementation' cannot be used to extend %kind0 because it was "
1767+
"'@objc @implementation' cannot be used to extend %kind0 because it was "
17691768
"defined by a Swift 'class' declaration, not an imported Objective-C "
17701769
"'@interface' declaration",
17711770
(ValueDecl *))
17721771
ERROR(attr_objc_implementation_must_have_super,none,
1773-
"'@_objcImplementation' cannot be used to implement root %kind0; declare "
1774-
"its superclass in the header",
1772+
"'@objc @implementation' cannot be used to implement root %kind0; "
1773+
"declare its superclass in the header",
17751774
(ValueDecl *))
17761775
ERROR(objc_implementation_cannot_have_generics,none,
1777-
"'@_objcImplementation' cannot be used to implement %kind0",
1776+
"'@objc @implementation' cannot be used to implement %kind0",
17781777
(ValueDecl *))
17791778
ERROR(attr_objc_implementation_category_not_found,none,
17801779
"could not find category %0 on Objective-C class %1; make sure your "
@@ -1792,10 +1791,22 @@ ERROR(attr_objc_implementation_no_category_for_func,none,
17921791
"name from this attribute",
17931792
(ValueDecl*))
17941793
ERROR(attr_objc_implementation_no_conformance,none,
1795-
"'@_objcImplementation' extension cannot add conformance to %0; "
1794+
"'@objc @implementation' extension cannot add conformance to %0; "
17961795
"add this conformance %select{with an ordinary extension|"
17971796
"in the Objective-C header}1",
17981797
(Type, bool))
1798+
ERROR(attr_objc_implementation_raise_minimum_deployment_target,none,
1799+
"'@implementation' of an Objective-C class requires a minimum deployment "
1800+
"target of at least %0 %1",
1801+
(StringRef, llvm::VersionTuple))
1802+
ERROR(attr_implementation_requires_language,none,
1803+
"'@implementation' used without specifying the language being "
1804+
"implemented",
1805+
())
1806+
ERROR(attr_implementation_category_goes_on_objc_attr,none,
1807+
"Objective-C category should be specified on '@objc', not "
1808+
"'@implementation'",
1809+
())
17991810

18001811
ERROR(member_of_objc_implementation_not_objc_or_final,none,
18011812
"%kind0 does not match any %kindonly0 declared in the headers for %1; "
@@ -1908,7 +1919,7 @@ NOTE(objc_implementation_requirement_here,none,
19081919
(ValueDecl *))
19091920

19101921
ERROR(objc_implementation_init_must_be_convenience, none,
1911-
"%kind0 is not valid in an '@_objcImplementation' extension because "
1922+
"%kind0 is not valid in an '@objc @implementation' extension because "
19121923
"Objective-C subclasses must be able to override "
19131924
"%select{designated|required}1 initializers",
19141925
(const ValueDecl *, /*isRequired=*/bool))
@@ -1922,7 +1933,7 @@ NOTE(objc_implementation_init_turn_required_to_convenience, none,
19221933

19231934
// Fallback diagnostic; super-general by nature.
19241935
ERROR(objc_implementation_member_requires_vtable, none,
1925-
"%kind0 is not valid in an '@_objcImplementation' extension because it "
1936+
"%kind0 is not valid in an '@objc @implementation' extension because it "
19261937
"is an overridable Swift-only %kindonly0",
19271938
(const ValueDecl *))
19281939

@@ -6293,7 +6304,7 @@ ERROR(objc_extension_not_class,none,
62936304
"'@objc' can only be applied to an extension of a class", ())
62946305

62956306
// If you change this, also change enum ObjCReason
6296-
#define OBJC_ATTR_SELECT "select{marked @_cdecl|marked dynamic|marked @objc|marked @objcMembers|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc override|an implementation of an @objc requirement|marked @IBInspectable|marked @GKInspectable|in an @objc extension of a class (without @nonobjc)|in an @_objcImplementation extension of a class (without final or @nonobjc)|marked @objc by an access note}"
6307+
#define OBJC_ATTR_SELECT "select{marked @_cdecl|marked dynamic|marked @objc|marked @objcMembers|marked @IBOutlet|marked @IBAction|marked @IBSegueAction|marked @NSManaged|a member of an @objc protocol|implicitly @objc|an @objc override|an implementation of an @objc requirement|marked @IBInspectable|marked @GKInspectable|in an @objc extension of a class (without @nonobjc)|in an @objc @implementation extension of a class (without final or @nonobjc)|marked @objc by an access note}"
62976308

62986309
ERROR(objc_invalid_on_var,none,
62996310
"property cannot be %" OBJC_ATTR_SELECT "0 "
@@ -6448,6 +6459,12 @@ ERROR(objc_redecl_same,none,
64486459
"previous declaration with the same Objective-C selector",
64496460
(unsigned, DeclName, unsigned, DeclName, ObjCSelector))
64506461

6462+
ERROR(objc_redecl_category_name,none,
6463+
"%select{|imported }0extension with Objective-C category name %2 "
6464+
"conflicts with previous %select{|imported }1extension with the same "
6465+
"category name",
6466+
(bool, bool, Identifier))
6467+
64516468
ERROR(objc_override_other,none,
64526469
OBJC_DIAG_SELECT " with Objective-C selector %4 conflicts with "
64536470
OBJC_DIAG_SELECT_2 " from superclass %5 with the same Objective-C "

include/swift/AST/FeatureAvailability.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ FEATURE(NoncopyableGenerics, (6, 0))
7676
FEATURE(TaskExecutor, FUTURE)
7777
FEATURE(Differentiation, FUTURE)
7878
FEATURE(InitRawStructMetadata, FUTURE)
79+
FEATURE(UpdatePureObjCClassMetadata, FUTURE)
7980

8081
#undef FEATURE
8182
#undef FUTURE

include/swift/AST/NameLookupRequests.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -970,6 +970,39 @@ class LookupIntrinsicRequest
970970
bool isCached() const { return true; }
971971
};
972972

973+
using ObjCCategoryNameMap =
974+
llvm::DenseMap<Identifier, llvm::TinyPtrVector<ExtensionDecl *>>;
975+
976+
/// Generate a map of all known extensions of the given class that have an
977+
/// explicit category name. This request does not force clang categories that
978+
/// haven't been imported already, but it will generate a new map if new
979+
/// categories have been imported since the cached value was generated.
980+
///
981+
/// \seeAlso ClassDecl::getObjCCategoryNameMap()
982+
class ObjCCategoryNameMapRequest
983+
: public SimpleRequest<ObjCCategoryNameMapRequest,
984+
ObjCCategoryNameMap(ClassDecl *, ExtensionDecl *),
985+
RequestFlags::Cached> {
986+
public:
987+
using SimpleRequest::SimpleRequest;
988+
989+
// Convenience to automatically extract `lastExtension`.
990+
ObjCCategoryNameMapRequest(ClassDecl *classDecl)
991+
: ObjCCategoryNameMapRequest(classDecl, classDecl->getLastExtension())
992+
{}
993+
994+
private:
995+
friend SimpleRequest;
996+
997+
// Evaluation.
998+
ObjCCategoryNameMap evaluate(Evaluator &evaluator,
999+
ClassDecl *classDecl,
1000+
ExtensionDecl *lastExtension) const;
1001+
1002+
public:
1003+
bool isCached() const { return true; }
1004+
};
1005+
9731006
#define SWIFT_TYPEID_ZONE NameLookup
9741007
#define SWIFT_TYPEID_HEADER "swift/AST/NameLookupTypeIDZone.def"
9751008
#include "swift/Basic/DefineTypeIDZone.h"

include/swift/AST/NameLookupTypeIDZone.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,3 +116,5 @@ SWIFT_REQUEST(NameLookup, ImplementsAttrProtocolRequest,
116116
ProtocolDecl *(const ImplementsAttr *, DeclContext *), Cached, NoLocationInfo)
117117
SWIFT_REQUEST(NameLookup, LookupIntrinsicRequest,
118118
FuncDecl *(ModuleDecl *, Identifier), Cached, NoLocationInfo)
119+
SWIFT_REQUEST(NameLookup, ObjCCategoryNameMapRequest,
120+
ObjCCategoryNameMap(ClassDecl *, ExtensionDecl *), Cached, NoLocationInfo)

include/swift/AST/SourceFile.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,10 @@ class SourceFile final : public FileUnit {
359359
/// List of Objective-C member conflicts we have found during type checking.
360360
llvm::SetVector<ObjCMethodConflict> ObjCMethodConflicts;
361361

362+
/// Categories (extensions with explicit @objc names) declared in this
363+
/// source file. They need to be checked for conflicts after type checking.
364+
llvm::TinyPtrVector<ExtensionDecl *> ObjCCategories;
365+
362366
/// List of attributes added by access notes, used to emit remarks for valid
363367
/// ones.
364368
llvm::DenseMap<ValueDecl *, std::vector<DeclAttribute *>>

include/swift/Basic/Features.def

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ SUPPRESSIBLE_LANGUAGE_FEATURE(SendingArgsAndResults, 430, "Sending arg and resul
202202
LANGUAGE_FEATURE(BorrowingSwitch, 432, "Noncopyable type pattern matching")
203203
CONDITIONALLY_SUPPRESSIBLE_LANGUAGE_FEATURE(IsolatedAny, 431, "@isolated(any) function types")
204204
LANGUAGE_FEATURE(IsolatedAny2, 431, "@isolated(any) function types")
205+
LANGUAGE_FEATURE(ObjCImplementation, 436, "@objc @implementation extensions")
205206

206207
// Swift 6
207208
UPCOMING_FEATURE(ConciseMagicFile, 274, 6)
@@ -376,8 +377,10 @@ EXPERIMENTAL_FEATURE(ClosureIsolation, true)
376377
// Whether lookup of members respects the enclosing file's imports.
377378
EXPERIMENTAL_FEATURE_EXCLUDED_FROM_MODULE_INTERFACE(MemberImportVisibility, true)
378379

379-
// Enable @implementation on extensions of ObjC classes.
380-
EXPERIMENTAL_FEATURE(ObjCImplementation, true)
380+
// Enable @implementation on extensions of ObjC classes with non-fixed layout
381+
// due to resilient stored properties. Requires OS support; this flag exists for
382+
// staging purposes.
383+
EXPERIMENTAL_FEATURE(ObjCImplementationWithResilientStorage, true)
381384

382385
// Enable @implementation on @_cdecl functions.
383386
EXPERIMENTAL_FEATURE(CImplementation, true)

include/swift/ClangImporter/ClangImporterRequests.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ struct ObjCInterfaceAndImplementation final {
256256
ObjCInterfaceAndImplementation()
257257
: interfaceDecls(), implementationDecl(nullptr) {}
258258

259-
operator bool() const {
259+
bool empty() const {
260260
return interfaceDecls.empty();
261261
}
262262

include/swift/Runtime/Metadata.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,13 @@ swift_updateClassMetadata2(ClassMetadata *self,
782782
size_t numFields,
783783
const TypeLayout * const *fieldTypes,
784784
size_t *fieldOffsets);
785+
786+
SWIFT_RUNTIME_EXPORT SWIFT_CC(swift)
787+
Class
788+
swift_updatePureObjCClassMetadata(Class self,
789+
ClassLayoutFlags flags,
790+
size_t numFields,
791+
const TypeLayout * const *fieldTypes);
785792
#endif
786793

787794
/// Given class metadata, a class descriptor and a method descriptor, look up

include/swift/Runtime/RuntimeFunctions.def

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,6 +1437,19 @@ FUNCTION(UpdateClassMetadata2,
14371437
EFFECT(MetaData),
14381438
UNKNOWN_MEMEFFECTS)
14391439

1440+
// objc_class *swift_updatePureObjCClassMetadata(
1441+
// objc_class *self,
1442+
// ClassLayoutFlags flags,
1443+
// size_t numFields,
1444+
// TypeLayout * const *fieldTypes);
1445+
FUNCTION(UpdatePureObjCClassMetadata,
1446+
swift_updatePureObjCClassMetadata, SwiftCC, AlwaysAvailable,
1447+
RETURNS(ObjCClassPtrTy),
1448+
ARGS(ObjCClassPtrTy, SizeTy, SizeTy, Int8PtrPtrTy->getPointerTo()),
1449+
ATTRS(NoUnwind),
1450+
EFFECT(MetaData),
1451+
UNKNOWN_MEMEFFECTS)
1452+
14401453
// void *swift_lookUpClassMethod(Metadata *metadata,
14411454
// ClassDescriptor *description,
14421455
// MethodDescriptor *method);

lib/AST/ASTPrinter.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1326,6 +1326,14 @@ void PrintAST::printAttributes(const Decl *D) {
13261326
}
13271327
}
13281328

1329+
// If we are suppressing @implementation, also suppress @objc on extensions.
1330+
if (auto ED = dyn_cast<ExtensionDecl>(D)) {
1331+
if (ED->isObjCImplementation() &&
1332+
Options.excludeAttrKind(DeclAttrKind::ObjCImplementation)) {
1333+
Options.ExcludeAttrList.push_back(DeclAttrKind::ObjC);
1334+
}
1335+
}
1336+
13291337
// We will handle ownership specifiers separately.
13301338
if (isa<FuncDecl>(D)) {
13311339
Options.ExcludeAttrList.push_back(DeclAttrKind::Mutating);

0 commit comments

Comments
 (0)