Skip to content

Commit e195093

Browse files
author
Gabor Horvath
committed
[cxx-interop] Fix the printing of types with generic arguments
Previously the code got the declaration for types with generic arguments and the printer used the declaration. This was a lossy operation, we printed the type with generic parameters instead of the arguments. This patch makes sure we print the type with the arguments. Unfortunately, the code structure is not the most clear, type printing is currently inherently part of the function signature printing. This code path needs to be factored out in the future to make the code easier to understand. rdar://130679337
1 parent c998bbc commit e195093

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)