File tree Expand file tree Collapse file tree 2 files changed +65
-1
lines changed Expand file tree Collapse file tree 2 files changed +65
-1
lines changed Original file line number Diff line number Diff line change @@ -85,8 +85,19 @@ class ClangDeclFinder
85
85
bool VisitCXXConstructorDecl (clang::CXXConstructorDecl *CXXCD) {
86
86
callback (CXXCD);
87
87
for (clang::CXXCtorInitializer *CXXCI : CXXCD->inits ()) {
88
- if (clang::FieldDecl *FD = CXXCI->getMember ())
88
+ if (clang::FieldDecl *FD = CXXCI->getMember ()) {
89
89
callback (FD);
90
+ // A throwing constructor might throw after the field is initialized,
91
+ // emitting additional cleanup code that destroys the field. Make sure
92
+ // we record the destructor of the field in that case as it might need
93
+ // to be potentially emitted.
94
+ if (auto *recordType = FD->getType ()->getAsCXXRecordDecl ()) {
95
+ if (auto *destructor = recordType->getDestructor ()) {
96
+ if (!destructor->isDeleted ())
97
+ callback (destructor);
98
+ }
99
+ }
100
+ }
90
101
}
91
102
return true ;
92
103
}
Original file line number Diff line number Diff line change
1
+ // RUN: rm -rf %t
2
+ // RUN: split-file %s %t
3
+ // RUN: %target-swiftxx-frontend -emit-ir -I %t/Inputs -validate-tbd-against-ir=none %t/test.swift | %FileCheck %s
4
+
5
+ //--- Inputs/module.modulemap
6
+ module ThrowingConstructorDestructorCleanupRef {
7
+ header " test.h "
8
+ requires cplusplus
9
+ }
10
+ //--- Inputs/test.h
11
+
12
+ void testFunc( int x) ;
13
+
14
+ template < class T>
15
+ class HasDestruct or {
16
+ T x = 0 ;
17
+ public:
18
+
19
+ HasDestructor ( ) { }
20
+ HasDestructor ( const HasDestruct or & other) : x( other. x) { }
21
+ inline ~ HasDestructor( ) { testFunc ( 42 ) ; }
22
+ } ;
23
+
24
+ template < class T>
25
+ class HasThrowingConstructor {
26
+ HasDestructor< T> m;
27
+ public:
28
+ HasThrowingConstructor ( ) ;
29
+ ~ HasThrowingConstructor( ) ;
30
+ inline HasThrowingConstructor( const HasThrowingConstructor & f ) : m( f. m) {
31
+ doSomethingThatMightThrow ( ) ;
32
+ }
33
+
34
+ void doSomethingThatMightThrow ( ) ;
35
+ } ;
36
+
37
+ inline void test33 ( const HasThrowingConstruct or< int> x) {
38
+
39
+ }
40
+
41
+ using HasThrowingConstructorInt = HasThrowingConstructor < int > ;
42
+
43
+ //--- test.swift
44
+
45
+ import ThrowingConstructorDestructorCleanupRef
46
+
47
+ public func test( ) {
48
+ let x = HasThrowingConstructorInt ( )
49
+ test33 ( x)
50
+ }
51
+
52
+ // Make sure we reach the destructor of 'HasDestructor'
53
+ // CHECK: define linkonce_odr {{.*}} @{{_ZN13HasDestructorIiED2Ev|"\?\?1\?\$HasDestructor@H@@QEAA@XZ"}}
You can’t perform that action at this time.
0 commit comments