2929
3030#include " clang/AST/DeclObjC.h"
3131#include " clang/Basic/Module.h"
32+ #include " llvm/ADT/STLExtras.h"
3233#include " llvm/ADT/SmallString.h"
3334#include < optional>
3435
@@ -242,10 +243,12 @@ swift::cxx_translation::getNameForCxx(const ValueDecl *VD,
242243namespace {
243244struct ObjCTypeWalker : TypeWalker {
244245 bool hadObjCType = false ;
246+ const ASTContext &ctx;
247+ ObjCTypeWalker (const ASTContext &ctx) : ctx(ctx) {}
245248 Action walkToTypePre (Type ty) override {
246249 if (auto *nominal = ty->getNominalOrBoundGenericNominal ()) {
247250 if (auto clangDecl = nominal->getClangDecl ()) {
248- if (cxx_translation::isObjCxxOnly (clangDecl)) {
251+ if (cxx_translation::isObjCxxOnly (clangDecl, ctx )) {
249252 hadObjCType = true ;
250253 return Action::Stop;
251254 }
@@ -257,19 +260,29 @@ struct ObjCTypeWalker : TypeWalker {
257260} // namespace
258261
259262bool swift::cxx_translation::isObjCxxOnly (const ValueDecl *VD) {
260- ObjCTypeWalker walker;
263+ ObjCTypeWalker walker{VD-> getASTContext ()} ;
261264 VD->getInterfaceType ().walk (walker);
262265 return walker.hadObjCType ;
263266}
264267
265- bool swift::cxx_translation::isObjCxxOnly (const clang::Decl *D) {
268+ bool swift::cxx_translation::isObjCxxOnly (const clang::Decl *D,
269+ const ASTContext &ctx) {
266270 // 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+ }));
273286}
274287
275288swift::cxx_translation::DeclRepresentation
0 commit comments