Skip to content

Commit b903382

Browse files
committed
ClangImporter: Fix importEnumCaseAlias() when the original is itself an alias
This comes up when an imported error enum has duplicate cases. The FooError.Code enum has an alias for the duplicate case, and the wrapper type FooError defines aliases for every member of FooError.Code. The implementation of importEnumCaseAlias() assumed that 'original' was an EnumElementDecl, and built AST accordingly; however if it is a 'VarDecl', we have to build a MemberRefExpr instead. This regression was introduced in #25009. Fixes <rdar://problem/58552618>.
1 parent b826b3c commit b903382

File tree

5 files changed

+58
-13
lines changed

5 files changed

+58
-13
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5823,23 +5823,38 @@ Decl *SwiftDeclConverter::importEnumCaseAlias(
58235823
if (!importIntoDC)
58245824
importIntoDC = importedEnum;
58255825

5826-
// Construct the original constant. Enum constants without payloads look
5827-
// like simple values, but actually have type 'MyEnum.Type -> MyEnum'.
5828-
auto constantRef =
5829-
new (Impl.SwiftContext) DeclRefExpr(original, DeclNameLoc(),
5830-
/*implicit*/ true);
5831-
constantRef->setType(original->getInterfaceType());
5832-
58335826
Type importedEnumTy = importedEnum->getDeclaredInterfaceType();
5834-
58355827
auto typeRef = TypeExpr::createImplicit(importedEnumTy, Impl.SwiftContext);
5836-
auto instantiate = new (Impl.SwiftContext)
5837-
DotSyntaxCallExpr(constantRef, SourceLoc(), typeRef);
5838-
instantiate->setType(importedEnumTy);
5839-
instantiate->setThrows(false);
5828+
5829+
Expr *result = nullptr;
5830+
if (auto *enumElt = dyn_cast<EnumElementDecl>(original)) {
5831+
assert(!enumElt->hasAssociatedValues());
5832+
5833+
// Construct the original constant. Enum constants without payloads look
5834+
// like simple values, but actually have type 'MyEnum.Type -> MyEnum'.
5835+
auto constantRef =
5836+
new (Impl.SwiftContext) DeclRefExpr(enumElt, DeclNameLoc(),
5837+
/*implicit*/ true);
5838+
constantRef->setType(enumElt->getInterfaceType());
5839+
5840+
auto instantiate = new (Impl.SwiftContext)
5841+
DotSyntaxCallExpr(constantRef, SourceLoc(), typeRef);
5842+
instantiate->setType(importedEnumTy);
5843+
instantiate->setThrows(false);
5844+
5845+
result = instantiate;
5846+
} else {
5847+
assert(isa<VarDecl>(original));
5848+
5849+
result =
5850+
new (Impl.SwiftContext) MemberRefExpr(typeRef, SourceLoc(),
5851+
original, DeclNameLoc(),
5852+
/*implicit*/ true);
5853+
result->setType(original->getInterfaceType());
5854+
}
58405855

58415856
Decl *CD = Impl.createConstant(name, importIntoDC, importedEnumTy,
5842-
instantiate, ConstantConvertKind::None,
5857+
result, ConstantConvertKind::None,
58435858
/*isStatic*/ true, alias);
58445859
Impl.importAttributes(alias, CD);
58455860
return CD;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
Name: AliasCaseErrorEnum
3+
Tags:
4+
- Name: AliasError
5+
NSErrorDomain: AliasErrorDomain
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
@import Foundation;
2+
3+
#define kAliasErrorDomain "com.acme.AliasErrorDomain"
4+
5+
extern NSString *const __nonnull AliasErrorDomain;
6+
7+
typedef NS_ENUM(NSInteger, AliasError) {
8+
AliasErrorRealName = 1,
9+
AliasErrorFakeName = 1,
10+
};
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
module AliasCaseErrorEnum {
2+
umbrella header "AliasCaseErrorEnum.h"
3+
export *
4+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -emit-sil %s -enable-objc-interop -I %S/Inputs/custom-modules/AliasCaseErrorEnum
2+
3+
// REQUIRES: objc_interop
4+
5+
import AliasCaseErrorEnum
6+
7+
// Make sure that we can reference aliases defined in the wrapper type
8+
// which themselves point at aliases inside the nested 'Code' type.
9+
10+
_ = AliasError.realName
11+
_ = AliasError.fakeName

0 commit comments

Comments
 (0)