Skip to content

Commit f101bfd

Browse files
authored
Merge pull request #82697 from xymus/cdecl-misc
AST: Misc improvements to `@decl` enums: implicit names, code gen fix and more tests
2 parents b4a5a0b + 5359656 commit f101bfd

File tree

8 files changed

+144
-10
lines changed

8 files changed

+144
-10
lines changed

lib/AST/ClangTypeConverter.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -653,12 +653,13 @@ clang::QualType ClangTypeConverter::visitEnumType(EnumType *type) {
653653
if (type->isUninhabited())
654654
return convert(Context.TheEmptyTupleType);
655655

656-
if (!type->getDecl()->isObjC())
657-
// Can't translate something not marked with @objc
656+
auto ED = type->getDecl();
657+
if (!ED->isObjC() && !ED->getAttrs().hasAttribute<CDeclAttr>())
658+
// Can't translate something not marked with @objc or @cdecl.
658659
return clang::QualType();
659660

660661
// @objc enums lower to their raw types.
661-
return convert(type->getDecl()->getRawType());
662+
return convert(ED->getRawType());
662663
}
663664

664665
template <bool templateArgument>

lib/AST/SwiftNameTranslation.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,8 @@ getNameForObjC(const ValueDecl *VD, CustomNamesOnly_t customNamesOnly) {
5151
}
5252

5353
if (auto cdeclAttr = VD->getAttrs().getAttribute<CDeclAttr>())
54-
return cdeclAttr->Name;
54+
if (!customNamesOnly || !cdeclAttr->Name.empty())
55+
return VD->getCDeclName();
5556

5657
if (customNamesOnly)
5758
return StringRef();

lib/SIL/IR/SILDeclRef.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1298,7 +1298,7 @@ std::string SILDeclRef::mangle(ManglingKind MKind) const {
12981298
}
12991299

13001300
// Use a given cdecl name for native-to-foreign thunks.
1301-
if (auto CDeclA = getDecl()->getAttrs().getAttribute<CDeclAttr>())
1301+
if (getDecl()->getAttrs().hasAttribute<CDeclAttr>())
13021302
if (isNativeToForeignThunk()) {
13031303
// If this is an @implementation @_cdecl, mangle it like the clang
13041304
// function it implements.
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t --leading-lines
3+
4+
/// Generate an internal cdecl.h
5+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) \
6+
// RUN: %t/Lib.swift -emit-module -verify -o %t -emit-module-doc \
7+
// RUN: -emit-clang-header-path %t/cdecl.h \
8+
// RUN: -enable-experimental-feature CDecl
9+
10+
/// Build and run a binary from Swift and C code.
11+
// RUN: %clang-no-modules -c %t/Client.c -o %t/Client.o \
12+
// RUN: -I %t -I %clang-include-dir -Werror -isysroot %sdk
13+
// RUN: %target-build-swift %t/Lib.swift %t/Client.o -O -o %t/a.out \
14+
// RUN: -enable-experimental-feature CDecl -parse-as-library
15+
// RUN: %target-codesign %t/a.out
16+
// RUN: %target-run %t/a.out > %t/run.log
17+
// RUN: %FileCheck %s --input-file %t/run.log
18+
19+
// REQUIRES: swift_feature_CDecl
20+
// REQUIRES: executable_test
21+
22+
//--- Lib.swift
23+
24+
/// My documentation
25+
@cdecl(simple) public func simpleNameSwiftSide(x: CInt, bar y: CInt) -> CInt {
26+
print(x, y)
27+
return x
28+
}
29+
30+
@cdecl func defaultName(x: Int) {
31+
print(x)
32+
}
33+
34+
@cdecl public func primitiveTypes(i: Int, ci: CInt, l: CLong, c: CChar, f: Float, d: Double, b: Bool) {
35+
print(i, ci, l, c, f, d, b)
36+
}
37+
38+
@cdecl enum CEnum: CInt { case A, B }
39+
40+
@cdecl func useEnum(e: CEnum) -> CEnum {
41+
print(e)
42+
return e
43+
}
44+
45+
//--- Client.c
46+
47+
#include <stdio.h>
48+
#include "cdecl.h"
49+
50+
int main() {
51+
int x = simple(42, 43);
52+
// CHECK: 42 43
53+
printf("%d\n", x);
54+
// CHECK-NEXT: 42
55+
56+
defaultName(121);
57+
// CHECK-NEXT: 121
58+
59+
primitiveTypes(1, 2, 3, 'a', 1.0f, 2.0, true);
60+
// CHECK-NEXT: 1 2 3 97 1.0 2.0 true
61+
62+
CEnum e = useEnum(CEnumB);
63+
// CHECK-NEXT: B
64+
printf("%d\n", e);
65+
// CHECK-NEXT: 1
66+
}

test/PrintAsObjC/cdecl-enums.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,18 @@ import Foundation
3131
// CHECK-NEXT: ObjcEnumNamedHelloDolly = 4,
3232
// CHECK-NEXT: };
3333

34-
@cdecl("ObjcEnumNamed") enum EnumNamed: Int {
34+
@cdecl(ObjcEnumNamed) enum EnumNamed: Int {
3535
case A, B, C, d, helloDolly
3636
}
3737

38-
// CHECK-LABEL: typedef SWIFT_ENUM_NAMED(unsigned int, ExplicitValues, "ExplicitValues", closed) {
38+
// CHECK-LABEL: typedef SWIFT_ENUM(unsigned int, ExplicitValues, closed) {
3939
// CHECK-NEXT: ExplicitValuesZim = 0,
4040
// CHECK-NEXT: ExplicitValuesZang = 219,
4141
// CHECK-NEXT: ExplicitValuesZung = 220,
4242
// CHECK-NEXT: };
4343
// NEGATIVE-NOT: ExplicitValuesDomain
4444

45-
@cdecl("ExplicitValues") enum ExplicitValues: CUnsignedInt {
45+
@cdecl enum ExplicitValues: CUnsignedInt {
4646
case Zim, Zang = 219, Zung
4747

4848
func methodNotExportedToC() {}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: split-file %s %t --leading-lines
3+
4+
/// Generate cdecl.h for an app
5+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) \
6+
// RUN: %t/Lib.swift -emit-module -verify -o %t -emit-module-doc \
7+
// RUN: -emit-clang-header-path %t/cdecl.h -package-name pkg \
8+
// RUN: -enable-experimental-feature CDecl
9+
// RUN: %FileCheck %s --input-file %t/cdecl.h --check-prefixes PUBLIC-AND-INTERNAL,INTERNAL-ONLY
10+
// RUN: %check-in-clang-c %t/cdecl.h
11+
12+
/// Generate cdecl.h for a library
13+
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -parse-as-library \
14+
// RUN: %t/Lib.swift -emit-module -verify -o %t -emit-module-doc \
15+
// RUN: -emit-clang-header-path %t/cdecl.h -package-name pkg \
16+
// RUN: -enable-experimental-feature CDecl
17+
// RUN: %FileCheck %s --input-file %t/cdecl.h --check-prefixes PUBLIC-AND-INTERNAL
18+
// RUN: %FileCheck %s --input-file %t/cdecl.h --implicit-check-not INTERNAL-ONLY
19+
// RUN: %check-in-clang-c %t/cdecl.h
20+
21+
// REQUIRES: swift_feature_CDecl
22+
23+
//--- Lib.swift
24+
25+
@cdecl private enum PrivateEnum: CInt { case A, B }
26+
// PUBLIC-AND-INTERNAL-NOT: PrivateEnum
27+
28+
@cdecl internal enum InternalEnum: CInt { case A, B }
29+
// INTERNAL-ONLY: typedef SWIFT_ENUM(int, InternalEnum, closed) {
30+
// INTERNAL-ONLY: InternalEnumA = 0,
31+
// INTERNAL-ONLY: InternalEnumB = 1,
32+
// INTERNAL-ONLY: };
33+
34+
@cdecl package enum PackageEnum: CInt { case A, B }
35+
// INTERNAL-ONLY: typedef SWIFT_ENUM(int, PackageEnum, closed) {
36+
// INTERNAL-ONLY: PackageEnumA = 0,
37+
// INTERNAL-ONLY: PackageEnumB = 1,
38+
// INTERNAL-ONLY: };
39+
40+
@cdecl public enum PublicEnum: CInt { case A, B }
41+
// PUBLIC-AND-INTERNAL: typedef SWIFT_ENUM(int, PublicEnum, closed) {
42+
// PUBLIC-AND-INTERNAL: PublicEnumA = 0,
43+
// PUBLIC-AND-INTERNAL: PublicEnumB = 1,
44+
// PUBLIC-AND-INTERNAL: };
45+
46+
/// Private documentation
47+
@cdecl private func a_private() {}
48+
// PUBLIC-AND-INTERNAL-NOT: // Private documentation
49+
// PUBLIC-AND-INTERNAL-NOT: a_private
50+
51+
/// Internal documentation
52+
@cdecl internal func b_internal() {}
53+
// INTERNAL-ONLY: // Internal documentation
54+
// INTERNAL-ONLY: b_internal
55+
56+
/// Package documentation
57+
@cdecl package func c_package() {}
58+
// INTERNAL-ONLY: // Package documentation
59+
// INTERNAL-ONLY: c_package
60+
61+
/// Public documentation
62+
@cdecl public func d_public() {}
63+
// PUBLIC-AND-INTERNAL: // Public documentation
64+
// PUBLIC-AND-INTERNAL: d_public

test/PrintAsObjC/cdecl-official.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
// CHECK: #endif
2929

3030
// CHECK: /// Enums
31-
// CHECK: typedef SWIFT_ENUM_NAMED(int, CEnum, "CEnum", closed) {
31+
// CHECK: typedef SWIFT_ENUM(int, CEnum, closed) {
3232
// CHECK: CEnumA = 0,
3333
// CHECK: CEnumB = 1,
3434
// CHECK: };
@@ -84,7 +84,7 @@ func g_nullablePointers(_ x: UnsafeMutableRawPointer,
8484

8585
/// Enums
8686

87-
@cdecl("CEnum")
87+
@cdecl
8888
enum CEnum: CInt { case A, B }
8989

9090
@cdecl("CEnumRenamed_CName")

test/attr/attr_cdecl_official.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ enum SwiftEnum { case A, B }
4949
@cdecl("CEnum") enum CEnum: Int { case A, B }
5050
#endif
5151

52+
@cdecl enum CEnumDefaultName: CInt { case A, B }
53+
5254
@cdecl("CEnumNoRawType") enum CEnumNoRawType { case A, B }
5355
// expected-error @-1 {{'@cdecl' enum must declare an integer raw type}}
5456

0 commit comments

Comments
 (0)