1 // Check that delete exprs call aligned (de)allocation functions if 2 // -faligned-allocation is passed in both C++11 and C++14. 3 // RUN: %clang_cc1 -std=c++11 -fexceptions -fsized-deallocation -faligned-allocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s 4 // RUN: %clang_cc1 -std=c++14 -fexceptions -fsized-deallocation -faligned-allocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s 5 // RUN: %clang_cc1 -std=c++1z -fexceptions -fsized-deallocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s 6 7 // Check that we don't used aligned (de)allocation without -faligned-allocation or C++1z. 8 // RUN: %clang_cc1 -std=c++14 -DUNALIGNED -fexceptions %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK-UNALIGNED 9 // RUN: %clang_cc1 -std=c++1z -DUNALIGNED -fexceptions -fno-aligned-allocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s --check-prefix=CHECK-UNALIGNED 10 11 // CHECK-UNALIGNED-NOT: _Znwm_St11align_val_t 12 // CHECK-UNALIGNED-NOT: _Znam_St11align_val_t 13 // CHECK-UNALIGNED-NOT: _ZdlPv_St11align_val_t 14 // CHECK-UNALIGNED-NOT: _ZdaPv_St11align_val_t 15 // CHECK-UNALIGNED-NOT: _ZdlPvm_St11align_val_t 16 // CHECK-UNALIGNED-NOT: _ZdaPvm_St11align_val_t 17 18 typedef decltype(sizeof(0)) size_t; 19 namespace std { enum class align_val_t : size_t {}; } 20 21 #define OVERALIGNED alignas(__STDCPP_DEFAULT_NEW_ALIGNMENT__ * 2) 22 23 // Global new and delete. 24 // ====================== 25 struct OVERALIGNED A { A(); int n[128]; }; 26 27 // CHECK-LABEL: define {{.*}} @_Z2a0v() 28 // CHECK: %[[ALLOC:.*]] = call i8* @_ZnwmSt11align_val_t(i64 512, i64 32) 29 // CHECK: call void @_ZdlPvSt11align_val_t(i8* %[[ALLOC]], i64 32) 30 void *a0() { return new A; } 31 32 // CHECK-LABEL: define {{.*}} @_Z2a1l( 33 // CHECK: %[[ALLOC:.*]] = call i8* @_ZnamSt11align_val_t(i64 %{{.*}}, i64 32) 34 // No array cookie. 35 // CHECK-NOT: store 36 // CHECK: invoke void @_ZN1AC1Ev( 37 // CHECK: call void @_ZdaPvSt11align_val_t(i8* %[[ALLOC]], i64 32) 38 void *a1(long n) { return new A[n]; } 39 40 // CHECK-LABEL: define {{.*}} @_Z2a2P1A( 41 // CHECK: call void @_ZdlPvmSt11align_val_t(i8* %{{.*}}, i64 512, i64 32) #9 42 void a2(A *p) { delete p; } 43 44 // CHECK-LABEL: define {{.*}} @_Z2a3P1A( 45 // CHECK: call void @_ZdaPvSt11align_val_t(i8* %{{.*}}, i64 32) #9 46 void a3(A *p) { delete[] p; } 47 48 49 // Class-specific usual new and delete. 50 // ==================================== 51 struct OVERALIGNED B { 52 B(); 53 // These are just a distraction. We should ignore them. 54 void *operator new(size_t); 55 void operator delete(void*, size_t); 56 void operator delete[](void*, size_t); 57 58 void *operator new(size_t, std::align_val_t); 59 void operator delete(void*, std::align_val_t); 60 void operator delete[](void*, std::align_val_t); 61 62 int n[128]; 63 }; 64 65 // CHECK-LABEL: define {{.*}} @_Z2b0v() 66 // CHECK: %[[ALLOC:.*]] = call i8* @_ZN1BnwEmSt11align_val_t(i64 512, i64 32) 67 // CHECK: call void @_ZN1BdlEPvSt11align_val_t(i8* %[[ALLOC]], i64 32) 68 void *b0() { return new B; } 69 70 // CHECK-LABEL: define {{.*}} @_Z2b1l( 71 // CHECK: %[[ALLOC:.*]] = call i8* @_ZnamSt11align_val_t(i64 %{{.*}}, i64 32) 72 // No array cookie. 73 // CHECK-NOT: store 74 // CHECK: invoke void @_ZN1BC1Ev( 75 // CHECK: call void @_ZN1BdaEPvSt11align_val_t(i8* %[[ALLOC]], i64 32) 76 void *b1(long n) { return new B[n]; } 77 78 // CHECK-LABEL: define {{.*}} @_Z2b2P1B( 79 // CHECK: call void @_ZN1BdlEPvSt11align_val_t(i8* %{{.*}}, i64 32) 80 void b2(B *p) { delete p; } 81 82 // CHECK-LABEL: define {{.*}} @_Z2b3P1B( 83 // CHECK: call void @_ZN1BdaEPvSt11align_val_t(i8* %{{.*}}, i64 32) 84 void b3(B *p) { delete[] p; } 85 86 struct OVERALIGNED C { 87 C(); 88 void *operator new[](size_t, std::align_val_t); 89 void operator delete[](void*, size_t, std::align_val_t); 90 91 // It doesn't matter that we have an unaligned operator delete[] that doesn't 92 // want the size. What matters is that the aligned one does. 93 void operator delete[](void*); 94 }; 95 96 // This one has an array cookie. 97 // CHECK-LABEL: define {{.*}} @_Z2b4l( 98 // CHECK: call {{.*}} @llvm.umul.with.overflow{{.*}}i64 32 99 // CHECK: call {{.*}} @llvm.uadd.with.overflow{{.*}}i64 32 100 // CHECK: %[[ALLOC:.*]] = call i8* @_ZN1CnaEmSt11align_val_t(i64 %{{.*}}, i64 32) 101 // CHECK: store 102 // CHECK: call void @_ZN1CC1Ev( 103 // 104 // Note, we're still calling a placement allocation function, and there is no 105 // matching placement operator delete. =( 106 // FIXME: This seems broken. 107 // CHECK-NOT: call void @_ZN1CdaEPvmSt11align_val_t( 108 #ifndef UNALIGNED 109 void *b4(long n) { return new C[n]; } 110 #endif 111 112 // CHECK-LABEL: define {{.*}} @_Z2b5P1C( 113 // CHECK: mul i64{{.*}} 32 114 // CHECK: add i64{{.*}} 32 115 // CHECK: call void @_ZN1CdaEPvmSt11align_val_t( 116 void b5(C *p) { delete[] p; } 117 118 119 // Global placement new. 120 // ===================== 121 122 struct Q { int n; } q; 123 void *operator new(size_t, Q); 124 void *operator new(size_t, std::align_val_t, Q); 125 void operator delete(void*, Q); 126 void operator delete(void*, std::align_val_t, Q); 127 128 // CHECK-LABEL: define {{.*}} @_Z2c0v( 129 // CHECK: %[[ALLOC:.*]] = call i8* @_ZnwmSt11align_val_t1Q(i64 512, i64 32, i32 % 130 // CHECK: call void @_ZdlPvSt11align_val_t1Q(i8* %[[ALLOC]], i64 32, i32 % 131 void *c0() { return new (q) A; } 132 133 134 // Class-specific placement new. 135 // ============================= 136 137 struct OVERALIGNED D { 138 D(); 139 void *operator new(size_t, Q); 140 void *operator new(size_t, std::align_val_t, Q); 141 void operator delete(void*, Q); 142 void operator delete(void*, std::align_val_t, Q); 143 }; 144 145 // CHECK-LABEL: define {{.*}} @_Z2d0v( 146 // CHECK: %[[ALLOC:.*]] = call i8* @_ZN1DnwEmSt11align_val_t1Q(i64 32, i64 32, i32 % 147 // CHECK: call void @_ZN1DdlEPvSt11align_val_t1Q(i8* %[[ALLOC]], i64 32, i32 % 148 void *d0() { return new (q) D; } 149 150 151 // Calling aligned new with placement syntax. 152 // ========================================== 153 154 #ifndef UNALIGNED 155 // CHECK-LABEL: define {{.*}} @_Z2e0v( 156 // CHECK: %[[ALLOC:.*]] = call i8* @_ZnwmSt11align_val_t(i64 512, i64 5) 157 // CHECK: call void @_ZdlPvSt11align_val_t(i8* %[[ALLOC]], i64 5) 158 void *e0() { return new (std::align_val_t(5)) A; } 159 160 // CHECK-LABEL: define {{.*}} @_Z2e1v( 161 // CHECK: %[[ALLOC:.*]] = call i8* @_ZN1BnwEmSt11align_val_t(i64 512, i64 5) 162 // CHECK: call void @_ZN1BdlEPvSt11align_val_t(i8* %[[ALLOC]], i64 5) 163 void *e1() { return new (std::align_val_t(5)) B; } 164 #endif 165 166 // Variadic placement/non-placement allocation functions. 167 // ====================================================== 168 169 struct OVERALIGNED F { 170 F(); 171 void *operator new(size_t, ...); 172 void operator delete(void*, ...); 173 int n[128]; 174 }; 175 176 // CHECK-LABEL: define {{.*}} @_Z2f0v( 177 // CHECK: %[[ALLOC:.*]] = call i8* (i64, ...) @_ZN1FnwEmz(i64 512, i64 32) 178 // Non-placement allocation function, uses normal deallocation lookup which 179 // cares about whether a parameter has type std::align_val_t. 180 // CHECK: call void (i8*, ...) @_ZN1FdlEPvz(i8* %[[ALLOC]]) 181 void *f0() { return new F; } 182 183 // CHECK-LABEL: define {{.*}} @_Z2f1v( 184 // CHECK: %[[ALLOC:.*]] = call i8* (i64, ...) @_ZN1FnwEmz(i64 512, i64 32, i32 % 185 // Placement allocation function, uses placement deallocation matching, which 186 // passes same arguments and therefore includes alignment. 187 // CHECK: call void (i8*, ...) @_ZN1FdlEPvz(i8* %[[ALLOC]], i64 32, i32 % 188 void *f1() { return new (q) F; } 189 190 struct OVERALIGNED G { 191 G(); 192 void *operator new(size_t, std::align_val_t, ...); 193 void operator delete(void*, std::align_val_t, ...); 194 int n[128]; 195 }; 196 #ifndef UNALIGNED 197 // CHECK-LABEL: define {{.*}} @_Z2g0v 198 // CHECK: %[[ALLOC:.*]] = call i8* (i64, i64, ...) @_ZN1GnwEmSt11align_val_tz(i64 512, i64 32) 199 // CHECK: call void (i8*, i64, ...) @_ZN1GdlEPvSt11align_val_tz(i8* %[[ALLOC]], i64 32) 200 void *g0() { return new G; } 201 202 // CHECK-LABEL: define {{.*}} @_Z2g1v 203 // CHECK: %[[ALLOC:.*]] = call i8* (i64, i64, ...) @_ZN1GnwEmSt11align_val_tz(i64 512, i64 32, i32 % 204 // CHECK: call void (i8*, i64, ...) @_ZN1GdlEPvSt11align_val_tz(i8* %[[ALLOC]], i64 32, i32 % 205 void *g1() { return new (q) G; } 206 #endif 207