Skip to content

Commit 738c8fb

Browse files
committed
[cxx-interop] Skip type metadata for C++ types that are only used in private C++ fields
This fixes compiler errors for C++ types that use pimpl idiom: ``` invalid application of 'sizeof' to an incomplete type ``` rdar://141960396
1 parent 660a2ea commit 738c8fb

File tree

5 files changed

+68
-0
lines changed

5 files changed

+68
-0
lines changed

lib/IRGen/GenReflection.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,15 @@ class FieldTypeMetadataBuilder : public ReflectionMetadataBuilder {
931931

932932
B.addInt32(getNumFields(NTD));
933933
forEachField(IGM, NTD, [&](Field field) {
934+
// Skip private C++ fields that were imported as private Swift fields.
935+
// The type of a private field might not have all the type witness
936+
// operations that Swift requires, for instance,
937+
// `std::unique_ptr<IncompleteType>` would not have a destructor.
938+
if (field.getKind() == Field::Kind::Var &&
939+
field.getVarDecl()->getClangDecl() &&
940+
field.getVarDecl()->getFormalAccess() == AccessLevel::Private)
941+
return;
942+
934943
addField(field);
935944
});
936945
}

test/Interop/Cxx/class/Inputs/module.modulemap

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,3 +151,9 @@ module Closure {
151151
header "closure.h"
152152
requires cplusplus
153153
}
154+
155+
module PIMPL {
156+
header "pimpl.h"
157+
requires cplusplus
158+
export *
159+
}

test/Interop/Cxx/class/Inputs/pimpl.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#include <memory>
2+
3+
// C++ types that use pointer-to-implementation idiom.
4+
5+
struct HasPIMPL {
6+
private:
7+
struct I;
8+
I *ptr;
9+
};
10+
11+
HasPIMPL createHasPIMPL();
12+
13+
struct HasSmartPIMPL {
14+
private:
15+
struct I;
16+
std::unique_ptr<I> smart_ptr;
17+
18+
public:
19+
HasSmartPIMPL();
20+
HasSmartPIMPL(const HasSmartPIMPL &other);
21+
~HasSmartPIMPL();
22+
};
23+
24+
HasSmartPIMPL createHasSmartPIMPL();
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %target-swiftxx-frontend -emit-irgen %s -I %S/Inputs | %FileCheck %s
2+
3+
// Make sure Swift handles the C++ pointer-to-implementation idiom properly.
4+
5+
import PIMPL
6+
7+
// Trigger type metadata to be emitted by conforming C++ types to a Swift protocol.
8+
protocol MyProto {}
9+
extension HasPIMPL : MyProto {}
10+
extension HasSmartPIMPL : MyProto {}
11+
12+
let _ = createHasPIMPL()
13+
let _ = createHasSmartPIMPL()
14+
15+
// CHECK-NOT: @"get_type_metadata {{.*}}default_delete{{.*}}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %target-swift-ide-test -print-module -module-to-print=PIMPL -print-access -I %S/Inputs -cxx-interoperability-mode=default -source-filename=x | %FileCheck %s
2+
3+
// FIXME: We can't import std::unique_ptr properly on Windows (https://github.com/apple/swift/issues/70226)
4+
// XFAIL: OS=windows-msvc
5+
6+
// CHECK: public struct HasPIMPL {
7+
// CHECK-NEXT: public init()
8+
// CHECK-NEXT: private var ptr: OpaquePointer!
9+
// CHECK-NEXT: }
10+
11+
// CHECK: public struct HasSmartPIMPL {
12+
// CHECK-NEXT: public init()
13+
// CHECK-NEXT: private var smart_ptr: std.
14+
// CHECK-NEXT: }

0 commit comments

Comments
 (0)