Marco Antognini | 8855963 | 2019-07-22 09:39:13 +0000 | [diff] [blame^] | 1 | // RUN: %clang_cc1 -triple %itanium_abi_triple -emit-llvm -std=c++17 -O0 %s -o - | FileCheck %s |
| 2 | // RUN: %clang_cc1 -triple %ms_abi_triple -emit-llvm -std=c++17 -O0 %s -o - | FileCheck %s |
| 3 | |
| 4 | // Minimal reproducer for PR42665. |
| 5 | |
| 6 | struct Foo { |
| 7 | Foo() = default; |
| 8 | virtual ~Foo() = default; |
| 9 | }; |
| 10 | |
| 11 | template <typename Deleter> |
| 12 | struct Pair { |
| 13 | Foo first; |
| 14 | Deleter second; |
| 15 | }; |
| 16 | |
| 17 | template <typename Deleter> |
| 18 | Pair(Foo, Deleter) -> Pair<Deleter>; |
| 19 | |
| 20 | template <typename T> |
| 21 | void deleter(T& t) { t.~T(); } |
| 22 | |
| 23 | auto make_pair() { |
| 24 | return Pair{ Foo(), deleter<Foo> }; |
| 25 | } |
| 26 | |
| 27 | void foobar() { |
| 28 | auto p = make_pair(); |
| 29 | auto& f = p.first; |
| 30 | auto& d = p.second; |
| 31 | d(f); // Invoke virtual destructor of Foo through d. |
| 32 | } // p's destructor is invoked. |
| 33 | |
| 34 | // Regexes are used to handle both kind of mangling. |
| 35 | // |
| 36 | // CHECK-LABEL: define linkonce_odr{{( dso_local)?}} void @{{.*deleter.*Foo.*}}(%struct.Foo* dereferenceable({{[0-9]+}}) |
| 37 | // CHECK-SAME: [[T:%.*]]) |
| 38 | // CHECK: [[T_ADDR:%.*]] = alloca %struct.Foo* |
| 39 | // CHECK: store %struct.Foo* [[T]], %struct.Foo** [[T_ADDR]] |
| 40 | // CHECK: [[R0:%.*]] = load %struct.Foo*, %struct.Foo** [[T_ADDR]] |
| 41 | // CHECK: [[R1:%.*]] = bitcast %struct.Foo* [[R0]] to [[TYPE:.*struct\.Foo.*]]*** |
| 42 | // CHECK: [[VTABLE:%.*]] = load [[TYPE]]**, [[TYPE]]*** [[R1]] |
| 43 | // CHECK: [[VFUN:%.*]] = getelementptr inbounds [[TYPE]]*, [[TYPE]]** [[VTABLE]], i64 0 |
| 44 | // CHECK: [[DTOR:%.*]] = load [[TYPE]]*, [[TYPE]]** [[VFUN]] |
| 45 | // CHECK: call {{(void|i8\*)}} [[DTOR]](%struct.Foo* [[R0]] |
| 46 | // |
| 47 | // CHECK-LABEL: define{{( dso_local)?}} void @{{.*foobar.*}}() |
| 48 | // CHECK: [[P:%.*]] = alloca %struct.Pair |
| 49 | // CHECK: [[F:%.*]] = alloca %struct.Foo* |
| 50 | // CHECK: [[D:%.*]] = alloca [[TYPE:void \(%struct.Foo\*\)]]** |
| 51 | // CHECK: call void @{{.*make_pair.*}}(%struct.Pair* sret [[P]]) |
| 52 | // CHECK: [[FIRST:%.*]] = getelementptr inbounds %struct.Pair, %struct.Pair* [[P]], i32 0, i32 0 |
| 53 | // CHECK: store %struct.Foo* [[FIRST]], %struct.Foo** [[F]] |
| 54 | // CHECK: [[SECOND:%.*]] = getelementptr inbounds %struct.Pair, %struct.Pair* [[P]], i32 0, i32 1 |
| 55 | // CHECK: store void (%struct.Foo*)** [[SECOND]], [[TYPE]]*** [[D]] |
| 56 | // CHECK: [[R0:%.*]] = load [[TYPE]]**, [[TYPE]]*** [[D]] |
| 57 | // CHECK: [[R1:%.*]] = load [[TYPE]]*, [[TYPE]]** [[R0]] |
| 58 | // CHECK: [[R2:%.*]] = load %struct.Foo*, %struct.Foo** [[F]] |
| 59 | // CHECK: call void [[R1]](%struct.Foo* dereferenceable({{[0-9]+}}) [[R2]]) |
| 60 | // CHECK: call void @{{.*Pair.*Foo.*}}(%struct.Pair* [[P]]) |
| 61 | |