Skip to content

Commit 616de41

Browse files
author
Gabor Horvath
committed
[cxx-interop] Fix nested structs for non-opaque types
The test for nested constructs used library evolution forcing all types to be opaque. As a result some code paths for non-opaque types were not updated to support nested types. This patch updates the rest of the code making sure we use fully qualified names (so they also work in the context of the nested classes), and generate correct names for the C compatibility structs that cannot contain "::". Fixes #80291 rdar://147882976
1 parent 8c8ed34 commit 616de41

8 files changed

+39
-27
lines changed

lib/PrintAsClang/ClangSyntaxPrinter.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "clang/AST/Decl.h"
2424
#include "clang/AST/DeclTemplate.h"
2525
#include "clang/AST/NestedNameSpecifier.h"
26+
#include "llvm/ADT/StringRef.h"
2627
#include "llvm/Support/Casting.h"
2728

2829
using namespace swift;
@@ -127,8 +128,8 @@ void ClangSyntaxPrinter::printClangTypeReference(const clang::Decl *typeDecl) {
127128
}
128129
}
129130

130-
bool ClangSyntaxPrinter::printNestedTypeNamespaceQualifiers(
131-
const ValueDecl *D) const {
131+
bool ClangSyntaxPrinter::printNestedTypeNamespaceQualifiers(const ValueDecl *D,
132+
bool forC) const {
132133
bool first = true;
133134
while (auto parent = dyn_cast_or_null<NominalTypeDecl>(
134135
D->getDeclContext()->getAsDecl())) {
@@ -137,9 +138,10 @@ bool ClangSyntaxPrinter::printNestedTypeNamespaceQualifiers(
137138
isa<clang::NamespaceDecl>(parent->getClangNode().getAsDecl()))
138139
break;
139140
if (!first)
140-
os << "::";
141+
os << (forC ? "_" : "::");
141142
first = false;
142-
os << "__";
143+
if (!forC)
144+
os << "__";
143145
printBaseName(parent);
144146
os << "Nested";
145147
D = parent;

lib/PrintAsClang/ClangSyntaxPrinter.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ class ClangSyntaxPrinter {
9696
const NominalTypeDecl *typeDecl);
9797

9898
// Returns true when no qualifiers were printed.
99-
bool printNestedTypeNamespaceQualifiers(const ValueDecl *D) const;
99+
bool printNestedTypeNamespaceQualifiers(const ValueDecl *D,
100+
bool forC = false) const;
100101

101102
/// Print out the C++ class access qualifier for the given Swift type
102103
/// declaration.

lib/PrintAsClang/PrintClangFunction.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1249,7 +1249,10 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
12491249
os << "void **vtable_ = *selfPtr_;\n";
12501250
os << "#endif\n";
12511251
os << "struct FTypeAddress {\n";
1252-
os << "decltype(" << cxx_synthesis::getCxxImplNamespaceName()
1252+
os << "decltype(";
1253+
ClangSyntaxPrinter(moduleContext->getASTContext(), os)
1254+
.printBaseName(moduleContext);
1255+
os << "::" << cxx_synthesis::getCxxImplNamespaceName()
12531256
<< "::" << swiftSymbolName << ") *";
12541257
if (auto ptrAuthDisc = dispatchInfo->getPointerAuthDiscriminator())
12551258
os << " __ptrauth_swift_class_method_pointer(" << ptrAuthDisc->value

lib/PrintAsClang/PrintClangValueType.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@ using namespace swift;
3131
static void printCTypeName(raw_ostream &os, const NominalTypeDecl *type) {
3232
ClangSyntaxPrinter printer(type->getASTContext(), os);
3333
printer.printModuleNameCPrefix(*type->getParentModule());
34-
if (!ClangSyntaxPrinter(type->getASTContext(), os).printNestedTypeNamespaceQualifiers(type))
35-
os << "::";
34+
if (!ClangSyntaxPrinter(type->getASTContext(), os)
35+
.printNestedTypeNamespaceQualifiers(type, /*forC=*/true))
36+
os << "_";
3637
printer.printBaseName(type);
3738
}
3839

test/Interop/SwiftToCxx/class/nested-classes-in-cxx.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
// RUN: %empty-directory(%t)
22
// RUN: %target-swift-frontend %s -enable-library-evolution -typecheck -module-name Classes -clang-header-expose-decls=all-public -emit-clang-header-path %t/classes.h
3+
// RUN: %check-interop-cxx-header-in-clang(%t/classes.h -DSWIFT_CXX_INTEROP_HIDE_STL_OVERLAY -std=c++17)
34

5+
// RUN: %empty-directory(%t)
6+
// RUN: %target-swift-frontend %s -typecheck -module-name Classes -clang-header-expose-decls=all-public -emit-clang-header-path %t/classes.h
47
// RUN: %check-interop-cxx-header-in-clang(%t/classes.h -DSWIFT_CXX_INTEROP_HIDE_STL_OVERLAY -std=c++17)
58

69
public class RecordConfig {

test/Interop/SwiftToCxx/class/swift-class-virtual-method-dispatch.swift

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ public func returnDerivedDerivedClass() -> DerivedDerivedClass {
124124
// CHECK-NEXT: void **vtable_ = *selfPtr_;
125125
// CHECK-NEXT: #endif
126126
// CHECK-NEXT: struct FTypeAddress {
127-
// CHECK-NEXT: decltype(_impl::$s5Class04BaseA0C13virtualMethodyyF) * func;
127+
// CHECK-NEXT: decltype(Class::_impl::$s5Class04BaseA0C13virtualMethodyyF) * func;
128128
// CHECK-NEXT: };
129129
// CHECK-NEXT: FTypeAddress *fptrptr_ = reinterpret_cast<FTypeAddress *>(vtable_ + [[#VM1:]] / sizeof(void *));
130130
// CHECK-NEXT: (* fptrptr_->func)(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
@@ -138,7 +138,7 @@ public func returnDerivedDerivedClass() -> DerivedDerivedClass {
138138
// CHECK-NEXT: void **vtable_ = *selfPtr_;
139139
// CHECK-NEXT: #endif
140140
// CHECK-NEXT: struct FTypeAddress {
141-
// CHECK-NEXT: decltype(_impl::$s5Class04BaseA0C016virtualMethodIntE0yS2iF) * func;
141+
// CHECK-NEXT: decltype(Class::_impl::$s5Class04BaseA0C016virtualMethodIntE0yS2iF) * func;
142142
// CHECK-NEXT: };
143143
// CHECK-NEXT: FTypeAddress *fptrptr_ = reinterpret_cast<FTypeAddress *>(vtable_ + [[#VM2:]] / sizeof(void *));
144144
// CHECK-NEXT: return (* fptrptr_->func)(x, ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
@@ -156,7 +156,7 @@ public func returnDerivedDerivedClass() -> DerivedDerivedClass {
156156
// CHECK-NEXT: void **vtable_ = *selfPtr_;
157157
// CHECK-NEXT: #endif
158158
// CHECK-NEXT: struct FTypeAddress {
159-
// CHECK-NEXT: decltype(_impl::$s5Class04BaseA0C19virtualComputedPropSivg) * func;
159+
// CHECK-NEXT: decltype(Class::_impl::$s5Class04BaseA0C19virtualComputedPropSivg) * func;
160160
// CHECK-NEXT: };
161161
// CHECK-NEXT: FTypeAddress *fptrptr_ = reinterpret_cast<FTypeAddress *>(vtable_ + [[#VM3:]] / sizeof(void *));
162162
// CHECK-NEXT: return (* fptrptr_->func)(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
@@ -170,7 +170,7 @@ public func returnDerivedDerivedClass() -> DerivedDerivedClass {
170170
// CHECK-NEXT: void **vtable_ = *selfPtr_;
171171
// CHECK-NEXT: #endif
172172
// CHECK-NEXT: struct FTypeAddress {
173-
// CHECK-NEXT: decltype(_impl::$s5Class04BaseA0C21virtualComputedGetSets5Int64Vvg) * func;
173+
// CHECK-NEXT: decltype(Class::_impl::$s5Class04BaseA0C21virtualComputedGetSets5Int64Vvg) * func;
174174
// CHECK-NEXT: };
175175
// CHECK-NEXT: FTypeAddress *fptrptr_ = reinterpret_cast<FTypeAddress *>(vtable_ + [[#VM4:]] / sizeof(void *));
176176
// CHECK-NEXT: return (* fptrptr_->func)(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
@@ -184,7 +184,7 @@ public func returnDerivedDerivedClass() -> DerivedDerivedClass {
184184
// CHECK-NEXT: void **vtable_ = *selfPtr_;
185185
// CHECK-NEXT: #endif
186186
// CHECK-NEXT: struct FTypeAddress {
187-
// CHECK-NEXT: decltype(_impl::$s5Class04BaseA0C21virtualComputedGetSets5Int64Vvs) * func;
187+
// CHECK-NEXT: decltype(Class::_impl::$s5Class04BaseA0C21virtualComputedGetSets5Int64Vvs) * func;
188188
// CHECK-NEXT: };
189189
// CHECK-NEXT: FTypeAddress *fptrptr_ = reinterpret_cast<FTypeAddress *>(vtable_ + [[#VM5:]] / sizeof(void *));
190190
// CHECK-NEXT: (* fptrptr_->func)(newValue, ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
@@ -198,7 +198,7 @@ public func returnDerivedDerivedClass() -> DerivedDerivedClass {
198198
// CHECK-NEXT: void **vtable_ = *selfPtr_;
199199
// CHECK-NEXT: #endif
200200
// CHECK-NEXT: struct FTypeAddress {
201-
// CHECK-NEXT: decltype(_impl::$s5Class04BaseA0C10storedPropSivg) * func;
201+
// CHECK-NEXT: decltype(Class::_impl::$s5Class04BaseA0C10storedPropSivg) * func;
202202
// CHECK-NEXT: };
203203
// CHECK-NEXT: FTypeAddress *fptrptr_ = reinterpret_cast<FTypeAddress *>(vtable_ + [[#VM7:]] / sizeof(void *));
204204
// CHECK-NEXT: return (* fptrptr_->func)(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
@@ -212,7 +212,7 @@ public func returnDerivedDerivedClass() -> DerivedDerivedClass {
212212
// CHECK-NEXT: void **vtable_ = *selfPtr_;
213213
// CHECK-NEXT: #endif
214214
// CHECK-NEXT: struct FTypeAddress {
215-
// CHECK-NEXT: decltype(_impl::$s5Class04BaseA0C10storedPropSivs) * func;
215+
// CHECK-NEXT: decltype(Class::_impl::$s5Class04BaseA0C10storedPropSivs) * func;
216216
// CHECK-NEXT: };
217217
// CHECK-NEXT: FTypeAddress *fptrptr_ = reinterpret_cast<FTypeAddress *>(vtable_ + [[#VM8:]] / sizeof(void *));
218218
// CHECK-NEXT: (* fptrptr_->func)(value, ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
@@ -226,7 +226,7 @@ public func returnDerivedDerivedClass() -> DerivedDerivedClass {
226226
// CHECK-NEXT: void **vtable_ = *selfPtr_;
227227
// CHECK-NEXT: #endif
228228
// CHECK-NEXT: struct FTypeAddress {
229-
// CHECK-NEXT: decltype(_impl::$s5Class04BaseA0CyS2icig) * func;
229+
// CHECK-NEXT: decltype(Class::_impl::$s5Class04BaseA0CyS2icig) * func;
230230
// CHECK-NEXT: };
231231
// CHECK-NEXT: FTypeAddress *fptrptr_ = reinterpret_cast<FTypeAddress *>(vtable_ + [[#VM10:]] / sizeof(void *));
232232
// CHECK-NEXT: return (* fptrptr_->func)(i, ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
@@ -240,7 +240,7 @@ public func returnDerivedDerivedClass() -> DerivedDerivedClass {
240240
// CHECK-NEXT: void **vtable_ = *selfPtr_;
241241
// CHECK-NEXT: #endif
242242
// CHECK-NEXT: struct FTypeAddress {
243-
// CHECK-NEXT: decltype(_impl::$s5Class07DerivedA0C13virtualMethodyyF) * func;
243+
// CHECK-NEXT: decltype(Class::_impl::$s5Class07DerivedA0C13virtualMethodyyF) * func;
244244
// CHECK-NEXT: };
245245
// CHECK-NEXT: FTypeAddress *fptrptr_ = reinterpret_cast<FTypeAddress *>(vtable_ + [[#VM1]] / sizeof(void *));
246246
// CHECK-NEXT: (* fptrptr_->func)(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
@@ -254,7 +254,7 @@ public func returnDerivedDerivedClass() -> DerivedDerivedClass {
254254
// CHECK-NEXT: void **vtable_ = *selfPtr_;
255255
// CHECK-NEXT: #endif
256256
// CHECK-NEXT: struct FTypeAddress {
257-
// CHECK-NEXT: decltype(_impl::$s5Class07DerivedA0C016virtualMethodIntE0yS2iF) * func;
257+
// CHECK-NEXT: decltype(Class::_impl::$s5Class07DerivedA0C016virtualMethodIntE0yS2iF) * func;
258258
// CHECK-NEXT: };
259259
// CHECK-NEXT: FTypeAddress *fptrptr_ = reinterpret_cast<FTypeAddress *>(vtable_ + [[#VM2]] / sizeof(void *));
260260
// CHECK-NEXT: return (* fptrptr_->func)(x, ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
@@ -268,7 +268,7 @@ public func returnDerivedDerivedClass() -> DerivedDerivedClass {
268268
// CHECK-NEXT: void **vtable_ = *selfPtr_;
269269
// CHECK-NEXT: #endif
270270
// CHECK-NEXT: struct FTypeAddress {
271-
// CHECK-NEXT: decltype(_impl::$s5Class07DerivedA0C015virtualMethodInB0yAA04BaseA0CAFF) * func;
271+
// CHECK-NEXT: decltype(Class::_impl::$s5Class07DerivedA0C015virtualMethodInB0yAA04BaseA0CAFF) * func;
272272
// CHECK-NEXT: };
273273
// CHECK-NEXT: FTypeAddress *fptrptr_ = reinterpret_cast<FTypeAddress *>(vtable_ + [[#VM11:]] / sizeof(void *));
274274
// CHECK-NEXT: return _impl::_impl_BaseClass::makeRetained((* fptrptr_->func)(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(x), ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this)));
@@ -282,7 +282,7 @@ public func returnDerivedDerivedClass() -> DerivedDerivedClass {
282282
// CHECK-NEXT: void **vtable_ = *selfPtr_;
283283
// CHECK-NEXT: #endif
284284
// CHECK-NEXT: struct FTypeAddress {
285-
// CHECK-NEXT: decltype(_impl::$s5Class07DerivedA0C19virtualComputedPropSivg) * func;
285+
// CHECK-NEXT: decltype(Class::_impl::$s5Class07DerivedA0C19virtualComputedPropSivg) * func;
286286
// CHECK-NEXT: };
287287
// CHECK-NEXT: FTypeAddress *fptrptr_ = reinterpret_cast<FTypeAddress *>(vtable_ + [[#VM3]] / sizeof(void *));
288288
// CHECK-NEXT: return (* fptrptr_->func)(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
@@ -296,7 +296,7 @@ public func returnDerivedDerivedClass() -> DerivedDerivedClass {
296296
// CHECK-NEXT: void **vtable_ = *selfPtr_;
297297
// CHECK-NEXT: #endif
298298
// CHECK-NEXT: struct FTypeAddress {
299-
// CHECK-NEXT: decltype(_impl::$s5Class07DerivedA0C21virtualComputedGetSets5Int64Vvg) * func;
299+
// CHECK-NEXT: decltype(Class::_impl::$s5Class07DerivedA0C21virtualComputedGetSets5Int64Vvg) * func;
300300
// CHECK-NEXT: };
301301
// CHECK-NEXT: FTypeAddress *fptrptr_ = reinterpret_cast<FTypeAddress *>(vtable_ + [[#VM4]] / sizeof(void *));
302302
// CHECK-NEXT: return (* fptrptr_->func)(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
@@ -310,7 +310,7 @@ public func returnDerivedDerivedClass() -> DerivedDerivedClass {
310310
// CHECK-NEXT: void **vtable_ = *selfPtr_;
311311
// CHECK-NEXT: #endif
312312
// CHECK-NEXT: struct FTypeAddress {
313-
// CHECK-NEXT: decltype(_impl::$s5Class07DerivedA0C21virtualComputedGetSets5Int64Vvs) * func;
313+
// CHECK-NEXT: decltype(Class::_impl::$s5Class07DerivedA0C21virtualComputedGetSets5Int64Vvs) * func;
314314
// CHECK-NEXT: };
315315
// CHECK-NEXT: FTypeAddress *fptrptr_ = reinterpret_cast<FTypeAddress *>(vtable_ + [[#VM5]] / sizeof(void *));
316316
// CHECK-NEXT: (* fptrptr_->func)(newValue, ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
@@ -324,7 +324,7 @@ public func returnDerivedDerivedClass() -> DerivedDerivedClass {
324324
// CHECK-NEXT: void **vtable_ = *selfPtr_;
325325
// CHECK-NEXT: #endif
326326
// CHECK-NEXT: struct FTypeAddress {
327-
// CHECK-NEXT: decltype(_impl::$s5Class07DerivedA0C10storedPropSivg) * func;
327+
// CHECK-NEXT: decltype(Class::_impl::$s5Class07DerivedA0C10storedPropSivg) * func;
328328
// CHECK-NEXT: };
329329
// CHECK-NEXT: FTypeAddress *fptrptr_ = reinterpret_cast<FTypeAddress *>(vtable_ + [[#VM7]] / sizeof(void *));
330330
// CHECK-NEXT: return (* fptrptr_->func)(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
@@ -338,7 +338,7 @@ public func returnDerivedDerivedClass() -> DerivedDerivedClass {
338338
// CHECK-NEXT: void **vtable_ = *selfPtr_;
339339
// CHECK-NEXT: #endif
340340
// CHECK-NEXT: struct FTypeAddress {
341-
// CHECK-NEXT: decltype(_impl::$s5Class07DerivedA0C10storedPropSivs) * func;
341+
// CHECK-NEXT: decltype(Class::_impl::$s5Class07DerivedA0C10storedPropSivs) * func;
342342
// CHECK-NEXT: };
343343
// CHECK-NEXT: FTypeAddress *fptrptr_ = reinterpret_cast<FTypeAddress *>(vtable_ + [[#VM8]] / sizeof(void *));
344344
// CHECK-NEXT: (* fptrptr_->func)(newValue, ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));
@@ -352,7 +352,7 @@ public func returnDerivedDerivedClass() -> DerivedDerivedClass {
352352
// CHECK-NEXT: void **vtable_ = *selfPtr_;
353353
// CHECK-NEXT: #endif
354354
// CHECK-NEXT: struct FTypeAddress {
355-
// CHECK-NEXT: decltype(_impl::$s5Class07DerivedA0CyS2icig) * func;
355+
// CHECK-NEXT: decltype(Class::_impl::$s5Class07DerivedA0CyS2icig) * func;
356356
// CHECK-NEXT: };
357357
// CHECK-NEXT: FTypeAddress *fptrptr_ = reinterpret_cast<FTypeAddress *>(vtable_ + [[#VM10]] / sizeof(void *));
358358
// CHECK-NEXT: return (* fptrptr_->func)(i, ::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));

test/Interop/SwiftToCxx/class/swift-subclass-of-resilient-class-virtual-method-dispatch.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ public func createCrossModuleDerivedDerivedClass() -> CrossModuleDerivedDerivedC
9494
// CHECK-NEXT: void **vtable_ = *selfPtr_;
9595
// CHECK-NEXT: #endif
9696
// CHECK-NEXT: struct FTypeAddress {
97-
// CHECK-NEXT: decltype(_impl::$s8UseClass018CrossModuleDerivedB0C015virtualMethodInE0yyF) * func;
97+
// CHECK-NEXT: decltype(UseClass::_impl::$s8UseClass018CrossModuleDerivedB0C015virtualMethodInE0yyF) * func;
9898
// CHECK-NEXT: };
9999
// CHECK-NEXT: FTypeAddress *fptrptr_ = reinterpret_cast<FTypeAddress *>(vtable_ + (_impl::$s8UseClass018CrossModuleDerivedB0CMo + 0) / sizeof(void *));
100100
// CHECK-NEXT: (* fptrptr_->func)(::swift::_impl::_impl_RefCountedClass::getOpaquePointer(*this));

test/Interop/SwiftToCxx/structs/nested-structs-in-cxx.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// RUN: %empty-directory(%t)
22
// RUN: %target-swift-frontend %s -enable-library-evolution -module-name Structs -clang-header-expose-decls=all-public -typecheck -verify -emit-clang-header-path %t/structs.h
3-
// RN: %FileCheck %s < %t/structs.h
3+
// RUN: %check-interop-cxx-header-in-clang(%t/structs.h -DSWIFT_CXX_INTEROP_HIDE_STL_OVERLAY -std=c++17)
44

5+
// RUN: %empty-directory(%t)
6+
// RUN: %target-swift-frontend %s -module-name Structs -clang-header-expose-decls=all-public -typecheck -verify -emit-clang-header-path %t/structs.h
57
// RUN: %check-interop-cxx-header-in-clang(%t/structs.h -DSWIFT_CXX_INTEROP_HIDE_STL_OVERLAY -std=c++17)
68

79
public enum AudioFileType {

0 commit comments

Comments
 (0)