@@ -356,7 +356,7 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
356
356
// for the inline bitfields.
357
357
union { uint64_t OpaqueBits;
358
358
359
- SWIFT_INLINE_BITFIELD_BASE (Decl, bitmax (NumDeclKindBits,8 )+1 +1 +1 +1 +1 +1 ,
359
+ SWIFT_INLINE_BITFIELD_BASE (Decl, bitmax (NumDeclKindBits,8 )+1 +1 +1 +1 +1 +1 + 1 ,
360
360
Kind : bitmax (NumDeclKindBits,8 ),
361
361
362
362
// / Whether this declaration is invalid.
@@ -382,7 +382,12 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
382
382
Hoisted : 1 ,
383
383
384
384
// / Whether the set of semantic attributes has been computed.
385
- SemanticAttrsComputed : 1
385
+ SemanticAttrsComputed : 1 ,
386
+
387
+ // / True if \c ObjCInterfaceAndImplementationRequest has been computed
388
+ // / and did \em not find anything. This is the fast path where we can bail
389
+ // / out without checking other caches or computing anything.
390
+ LacksObjCInterfaceOrImplementation : 1
386
391
);
387
392
388
393
SWIFT_INLINE_BITFIELD_FULL (PatternBindingDecl, Decl, 1 +1 +2 +16 ,
@@ -810,13 +815,6 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
810
815
private:
811
816
llvm::PointerUnion<DeclContext *, ASTContext *> Context;
812
817
813
- // / The imported Clang declaration representing the \c @_objcInterface for
814
- // / this declaration (or vice versa), or \c nullptr if there is none.
815
- // /
816
- // / If \c this (an otherwise nonsensical value), the value has not yet been
817
- // / computed.
818
- Decl *CachedObjCImplementationDecl;
819
-
820
818
Decl (const Decl&) = delete ;
821
819
void operator =(const Decl&) = delete ;
822
820
SourceLoc getLocFromSource () const ;
@@ -834,14 +832,15 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
834
832
protected:
835
833
836
834
Decl (DeclKind kind, llvm::PointerUnion<DeclContext *, ASTContext *> context)
837
- : Context (context), CachedObjCImplementationDecl ( this ) {
835
+ : Context (context) {
838
836
Bits.OpaqueBits = 0 ;
839
837
Bits.Decl .Kind = unsigned (kind);
840
838
Bits.Decl .Invalid = false ;
841
839
Bits.Decl .Implicit = false ;
842
840
Bits.Decl .FromClang = false ;
843
841
Bits.Decl .EscapedFromIfConfig = false ;
844
842
Bits.Decl .Hoisted = false ;
843
+ Bits.Decl .LacksObjCInterfaceOrImplementation = false ;
845
844
}
846
845
847
846
// / Get the Clang node associated with this declaration.
@@ -1162,29 +1161,36 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
1162
1161
}
1163
1162
1164
1163
// / If this is the Swift implementation of a declaration imported from ObjC,
1165
- // / returns the imported declaration. Otherwise return \c nullptr.
1164
+ // / returns the imported declaration. (If there are several, only the main
1165
+ // / class body will be returned.) Otherwise return \c nullptr.
1166
+ // /
1167
+ // / \seeAlso ExtensionDecl::isObjCInterface()
1168
+ Decl *getImplementedObjCDecl () const {
1169
+ auto impls = getAllImplementedObjCDecls ();
1170
+ if (impls.empty ())
1171
+ return nullptr ;
1172
+ return impls.front ();
1173
+ }
1174
+
1175
+ // / If this is the Swift implementation of a declaration imported from ObjC,
1176
+ // / returns the imported declarations. (There may be several for a main class
1177
+ // / body; if so, the first will be the class itself.) Otherwise return an empty list.
1166
1178
// /
1167
1179
// / \seeAlso ExtensionDecl::isObjCInterface()
1168
- Decl *getImplementedObjCDecl () const ;
1180
+ llvm::TinyPtrVector< Decl *> getAllImplementedObjCDecls () const ;
1169
1181
1170
1182
// / If this is the ObjC interface of a declaration implemented in Swift,
1171
1183
// / returns the implementating declaration. Otherwise return \c nullptr.
1172
1184
// /
1173
1185
// / \seeAlso ExtensionDecl::isObjCInterface()
1174
1186
Decl *getObjCImplementationDecl () const ;
1175
1187
1176
- llvm::Optional<Decl *> getCachedObjCImplementationDecl () const {
1177
- if (CachedObjCImplementationDecl == this )
1178
- return llvm::None;
1179
- return CachedObjCImplementationDecl;
1188
+ bool getCachedLacksObjCInterfaceOrImplementation () const {
1189
+ return Bits.Decl .LacksObjCInterfaceOrImplementation ;
1180
1190
}
1181
1191
1182
- void setCachedObjCImplementationDecl (Decl *decl) {
1183
- assert ((CachedObjCImplementationDecl == this
1184
- || CachedObjCImplementationDecl == decl)
1185
- && " can't change CachedObjCInterfaceDecl once it's computed" );
1186
- assert (decl != this && " can't form circular reference" );
1187
- CachedObjCImplementationDecl = decl;
1192
+ void setCachedLacksObjCInterfaceOrImplementation (bool value) {
1193
+ Bits.Decl .LacksObjCInterfaceOrImplementation = value;
1188
1194
}
1189
1195
1190
1196
// / Return the GenericContext if the Decl has one.
@@ -1846,8 +1852,8 @@ class ExtensionDecl final : public GenericContext, public Decl,
1846
1852
bool isEquivalentToExtendedContext () const ;
1847
1853
1848
1854
// / Returns the name of the category specified by the \c \@_objcImplementation
1849
- // / attribute, or \c None if the name is invalid. Do not call unless
1850
- // / \c isObjCImplementation() returns \c true .
1855
+ // / attribute, or \c None if the name is invalid or
1856
+ // / \c isObjCImplementation() is false .
1851
1857
llvm::Optional<Identifier> getCategoryNameForObjCImplementation () const ;
1852
1858
1853
1859
// / If this extension represents an imported Objective-C category, returns the
@@ -4962,11 +4968,14 @@ class ClassDecl final : public NominalTypeDecl {
4962
4968
// / the Objective-C runtime.
4963
4969
StringRef getObjCRuntimeName (llvm::SmallVectorImpl<char > &buffer) const ;
4964
4970
4965
- // / Return the imported declaration for the category with the given name; this
4966
- // / will always be an Objective-C-backed \c ExtensionDecl or, if \p name is
4967
- // / empty, \c ClassDecl. Returns \c nullptr if the class was not imported from
4968
- // / Objective-C or does not have an imported category by that name.
4969
- IterableDeclContext *getImportedObjCCategory (Identifier name) const ;
4971
+ // / Return the imported declaration(s) for the category with the given name; this
4972
+ // / will either be a single imported \c ExtensionDecl, an imported
4973
+ // / \c ClassDecl followed by zero or more imported \c ExtensionDecl s (if
4974
+ // / \p name is empty; the extensions are for any class extensions), or empty
4975
+ // / if the class was not imported from Objective-C or does not have a
4976
+ // / category by that name.
4977
+ llvm::TinyPtrVector<Decl *>
4978
+ getImportedObjCCategory (Identifier name) const ;
4970
4979
4971
4980
// Implement isa/cast/dyncast/etc.
4972
4981
static bool classof (const Decl *D) {
0 commit comments