@@ -207,17 +207,21 @@ void simple_display(llvm::raw_ostream &out,
207
207
const ClangCategoryLookupDescriptor &desc);
208
208
SourceLoc extractNearestSourceLoc (const ClangCategoryLookupDescriptor &desc);
209
209
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.
216
213
// /
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.
218
222
class ClangCategoryLookupRequest
219
223
: public SimpleRequest<ClangCategoryLookupRequest,
220
- IterableDeclContext * (ClangCategoryLookupDescriptor),
224
+ TinyPtrVector<Decl *> (ClangCategoryLookupDescriptor),
221
225
RequestFlags::Uncached> {
222
226
public:
223
227
using SimpleRequest::SimpleRequest;
@@ -226,39 +230,46 @@ class ClangCategoryLookupRequest
226
230
friend SimpleRequest;
227
231
228
232
// Evaluation.
229
- IterableDeclContext * evaluate (Evaluator &evaluator,
233
+ TinyPtrVector<Decl *> evaluate (Evaluator &evaluator,
230
234
ClangCategoryLookupDescriptor desc) const ;
231
235
};
232
236
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.
235
244
struct ObjCInterfaceAndImplementation final {
236
- Decl *interfaceDecl ;
245
+ llvm::TinyPtrVector< Decl *> interfaceDecls ;
237
246
Decl *implementationDecl;
238
247
239
- ObjCInterfaceAndImplementation (Decl *interfaceDecl ,
248
+ ObjCInterfaceAndImplementation (llvm::TinyPtrVector< Decl *> interfaceDecls ,
240
249
Decl *implementationDecl)
241
- : interfaceDecl(interfaceDecl ), implementationDecl(implementationDecl)
250
+ : interfaceDecls(interfaceDecls ), implementationDecl(implementationDecl)
242
251
{
243
- assert (interfaceDecl && implementationDecl &&
252
+ assert (!interfaceDecls. empty () && implementationDecl &&
244
253
" interface and implementation are both non-null" );
245
254
}
246
255
247
256
ObjCInterfaceAndImplementation ()
248
- : interfaceDecl( nullptr ), implementationDecl(nullptr ) {}
257
+ : interfaceDecls( ), implementationDecl(nullptr ) {}
249
258
250
259
operator bool () const {
251
- return interfaceDecl ;
260
+ return interfaceDecls. empty () ;
252
261
}
253
262
254
263
friend llvm::hash_code
255
264
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 );
257
268
}
258
269
259
270
friend bool operator ==(const ObjCInterfaceAndImplementation &lhs,
260
271
const ObjCInterfaceAndImplementation &rhs) {
261
- return lhs.interfaceDecl == rhs.interfaceDecl
272
+ return lhs.interfaceDecls == rhs.interfaceDecls
262
273
&& lhs.implementationDecl == rhs.implementationDecl ;
263
274
}
264
275
@@ -272,13 +283,12 @@ void simple_display(llvm::raw_ostream &out,
272
283
const ObjCInterfaceAndImplementation &desc);
273
284
SourceLoc extractNearestSourceLoc (const ObjCInterfaceAndImplementation &desc);
274
285
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.
279
289
// /
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.
282
292
class ObjCInterfaceAndImplementationRequest
283
293
: public SimpleRequest<ObjCInterfaceAndImplementationRequest,
284
294
ObjCInterfaceAndImplementation (Decl *),
0 commit comments