29
29
30
30
#include " clang/AST/DeclObjC.h"
31
31
#include " clang/Basic/Module.h"
32
+ #include " llvm/ADT/STLExtras.h"
32
33
#include " llvm/ADT/SmallString.h"
33
34
#include < optional>
34
35
@@ -242,10 +243,12 @@ swift::cxx_translation::getNameForCxx(const ValueDecl *VD,
242
243
namespace {
243
244
struct ObjCTypeWalker : TypeWalker {
244
245
bool hadObjCType = false ;
246
+ const ASTContext &ctx;
247
+ ObjCTypeWalker (const ASTContext &ctx) : ctx(ctx) {}
245
248
Action walkToTypePre (Type ty) override {
246
249
if (auto *nominal = ty->getNominalOrBoundGenericNominal ()) {
247
250
if (auto clangDecl = nominal->getClangDecl ()) {
248
- if (cxx_translation::isObjCxxOnly (clangDecl)) {
251
+ if (cxx_translation::isObjCxxOnly (clangDecl, ctx )) {
249
252
hadObjCType = true ;
250
253
return Action::Stop;
251
254
}
@@ -257,19 +260,29 @@ struct ObjCTypeWalker : TypeWalker {
257
260
} // namespace
258
261
259
262
bool swift::cxx_translation::isObjCxxOnly (const ValueDecl *VD) {
260
- ObjCTypeWalker walker;
263
+ ObjCTypeWalker walker{VD-> getASTContext ()} ;
261
264
VD->getInterfaceType ().walk (walker);
262
265
return walker.hadObjCType ;
263
266
}
264
267
265
- bool swift::cxx_translation::isObjCxxOnly (const clang::Decl *D) {
268
+ bool swift::cxx_translation::isObjCxxOnly (const clang::Decl *D,
269
+ const ASTContext &ctx) {
266
270
// By default, we import all modules in Obj-C++ mode, so there is no robust
267
- // way to tell if something is coming from an Obj-C module. The best
268
- // approximation is to check if something is a framework module as most of
269
- // those are written in Obj-C. Ideally, we want to add `requires ObjC` to all
270
- // ObjC modules and respect that here to make this completely precise.
271
- return D->getASTContext ().getLangOpts ().ObjC &&
272
- D->getOwningModule ()->isPartOfFramework ();
271
+ // way to tell if something is coming from an Obj-C module. Use the
272
+ // requirements and the language options to check if we should actually
273
+ // consider the module to have ObjC constructs.
274
+ const auto &langOpts = D->getASTContext ().getLangOpts ();
275
+ auto clangModule = D->getOwningModule ()->getTopLevelModule ();
276
+ bool requiresObjC = false ;
277
+ for (auto req : clangModule->Requirements )
278
+ if (req.RequiredState && req.FeatureName == " objc" )
279
+ requiresObjC = true ;
280
+ return langOpts.ObjC &&
281
+ (requiresObjC ||
282
+ llvm::any_of (ctx.LangOpts .ModulesRequiringObjC ,
283
+ [clangModule](StringRef moduleName) {
284
+ return clangModule->getFullModuleName () == moduleName;
285
+ }));
273
286
}
274
287
275
288
swift::cxx_translation::DeclRepresentation
0 commit comments