Skip to content

Commit 9f18481

Browse files
authored
Merge pull request #74637 from beccadax/enum-my
[PrintAsCxx] Fix printing of C++ enum args
2 parents 9caf750 + 7fa35d4 commit 9f18481

File tree

4 files changed

+95
-24
lines changed

4 files changed

+95
-24
lines changed

lib/AST/SwiftNameTranslation.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,6 @@ swift::cxx_translation::getNameForCxx(const ValueDecl *VD,
212212

213213
swift::cxx_translation::DeclRepresentation
214214
swift::cxx_translation::getDeclRepresentation(const ValueDecl *VD) {
215-
if (VD->isObjC())
216-
return {Unsupported, UnrepresentableObjC};
217215
if (getActorIsolation(const_cast<ValueDecl *>(VD)).isActorIsolated())
218216
return {Unsupported, UnrepresentableIsolatedInActor};
219217
if (isa<MacroDecl>(VD))
@@ -239,6 +237,8 @@ swift::cxx_translation::getDeclRepresentation(const ValueDecl *VD) {
239237
// Swift's consume semantics are not yet supported in C++.
240238
if (!typeDecl->canBeCopyable())
241239
return {Unsupported, UnrepresentableMoveOnly};
240+
if (isa<ClassDecl>(VD) && VD->isObjC())
241+
return {Unsupported, UnrepresentableObjC};
242242
if (typeDecl->isGeneric()) {
243243
if (isa<ClassDecl>(VD))
244244
return {Unsupported, UnrepresentableGeneric};

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2927,16 +2927,34 @@ static bool isEnumExposableToCxx(const ValueDecl *VD,
29272927
}
29282928

29292929
bool DeclAndTypePrinter::shouldInclude(const ValueDecl *VD) {
2930-
return !VD->isInvalid() && (!requiresExposedAttribute || hasExposeAttr(VD)) &&
2931-
(outputLang == OutputLanguageMode::Cxx
2932-
? cxx_translation::isVisibleToCxx(VD, minRequiredAccess) &&
2933-
isExposedToThisModule(M, VD, exposedModules) &&
2934-
cxx_translation::isExposableToCxx(VD) &&
2935-
isEnumExposableToCxx(VD, *this)
2936-
: isVisibleToObjC(VD, minRequiredAccess)) &&
2937-
!VD->getAttrs().hasAttribute<ImplementationOnlyAttr>() &&
2938-
!isAsyncAlternativeOfOtherDecl(VD) &&
2939-
!excludeForObjCImplementation(VD);
2930+
if (VD->isInvalid())
2931+
return false;
2932+
2933+
if (requiresExposedAttribute && !hasExposeAttr(VD))
2934+
return false;
2935+
2936+
if (!isVisible(VD))
2937+
return false;
2938+
2939+
if (outputLang == OutputLanguageMode::Cxx) {
2940+
if (!isExposedToThisModule(M, VD, exposedModules))
2941+
return false;
2942+
if (!cxx_translation::isExposableToCxx(VD))
2943+
return false;
2944+
if (!isEnumExposableToCxx(VD, *this))
2945+
return false;
2946+
}
2947+
2948+
if (VD->getAttrs().hasAttribute<ImplementationOnlyAttr>())
2949+
return false;
2950+
2951+
if (isAsyncAlternativeOfOtherDecl(VD))
2952+
return false;
2953+
2954+
if (excludeForObjCImplementation(VD))
2955+
return false;
2956+
2957+
return true;
29402958
}
29412959

29422960
bool DeclAndTypePrinter::isVisible(const ValueDecl *vd) const {

lib/PrintAsClang/PrintClangFunction.cpp

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -104,18 +104,45 @@ struct CFunctionSignatureTypePrinterModifierDelegate {
104104

105105
class ClangTypeHandler {
106106
public:
107-
ClangTypeHandler(const clang::Decl *typeDecl) : typeDecl(typeDecl) {}
107+
ClangTypeHandler(const clang::Decl *typeDecl)
108+
: typeDecl(dyn_cast<clang::TagDecl>(typeDecl)) {}
108109

109110
bool isRepresentable() const {
110-
// We can only return trivial types, or
111-
// types that can be moved or copied.
112-
if (auto *record = dyn_cast<clang::CXXRecordDecl>(typeDecl)) {
113-
return record->isTrivial() || record->hasMoveConstructor() ||
114-
record->hasCopyConstructorWithConstParam();
111+
// We can only return tag types.
112+
if (typeDecl) {
113+
// We can return trivial types.
114+
if (isTrivial(typeDecl))
115+
return true;
116+
117+
// We can return nontrivial types iff they can be moved or copied.
118+
if (auto *record = dyn_cast<clang::CXXRecordDecl>(typeDecl)) {
119+
return record->hasMoveConstructor() ||
120+
record->hasCopyConstructorWithConstParam();
121+
}
115122
}
123+
124+
// Otherwise, we can't return this type.
116125
return false;
117126
}
118127

128+
private:
129+
/// Is the tag type trivial?
130+
static bool isTrivial(const clang::TagDecl *typeDecl) {
131+
if (!typeDecl)
132+
return false;
133+
134+
if (auto *record = dyn_cast<clang::CXXRecordDecl>(typeDecl))
135+
return record->isTrivial();
136+
137+
// FIXME: If we can get plain clang::RecordDecls here, we need to figure out
138+
// how nontrivial (i.e. ARC) fields work.
139+
assert(!isa<clang::RecordDecl>(typeDecl));
140+
141+
// C-family enums are always trivial.
142+
return isa<clang::EnumDecl>(typeDecl);
143+
}
144+
145+
public:
119146
void printTypeName(raw_ostream &os) const {
120147
ClangSyntaxPrinter(os).printClangTypeReference(typeDecl);
121148
}
@@ -135,15 +162,15 @@ class ClangTypeHandler {
135162
llvm::raw_string_ostream typeNameOS(fullQualifiedType);
136163
printTypeName(typeNameOS);
137164
llvm::raw_string_ostream unqualTypeNameOS(typeName);
138-
unqualTypeNameOS << cast<clang::NamedDecl>(typeDecl)->getName();
165+
unqualTypeNameOS << typeDecl->getName();
139166
}
140167
printReturnScaffold(typeDecl, os, fullQualifiedType, typeName,
141168
bodyOfReturn);
142169
}
143170

144171
private:
145172
static void
146-
printReturnScaffold(const clang::Decl *typeDecl, raw_ostream &os,
173+
printReturnScaffold(const clang::TagDecl *typeDecl, raw_ostream &os,
147174
StringRef fullQualifiedType, StringRef typeName,
148175
llvm::function_ref<void(StringRef)> bodyOfReturn) {
149176
os << "alignas(alignof(" << fullQualifiedType << ")) char storage[sizeof("
@@ -152,7 +179,7 @@ class ClangTypeHandler {
152179
<< fullQualifiedType << " *>(storage);\n";
153180
bodyOfReturn("storage");
154181
os << ";\n";
155-
if (typeDecl && cast<clang::CXXRecordDecl>(typeDecl)->isTrivial()) {
182+
if (isTrivial(typeDecl)) {
156183
// Trivial object can be just copied and not destroyed.
157184
os << "return *storageObjectPtr;\n";
158185
return;
@@ -164,7 +191,7 @@ class ClangTypeHandler {
164191
os << "return result;\n";
165192
}
166193

167-
const clang::Decl *typeDecl;
194+
const clang::TagDecl *typeDecl;
168195
};
169196

170197
// Prints types in the C function signature that corresponds to the
@@ -378,6 +405,7 @@ class CFunctionSignatureTypePrinter
378405
return ClangRepresentation::unsupported;
379406

380407
if (decl->hasClangNode()) {
408+
assert(genericArgs.empty() && "this path doesn't support generic args");
381409
ClangTypeHandler handler(decl->getClangDecl());
382410
if (!handler.isRepresentable())
383411
return ClangRepresentation::unsupported;

test/Interop/CxxToSwiftToCxx/bridge-cxx-struct-back-to-cxx.swift

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33

44
// RUN: %target-swift-frontend -typecheck %t/use-cxx-types.swift -typecheck -module-name UseCxxTy -emit-clang-header-path %t/UseCxxTy.h -I %t -enable-experimental-cxx-interop -clang-header-expose-decls=all-public -disable-availability-checking
55

6-
// RUN: %FileCheck %s < %t/UseCxxTy.h
6+
// RUN: %FileCheck %s --input-file %t/UseCxxTy.h
77

88
// RUN: %target-swift-frontend -typecheck %t/use-cxx-types.swift -typecheck -module-name UseCxxTy -emit-clang-header-path %t/UseCxxTyExposeOnly.h -I %t -enable-experimental-cxx-interop -clang-header-expose-decls=has-expose-attr -disable-availability-checking
99

10-
// RUN: %FileCheck %s < %t/UseCxxTyExposeOnly.h
10+
// RUN: %FileCheck %s --input-file %t/UseCxxTyExposeOnly.h
1111

1212
// FIXME: remove once https://github.com/apple/swift/pull/60971 lands.
1313
// RUN: echo "#include \"header.h\"" > %t/full-cxx-swift-cxx-bridging.h
@@ -91,6 +91,9 @@ using anonStructInNS = struct { float row; };
9191

9292
}
9393

94+
enum class SimpleScopedEnum { x = 0, y = 2 };
95+
typedef SimpleScopedEnum SimpleScopedEnumTypedef;
96+
9497
//--- module.modulemap
9598
module CxxTest {
9699
header "header.h"
@@ -130,6 +133,16 @@ public func retNonTrivialTypeAlias() -> ns.TypeAlias {
130133
return ns.TypeAlias()
131134
}
132135

136+
@_expose(Cxx)
137+
public func retSimpleScopedEnum() -> SimpleScopedEnum {
138+
return .x
139+
}
140+
141+
@_expose(Cxx)
142+
public func retSimpleScopedEnumTypedef() -> SimpleScopedEnumTypedef {
143+
return .x
144+
}
145+
133146
@_expose(Cxx)
134147
public func retSimpleTypedef() -> SimpleTypedef {
135148
return SimpleTypedef()
@@ -152,6 +165,10 @@ public func takeImmortalTemplate(_ x: ns.ImmortalCInt) {
152165
public func takeNonTrivial2(_ x: ns.NonTrivialTemplateTrivial) {
153166
}
154167

168+
@_expose(Cxx)
169+
public func takeSimpleScopedEnum(_ x: SimpleScopedEnum) {
170+
}
171+
155172
@_expose(Cxx)
156173
public func takeTrivial(_ x: Trivial) {
157174
}
@@ -275,6 +292,12 @@ public struct Strct {
275292

276293
// CHECK: ns::NonTrivialTemplate<ns::TrivialinNS> retNonTrivialTypeAlias() noexcept SWIFT_SYMBOL({{.*}}) SWIFT_WARN_UNUSED_RESULT {
277294

295+
// CHECK: SimpleScopedEnum retSimpleScopedEnum() noexcept SWIFT_SYMBOL({{.*}}) SWIFT_WARN_UNUSED_RESULT {
296+
297+
// FIXME: Would we prefer to print these with the typedef names?
298+
// CHECK: SimpleScopedEnum retSimpleScopedEnumTypedef() noexcept SWIFT_SYMBOL({{.*}}) SWIFT_WARN_UNUSED_RESULT {
299+
// CHECK: int32_t retSimpleTypedef() noexcept SWIFT_SYMBOL({{.*}}) SWIFT_WARN_UNUSED_RESULT {
300+
278301
// CHECK: SWIFT_INLINE_THUNK Trivial retTrivial() noexcept SWIFT_SYMBOL({{.*}}) SWIFT_WARN_UNUSED_RESULT {
279302
// CHECK-NEXT: alignas(alignof(Trivial)) char storage[sizeof(Trivial)];
280303
// CHECK-NEXT: auto * _Nonnull storageObjectPtr = reinterpret_cast<Trivial *>(storage);
@@ -294,6 +317,8 @@ public struct Strct {
294317
// CHECK-NEXT: _impl::$s8UseCxxTy15takeNonTrivial2yySo2nsO0037NonTrivialTemplateTrivialinNS_CsGGkdcVF(swift::_impl::getOpaquePointer(x));
295318
// CHECK-NEXT: }
296319

320+
// CHECK: SWIFT_INLINE_THUNK void takeSimpleScopedEnum(const SimpleScopedEnum& x) noexcept SWIFT_SYMBOL({{.*}}) {
321+
297322
// CHECK: SWIFT_INLINE_THUNK void takeTrivial(const Trivial& x) noexcept SWIFT_SYMBOL({{.*}}) {
298323
// CHECK-NEXT: _impl::$s8UseCxxTy11takeTrivialyySo0E0VF(_impl::swift_interop_passDirect_UseCxxTy_uint32_t_0_4(reinterpret_cast<const char *>(swift::_impl::getOpaquePointer(x))));
299324
// CHECK-NEXT: }

0 commit comments

Comments
 (0)