223 lines · cpp
1// Check that delete exprs call aligned (de)allocation functions if2// -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 %s4// RUN: %clang_cc1 -std=c++14 -fexceptions -faligned-allocation %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s5// RUN: %clang_cc1 -std=c++1z -fexceptions %s -emit-llvm -triple x86_64-linux-gnu -o - | FileCheck %s6 7// RUN: %clang_cc1 -std=c++1z -fexceptions %s -emit-llvm -triple x86_64-windows-msvc -o - | FileCheck %s --check-prefix=CHECK-MS8 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-UNALIGNED11// 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-UNALIGNED12 13// CHECK-UNALIGNED-NOT: _Znwm_St11align_val_t14// CHECK-UNALIGNED-NOT: _Znam_St11align_val_t15// CHECK-UNALIGNED-NOT: _ZdlPv_St11align_val_t16// CHECK-UNALIGNED-NOT: _ZdaPv_St11align_val_t17// CHECK-UNALIGNED-NOT: _ZdlPvm_St11align_val_t18// CHECK-UNALIGNED-NOT: _ZdaPvm_St11align_val_t19 20typedef decltype(sizeof(0)) size_t;21namespace 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// ======================27struct OVERALIGNED A { A(); int n[128]; };28 29// CHECK-LABEL: define {{.*}} @_Z2a0v()30// CHECK: %[[ALLOC:.*]] = call noalias noundef nonnull align 32 ptr @_ZnwmSt11align_val_t(i64 noundef 512, i64 noundef 32)31// CHECK: call void @_ZdlPvSt11align_val_t(ptr noundef %[[ALLOC]], i64 noundef 32)32// CHECK-MS-LABEL: define {{.*}} @"?a0@@YAPEAXXZ"()33// CHECK-MS: %[[ALLOC:.*]] = call noalias noundef nonnull align 32 ptr @"??2@YAPEAX_KW4align_val_t@std@@@Z"(i64 noundef 512, i64 noundef 32)34// CHECK-MS: cleanuppad35// CHECK-MS: call void @"??3@YAXPEAXW4align_val_t@std@@@Z"(ptr noundef %[[ALLOC]], i64 noundef 32)36void *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 ptr @_ZnamSt11align_val_t(i64 noundef %{{.*}}, i64 noundef 32)43// No array cookie.44// CHECK-NOT: store45// CHECK: invoke void @_ZN1AC1Ev(46// CHECK: call void @_ZdaPvSt11align_val_t(ptr noundef %[[ALLOC]], i64 noundef 32)47// CHECK-MS-LABEL: define {{.*}} @"?a1@@YAPEAXJ@Z"(48// CHECK-MS: %[[ALLOC:.*]] = call noalias noundef nonnull align 32 ptr @"??_U@YAPEAX_KW4align_val_t@std@@@Z"(i64 noundef %{{.*}}, i64 noundef 32)49// No array cookie.50// CHECK-MS-NOT: store51// CHECK-MS: invoke noundef ptr @"??0A@@QEAA@XZ"(52// CHECK-MS: cleanuppad53// CHECK-MS: call void @"??_V@YAXPEAXW4align_val_t@std@@@Z"(ptr noundef %[[ALLOC]], i64 noundef 32)54void *a1(long n) { return new A[n]; }55 56// CHECK-LABEL: define {{.*}} @_Z2a2P1A(57// CHECK: call void @_ZdlPvmSt11align_val_t(ptr noundef %{{.*}}, i64 noundef 512, i64 noundef 32) #958void a2(A *p) { delete p; }59 60// CHECK-LABEL: define {{.*}} @_Z2a3P1A(61// CHECK: call void @_ZdaPvSt11align_val_t(ptr noundef %{{.*}}, i64 noundef 32) #962void a3(A *p) { delete[] p; }63 64 65// Class-specific usual new and delete.66// ====================================67struct 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 ptr @_ZN1BnwEmSt11align_val_t(i64 noundef 512, i64 noundef 32)83// CHECK: call void @_ZN1BdlEPvSt11align_val_t(ptr noundef %[[ALLOC]], i64 noundef 32)84void *b0() { return new B; }85 86// CHECK-LABEL: define {{.*}} @_Z2b1l(87// CHECK: %[[ALLOC:.*]] = call noalias noundef nonnull align 32 ptr @_ZnamSt11align_val_t(i64 noundef %{{.*}}, i64 noundef 32)88// No array cookie.89// CHECK-NOT: store90// CHECK: invoke void @_ZN1BC1Ev(91// CHECK: call void @_ZN1BdaEPvSt11align_val_t(ptr noundef %[[ALLOC]], i64 noundef 32)92void *b1(long n) { return new B[n]; }93 94// CHECK-LABEL: define {{.*}} @_Z2b2P1B(95// CHECK: call void @_ZN1BdlEPvSt11align_val_t(ptr noundef %{{.*}}, i64 noundef 32)96void b2(B *p) { delete p; }97 98// CHECK-LABEL: define {{.*}} @_Z2b3P1B(99// CHECK: call void @_ZN1BdaEPvSt11align_val_t(ptr noundef %{{.*}}, i64 noundef 32)100void b3(B *p) { delete[] p; }101 102struct 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't108 // 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 32115// CHECK: call {{.*}} @llvm.uadd.with.overflow{{.*}}i64 32116// CHECK: %[[ALLOC:.*]] = call noundef ptr @_ZN1CnaEmSt11align_val_t(i64 noundef %{{.*}}, i64 noundef 32)117// CHECK: store118// CHECK: call void @_ZN1CC1Ev(119//120// Note, we're still calling a placement allocation function, and there is no121// matching placement operator delete. =(122// FIXME: This seems broken.123// CHECK-NOT: call void @_ZN1CdaEPvmSt11align_val_t(124#ifndef UNALIGNED125void *b4(long n) { return new C[n]; }126#endif127 128// CHECK-LABEL: define {{.*}} @_Z2b5P1C(129// CHECK: mul i64{{.*}} 32130// CHECK: add i64{{.*}} 32131// CHECK: call void @_ZN1CdaEPvmSt11align_val_t(132void b5(C *p) { delete[] p; }133 134 135// Global placement new.136// =====================137 138struct Q { int n; } q;139void *operator new(size_t, Q);140void *operator new(size_t, std::align_val_t, Q);141void operator delete(void*, Q);142void operator delete(void*, std::align_val_t, Q);143 144// CHECK-LABEL: define {{.*}} @_Z2c0v(145// CHECK: %[[ALLOC:.*]] = call noundef ptr @_ZnwmSt11align_val_t1Q(i64 noundef 512, i64 noundef 32, i32 %146// CHECK: call void @_ZdlPvSt11align_val_t1Q(ptr noundef %[[ALLOC]], i64 noundef 32, i32 %147void *c0() { return new (q) A; }148 149 150// Class-specific placement new.151// =============================152 153struct 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 ptr @_ZN1DnwEmSt11align_val_t1Q(i64 noundef 32, i64 noundef 32, i32 %163// CHECK: call void @_ZN1DdlEPvSt11align_val_t1Q(ptr noundef %[[ALLOC]], i64 noundef 32, i32 %164void *d0() { return new (q) D; }165 166 167// Calling aligned new with placement syntax.168// ==========================================169 170#ifndef UNALIGNED171// CHECK-LABEL: define {{.*}} @_Z2e0v(172// CHECK: %[[ALLOC:.*]] = call noalias noundef nonnull align 4 ptr @_ZnwmSt11align_val_t(i64 noundef 512, i64 noundef 4)173// CHECK: call void @_ZdlPvSt11align_val_t(ptr noundef %[[ALLOC]], i64 noundef 4)174void *e0() { return new (std::align_val_t(4)) A; }175 176// CHECK-LABEL: define {{.*}} @_Z2e1v(177// CHECK: %[[ALLOC:.*]] = call noundef ptr @_ZN1BnwEmSt11align_val_t(i64 noundef 512, i64 noundef 4)178// CHECK: call void @_ZN1BdlEPvSt11align_val_t(ptr noundef %[[ALLOC]], i64 noundef 4)179void *e1() { return new (std::align_val_t(4)) B; }180#endif181 182// Variadic placement/non-placement allocation functions.183// ======================================================184 185struct 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 ptr (i64, ...) @_ZN1FnwEmz(i64 noundef 512, i64 noundef 32)194// Non-placement allocation function, uses normal deallocation lookup which195// cares about whether a parameter has type std::align_val_t.196// CHECK: call void (ptr, ...) @_ZN1FdlEPvz(ptr noundef %[[ALLOC]])197void *f0() { return new F; }198 199// CHECK-LABEL: define {{.*}} @_Z2f1v(200// CHECK: %[[ALLOC:.*]] = call noundef ptr (i64, ...) @_ZN1FnwEmz(i64 noundef 512, i64 noundef 32, i32 %201// Placement allocation function, uses placement deallocation matching, which202// passes same arguments and therefore includes alignment.203// CHECK: call void (ptr, ...) @_ZN1FdlEPvz(ptr noundef %[[ALLOC]], i64 noundef 32, i32 %204void *f1() { return new (q) F; }205 206struct 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 UNALIGNED213// CHECK-LABEL: define {{.*}} @_Z2g0v214// CHECK: %[[ALLOC:.*]] = call noundef ptr (i64, i64, ...) @_ZN1GnwEmSt11align_val_tz(i64 noundef 512, i64 noundef 32)215// CHECK: call void (ptr, i64, ...) @_ZN1GdlEPvSt11align_val_tz(ptr noundef %[[ALLOC]], i64 noundef 32)216void *g0() { return new G; }217 218// CHECK-LABEL: define {{.*}} @_Z2g1v219// CHECK: %[[ALLOC:.*]] = call noundef ptr (i64, i64, ...) @_ZN1GnwEmSt11align_val_tz(i64 noundef 512, i64 noundef 32, i32 %220// CHECK: call void (ptr, i64, ...) @_ZN1GdlEPvSt11align_val_tz(ptr noundef %[[ALLOC]], i64 noundef 32, i32 %221void *g1() { return new (q) G; }222#endif223