[cxx-interop] Refactor: do not rely on Clang module importer being available

This makes sure that we can emit a pch from a C++ header that uses `CF_OPTIONS`.

rdar://112225263
This commit is contained in:
Egor Zhdan
2023-09-15 17:10:04 +01:00
parent f7c2257f51
commit 6a2f10a388
6 changed files with 27 additions and 20 deletions

View File

@@ -306,9 +306,6 @@ public:
virtual EffectiveClangContext getEffectiveClangContext(
const NominalTypeDecl *nominal) = 0;
virtual const clang::TypedefType *
getTypeDefForCXXCFOptionsDefinition(const clang::Decl *candidateDecl) = 0;
virtual SourceLoc importSourceLocation(clang::SourceLocation loc) = 0;
};

View File

@@ -603,8 +603,8 @@ public:
/// Enable the symbolic import experimental feature for the given callback.
void withSymbolicFeatureEnabled(llvm::function_ref<void(void)> callback);
const clang::TypedefType *getTypeDefForCXXCFOptionsDefinition(
const clang::Decl *candidateDecl) override;
static const clang::TypedefType *getTypedefForCXXCFOptionsDefinition(
const clang::Decl *candidateDecl, const ASTContext &ctx);
SourceLoc importSourceLocation(clang::SourceLocation loc) override;
};

View File

@@ -2541,8 +2541,8 @@ ASTMangler::getTypeDefForCXXCFOptionsDefinition(const ValueDecl *decl) {
if (!clangDecl)
return nullptr;
const auto &clangModuleLoader = decl->getASTContext().getClangModuleLoader();
return clangModuleLoader->getTypeDefForCXXCFOptionsDefinition(clangDecl);
auto &ctx = decl->getASTContext();
return ClangImporter::getTypedefForCXXCFOptionsDefinition(clangDecl, ctx);
}
const clang::NamedDecl *

View File

@@ -7022,26 +7022,23 @@ void ClangImporter::withSymbolicFeatureEnabled(
oldImportSymbolicCXXDecls.get());
}
const clang::TypedefType *ClangImporter::getTypeDefForCXXCFOptionsDefinition(
const clang::Decl *candidateDecl) {
if (!Impl.SwiftContext.LangOpts.EnableCXXInterop)
const clang::TypedefType *ClangImporter::getTypedefForCXXCFOptionsDefinition(
const clang::Decl *candidateDecl, const ASTContext &ctx) {
if (!ctx.LangOpts.EnableCXXInterop)
return nullptr;
auto enumDecl = dyn_cast<clang::EnumDecl>(candidateDecl);
if (!enumDecl)
return nullptr;
if (!enumDecl->getDeclName().isEmpty())
return nullptr;
const clang::ElaboratedType *elaboratedType =
dyn_cast<clang::ElaboratedType>(enumDecl->getIntegerType().getTypePtr());
enumDecl->getIntegerType()->getAs<clang::ElaboratedType>();
if (auto typedefType =
elaboratedType
? dyn_cast<clang::TypedefType>(elaboratedType->desugar())
: dyn_cast<clang::TypedefType>(
enumDecl->getIntegerType().getTypePtr())) {
: enumDecl->getIntegerType()->getAs<clang::TypedefType>()) {
auto enumExtensibilityAttr =
elaboratedType
? enumDecl->getAttr<clang::EnumExtensibilityAttr>()
@@ -7054,8 +7051,13 @@ const clang::TypedefType *ClangImporter::getTypeDefForCXXCFOptionsDefinition(
enumExtensibilityAttr->getExtensibility() ==
clang::EnumExtensibilityAttr::Open &&
hasFlagEnumAttr) {
return Impl.isUnavailableInSwift(typedefType->getDecl()) ? typedefType
: nullptr;
// Make sure the typedef is marked as unavailable in Swift.
auto typedefDecl = typedefType->getDecl();
for (auto *attr :
typedefDecl->specific_attrs<clang::AvailabilityAttr>()) {
if (attr->getPlatform()->getName() == "swift")
return typedefType;
}
}
}

View File

@@ -2656,9 +2656,8 @@ ArgumentAttrs ClangImporter::Implementation::inferDefaultArgument(
if (declIter != declsInContext.end()) {
if (auto enumDecl = dyn_cast<clang::EnumDecl>(*declIter)) {
if (auto cfOptionsTy =
nameImporter.getContext()
.getClangModuleLoader()
->getTypeDefForCXXCFOptionsDefinition(enumDecl)) {
ClangImporter::getTypedefForCXXCFOptionsDefinition(
enumDecl, nameImporter.getContext())) {
if (cfOptionsTy->getDecl() == typedefDecl) {
auto enumName = typedefDecl->getName();
ArgumentAttrs argumentAttrs(DefaultArgumentKind::None, true,

View File

@@ -1,7 +1,16 @@
// RUN: rm -rf %t
// RUN: mkdir -p %t/pch
// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %S/Inputs -enable-objc-interop -enable-experimental-cxx-interop
// RUN: %target-swift-frontend -emit-pch -enable-objc-interop -enable-experimental-cxx-interop -o %t/pch/customNSOptions.pch %S/Inputs/customNSOptions.h
// RUN: %target-typecheck-verify-swift -D BRIDGING_HEADER -I %S/Inputs -import-objc-header %t/pch/customNSOptions.pch -enable-objc-interop -enable-experimental-cxx-interop %s
// REQUIRES: objc_interop
#if !BRIDGING_HEADER
import CustomNSOptions
#endif
let flags1: MyControlFlags = []
let flags2: MyControlFlags = [.first]