Skip to content

Commit a22dd98

Browse files
authored
Merge pull request #75372 from swiftlang/gaborh/fix-generic-arrays
[cxx-interop] Fix the printing of types with generic arguments
2 parents ed38b93 + e195093 commit a22dd98

File tree

6 files changed

+90
-15
lines changed

6 files changed

+90
-15
lines changed

lib/PrintAsClang/DeclAndTypePrinter.cpp

Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,13 +39,14 @@
3939
#include "swift/Parse/Lexer.h"
4040
#include "swift/Parse/Parser.h"
4141

42+
#include "SwiftToClangInteropContext.h"
4243
#include "clang/AST/ASTContext.h"
4344
#include "clang/AST/Attr.h"
4445
#include "clang/AST/Decl.h"
4546
#include "clang/AST/DeclObjC.h"
4647
#include "clang/Basic/CharInfo.h"
4748
#include "clang/Basic/SourceManager.h"
48-
#include "SwiftToClangInteropContext.h"
49+
#include "llvm/Support/raw_ostream.h"
4950

5051
using namespace swift;
5152
using namespace swift::objc_translation;
@@ -561,8 +562,8 @@ class DeclAndTypePrinter::Implementation
561562
outOfLineOS << " return swift::";
562563
outOfLineOS << cxx_synthesis::getCxxImplNamespaceName();
563564
outOfLineOS << "::implClassFor<";
564-
outOfLineSyntaxPrinter.printNominalTypeReference(
565-
objectTypeDecl,
565+
owningPrinter.printTypeName(
566+
outOfLineOS, paramType,
566567
elementDecl->getParentEnum()->getModuleContext());
567568
outOfLineOS << ">::type";
568569
if (!isOptional && isa<ClassDecl>(objectTypeDecl)) {
@@ -574,8 +575,8 @@ class DeclAndTypePrinter::Implementation
574575
outOfLineOS << " swift::"
575576
<< cxx_synthesis::getCxxImplNamespaceName();
576577
outOfLineOS << "::implClassFor<";
577-
outOfLineSyntaxPrinter.printNominalTypeReference(
578-
objectTypeDecl,
578+
owningPrinter.printTypeName(
579+
outOfLineOS, paramType,
579580
elementDecl->getParentEnum()->getModuleContext());
580581
outOfLineOS << ">::type";
581582
outOfLineOS << "::initializeWithTake(result, "
@@ -729,31 +730,36 @@ class DeclAndTypePrinter::Implementation
729730
objectTypeDecl =
730731
paramType->getNominalOrBoundGenericNominal();
731732
outOfLineOS << " alignas(";
732-
outOfLineSyntaxPrinter.printNominalTypeReference(
733-
objectTypeDecl, ED->getModuleContext());
733+
owningPrinter.printTypeName(
734+
outOfLineOS, paramType,
735+
elementDecl->getParentEnum()->getModuleContext());
734736
outOfLineOS << ") unsigned char buffer[sizeof(";
735-
outOfLineSyntaxPrinter.printNominalTypeReference(
736-
objectTypeDecl, ED->getModuleContext());
737+
owningPrinter.printTypeName(
738+
outOfLineOS, paramType,
739+
elementDecl->getParentEnum()->getModuleContext());
737740
outOfLineOS << ")];\n";
738741
outOfLineOS << " auto *valCopy = new(buffer) ";
739-
outOfLineSyntaxPrinter.printNominalTypeReference(
740-
objectTypeDecl, ED->getModuleContext());
742+
owningPrinter.printTypeName(
743+
outOfLineOS, paramType,
744+
elementDecl->getParentEnum()->getModuleContext());
741745
outOfLineOS << "(val);\n";
742746
outOfLineOS << " ";
743747
outOfLineOS << cxx_synthesis::getCxxSwiftNamespaceName()
744748
<< "::";
745749
outOfLineOS << cxx_synthesis::getCxxImplNamespaceName();
746750
outOfLineOS << "::implClassFor<";
747-
outOfLineSyntaxPrinter.printNominalTypeReference(
748-
objectTypeDecl, ED->getModuleContext());
751+
owningPrinter.printTypeName(
752+
outOfLineOS, paramType,
753+
elementDecl->getParentEnum()->getModuleContext());
749754
outOfLineOS << ">::type::initializeWithTake(result._"
750755
"getOpaquePointer(), ";
751756
outOfLineOS << cxx_synthesis::getCxxSwiftNamespaceName()
752757
<< "::";
753758
outOfLineOS << cxx_synthesis::getCxxImplNamespaceName();
754759
outOfLineOS << "::implClassFor<";
755-
outOfLineSyntaxPrinter.printNominalTypeReference(
756-
objectTypeDecl, ED->getModuleContext());
760+
owningPrinter.printTypeName(
761+
outOfLineOS, paramType,
762+
elementDecl->getParentEnum()->getModuleContext());
757763
outOfLineOS << ">::type::getOpaquePointer(*valCopy)";
758764
outOfLineOS << ");\n";
759765
}
@@ -2958,6 +2964,15 @@ void DeclAndTypePrinter::print(Type ty) {
29582964
getImpl().print(ty, /*overridingOptionality*/ std::nullopt);
29592965
}
29602966

2967+
void DeclAndTypePrinter::printTypeName(raw_ostream &os, Type ty,
2968+
const ModuleDecl *moduleContext) {
2969+
std::string dummy;
2970+
llvm::raw_string_ostream dummyOS(dummy);
2971+
DeclAndTypeClangFunctionPrinter printer(os, dummyOS, typeMapping,
2972+
interopContext, *this);
2973+
printer.printTypeName(ty, moduleContext);
2974+
}
2975+
29612976
void DeclAndTypePrinter::printAvailability(raw_ostream &os, const Decl *D) {
29622977
getImpl().printAvailability(os, D);
29632978
}

lib/PrintAsClang/DeclAndTypePrinter.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "OutputLanguageMode.h"
1717

1818
#include "swift/AST/Decl.h"
19+
#include "swift/AST/Module.h"
1920
#include "swift/AST/Type.h"
2021
// for OptionalTypeKind
2122
#include "swift/ClangImporter/ClangImporter.h"
@@ -117,6 +118,9 @@ class DeclAndTypePrinter {
117118
void print(const Decl *D);
118119
void print(Type ty);
119120

121+
/// Prints the name of the type including generic arguments.
122+
void printTypeName(raw_ostream &os, Type ty, const ModuleDecl *moduleContext);
123+
120124
void printAvailability(raw_ostream &os, const Decl *D);
121125

122126
/// Is \p ED empty of members and protocol conformances to include?

lib/PrintAsClang/PrintClangFunction.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1760,3 +1760,13 @@ ClangRepresentation DeclAndTypeClangFunctionPrinter::getTypeRepresentation(
17601760
return typePrinter.visit(ty, OptionalTypeKind::OTK_None,
17611761
/*isInOutParam=*/false);
17621762
}
1763+
1764+
void DeclAndTypeClangFunctionPrinter::printTypeName(
1765+
Type ty, const ModuleDecl *moduleContext) {
1766+
CFunctionSignatureTypePrinterModifierDelegate delegate;
1767+
CFunctionSignatureTypePrinter typePrinter(
1768+
os, cPrologueOS, typeMapping, OutputLanguageMode::Cxx, interopContext,
1769+
delegate, moduleContext, declPrinter,
1770+
FunctionSignatureTypeUse::TypeReference);
1771+
typePrinter.visit(ty, std::nullopt, /*isInOut=*/false);
1772+
}

lib/PrintAsClang/PrintClangFunction.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,9 @@ class DeclAndTypeClangFunctionPrinter {
170170
DeclAndTypePrinter &declPrinter,
171171
const ModuleDecl *emittedModule, Type ty);
172172

173+
/// Prints the name of the type including generic arguments.
174+
void printTypeName(Type ty, const ModuleDecl *moduleContext);
175+
173176
private:
174177
void printCxxToCFunctionParameterUse(Type type, StringRef name,
175178
const ModuleDecl *moduleContext,

test/Interop/SwiftToCxx/enums/enum-associated-value-class-type-cxx.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,19 @@ int main() {
5252
assert(c.getX() == 5678);
5353
}
5454

55+
{
56+
auto c = C::init(5);
57+
auto arr = swift::Array<C>::init(c, 2);
58+
auto f = F::b(arr);
59+
assert(f.getB().getCount() == 2);
60+
}
61+
62+
{
63+
auto arr = swift::Array<swift::Int>::init(42, 2);
64+
auto g = G<swift::Int>::b(arr);
65+
assert(g.getB().getCount() == 2);
66+
}
67+
5568
assert(getRetainCount(c) == 1);
5669
return 0;
5770
}

test/Interop/SwiftToCxx/enums/enum-associated-value-class-type-cxx.swift

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ extension E {
2929
}
3030
}
3131

32+
public enum F {
33+
case a(Int)
34+
case b([C])
35+
}
36+
37+
public enum G<T> {
38+
case a(Int)
39+
case b([T])
40+
}
41+
3242
// CHECK: SWIFT_INLINE_THUNK E E::_impl_c::operator()(const C& val) const {
3343
// CHECK-NEXT: auto result = E::_make();
3444
// CHECK-NEXT: auto op = swift::_impl::_impl_RefCountedClass::copyOpaquePointer(val);
@@ -47,3 +57,23 @@ extension E {
4757

4858
// CHECK: SWIFT_INLINE_THUNK bool E::matchesIntValue(swift::Int value) const {
4959
// CHECK-NEXT: return _impl::$s5Enums1EO15matchesIntValueySbSiF(value, _impl::swift_interop_passDirect_Enums_uint64_t_0_8_uint8_t_8_9(_getOpaquePointer()));
60+
61+
// CHECK: SWIFT_INLINE_THUNK swift::Array<C> F::getB() const {
62+
// CHECK-NEXT: if (!isB()) abort();
63+
// CHECK-NEXT: alignas(F) unsigned char buffer[sizeof(F)];
64+
// CHECK-NEXT: auto *thisCopy = new(buffer) F(*this);
65+
// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData();
66+
// CHECK-NEXT: return swift::_impl::implClassFor<swift::Array<C>>::type::returnNewValue([&](char * _Nonnull result) SWIFT_INLINE_THUNK_ATTRIBUTES {
67+
// CHECK-NEXT: swift::_impl::implClassFor<swift::Array<C>>::type::initializeWithTake(result, payloadFromDestruction);
68+
// CHECK-NEXT: });
69+
// CHECK-NEXT: }
70+
71+
// CHECK: SWIFT_INLINE_THUNK swift::Array<T_0_0> G<T_0_0>::getB() const {
72+
// CHECK-NEXT: if (!isB()) abort();
73+
// CHECK-NEXT: alignas(G) unsigned char buffer[sizeof(G)];
74+
// CHECK-NEXT: auto *thisCopy = new(buffer) G(*this);
75+
// CHECK-NEXT: char * _Nonnull payloadFromDestruction = thisCopy->_destructiveProjectEnumData();
76+
// CHECK-NEXT: return swift::_impl::implClassFor<swift::Array<T_0_0>>::type::returnNewValue([&](char * _Nonnull result) SWIFT_INLINE_THUNK_ATTRIBUTES {
77+
// CHECK-NEXT: swift::_impl::implClassFor<swift::Array<T_0_0>>::type::initializeWithTake(result, payloadFromDestruction);
78+
// CHECK-NEXT: });
79+
// CHECK-NEXT: }

0 commit comments

Comments
 (0)