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