Skip to content

Commit 5fa0d63

Browse files
Xazax-hunGabor Horvath
authored and
Gabor Horvath
committed
[6.1][cxx-interop] Fix nested structs for non-opaque types
Explanation: Fixes an issue where the generated reverse interop header would not compile for nested types when library evolution is off. While this is a bug in a new feature in 6.1, users upgrading from 6.0 to 6.1 can see this as a regression because the new constructs that we started to expose to the interop header in 6.1 will trigger the compilation error. Scope: C++ reverse interop for nested classes for non-opaque types. Issue: rdar://147882976 Risk: Low, the fix is fairly targeted. While it does affect other (non-nested type) scenarios, those changes are straightforward making some names fully qualified. Moreover, that is well tested in our test suite. Testing: Added tests to test suite Reviewer: @egorzhdan
1 parent 9843a75 commit 5fa0d63

7 files changed

+37
-28
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
@@ -95,7 +95,8 @@ class ClangSyntaxPrinter {
9595
const NominalTypeDecl *typeDecl);
9696

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

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

lib/PrintAsClang/PrintClangFunction.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1238,7 +1238,10 @@ void DeclAndTypeClangFunctionPrinter::printCxxThunkBody(
12381238
os << "void **vtable_ = *selfPtr_;\n";
12391239
os << "#endif\n";
12401240
os << "struct FTypeAddress {\n";
1241-
os << "decltype(" << cxx_synthesis::getCxxImplNamespaceName()
1241+
os << "decltype(";
1242+
ClangSyntaxPrinter(moduleContext->getASTContext(), os)
1243+
.printBaseName(moduleContext);
1244+
os << "::" << cxx_synthesis::getCxxImplNamespaceName()
12421245
<< "::" << swiftSymbolName << ") *";
12431246
if (auto ptrAuthDisc = dispatchInfo->getPointerAuthDiscriminator())
12441247
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(os);
3333
printer.printModuleNameCPrefix(*type->getParentModule());
34-
if (!ClangSyntaxPrinter(os).printNestedTypeNamespaceQualifiers(type))
35-
os << "::";
34+
if (!ClangSyntaxPrinter(os)
35+
.printNestedTypeNamespaceQualifiers(type, /*forC=*/true))
36+
os << "_";
3637
printer.printBaseName(type);
3738
}
3839

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: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %target-swift-frontend %s -enable-library-evolution -typecheck -module-name Structs -clang-header-expose-decls=all-public -emit-clang-header-path %t/structs.h
3-
// RN: %FileCheck %s < %t/structs.h
2+
// 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+
// 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)