Skip to content

Commit 8d98f50

Browse files
committed
[cxx-interop][rebranch] Handle clang elaborated types properly
Clang recently started wrapping more types in `clang::ElaboratedType` after this change: https://reviews.llvm.org/D112374 This broke some assumptions in ClangImporter, specifically in enum handling logic. This change adjusts those. Fixes these tests in rebranch: * `Interop/Cxx/enum/anonymous-with-swift-name-module-interface.swift` * `Interop/Cxx/enum/anonymous-with-swift-name-objc-module-interface.swift` * `Interop/Cxx/enum/anonymous-with-swift-name.swift` * `Interop/Cxx/enum/c-enums-NS_OPTIONS-NS_REFINED_FOR_SWIFT.swift` * `Interop/Cxx/enum/c-enums-NS_OPTIONS.swift` * `Interop/Cxx/enum/c-enums-withOptions-omit.swift` * `Interop/Cxx/class/inheritance/fields-module-interface.swift` * `Interop/Cxx/class/inheritance/fields.swift` * `Interop/Cxx/class/inheritance/functions-module-interface.swift` * `Interop/Cxx/class/inheritance/sub-types-module-interface.swift` * `Interop/Cxx/class/inheritance/type-aliases-module-interface.swift`
1 parent c5a7eff commit 8d98f50

File tree

5 files changed

+49
-20
lines changed

5 files changed

+49
-20
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5659,6 +5659,8 @@ SwiftDeclConverter::getImplicitProperty(ImportedName importedName,
56595659
getAccessorPropertyType(getter, false, getterName.getSelfIndex());
56605660
if (propertyType.isNull())
56615661
return nullptr;
5662+
if (auto elaborated = dyn_cast<clang::ElaboratedType>(propertyType))
5663+
propertyType = elaborated->desugar();
56625664

56635665
// If there is a setter, check that the property it implies
56645666
// matches that of the getter.
@@ -7133,6 +7135,8 @@ canSkipOverTypedef(ClangImporter::Implementation &Impl,
71337135
return nullptr;
71347136

71357137
clang::QualType UnderlyingType = ClangTypedef->getUnderlyingType();
7138+
if (auto elaborated = dyn_cast<clang::ElaboratedType>(UnderlyingType))
7139+
UnderlyingType = elaborated->desugar();
71367140

71377141
// A typedef to a typedef should get imported as a typealias.
71387142
auto *TypedefT = UnderlyingType->getAs<clang::TypedefType>();
@@ -8456,6 +8460,8 @@ void ClangImporter::Implementation::loadAllMembersOfRecordDecl(
84568460
clang::QualType baseType = base.getType();
84578461
if (auto spectType = dyn_cast<clang::TemplateSpecializationType>(baseType))
84588462
baseType = spectType->desugar();
8463+
if (auto elaborated = dyn_cast<clang::ElaboratedType>(baseType))
8464+
baseType = elaborated->desugar();
84598465
if (!isa<clang::RecordType>(baseType))
84608466
continue;
84618467

lib/ClangImporter/ImportEnumInfo.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,12 @@ void EnumInfo::classifyEnum(const clang::EnumDecl *decl,
7070
// name for the Swift type.
7171
if (!decl->hasNameForLinkage()) {
7272
// If this enum comes from a typedef, we can find a name.
73-
if (!isa<clang::TypedefType>(decl->getIntegerType().getTypePtr()) ||
73+
const clang::Type *underlyingType = getUnderlyingType(decl);
74+
if (!isa<clang::TypedefType>(underlyingType) ||
7475
// If the typedef is available in Swift, the user will get ambiguity.
7576
// It also means they may not have intended this API to be imported like this.
7677
!importer::isUnavailableInSwift(
77-
cast<clang::TypedefType>(decl->getIntegerType().getTypePtr())->getDecl(),
78+
cast<clang::TypedefType>(underlyingType)->getDecl(),
7879
nullptr, true)) {
7980
kind = EnumKind::Constants;
8081
return;
@@ -241,6 +242,13 @@ StringRef importer::getCommonPluralPrefix(StringRef singular,
241242
return commonPrefix;
242243
}
243244

245+
const clang::Type *importer::getUnderlyingType(const clang::EnumDecl *decl) {
246+
const clang::Type *underlyingType = decl->getIntegerType().getTypePtr();
247+
if (auto elaborated = dyn_cast<clang::ElaboratedType>(underlyingType))
248+
underlyingType = elaborated->desugar().getTypePtr();
249+
return underlyingType;
250+
}
251+
244252
/// Determine the prefix to be stripped from the names of the enum constants
245253
/// within the given enum.
246254
void EnumInfo::determineConstantNamePrefix(const clang::EnumDecl *decl) {
@@ -350,8 +358,8 @@ void EnumInfo::determineConstantNamePrefix(const clang::EnumDecl *decl) {
350358
StringRef enumNameStr;
351359
// If there's no name, this must be typedef. So use the typedef's name.
352360
if (!decl->hasNameForLinkage()) {
353-
auto typedefDecl = cast<clang::TypedefType>(
354-
decl->getIntegerType().getTypePtr())->getDecl();
361+
const clang::Type *underlyingType = getUnderlyingType(decl);
362+
auto typedefDecl = cast<clang::TypedefType>(underlyingType)->getDecl();
355363
enumNameStr = typedefDecl->getName();
356364
} else {
357365
enumNameStr = decl->getName();

lib/ClangImporter/ImportEnumInfo.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,10 @@ StringRef getCommonWordPrefix(StringRef a, StringRef b,
159159
///
160160
/// \see getCommonWordPrefix
161161
StringRef getCommonPluralPrefix(StringRef singular, StringRef plural);
162+
163+
/// Returns the underlying integer type of an enum. If clang treats the type as
164+
/// an elaborated type, an unwrapped type is returned.
165+
const clang::Type *getUnderlyingType(const clang::EnumDecl *decl);
162166
}
163167
}
164168

lib/ClangImporter/ImportName.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -645,7 +645,7 @@ findSwiftNameAttr(const clang::Decl *decl, ImportNameVersion version) {
645645

646646
if (auto enumDecl = dyn_cast<clang::EnumDecl>(decl)) {
647647
// Intentionally don't get the canonical type here.
648-
if (auto typedefType = dyn_cast<clang::TypedefType>(enumDecl->getIntegerType().getTypePtr())) {
648+
if (auto typedefType = dyn_cast<clang::TypedefType>(getUnderlyingType(enumDecl))) {
649649
// If the typedef is available in Swift, the user will get ambiguity.
650650
// It also means they may not have intended this API to be imported like this.
651651
if (importer::isUnavailableInSwift(typedefType->getDecl(), nullptr, true)) {
@@ -1796,7 +1796,7 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,
17961796
// typedef (even if it's an anonymous enum).
17971797
if (auto enumDecl = dyn_cast<clang::EnumDecl>(D)) {
17981798
// Intentionally don't get the canonical type here.
1799-
if (auto typedefType = dyn_cast<clang::TypedefType>(enumDecl->getIntegerType().getTypePtr())) {
1799+
if (auto typedefType = dyn_cast<clang::TypedefType>(getUnderlyingType(enumDecl))) {
18001800
// If the typedef is available in Swift, the user will get ambiguity.
18011801
// It also means they may not have intended this API to be imported like this.
18021802
if (importer::isUnavailableInSwift(typedefType->getDecl(), nullptr, true)) {

lib/ClangImporter/ImportType.cpp

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2086,18 +2086,22 @@ ImportedType ClangImporter::Implementation::importFunctionReturnType(
20862086
OptionalityOfReturn = OTK_ImplicitlyUnwrappedOptional;
20872087
}
20882088

2089+
clang::QualType returnType = clangDecl->getReturnType();
2090+
if (auto elaborated =
2091+
dyn_cast<clang::ElaboratedType>(returnType))
2092+
returnType = elaborated->desugar();
2093+
20892094
// Specialized templates need to match the args/result exactly (i.e.,
20902095
// ptr -> ptr not ptr -> Optional<ptr>).
2091-
if (clangDecl->getReturnType()->isPointerType() &&
2092-
clangDecl->getPrimaryTemplate() &&
2096+
if (returnType->isPointerType() && clangDecl->getPrimaryTemplate() &&
20932097
clangDecl
20942098
->getPrimaryTemplate()
20952099
->getAsFunction()
20962100
->getReturnType()
20972101
->isTemplateTypeParmType())
20982102
OptionalityOfReturn = OTK_None;
20992103

2100-
if (auto typedefType = dyn_cast<clang::TypedefType>(clangDecl->getReturnType().getTypePtr())) {
2104+
if (auto typedefType = dyn_cast<clang::TypedefType>(returnType)) {
21012105
if (isUnavailableInSwift(typedefType->getDecl())) {
21022106
if (auto clangEnum = findAnonymousEnumForTypedef(SwiftContext, typedefType)) {
21032107
// If this fails, it means that we need a stronger predicate for
@@ -2112,7 +2116,7 @@ ImportedType ClangImporter::Implementation::importFunctionReturnType(
21122116
}
21132117

21142118
// Import the result type.
2115-
return importType(clangDecl->getReturnType(),
2119+
return importType(returnType,
21162120
(isAuditedResult ? ImportTypeKind::AuditedResult
21172121
: ImportTypeKind::Result),
21182122
ImportDiagnosticAdder(*this, clangDecl,
@@ -2159,7 +2163,11 @@ ImportedType ClangImporter::Implementation::importFunctionParamsAndReturnType(
21592163
ImportedType importedType;
21602164
ImportDiagnosticAdder addDiag(*this, clangDecl,
21612165
clangDecl->getSourceRange().getBegin());
2162-
if (auto typedefType = dyn_cast<clang::TypedefType>(clangDecl->getReturnType().getTypePtr())) {
2166+
clang::QualType returnType = clangDecl->getReturnType();
2167+
if (auto elaborated = dyn_cast<clang::ElaboratedType>(returnType))
2168+
returnType = elaborated->desugar();
2169+
2170+
if (auto typedefType = dyn_cast<clang::TypedefType>(returnType)) {
21632171
if (isUnavailableInSwift(typedefType->getDecl())) {
21642172
if (auto clangEnum = findAnonymousEnumForTypedef(SwiftContext, typedefType)) {
21652173
// If this fails, it means that we need a stronger predicate for
@@ -2174,15 +2182,15 @@ ImportedType ClangImporter::Implementation::importFunctionParamsAndReturnType(
21742182
}
21752183

21762184
if (auto templateType =
2177-
dyn_cast<clang::TemplateTypeParmType>(clangDecl->getReturnType())) {
2185+
dyn_cast<clang::TemplateTypeParmType>(returnType)) {
21782186
importedType = {findGenericTypeInGenericDecls(
21792187
*this, templateType, genericParams,
21802188
getImportTypeAttrs(clangDecl), addDiag),
21812189
false};
2182-
} else if ((isa<clang::PointerType>(clangDecl->getReturnType()) ||
2183-
isa<clang::ReferenceType>(clangDecl->getReturnType())) &&
2184-
isa<clang::TemplateTypeParmType>(clangDecl->getReturnType()->getPointeeType())) {
2185-
auto pointeeType = clangDecl->getReturnType()->getPointeeType();
2190+
} else if ((isa<clang::PointerType>(returnType) ||
2191+
isa<clang::ReferenceType>(returnType)) &&
2192+
isa<clang::TemplateTypeParmType>(returnType->getPointeeType())) {
2193+
auto pointeeType = returnType->getPointeeType();
21862194
auto templateParamType = cast<clang::TemplateTypeParmType>(pointeeType);
21872195
PointerTypeKind pointerKind = pointeeType.getQualifiers().hasConst()
21882196
? PTK_UnsafePointer
@@ -2191,13 +2199,13 @@ ImportedType ClangImporter::Implementation::importFunctionParamsAndReturnType(
21912199
findGenericTypeInGenericDecls(*this, templateParamType, genericParams,
21922200
getImportTypeAttrs(clangDecl), addDiag);
21932201
importedType = {genericType->wrapInPointer(pointerKind), false};
2194-
} else if (!(isa<clang::RecordType>(clangDecl->getReturnType()) ||
2195-
isa<clang::TemplateSpecializationType>(clangDecl->getReturnType())) ||
2202+
} else if (!(isa<clang::RecordType>(returnType) ||
2203+
isa<clang::TemplateSpecializationType>(returnType)) ||
21962204
// TODO: we currently don't lazily load operator return types, but
21972205
// this should be trivial to add.
21982206
clangDecl->isOverloadedOperator() ||
21992207
// Dependant types are trivially mapped as Any.
2200-
clangDecl->getReturnType()->isDependentType()) {
2208+
returnType->isDependentType()) {
22012209
// If importedType is already initialized, it means we found the enum that
22022210
// was supposed to be used (instead of the typedef type).
22032211
if (!importedType) {
@@ -2244,6 +2252,8 @@ ClangImporter::Implementation::importParameterType(
22442252
ArrayRef<GenericTypeParamDecl *> genericParams,
22452253
llvm::function_ref<void(Diagnostic &&)> addImportDiagnosticFn) {
22462254
auto paramTy = param->getType();
2255+
if (auto elaborated = dyn_cast<clang::ElaboratedType>(paramTy))
2256+
paramTy = elaborated->desugar();
22472257

22482258
ImportTypeKind importKind = getImportTypeKindForParam(param);
22492259

@@ -2845,7 +2855,8 @@ ImportedType ClangImporter::Implementation::importMethodParamsAndReturnType(
28452855
ImportDiagnosticAdder addImportDiag(*this, clangDecl,
28462856
clangDecl->getLocation());
28472857
clang::QualType resultType = clangDecl->getReturnType();
2848-
2858+
if (auto elaborated = dyn_cast<clang::ElaboratedType>(resultType))
2859+
resultType = elaborated->desugar();
28492860

28502861
ImportedType importedType;
28512862
if (auto typedefType = dyn_cast<clang::TypedefType>(resultType.getTypePtr())) {

0 commit comments

Comments
 (0)