Skip to content

Commit 1f534e1

Browse files
committed
DeinitDevirtualizer: bail out for C++ move-only types.
We cannot de-virtualize C++ destructor calls of C++ move-only types because we cannot get its destructor in SIL. Fixes a miscompile.
1 parent f536359 commit 1f534e1

File tree

3 files changed

+29
-1
lines changed

3 files changed

+29
-1
lines changed

SwiftCompilerSources/Sources/Optimizer/Utilities/Devirtualization.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ private func devirtualize(destroy: some DevirtualizableDestroy, _ context: some
3939
return true
4040
}
4141

42+
// We cannot de-virtualize C++ destructor calls of C++ move-only types because we cannot get
43+
// its destructor (`nominal.valueTypeDestructor` is nil).
44+
if nominal.hasClangNode {
45+
return false
46+
}
47+
4248
if nominal.valueTypeDestructor != nil && !destroy.shouldDropDeinit {
4349
guard let deinitFunc = context.lookupDeinit(ofNominal: nominal) else {
4450
return false

test/SILOptimizer/Inputs/CXXTypesWithUserProvidedDestructor.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,15 @@ struct HasMemberWithUserProvidedDestructor {
1919
~HasMemberWithUserProvidedDestructor() {}
2020
};
2121

22+
void foo();
23+
24+
struct NonCopyable {
25+
NonCopyable(int x) : x(x) {}
26+
NonCopyable(const NonCopyable &) = delete;
27+
NonCopyable(NonCopyable &&other) : x(other.x) { other.x = -123; }
28+
~NonCopyable() { foo(); }
29+
30+
int x;
31+
};
32+
2233
#endif // TEST_SIL_OPTIMIZER_CXX_WITH_CUSTOM_DESTRUCTOR_H

test/SILOptimizer/devirt_deinits.sil

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-sil-opt -sil-print-types %s -deinit-devirtualizer -module-name=test | %FileCheck %s
1+
// RUN: %target-sil-opt -sil-print-types %s -deinit-devirtualizer -module-name=test -enable-experimental-cxx-interop -I %S/Inputs | %FileCheck %s
22

33
// REQUIRES: swift_in_compiler
44

@@ -7,6 +7,7 @@ sil_stage canonical
77
import Builtin
88
import Swift
99
import SwiftShims
10+
import CXXTypesWithUserProvidedDestructor
1011

1112
@inline(never) func log(_ s: StaticString)
1213

@@ -283,6 +284,16 @@ bb0(%0 : $*T):
283284
return %r : $()
284285
}
285286

287+
// CHECK-LABEL: sil [ossa] @nodevirt_of_cxx_type :
288+
// CHECK: destroy_addr %0
289+
// CHECK: } // end sil function 'nodevirt_of_cxx_type'
290+
sil [ossa] @nodevirt_of_cxx_type : $@convention(thin) (@in NonCopyable) -> () {
291+
bb0(%0 : $*NonCopyable):
292+
destroy_addr %0
293+
%5 = tuple ()
294+
return %5
295+
}
296+
286297
// CHECK-LABEL: sil @test_non_ossa :
287298
// CHECK: destroy_addr %0
288299
// CHECK: } // end sil function 'test_non_ossa'

0 commit comments

Comments
 (0)