Skip to content

Commit efcbe90

Browse files
committed
Merge remote-tracking branch 'origin/main' into rebranch
2 parents e844c61 + d991200 commit efcbe90

Some content is hidden

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

41 files changed

+1484
-310
lines changed

include/swift/AST/Attr.h

+3
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

+15-9
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
@@ -1912,11 +1916,6 @@ class ExtensionDecl final : public GenericContext, public Decl,
19121916
/// \endcode
19131917
bool isWrittenWithConstraints() const;
19141918

1915-
/// Returns the name of the category specified by the \c \@_objcImplementation
1916-
/// attribute, or \c None if the name is invalid or
1917-
/// \c isObjCImplementation() is false.
1918-
std::optional<Identifier> getCategoryNameForObjCImplementation() const;
1919-
19201919
/// If this extension represents an imported Objective-C category, returns the
19211920
/// category's name. Otherwise returns the empty identifier.
19221921
Identifier getObjCCategoryName() const;
@@ -3177,10 +3176,6 @@ class ValueDecl : public Decl {
31773176
/// can't be "static" or are in a context where "static" doesn't make sense.
31783177
bool isStatic() const;
31793178

3180-
/// Retrieve the location at which we should insert a new attribute or
3181-
/// modifier.
3182-
SourceLoc getAttributeInsertionLoc(bool forModifier) const;
3183-
31843179
static bool classof(const Decl *D) {
31853180
return D->getKind() >= DeclKind::First_ValueDecl &&
31863181
D->getKind() <= DeclKind::Last_ValueDecl;
@@ -4204,6 +4199,12 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
42044199
/// Retrieve the set of extensions of this type.
42054200
ExtensionRange getExtensions();
42064201

4202+
/// Retrieve the extension most recently added to this type. Helpful to
4203+
/// determine if an extension has been added.
4204+
ExtensionDecl *getLastExtension() const {
4205+
return LastExtension;
4206+
}
4207+
42074208
/// Special-behaviour flags passed to lookupDirect()
42084209
enum class LookupDirectFlags {
42094210
/// Whether to include @_implements members.
@@ -5069,6 +5070,11 @@ class ClassDecl final : public NominalTypeDecl {
50695070
llvm::TinyPtrVector<Decl *>
50705071
getImportedObjCCategory(Identifier name) const;
50715072

5073+
/// Return a map of category names to extensions with that category name,
5074+
/// whether imported or otherwise.
5075+
llvm::DenseMap<Identifier, llvm::TinyPtrVector<ExtensionDecl *>>
5076+
getObjCCategoryNameMap();
5077+
50725078
// Implement isa/cast/dyncast/etc.
50735079
static bool classof(const Decl *D) {
50745080
return D->getKind() == DeclKind::Class;

include/swift/AST/DiagnosticsClangImporter.def

+3-5
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/DiagnosticsSema.def

+18-5
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,10 +1763,6 @@ 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,
17681767
"'@_objcImplementation' cannot be used to extend %kind0 because it was "
17691768
"defined by a Swift 'class' declaration, not an imported Objective-C "
@@ -1800,6 +1799,14 @@ ERROR(attr_objc_implementation_raise_minimum_deployment_target,none,
18001799
"'@implementation' of an Objective-C class requires a minimum deployment "
18011800
"target of at least %0 %1",
18021801
(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+
())
18031810

18041811
ERROR(member_of_objc_implementation_not_objc_or_final,none,
18051812
"%kind0 does not match any %kindonly0 declared in the headers for %1; "
@@ -6310,7 +6317,7 @@ ERROR(objc_extension_not_class,none,
63106317
"'@objc' can only be applied to an extension of a class", ())
63116318

63126319
// If you change this, also change enum ObjCReason
6313-
#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}"
6320+
#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}"
63146321

63156322
ERROR(objc_invalid_on_var,none,
63166323
"property cannot be %" OBJC_ATTR_SELECT "0 "
@@ -6465,6 +6472,12 @@ ERROR(objc_redecl_same,none,
64656472
"previous declaration with the same Objective-C selector",
64666473
(unsigned, DeclName, unsigned, DeclName, ObjCSelector))
64676474

6475+
ERROR(objc_redecl_category_name,none,
6476+
"%select{|imported }0extension with Objective-C category name %2 "
6477+
"conflicts with previous %select{|imported }1extension with the same "
6478+
"category name",
6479+
(bool, bool, Identifier))
6480+
64686481
ERROR(objc_override_other,none,
64696482
OBJC_DIAG_SELECT " with Objective-C selector %4 conflicts with "
64706483
OBJC_DIAG_SELECT_2 " from superclass %5 with the same Objective-C "

include/swift/AST/NameLookupRequests.h

+33
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

+2
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

+4
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/ClangImporter/ClangImporterRequests.h

+1-1
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

lib/AST/Decl.cpp

+93-28
Original file line numberDiff line numberDiff line change
@@ -1891,16 +1891,6 @@ bool Decl::isObjCImplementation() const {
18911891
return getAttrs().hasAttribute<ObjCImplementationAttr>(/*AllowInvalid=*/true);
18921892
}
18931893

1894-
std::optional<Identifier>
1895-
ExtensionDecl::getCategoryNameForObjCImplementation() const {
1896-
auto attr = getAttrs()
1897-
.getAttribute<ObjCImplementationAttr>(/*AllowInvalid=*/true);
1898-
if (!attr || attr->isCategoryNameInvalid())
1899-
return std::nullopt;
1900-
1901-
return attr->CategoryName;
1902-
}
1903-
19041894
PatternBindingDecl::PatternBindingDecl(SourceLoc StaticLoc,
19051895
StaticSpellingKind StaticSpelling,
19061896
SourceLoc VarLoc,
@@ -3745,6 +3735,20 @@ void ValueDecl::setIsObjC(bool value) {
37453735
LazySemanticInfo.isObjC = value;
37463736
}
37473737

3738+
Identifier ExtensionDecl::getObjCCategoryName() const {
3739+
// If there's an @objc attribute, it's authoritative. (ClangImporter
3740+
// attaches one automatically.)
3741+
if (auto objcAttr = getAttrs().getAttribute<ObjCAttr>(/*AllowInvalid*/true)) {
3742+
if (objcAttr->hasName() && objcAttr->getName()->getNumArgs() == 0)
3743+
return objcAttr->getName()->getSimpleName();
3744+
3745+
return Identifier();
3746+
}
3747+
3748+
// Not a category, evidently.
3749+
return Identifier();
3750+
}
3751+
37483752
bool ValueDecl::isSemanticallyFinal() const {
37493753
// Actor types are semantically final.
37503754
if (auto classDecl = dyn_cast<ClassDecl>(this)) {
@@ -4039,25 +4043,86 @@ bool ValueDecl::canInferObjCFromRequirement(ValueDecl *requirement) {
40394043
return false;
40404044
}
40414045

4042-
SourceLoc ValueDecl::getAttributeInsertionLoc(bool forModifier) const {
4043-
if (isImplicit())
4046+
SourceLoc Decl::getAttributeInsertionLoc(bool forModifier) const {
4047+
// Some decls have a parent/child split where the introducer keyword is on the
4048+
// parent, but the attributes are on the children. If this is a child in such
4049+
// a pair, `introDecl` will be changed to point to the parent. (The parent
4050+
// decl should delegate to one of its children.)
4051+
const Decl *introDecl = this;
4052+
4053+
switch (getKind()) {
4054+
case DeclKind::Module:
4055+
case DeclKind::TopLevelCode:
4056+
case DeclKind::IfConfig:
4057+
case DeclKind::PoundDiagnostic:
4058+
case DeclKind::Missing:
4059+
case DeclKind::MissingMember:
4060+
case DeclKind::MacroExpansion:
4061+
case DeclKind::BuiltinTuple:
4062+
// These don't take attributes.
40444063
return SourceLoc();
40454064

4046-
if (auto var = dyn_cast<VarDecl>(this)) {
4047-
// [attrs] var ...
4048-
// The attributes are part of the VarDecl, but the 'var' is part of the PBD.
4049-
SourceLoc resultLoc = var->getAttrs().getStartLoc(forModifier);
4050-
if (resultLoc.isValid()) {
4051-
return resultLoc;
4052-
} else if (auto pbd = var->getParentPatternBinding()) {
4053-
return pbd->getStartLoc();
4054-
} else {
4055-
return var->getStartLoc();
4065+
case DeclKind::EnumCase:
4066+
// An ECD's attributes are attached to its elements.
4067+
if (auto elem = cast<EnumCaseDecl>(this)->getFirstElement())
4068+
return elem->getAttributeInsertionLoc(forModifier);
4069+
break;
4070+
4071+
case DeclKind::EnumElement:
4072+
// An EED's introducer keyword is on its parent case.
4073+
if (auto parent = cast<EnumElementDecl>(this)->getParentCase())
4074+
introDecl = parent;
4075+
break;
4076+
4077+
case DeclKind::PatternBinding: {
4078+
// A PBD's attributes are attached to the vars in its patterns.
4079+
auto pbd = cast<PatternBindingDecl>(this);
4080+
4081+
for (unsigned i = 0; i < pbd->getNumPatternEntries(); i++) {
4082+
if (auto var = pbd->getAnchoringVarDecl(i)) {
4083+
return var->getAttributeInsertionLoc(forModifier);
4084+
}
40564085
}
4086+
4087+
break;
40574088
}
40584089

4090+
case DeclKind::Var:
4091+
case DeclKind::Param:
4092+
// A VarDecl's introducer keyword, if it has one, is on its pattern binding.
4093+
if (auto pbd = cast<VarDecl>(this)->getParentPatternBinding())
4094+
introDecl = pbd;
4095+
break;
4096+
4097+
case DeclKind::Enum:
4098+
case DeclKind::Struct:
4099+
case DeclKind::Class:
4100+
case DeclKind::Protocol:
4101+
case DeclKind::OpaqueType:
4102+
case DeclKind::TypeAlias:
4103+
case DeclKind::GenericTypeParam:
4104+
case DeclKind::AssociatedType:
4105+
case DeclKind::Subscript:
4106+
case DeclKind::Constructor:
4107+
case DeclKind::Destructor:
4108+
case DeclKind::Func:
4109+
case DeclKind::Accessor:
4110+
case DeclKind::Macro:
4111+
case DeclKind::Extension:
4112+
case DeclKind::Import:
4113+
case DeclKind::PrecedenceGroup:
4114+
case DeclKind::InfixOperator:
4115+
case DeclKind::PrefixOperator:
4116+
case DeclKind::PostfixOperator:
4117+
// Both the introducer keyword and the attributes are on `this`.
4118+
break;
4119+
}
4120+
4121+
if (isImplicit())
4122+
return SourceLoc();
4123+
40594124
SourceLoc resultLoc = getAttrs().getStartLoc(forModifier);
4060-
return resultLoc.isValid() ? resultLoc : getStartLoc();
4125+
return resultLoc.isValid() ? resultLoc : introDecl->getStartLoc();
40614126
}
40624127

40634128
/// Returns true if \p VD needs to be treated as publicly-accessible
@@ -11323,7 +11388,7 @@ void swift::simple_display(llvm::raw_ostream &out, const Decl *decl) {
1132311388
}
1132411389

1132511390
if (auto value = dyn_cast<ValueDecl>(decl)) {
11326-
simple_display(out, value);
11391+
return simple_display(out, value);
1132711392
} else if (auto ext = dyn_cast<ExtensionDecl>(decl)) {
1132811393
out << "extension of ";
1132911394
if (auto typeRepr = ext->getExtendedTypeRepr())
@@ -11333,13 +11398,13 @@ void swift::simple_display(llvm::raw_ostream &out, const Decl *decl) {
1133311398
} else if (auto med = dyn_cast<MacroExpansionDecl>(decl)) {
1133411399
out << '#' << med->getMacroName() << " in ";
1133511400
printContext(out, med->getDeclContext());
11336-
if (med->getLoc().isValid()) {
11337-
out << '@';
11338-
med->getLoc().print(out, med->getASTContext().SourceMgr);
11339-
}
1134011401
} else {
1134111402
out << "(unknown decl)";
1134211403
}
11404+
if (decl->getLoc().isValid()) {
11405+
out << '@';
11406+
decl->getLoc().print(out, decl->getASTContext().SourceMgr);
11407+
}
1134311408
}
1134411409

1134511410
void swift::simple_display(llvm::raw_ostream &out,

0 commit comments

Comments
 (0)