Skip to content

Commit 9220ec1

Browse files
authored
Merge pull request #66557 from apple/egorzhdan/irgen-defaulted-constructor
[cxx-interop] Avoid linker errors when calling a defaulted constructor
2 parents 9f51c06 + b459fb5 commit 9220ec1

File tree

5 files changed

+45
-19
lines changed

5 files changed

+45
-19
lines changed

lib/ClangImporter/ImportDecl.cpp

+29-17
Original file line numberDiff line numberDiff line change
@@ -2635,30 +2635,38 @@ namespace {
26352635
}
26362636
clang::CXXConstructorDecl *copyCtor = nullptr;
26372637
clang::CXXConstructorDecl *moveCtor = nullptr;
2638+
clang::CXXConstructorDecl *defaultCtor = nullptr;
26382639
if (decl->needsImplicitCopyConstructor()) {
26392640
copyCtor = clangSema.DeclareImplicitCopyConstructor(
26402641
const_cast<clang::CXXRecordDecl *>(decl));
2641-
} else if (decl->needsImplicitMoveConstructor()) {
2642+
}
2643+
if (decl->needsImplicitMoveConstructor()) {
26422644
moveCtor = clangSema.DeclareImplicitMoveConstructor(
26432645
const_cast<clang::CXXRecordDecl *>(decl));
2644-
} else {
2645-
// We may have a defaulted copy constructor that needs to be defined.
2646-
// Try to find it.
2647-
for (auto methods : decl->methods()) {
2648-
if (auto declCtor = dyn_cast<clang::CXXConstructorDecl>(methods)) {
2649-
if (declCtor->isDefaulted() &&
2650-
declCtor->getAccess() == clang::AS_public &&
2651-
!declCtor->isDeleted() &&
2652-
// Note: we use "doesThisDeclarationHaveABody" here because
2653-
// that's what "DefineImplicitCopyConstructor" checks.
2654-
!declCtor->doesThisDeclarationHaveABody()) {
2655-
if (declCtor->isCopyConstructor()) {
2646+
}
2647+
if (decl->needsImplicitDefaultConstructor()) {
2648+
defaultCtor = clangSema.DeclareImplicitDefaultConstructor(
2649+
const_cast<clang::CXXRecordDecl *>(decl));
2650+
}
2651+
// We may have a defaulted copy/move/default constructor that needs to
2652+
// be defined. Try to find it.
2653+
for (auto methods : decl->methods()) {
2654+
if (auto declCtor = dyn_cast<clang::CXXConstructorDecl>(methods)) {
2655+
if (declCtor->isDefaulted() &&
2656+
declCtor->getAccess() == clang::AS_public &&
2657+
!declCtor->isDeleted() &&
2658+
// Note: we use "doesThisDeclarationHaveABody" here because
2659+
// that's what "DefineImplicitCopyConstructor" checks.
2660+
!declCtor->doesThisDeclarationHaveABody()) {
2661+
if (declCtor->isCopyConstructor()) {
2662+
if (!copyCtor)
26562663
copyCtor = declCtor;
2657-
break;
2658-
} else if (declCtor->isMoveConstructor()) {
2664+
} else if (declCtor->isMoveConstructor()) {
2665+
if (!moveCtor)
26592666
moveCtor = declCtor;
2660-
break;
2661-
}
2667+
} else if (declCtor->isDefaultConstructor()) {
2668+
if (!defaultCtor)
2669+
defaultCtor = declCtor;
26622670
}
26632671
}
26642672
}
@@ -2671,6 +2679,10 @@ namespace {
26712679
clangSema.DefineImplicitMoveConstructor(clang::SourceLocation(),
26722680
moveCtor);
26732681
}
2682+
if (defaultCtor) {
2683+
clangSema.DefineImplicitDefaultConstructor(clang::SourceLocation(),
2684+
defaultCtor);
2685+
}
26742686

26752687
if (decl->needsImplicitDestructor()) {
26762688
auto dtor = clangSema.DeclareImplicitDestructor(

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

+5
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ struct ImplicitDefaultConstructor {
1010
int x = 42;
1111
};
1212

13+
struct DefaultedDefaultConstructor {
14+
int x = 42;
15+
DefaultedDefaultConstructor() = default;
16+
};
17+
1318
struct MemberOfClassType {
1419
ImplicitDefaultConstructor member;
1520
};

test/Interop/Cxx/class/constructors-executable.swift

+6
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,12 @@ CxxConstructorTestSuite.test("ImplicitDefaultConstructor") {
1919
expectEqual(42, instance.x)
2020
}
2121

22+
CxxConstructorTestSuite.test("DefaultedDefaultConstructor") {
23+
let instance = DefaultedDefaultConstructor()
24+
25+
expectEqual(42, instance.x)
26+
}
27+
2228
CxxConstructorTestSuite.test("MemberOfClassType") {
2329
let instance = MemberOfClassType()
2430

test/Interop/Cxx/class/constructors-module-interface.swift

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@
99
// CHECK-NEXT: init(x: Int32)
1010
// CHECK-NEXT: var x: Int32
1111
// CHECK-NEXT: }
12+
// CHECK-NEXT: struct DefaultedDefaultConstructor {
13+
// CHECK-NEXT: init()
14+
// CHECK-NEXT: init(x: Int32)
15+
// CHECK-NEXT: var x: Int32
16+
// CHECK-NEXT: }
1217
// CHECK-NEXT: struct MemberOfClassType {
1318
// CHECK-NEXT: init()
1419
// CHECK-NEXT: init(member: ImplicitDefaultConstructor)

test/Interop/Cxx/stdlib/use-std-map.swift

-2
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,11 @@ import Cxx
1111

1212
var StdMapTestSuite = TestSuite("StdMap")
1313

14-
#if !os(Linux) // https://github.com/apple/swift/issues/61412
1514
StdMapTestSuite.test("init") {
1615
let m = Map()
1716
expectEqual(m.size(), 0)
1817
expectTrue(m.empty())
1918
}
20-
#endif
2119

2220
StdMapTestSuite.test("Map.subscript") {
2321
// This relies on the `std::map` conformance to `CxxDictionary` protocol.

0 commit comments

Comments
 (0)