Skip to content

Commit 0dc470c

Browse files
authored
Merge pull request #65351 from hyp/eng/5.9/71ef7e8d3d2472735caecad9b09fee80d8aa2e3e
[interop][SwiftToCxx] do not expose unsupported enums yet
2 parents 1068536 + ebe2d52 commit 0dc470c

File tree

7 files changed

+86
-8
lines changed

7 files changed

+86
-8
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1685,6 +1685,12 @@ ERROR(expose_generic_requirement_to_cxx,none,
16851685
"generic requirements for %0 %1 can not yet be represented in C++", (DescriptiveDeclKind, ValueDecl *))
16861686
ERROR(expose_throwing_to_cxx,none,
16871687
"%0 %1 can not yet be represented in C++ as it may throw an error", (DescriptiveDeclKind, ValueDecl *))
1688+
ERROR(expose_indirect_enum_cxx,none,
1689+
"indirect enum %0 can not yet be represented in C++", (ValueDecl *))
1690+
ERROR(expose_enum_case_type_to_cxx,none,
1691+
"enum %0 can not be represented in C++ as one of its cases has an associated value with type that can't be represented in C++", (ValueDecl *))
1692+
ERROR(expose_enum_case_tuple_to_cxx,none,
1693+
"enum %0 can not yet be represented in C++ as one of its cases has multiple associated values", (ValueDecl *))
16881694

16891695
ERROR(attr_methods_only,none,
16901696
"only methods can be declared %0", (DeclAttribute))

include/swift/AST/SwiftNameTranslation.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,10 @@ enum RepresentationError {
7272
UnrepresentableRequiresClientEmission,
7373
UnrepresentableGeneric,
7474
UnrepresentableGenericRequirements,
75-
UnrepresentableThrows
75+
UnrepresentableThrows,
76+
UnrepresentableIndirectEnum,
77+
UnrepresentableEnumCaseType,
78+
UnrepresentableEnumCaseTuple,
7679
};
7780

7881
struct DeclRepresentation {

lib/AST/SwiftNameTranslation.cpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,29 @@ swift::cxx_translation::getDeclRepresentation(const ValueDecl *VD) {
234234
return {Unsupported, UnrepresentableThrows};
235235
}
236236
}
237+
if (const auto *enumDecl = dyn_cast<EnumDecl>(VD)) {
238+
if (enumDecl->isIndirect())
239+
return {Unsupported, UnrepresentableIndirectEnum};
240+
for (const auto *enumCase : enumDecl->getAllCases()) {
241+
for (const auto *elementDecl : enumCase->getElements()) {
242+
if (!elementDecl->hasAssociatedValues())
243+
continue;
244+
// Do not expose any enums with > 1
245+
// enum parameter, or any enum parameter
246+
// whose type we do not yet support.
247+
if (auto *params = elementDecl->getParameterList()) {
248+
if (params->size() > 1)
249+
return {Unsupported, UnrepresentableEnumCaseTuple};
250+
for (const auto *param : *params) {
251+
auto paramType = param->getInterfaceType();
252+
if (!paramType->is<GenericTypeParamType>() &&
253+
!paramType->getNominalOrBoundGenericNominal())
254+
return {Unsupported, UnrepresentableEnumCaseType};
255+
}
256+
}
257+
}
258+
}
259+
}
237260
// Generic requirements are not yet supported in C++.
238261
if (genericSignature && !genericSignature->getRequirements().empty())
239262
return {Unsupported, UnrepresentableGenericRequirements};

lib/Sema/TypeCheckAttr.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2067,6 +2067,15 @@ void AttributeChecker::visitExposeAttr(ExposeAttr *attr) {
20672067
diagnose(attr->getLocation(), diag::expose_throwing_to_cxx,
20682068
VD->getDescriptiveKind(), VD);
20692069
break;
2070+
case UnrepresentableIndirectEnum:
2071+
diagnose(attr->getLocation(), diag::expose_indirect_enum_cxx, VD);
2072+
break;
2073+
case UnrepresentableEnumCaseType:
2074+
diagnose(attr->getLocation(), diag::expose_enum_case_type_to_cxx, VD);
2075+
break;
2076+
case UnrepresentableEnumCaseTuple:
2077+
diagnose(attr->getLocation(), diag::expose_enum_case_tuple_to_cxx, VD);
2078+
break;
20702079
}
20712080
}
20722081

test/Interop/SwiftToCxx/cross-module-refs/Inputs/enums.swift

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
1+
2+
public struct IntTuple {
3+
let values: (Int64, Int64, Int64, Int64, Int64, Int64)
4+
}
5+
16
// Large enum passed indirectly.
27
public enum LargeEnum {
3-
case A(x1: Int64, x2: Int64, x3: Int64, x4: Int64, x5: Int64)
8+
case A(IntTuple)
49
case B
510
}
611

test/Interop/SwiftToCxx/enums/large-enums-pass-return-in-cxx.swift

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,23 @@
44

55
// RUN: %check-interop-cxx-header-in-clang(%t/enums.h -Wno-unused-private-field -Wno-unused-function)
66

7+
public struct IntTuple {
8+
let values: (Int64, Int64, Int64, Int64, Int64, Int64)
9+
}
10+
711
public enum Large {
8-
case first(Int64, Int64, Int64, Int64, Int64, Int64)
12+
case first(IntTuple)
913
case second
1014
}
1115

1216
public func makeLarge(_ x: Int) -> Large {
13-
return x >= 0 ? .first(0, 1, 2, 3, 4, 5) : .second
17+
return x >= 0 ? .first(IntTuple(values: (0, 1, 2, 3, 4, 5))) : .second
1418
}
1519

1620
public func printLarge(_ en: Large) {
1721
switch en {
18-
case let .first(a, b, c, d, e, f):
19-
let x = (a, b, c, d, e, f)
20-
print("Large.first\(x)")
22+
case let .first(x):
23+
print("Large.first\(x.values)")
2124
case .second:
2225
print("Large.second")
2326
}
@@ -29,7 +32,7 @@ public func passThroughLarge(_ en: Large) -> Large {
2932

3033
public func inoutLarge(_ en: inout Large, _ x: Int) {
3134
if x >= 0 {
32-
en = .first(-1, -2, -3, -4, -5, -6)
35+
en = .first(IntTuple(values: (-1, -2, -3, -4, -5, -6)))
3336
} else {
3437
en = .second
3538
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend %s -typecheck -module-name Functions -verify -clang-header-expose-decls=has-expose-attr -disable-availability-checking -emit-clang-header-path %t/functions.h
3+
4+
// RUN: cat %s | grep -v _expose > %t/clean.swift
5+
// RUN: %target-swift-frontend %t/clean.swift -typecheck -module-name Functions -clang-header-expose-decls=all-public -disable-availability-checking -emit-clang-header-path %t/header.h
6+
// RUN: %FileCheck %s < %t/header.h
7+
8+
// CHECK-NOT: unsupported
9+
10+
public typealias FnType = () -> ()
11+
12+
@_expose(Cxx) // expected-error {{enum 'unsupportedEnumAssociatedValueType' can not be represented in C++ as one of its cases has an associated value with type that can't be represented in C++}}
13+
public enum unsupportedEnumAssociatedValueType {
14+
case A
15+
case B(FnType)
16+
}
17+
18+
@_expose(Cxx) // expected-error {{enum 'unsupportedEnumMultipleAssociatedValues' can not yet be represented in C++ as one of its cases has multiple associated values}}
19+
public enum unsupportedEnumMultipleAssociatedValues {
20+
case A
21+
case B(Int, Int)
22+
}
23+
24+
@_expose(Cxx) // expected-error {{indirect enum 'unsupportedEnumIndirect' can not yet be represented in C++}}
25+
public indirect enum unsupportedEnumIndirect {
26+
case A
27+
case B
28+
}
29+

0 commit comments

Comments
 (0)