@@ -207,17 +207,21 @@ void simple_display(llvm::raw_ostream &out,
207207 const ClangCategoryLookupDescriptor &desc);
208208SourceLoc extractNearestSourceLoc (const ClangCategoryLookupDescriptor &desc);
209209
210- // / Given a Swift class, find the imported Swift decl representing the
211- // / \c \@interface with the given category name. That is, this will return an
212- // / \c swift::ExtensionDecl backed by a \c clang::ObjCCategoryDecl, or a
213- // / \c swift::ClassDecl backed by a \c clang::ObjCInterfaceDecl, or \c nullptr
214- // / if the class is not imported from Clang or it does not have a category by
215- // / that name.
210+ // / Given a Swift class, find the imported Swift decl(s) representing the
211+ // / \c \@interface with the given category name. An empty \c categoryName
212+ // / represents the main interface for the class.
216213// /
217- // / An empty/invalid \c categoryName requests the main interface for the class.
214+ // / That is, this request will return one of:
215+ // /
216+ // / \li a single \c swift::ExtensionDecl backed by a \c clang::ObjCCategoryDecl
217+ // / \li a \c swift::ClassDecl backed by a \c clang::ObjCInterfaceDecl, plus
218+ // / zero or more \c swift::ExtensionDecl s backed by
219+ // / \c clang::ObjCCategoryDecl s (representing ObjC class extensions).
220+ // / \li an empty list if the class is not imported from Clang or it does not
221+ // / have a category by that name.
218222class ClangCategoryLookupRequest
219223 : public SimpleRequest<ClangCategoryLookupRequest,
220- IterableDeclContext * (ClangCategoryLookupDescriptor),
224+ TinyPtrVector<Decl *> (ClangCategoryLookupDescriptor),
221225 RequestFlags::Uncached> {
222226public:
223227 using SimpleRequest::SimpleRequest;
@@ -226,39 +230,46 @@ class ClangCategoryLookupRequest
226230 friend SimpleRequest;
227231
228232 // Evaluation.
229- IterableDeclContext * evaluate (Evaluator &evaluator,
233+ TinyPtrVector<Decl *> evaluate (Evaluator &evaluator,
230234 ClangCategoryLookupDescriptor desc) const ;
231235};
232236
233- // / Links an imported Clang decl to the native Swift decl(s) that implement it
234- // / using \c \@_objcImplementation.
237+ // / Links an \c \@_objcImplementation decl to the imported declaration(s) that
238+ // / it implements.
239+ // /
240+ // / There is usually a 1:1 correspondence between interfaces and
241+ // / implementations, except that a class's main implementation implements
242+ // / both its main interface and any class extension interfaces. In this
243+ // / situation, the main class is always the first decl in \c interfaceDecls.
235244struct ObjCInterfaceAndImplementation final {
236- Decl *interfaceDecl ;
245+ llvm::TinyPtrVector< Decl *> interfaceDecls ;
237246 Decl *implementationDecl;
238247
239- ObjCInterfaceAndImplementation (Decl *interfaceDecl ,
248+ ObjCInterfaceAndImplementation (llvm::TinyPtrVector< Decl *> interfaceDecls ,
240249 Decl *implementationDecl)
241- : interfaceDecl(interfaceDecl ), implementationDecl(implementationDecl)
250+ : interfaceDecls(interfaceDecls ), implementationDecl(implementationDecl)
242251 {
243- assert (interfaceDecl && implementationDecl &&
252+ assert (!interfaceDecls. empty () && implementationDecl &&
244253 " interface and implementation are both non-null" );
245254 }
246255
247256 ObjCInterfaceAndImplementation ()
248- : interfaceDecl( nullptr ), implementationDecl(nullptr ) {}
257+ : interfaceDecls( ), implementationDecl(nullptr ) {}
249258
250259 operator bool () const {
251- return interfaceDecl ;
260+ return interfaceDecls. empty () ;
252261 }
253262
254263 friend llvm::hash_code
255264 hash_value (const ObjCInterfaceAndImplementation &pair) {
256- return llvm::hash_combine (pair.interfaceDecl , pair.implementationDecl );
265+ return hash_combine (llvm::hash_combine_range (pair.interfaceDecls .begin (),
266+ pair.interfaceDecls .end ()),
267+ pair.implementationDecl );
257268 }
258269
259270 friend bool operator ==(const ObjCInterfaceAndImplementation &lhs,
260271 const ObjCInterfaceAndImplementation &rhs) {
261- return lhs.interfaceDecl == rhs.interfaceDecl
272+ return lhs.interfaceDecls == rhs.interfaceDecls
262273 && lhs.implementationDecl == rhs.implementationDecl ;
263274 }
264275
@@ -272,13 +283,12 @@ void simple_display(llvm::raw_ostream &out,
272283 const ObjCInterfaceAndImplementation &desc);
273284SourceLoc extractNearestSourceLoc (const ObjCInterfaceAndImplementation &desc);
274285
275- // / Given a \c Decl whose declaration is imported from ObjC but whose
276- // / implementation is provided by a Swift \c \@_objcImplementation
277- // / \c extension , return both decls, with the imported interface first.
278- // / Otherwise return \c {nullptr,nullptr} .
286+ // / Given a \c Decl , determine if it is an implementation with separate
287+ // / interfaces imported from ObjC (or vice versa) and if so, return all of the
288+ // / declarations involved in this relationship. Otherwise return an empty value.
279289// /
280- // / We retrieve both in a single request because we want to cache the
281- // / relationship on both sides to avoid duplicating work.
290+ // / We perform this lookup in both directions using a single request because
291+ // / we want to cache the relationship on both sides to avoid duplicating work.
282292class ObjCInterfaceAndImplementationRequest
283293 : public SimpleRequest<ObjCInterfaceAndImplementationRequest,
284294 ObjCInterfaceAndImplementation (Decl *),
0 commit comments