3030
3131#include " clang/AST/DeclObjC.h"
3232#include " clang/Basic/Module.h"
33+ #include " llvm/ADT/STLExtras.h"
3334#include " llvm/ADT/SmallString.h"
3435#include < optional>
3536
@@ -241,10 +242,12 @@ swift::cxx_translation::getNameForCxx(const ValueDecl *VD,
241242namespace {
242243struct ObjCTypeWalker : TypeWalker {
243244 bool hadObjCType = false ;
245+ const ASTContext &ctx;
246+ ObjCTypeWalker (const ASTContext &ctx) : ctx(ctx) {}
244247 Action walkToTypePre (Type ty) override {
245248 if (auto *nominal = ty->getNominalOrBoundGenericNominal ()) {
246249 if (auto clangDecl = nominal->getClangDecl ()) {
247- if (cxx_translation::isObjCxxOnly (clangDecl)) {
250+ if (cxx_translation::isObjCxxOnly (clangDecl, ctx )) {
248251 hadObjCType = true ;
249252 return Action::Stop;
250253 }
@@ -256,19 +259,29 @@ struct ObjCTypeWalker : TypeWalker {
256259} // namespace
257260
258261bool swift::cxx_translation::isObjCxxOnly (const ValueDecl *VD) {
259- ObjCTypeWalker walker;
262+ ObjCTypeWalker walker{VD-> getASTContext ()} ;
260263 VD->getInterfaceType ().walk (walker);
261264 return walker.hadObjCType ;
262265}
263266
264- bool swift::cxx_translation::isObjCxxOnly (const clang::Decl *D) {
267+ bool swift::cxx_translation::isObjCxxOnly (const clang::Decl *D,
268+ const ASTContext &ctx) {
265269 // By default, we import all modules in Obj-C++ mode, so there is no robust
266- // way to tell if something is coming from an Obj-C module. The best
267- // approximation is to check if something is a framework module as most of
268- // those are written in Obj-C. Ideally, we want to add `requires ObjC` to all
269- // ObjC modules and respect that here to make this completely precise.
270- return D->getASTContext ().getLangOpts ().ObjC &&
271- D->getOwningModule ()->isPartOfFramework ();
270+ // way to tell if something is coming from an Obj-C module. Use the
271+ // requirements and the language options to check if we should actually
272+ // consider the module to have ObjC constructs.
273+ const auto &langOpts = D->getASTContext ().getLangOpts ();
274+ auto clangModule = D->getOwningModule ()->getTopLevelModule ();
275+ bool requiresObjC = false ;
276+ for (auto req : clangModule->Requirements )
277+ if (req.RequiredState && req.FeatureName == " objc" )
278+ requiresObjC = true ;
279+ return langOpts.ObjC &&
280+ (requiresObjC ||
281+ llvm::any_of (ctx.LangOpts .ModulesRequiringObjC ,
282+ [clangModule](StringRef moduleName) {
283+ return clangModule->getFullModuleName () == moduleName;
284+ }));
272285}
273286
274287swift::cxx_translation::DeclRepresentation
0 commit comments