Skip to content

Commit 828876f

Browse files
authored
Merge pull request #81625 from j-hui/fix-unavailable-enum
2 parents 021bd4a + 89f8855 commit 828876f

11 files changed

+164
-219
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 6 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -847,31 +847,6 @@ static bool isPrintLikeMethod(DeclName name, const DeclContext *dc) {
847847
using MirroredMethodEntry =
848848
std::tuple<const clang::ObjCMethodDecl*, ProtocolDecl*, bool /*isAsync*/>;
849849

850-
ImportedType findOptionSetType(clang::QualType type,
851-
ClangImporter::Implementation &Impl) {
852-
ImportedType importedType;
853-
auto fieldType = type;
854-
if (auto elaborated = dyn_cast<clang::ElaboratedType>(fieldType))
855-
fieldType = elaborated->desugar();
856-
if (auto typedefType = dyn_cast<clang::TypedefType>(fieldType)) {
857-
if (Impl.isUnavailableInSwift(typedefType->getDecl())) {
858-
if (auto clangEnum =
859-
findAnonymousEnumForTypedef(Impl.SwiftContext, typedefType)) {
860-
// If this fails, it means that we need a stronger predicate for
861-
// determining the relationship between an enum and typedef.
862-
assert(
863-
clangEnum.value()->getIntegerType()->getCanonicalTypeInternal() ==
864-
typedefType->getCanonicalTypeInternal());
865-
if (auto swiftEnum = Impl.importDecl(*clangEnum, Impl.CurrentVersion)) {
866-
importedType = {cast<TypeDecl>(swiftEnum)->getDeclaredInterfaceType(),
867-
false};
868-
}
869-
}
870-
}
871-
}
872-
return importedType;
873-
}
874-
875850
static bool areRecordFieldsComplete(const clang::CXXRecordDecl *decl) {
876851
for (const auto *f : decl->fields()) {
877852
auto *fieldRecord = f->getType()->getAsCXXRecordDecl();
@@ -4511,8 +4486,8 @@ namespace {
45114486
return nullptr;
45124487
}
45134488

4514-
auto fieldType = decl->getType();
4515-
ImportedType importedType = findOptionSetType(fieldType, Impl);
4489+
auto fieldType = desugarIfElaborated(decl->getType());
4490+
ImportedType importedType = importer::findOptionSetEnum(fieldType, Impl);
45164491

45174492
if (!importedType)
45184493
importedType =
@@ -6155,8 +6130,8 @@ namespace {
61556130
}
61566131
}
61576132

6158-
auto fieldType = decl->getType();
6159-
ImportedType importedType = findOptionSetType(fieldType, Impl);
6133+
auto fieldType = desugarIfElaborated(decl->getType());
6134+
ImportedType importedType = importer::findOptionSetEnum(fieldType, Impl);
61606135

61616136
if (!importedType)
61626137
importedType = Impl.importPropertyType(decl, isInSystemModule(dc));
@@ -7120,8 +7095,7 @@ SwiftDeclConverter::getImplicitProperty(ImportedName importedName,
71207095
getAccessorPropertyType(getter, false, getterName.getSelfIndex());
71217096
if (propertyType.isNull())
71227097
return nullptr;
7123-
if (auto elaborated = dyn_cast<clang::ElaboratedType>(propertyType))
7124-
propertyType = elaborated->desugar();
7098+
propertyType = desugarIfElaborated(propertyType);
71257099

71267100
// If there is a setter, check that the property it implies
71277101
// matches that of the getter.
@@ -7147,24 +7121,7 @@ SwiftDeclConverter::getImplicitProperty(ImportedName importedName,
71477121
if (dc->isTypeContext() && !getterName.getSelfIndex())
71487122
isStatic = true;
71497123

7150-
ImportedType importedType;
7151-
7152-
// Sometimes we import unavailable typedefs as enums. If that's the case,
7153-
// use the enum, not the typedef here.
7154-
if (auto typedefType = dyn_cast<clang::TypedefType>(propertyType.getTypePtr())) {
7155-
if (Impl.isUnavailableInSwift(typedefType->getDecl())) {
7156-
if (auto clangEnum = findAnonymousEnumForTypedef(Impl.SwiftContext, typedefType)) {
7157-
// If this fails, it means that we need a stronger predicate for
7158-
// determining the relationship between an enum and typedef.
7159-
assert(clangEnum.value()->getIntegerType()->getCanonicalTypeInternal() ==
7160-
typedefType->getCanonicalTypeInternal());
7161-
if (auto swiftEnum = Impl.importDecl(*clangEnum, Impl.CurrentVersion)) {
7162-
importedType = {cast<TypeDecl>(swiftEnum)->getDeclaredInterfaceType(),
7163-
false};
7164-
}
7165-
}
7166-
}
7167-
}
7124+
ImportedType importedType = importer::findOptionSetEnum(propertyType, Impl);
71687125

71697126
if (!importedType) {
71707127
// Compute the property type.

lib/ClangImporter/ImportEnumInfo.cpp

Lines changed: 38 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -244,10 +244,44 @@ StringRef importer::getCommonPluralPrefix(StringRef singular,
244244
}
245245

246246
const clang::Type *importer::getUnderlyingType(const clang::EnumDecl *decl) {
247-
const clang::Type *underlyingType = decl->getIntegerType().getTypePtr();
248-
if (auto elaborated = dyn_cast<clang::ElaboratedType>(underlyingType))
249-
underlyingType = elaborated->desugar().getTypePtr();
250-
return underlyingType;
247+
return importer::desugarIfElaborated(decl->getIntegerType().getTypePtr());
248+
}
249+
250+
ImportedType importer::findOptionSetEnum(clang::QualType type,
251+
ClangImporter::Implementation &Impl) {
252+
auto typedefType = dyn_cast<clang::TypedefType>(type);
253+
if (!typedefType || !Impl.isUnavailableInSwift(typedefType->getDecl()))
254+
// If this isn't a typedef, or it is a typedef that is available in Swift,
255+
// then this definitely isn't used for {CF,NS}_OPTIONS.
256+
return ImportedType();
257+
258+
if (Impl.SwiftContext.LangOpts.EnableCXXInterop &&
259+
!isCFOptionsMacro(typedefType->getDecl(), Impl.getClangPreprocessor())) {
260+
return ImportedType();
261+
}
262+
263+
auto clangEnum = findAnonymousEnumForTypedef(Impl.SwiftContext, typedefType);
264+
if (!clangEnum)
265+
return ImportedType();
266+
267+
// Assert that the typedef has the same underlying integer representation as
268+
// the enum we think it assigns a type name to.
269+
//
270+
// If these fails, it means that we need a stronger predicate for
271+
// determining the relationship between an enum and typedef.
272+
if (auto *tdEnum =
273+
dyn_cast<clang::EnumType>(typedefType->getCanonicalTypeInternal())) {
274+
ASSERT(clangEnum.value()->getIntegerType()->getCanonicalTypeInternal() ==
275+
tdEnum->getDecl()->getIntegerType()->getCanonicalTypeInternal());
276+
} else {
277+
ASSERT(clangEnum.value()->getIntegerType()->getCanonicalTypeInternal() ==
278+
typedefType->getCanonicalTypeInternal());
279+
}
280+
281+
if (auto *swiftEnum = Impl.importDecl(*clangEnum, Impl.CurrentVersion))
282+
return {cast<TypeDecl>(swiftEnum)->getDeclaredInterfaceType(), false};
283+
284+
return ImportedType();
251285
}
252286

253287
/// Determine the prefix to be stripped from the names of the enum constants

lib/ClangImporter/ImportEnumInfo.h

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919

2020
#include "swift/AST/ASTContext.h"
2121
#include "swift/AST/Decl.h"
22+
#include "clang/Lex/Preprocessor.h"
23+
#include "clang/Sema/Sema.h"
2224
#include "llvm/ADT/APSInt.h"
2325
#include "llvm/ADT/DenseMap.h"
2426

@@ -164,14 +166,18 @@ StringRef getCommonPluralPrefix(StringRef singular, StringRef plural);
164166
/// an elaborated type, an unwrapped type is returned.
165167
const clang::Type *getUnderlyingType(const clang::EnumDecl *decl);
166168

167-
inline bool isCFOptionsMacro(StringRef macroName) {
168-
return llvm::StringSwitch<bool>(macroName)
169+
inline bool isCFOptionsMacro(const clang::NamedDecl *decl,
170+
clang::Preprocessor &preprocessor) {
171+
auto loc = decl->getEndLoc();
172+
if (!loc.isMacroID())
173+
return false;
174+
return llvm::StringSwitch<bool>(preprocessor.getImmediateMacroName(loc))
169175
.Case("CF_OPTIONS", true)
170176
.Case("NS_OPTIONS", true)
171177
.Default(false);
172178
}
173179

174-
}
175-
}
180+
} // namespace importer
181+
} // namespace swift
176182

177183
#endif // SWIFT_CLANG_IMPORT_ENUM_H

lib/ClangImporter/ImportName.cpp

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "CFTypeInfo.h"
1919
#include "ClangClassTemplateNamePrinter.h"
2020
#include "ClangDiagnosticConsumer.h"
21+
#include "ImportEnumInfo.h"
2122
#include "ImporterImpl.h"
2223
#include "swift/AST/ASTContext.h"
2324
#include "swift/AST/ClangSwiftTypeCorrespondence.h"
@@ -1877,15 +1878,9 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
18771878
// imported into Swift to avoid having two types with the same name, which
18781879
// cause subtle name lookup issues.
18791880
if (swiftCtx.LangOpts.EnableCXXInterop &&
1880-
isUnavailableInSwift(D, nullptr, true)) {
1881-
auto loc = D->getEndLoc();
1882-
if (loc.isMacroID()) {
1883-
StringRef macroName =
1884-
clangSema.getPreprocessor().getImmediateMacroName(loc);
1885-
if (isCFOptionsMacro(macroName))
1886-
return ImportedName();
1887-
}
1888-
}
1881+
isUnavailableInSwift(D, nullptr, true) &&
1882+
isCFOptionsMacro(D, clangSema.getPreprocessor()))
1883+
return ImportedName();
18891884

18901885
/// Whether the result is a function name.
18911886
bool isFunction = false;

lib/ClangImporter/ImportType.cpp

Lines changed: 19 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
//===----------------------------------------------------------------------===//
1616

1717
#include "CFTypeInfo.h"
18+
#include "ImportEnumInfo.h"
1819
#include "ImporterImpl.h"
1920
#include "SwiftDeclSynthesizer.h"
2021
#include "swift/ABI/MetadataValues.h"
@@ -2282,10 +2283,7 @@ ImportedType ClangImporter::Implementation::importFunctionReturnType(
22822283
OptionalityOfReturn = OTK_ImplicitlyUnwrappedOptional;
22832284
}
22842285

2285-
clang::QualType returnType = clangDecl->getReturnType();
2286-
if (auto elaborated =
2287-
dyn_cast<clang::ElaboratedType>(returnType))
2288-
returnType = elaborated->desugar();
2286+
clang::QualType returnType = desugarIfElaborated(clangDecl->getReturnType());
22892287
// In C interop mode, the return type of library builtin functions
22902288
// like 'memcpy' from headers like 'string.h' drops
22912289
// any nullability specifiers from their return type, and preserves it on the
@@ -2323,19 +2321,9 @@ ImportedType ClangImporter::Implementation::importFunctionReturnType(
23232321
->isTemplateTypeParmType())
23242322
OptionalityOfReturn = OTK_None;
23252323

2326-
if (auto typedefType = dyn_cast<clang::TypedefType>(returnType)) {
2327-
if (isUnavailableInSwift(typedefType->getDecl())) {
2328-
if (auto clangEnum = findAnonymousEnumForTypedef(SwiftContext, typedefType)) {
2329-
// If this fails, it means that we need a stronger predicate for
2330-
// determining the relationship between an enum and typedef.
2331-
assert(clangEnum.value()->getIntegerType()->getCanonicalTypeInternal() ==
2332-
typedefType->getCanonicalTypeInternal());
2333-
if (auto swiftEnum = importDecl(*clangEnum, CurrentVersion)) {
2334-
return {cast<TypeDecl>(swiftEnum)->getDeclaredInterfaceType(), false};
2335-
}
2336-
}
2337-
}
2338-
}
2324+
ImportedType optionSetEnum = importer::findOptionSetEnum(returnType, *this);
2325+
if (optionSetEnum)
2326+
return optionSetEnum;
23392327

23402328
// Import the underlying result type.
23412329
if (clangDecl) {
@@ -2399,27 +2387,11 @@ ImportedType ClangImporter::Implementation::importFunctionParamsAndReturnType(
23992387

24002388
// Only eagerly import the return type if it's not too expensive (the current
24012389
// heuristic for that is if it's not a record type).
2402-
ImportedType importedType;
24032390
ImportDiagnosticAdder addDiag(*this, clangDecl,
24042391
clangDecl->getSourceRange().getBegin());
2405-
clang::QualType returnType = clangDecl->getReturnType();
2406-
if (auto elaborated = dyn_cast<clang::ElaboratedType>(returnType))
2407-
returnType = elaborated->desugar();
2408-
2409-
if (auto typedefType = dyn_cast<clang::TypedefType>(returnType)) {
2410-
if (isUnavailableInSwift(typedefType->getDecl())) {
2411-
if (auto clangEnum = findAnonymousEnumForTypedef(SwiftContext, typedefType)) {
2412-
// If this fails, it means that we need a stronger predicate for
2413-
// determining the relationship between an enum and typedef.
2414-
assert(clangEnum.value()->getIntegerType()->getCanonicalTypeInternal() ==
2415-
typedefType->getCanonicalTypeInternal());
2416-
if (auto swiftEnum = importDecl(*clangEnum, CurrentVersion)) {
2417-
importedType = {cast<TypeDecl>(swiftEnum)->getDeclaredInterfaceType(),
2418-
false};
2419-
}
2420-
}
2421-
}
2422-
}
2392+
clang::QualType returnType = desugarIfElaborated(clangDecl->getReturnType());
2393+
2394+
ImportedType importedType = importer::findOptionSetEnum(returnType, *this);
24232395

24242396
if (auto templateType =
24252397
dyn_cast<clang::TemplateTypeParmType>(returnType)) {
@@ -2483,9 +2455,7 @@ ClangImporter::Implementation::importParameterType(
24832455
std::optional<unsigned> completionHandlerErrorParamIndex,
24842456
ArrayRef<GenericTypeParamDecl *> genericParams,
24852457
llvm::function_ref<void(Diagnostic &&)> addImportDiagnosticFn) {
2486-
auto paramTy = param->getType();
2487-
if (auto elaborated = dyn_cast<clang::ElaboratedType>(paramTy))
2488-
paramTy = elaborated->desugar();
2458+
auto paramTy = desugarIfElaborated(param->getType());
24892459

24902460
ImportTypeKind importKind = paramIsCompletionHandler
24912461
? ImportTypeKind::CompletionHandlerParameter
@@ -2498,23 +2468,8 @@ ClangImporter::Implementation::importParameterType(
24982468
bool isConsuming = false;
24992469
bool isParamTypeImplicitlyUnwrapped = false;
25002470

2501-
// Sometimes we import unavailable typedefs as enums. If that's the case,
2502-
// use the enum, not the typedef here.
2503-
if (auto typedefType = dyn_cast<clang::TypedefType>(paramTy.getTypePtr())) {
2504-
if (isUnavailableInSwift(typedefType->getDecl())) {
2505-
if (auto clangEnum =
2506-
findAnonymousEnumForTypedef(SwiftContext, typedefType)) {
2507-
// If this fails, it means that we need a stronger predicate for
2508-
// determining the relationship between an enum and typedef.
2509-
assert(clangEnum.value()
2510-
->getIntegerType()
2511-
->getCanonicalTypeInternal() ==
2512-
typedefType->getCanonicalTypeInternal());
2513-
if (auto swiftEnum = importDecl(*clangEnum, CurrentVersion)) {
2514-
swiftParamTy = cast<TypeDecl>(swiftEnum)->getDeclaredInterfaceType();
2515-
}
2516-
}
2517-
}
2471+
if (auto optionSetEnum = importer::findOptionSetEnum(paramTy, *this)) {
2472+
swiftParamTy = optionSetEnum.getType();
25182473
} else if (isa<clang::PointerType>(paramTy) &&
25192474
isa<clang::TemplateTypeParmType>(paramTy->getPointeeType())) {
25202475
auto pointeeType = paramTy->getPointeeType();
@@ -2955,13 +2910,8 @@ ArgumentAttrs ClangImporter::Implementation::inferDefaultArgument(
29552910
return argumentAttrs;
29562911
}
29572912
}
2958-
auto loc = typedefDecl->getEndLoc();
2959-
if (loc.isMacroID()) {
2960-
StringRef macroName =
2961-
nameImporter.getClangPreprocessor().getImmediateMacroName(loc);
2962-
if (isCFOptionsMacro(macroName))
2963-
return argumentAttrs;
2964-
}
2913+
if (isCFOptionsMacro(typedefDecl, nameImporter.getClangPreprocessor()))
2914+
return argumentAttrs;
29652915
}
29662916
}
29672917

@@ -3234,26 +3184,8 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
32343184

32353185
ImportDiagnosticAdder addImportDiag(*this, clangDecl,
32363186
clangDecl->getLocation());
3237-
clang::QualType resultType = clangDecl->getReturnType();
3238-
if (auto elaborated = dyn_cast<clang::ElaboratedType>(resultType))
3239-
resultType = elaborated->desugar();
3240-
3241-
ImportedType importedType;
3242-
if (auto typedefType = dyn_cast<clang::TypedefType>(resultType.getTypePtr())) {
3243-
if (isUnavailableInSwift(typedefType->getDecl())) {
3244-
if (auto clangEnum = findAnonymousEnumForTypedef(SwiftContext, typedefType)) {
3245-
// If this fails, it means that we need a stronger predicate for
3246-
// determining the relationship between an enum and typedef.
3247-
assert(clangEnum.value()->getIntegerType()->getCanonicalTypeInternal() ==
3248-
typedefType->getCanonicalTypeInternal());
3249-
if (auto swiftEnum = importDecl(*clangEnum, CurrentVersion)) {
3250-
importedType = {cast<TypeDecl>(swiftEnum)->getDeclaredInterfaceType(),
3251-
false};
3252-
}
3253-
}
3254-
}
3255-
}
3256-
3187+
clang::QualType resultType = desugarIfElaborated(clangDecl->getReturnType());
3188+
ImportedType importedType = importer::findOptionSetEnum(resultType, *this);
32573189
if (!importedType)
32583190
importedType = importType(resultType, resultKind, addImportDiag,
32593191
allowNSUIntegerAsIntInResult, Bridgeability::Full,
@@ -3501,9 +3433,6 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
35013433
importedType.isImplicitlyUnwrapped()};
35023434
}
35033435

3504-
ImportedType findOptionSetType(clang::QualType type,
3505-
ClangImporter::Implementation &Impl);
3506-
35073436
ImportedType ClangImporter::Implementation::importAccessorParamsAndReturnType(
35083437
const DeclContext *dc, const clang::ObjCPropertyDecl *property,
35093438
const clang::ObjCMethodDecl *clangDecl, bool isFromSystemModule,
@@ -3529,11 +3458,11 @@ ImportedType ClangImporter::Implementation::importAccessorParamsAndReturnType(
35293458
if (!origDC)
35303459
return {Type(), false};
35313460

3532-
auto fieldType = isGetter ? clangDecl->getReturnType()
3533-
: clangDecl->getParamDecl(0)->getType();
3534-
3461+
auto fieldType =
3462+
desugarIfElaborated(isGetter ? clangDecl->getReturnType()
3463+
: clangDecl->getParamDecl(0)->getType());
35353464
// Import the property type, independent of what kind of accessor this is.
3536-
ImportedType importedType = findOptionSetType(fieldType, *this);
3465+
ImportedType importedType = importer::findOptionSetEnum(fieldType, *this);
35373466
if (!importedType)
35383467
importedType = importPropertyType(property, isFromSystemModule);
35393468
if (!importedType)

0 commit comments

Comments
 (0)