@@ -356,7 +356,7 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
356356 // for the inline bitfields.
357357 union { uint64_t OpaqueBits;
358358
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 ,
360360 Kind : bitmax (NumDeclKindBits,8 ),
361361
362362 // / Whether this declaration is invalid.
@@ -382,7 +382,12 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
382382 Hoisted : 1 ,
383383
384384 // / 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
386391 );
387392
388393 SWIFT_INLINE_BITFIELD_FULL (PatternBindingDecl, Decl, 1 +1 +2 +16 ,
@@ -810,13 +815,6 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
810815private:
811816 llvm::PointerUnion<DeclContext *, ASTContext *> Context;
812817
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-
820818 Decl (const Decl&) = delete ;
821819 void operator =(const Decl&) = delete ;
822820 SourceLoc getLocFromSource () const ;
@@ -834,14 +832,15 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
834832protected:
835833
836834 Decl (DeclKind kind, llvm::PointerUnion<DeclContext *, ASTContext *> context)
837- : Context (context), CachedObjCImplementationDecl ( this ) {
835+ : Context (context) {
838836 Bits.OpaqueBits = 0 ;
839837 Bits.Decl .Kind = unsigned (kind);
840838 Bits.Decl .Invalid = false ;
841839 Bits.Decl .Implicit = false ;
842840 Bits.Decl .FromClang = false ;
843841 Bits.Decl .EscapedFromIfConfig = false ;
844842 Bits.Decl .Hoisted = false ;
843+ Bits.Decl .LacksObjCInterfaceOrImplementation = false ;
845844 }
846845
847846 // / Get the Clang node associated with this declaration.
@@ -1162,29 +1161,36 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
11621161 }
11631162
11641163 // / 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.
11661178 // /
11671179 // / \seeAlso ExtensionDecl::isObjCInterface()
1168- Decl *getImplementedObjCDecl () const ;
1180+ llvm::TinyPtrVector< Decl *> getAllImplementedObjCDecls () const ;
11691181
11701182 // / If this is the ObjC interface of a declaration implemented in Swift,
11711183 // / returns the implementating declaration. Otherwise return \c nullptr.
11721184 // /
11731185 // / \seeAlso ExtensionDecl::isObjCInterface()
11741186 Decl *getObjCImplementationDecl () const ;
11751187
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 ;
11801190 }
11811191
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;
11881194 }
11891195
11901196 // / Return the GenericContext if the Decl has one.
@@ -1846,8 +1852,8 @@ class ExtensionDecl final : public GenericContext, public Decl,
18461852 bool isEquivalentToExtendedContext () const ;
18471853
18481854 // / 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 .
18511857 llvm::Optional<Identifier> getCategoryNameForObjCImplementation () const ;
18521858
18531859 // / If this extension represents an imported Objective-C category, returns the
@@ -4962,11 +4968,14 @@ class ClassDecl final : public NominalTypeDecl {
49624968 // / the Objective-C runtime.
49634969 StringRef getObjCRuntimeName (llvm::SmallVectorImpl<char > &buffer) const ;
49644970
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 ;
49704979
49714980 // Implement isa/cast/dyncast/etc.
49724981 static bool classof (const Decl *D) {
0 commit comments