// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -emit-llvm -o - | FileCheck %s typedef __typeof__(sizeof(0)) size_t; // Declare an 'operator new' template to tickle a bug in __builtin_operator_new. template void *operator new(size_t, int (*)(T)); // Ensure that this declaration doesn't cause operator new to lose its // 'noalias' attribute. void *operator new[](size_t); void t1() { delete new int; delete [] new int [3]; } // CHECK: declare noundef nonnull ptr @_Znwm(i64 noundef) [[ATTR_NOBUILTIN:#[^ ]*]] // CHECK: declare void @_ZdlPvm(ptr noundef, i64 noundef) [[ATTR_NOBUILTIN_NOUNWIND:#[^ ]*]] // CHECK: declare noundef nonnull ptr @_Znam(i64 noundef) [[ATTR_NOBUILTIN]] // CHECK: declare void @_ZdaPv(ptr noundef) [[ATTR_NOBUILTIN_NOUNWIND]] namespace std { struct nothrow_t {}; } std::nothrow_t nothrow; // Declare the reserved placement operators. void *operator new(size_t, void*) throw(); void operator delete(void*, void*) throw(); void *operator new[](size_t, void*) throw(); void operator delete[](void*, void*) throw(); // Declare the replaceable global allocation operators. void *operator new(size_t, const std::nothrow_t &) throw(); void *operator new[](size_t, const std::nothrow_t &) throw(); void operator delete(void *, const std::nothrow_t &) throw(); void operator delete[](void *, const std::nothrow_t &) throw(); // Declare some other placemenet operators. void *operator new(size_t, void*, bool) throw(); void *operator new[](size_t, void*, bool) throw(); void t2(int* a) { int* b = new (a) int; } struct S { int a; }; // POD types. void t3() { int *a = new int(10); _Complex int* b = new _Complex int(10i); S s; s.a = 10; S *sp = new S(s); } // Non-POD struct T { T(); int a; }; void t4() { // CHECK: call void @_ZN1TC1Ev T *t = new T; } struct T2 { int a; T2(int, int); }; void t5() { // CHECK: call void @_ZN2T2C1Eii T2 *t2 = new T2(10, 10); } int *t6() { // Null check. return new (0) int(10); } void t7() { new int(); } struct U { ~U(); }; void t8(int n) { new int[10]; new int[n]; // Non-POD new T[10]; new T[n]; // Cookie required new U[10]; new U[n]; } void t9() { bool b; new bool(true); new (&b) bool(true); } struct A { void* operator new(__typeof(sizeof(int)), int, float, ...); A(); }; A* t10() { // CHECK: @_ZN1AnwEmifz return new(1, 2, 3.45, 100) A; } // CHECK-LABEL: define{{.*}} void @_Z3t11i struct B { int a; }; struct Bmemptr { int Bmemptr::* memptr; int a; }; void t11(int n) { // CHECK: call noalias noundef nonnull ptr @_Znwm // CHECK: call void @llvm.memset.p0.i64( B* b = new B(); // CHECK: call noalias noundef nonnull ptr @_Znam // CHECK: {{call void.*llvm.memset.p0.i64.*i8 0, i64 %}} B *b2 = new B[n](); // CHECK: call noalias noundef nonnull ptr @_Znam // CHECK: call void @llvm.memcpy.p0.p0.i64 // CHECK: br Bmemptr *b_memptr = new Bmemptr[n](); // CHECK: ret void } struct Empty { }; // We don't need to initialize an empty class. // CHECK-LABEL: define{{.*}} void @_Z3t12v void t12() { // CHECK: call noalias noundef nonnull ptr @_Znam // CHECK-NOT: br (void)new Empty[10]; // CHECK: call noalias noundef nonnull ptr @_Znam // CHECK-NOT: br (void)new Empty[10](); // CHECK: ret void } // Zero-initialization // CHECK-LABEL: define{{.*}} void @_Z3t13i void t13(int n) { // CHECK: call noalias noundef nonnull ptr @_Znwm // CHECK: store i32 0, ptr (void)new int(); // CHECK: call noalias noundef nonnull ptr @_Znam // CHECK: {{call void.*llvm.memset.p0.i64.*i8 0, i64 %}} (void)new int[n](); // CHECK-NEXT: ret void } struct Alloc{ int x; void* operator new[](size_t size); __attribute__((returns_nonnull)) void *operator new[](size_t size, const std::nothrow_t &) throw(); void operator delete[](void* p); ~Alloc(); }; void f() { // CHECK: call noundef ptr @_ZN5AllocnaEm(i64 noundef 808) // CHECK: store i64 200 // CHECK: call void @_ZN5AllocD1Ev( // CHECK: call void @_ZN5AllocdaEPv(ptr delete[] new Alloc[10][20]; // CHECK: [[P:%.*]] = call noundef nonnull ptr @_ZN5AllocnaEmRKSt9nothrow_t(i64 noundef 808, {{.*}}) [[ATTR_NOUNWIND:#[^ ]*]] // CHECK-NOT: icmp eq ptr [[P]], null // CHECK: store i64 200 delete[] new (nothrow) Alloc[10][20]; // CHECK: call noalias noundef nonnull ptr @_Znwm // CHECK: call void @_ZdlPvm(ptr noundef {{%.*}}, i64 noundef 1) delete new bool; // CHECK: ret void } namespace test15 { struct A { A(); ~A(); }; // CHECK-LABEL: define{{.*}} void @_ZN6test156test0aEPv( // CHECK: [[P:%.*]] = load ptr, ptr // CHECK-NOT: icmp eq ptr [[P]], null // CHECK-NOT: br i1 // CHECK-NEXT: call void @_ZN6test151AC1Ev(ptr {{[^,]*}} [[P]]) void test0a(void *p) { new (p) A(); } // CHECK-LABEL: define{{.*}} void @_ZN6test156test0bEPv( // CHECK: [[P0:%.*]] = load ptr, ptr // CHECK: [[P:%.*]] = call noundef ptr @_ZnwmPvb(i64 noundef 1, ptr noundef [[P0]] // CHECK-NEXT: icmp eq ptr [[P]], null // CHECK-NEXT: br i1 // CHECK: call void @_ZN6test151AC1Ev(ptr {{[^,]*}} [[P]]) void test0b(void *p) { new (p, true) A(); } // CHECK-LABEL: define{{.*}} void @_ZN6test156test1aEPv( // CHECK: [[P:%.*]] = load ptr, ptr // CHECK-NOT: icmp eq ptr [[P]], null // CHECK-NOT: br i1 // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [[A:.*]], ptr [[P]], i64 5 // CHECK-NEXT: br label // CHECK: [[CUR:%.*]] = phi ptr [ [[P]], {{%.*}} ], [ [[NEXT:%.*]], {{%.*}} ] // CHECK-NEXT: call void @_ZN6test151AC1Ev(ptr {{[^,]*}} [[CUR]]) // CHECK-NEXT: [[NEXT]] = getelementptr inbounds [[A]], ptr [[CUR]], i64 1 // CHECK-NEXT: [[DONE:%.*]] = icmp eq ptr [[NEXT]], [[END]] // CHECK-NEXT: br i1 [[DONE]] void test1a(void *p) { new (p) A[5]; } // CHECK-LABEL: define{{.*}} void @_ZN6test156test1bEPv( // CHECK: [[P0:%.*]] = load ptr, ptr // CHECK: [[P:%.*]] = call noundef ptr @_ZnamPvb(i64 noundef 13, ptr noundef [[P0]] // CHECK-NEXT: icmp eq ptr [[P]], null // CHECK-NEXT: br i1 // CHECK: [[AFTER_COOKIE:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 8 // CHECK-NEXT: [[END:%.*]] = getelementptr inbounds [[A]], ptr [[AFTER_COOKIE]], i64 5 // CHECK-NEXT: br label // CHECK: [[CUR:%.*]] = phi ptr [ [[AFTER_COOKIE]], {{%.*}} ], [ [[NEXT:%.*]], {{%.*}} ] // CHECK-NEXT: call void @_ZN6test151AC1Ev(ptr {{[^,]*}} [[CUR]]) // CHECK-NEXT: [[NEXT]] = getelementptr inbounds [[A]], ptr [[CUR]], i64 1 // CHECK-NEXT: [[DONE:%.*]] = icmp eq ptr [[NEXT]], [[END]] // CHECK-NEXT: br i1 [[DONE]] void test1b(void *p) { new (p, true) A[5]; } // TODO: it's okay if all these size calculations get dropped. // FIXME: maybe we should try to throw on overflow? // CHECK-LABEL: define{{.*}} void @_ZN6test155test2EPvi( // CHECK: [[N:%.*]] = load i32, ptr // CHECK-NEXT: [[T0:%.*]] = sext i32 [[N]] to i64 // CHECK-NEXT: [[P:%.*]] = load ptr, ptr // CHECK-NEXT: [[ISEMPTY:%.*]] = icmp eq i64 [[T0]], 0 // CHECK-NEXT: br i1 [[ISEMPTY]], // CHECK: [[END:%.*]] = getelementptr inbounds [[A]], ptr [[P]], i64 [[T0]] // CHECK-NEXT: br label // CHECK: [[CUR:%.*]] = phi ptr [ [[P]], // CHECK-NEXT: call void @_ZN6test151AC1Ev(ptr {{[^,]*}} [[CUR]]) void test2(void *p, int n) { new (p) A[n]; } } namespace PR10197 { // CHECK-LABEL: define weak_odr void @_ZN7PR101971fIiEEvv() template void f() { // CHECK: [[CALL:%.*]] = call noalias noundef nonnull ptr @_Znwm new T; // CHECK-NEXT: ret void } template void f(); } namespace PR11523 { class MyClass; typedef int MyClass::* NewTy; // CHECK-LABEL: define{{.*}} ptr @_ZN7PR115231fEv // CHECK: store i64 -1 NewTy* f() { return new NewTy[2](); } } namespace PR11757 { // Make sure we elide the copy construction. struct X { X(); X(const X&); }; X* a(X* x) { return new X(X()); } // CHECK: define {{.*}} @_ZN7PR117571aEPNS_1XE // CHECK: [[CALL:%.*]] = call noalias noundef nonnull ptr @_Znwm // CHECK: ret {{.*}} [[CALL]] } namespace PR13380 { struct A { A() {} }; struct B : public A { int x; }; // CHECK-LABEL: define{{.*}} ptr @_ZN7PR133801fEv // CHECK: call noalias noundef nonnull ptr @_Znam( // CHECK: call void @llvm.memset.p0 // CHECK-NEXT: call void @_ZN7PR133801BC1Ev void* f() { return new B[2](); } } struct MyPlacementType {} mpt; void *operator new(size_t, MyPlacementType); namespace N3664 { struct S { S() throw(int); }; // CHECK-LABEL: define{{.*}} void @_ZN5N36641fEv void f() { // CHECK: call noalias noundef nonnull ptr @_Znwm(i64 noundef 4) [[ATTR_BUILTIN_NEW:#[^ ]*]] int *p = new int; // expected-note {{allocated with 'new' here}} // CHECK: call void @_ZdlPvm({{.*}}) [[ATTR_BUILTIN_DELETE:#[^ ]*]] delete p; // CHECK: call noalias noundef nonnull ptr @_Znam(i64 noundef 12) [[ATTR_BUILTIN_NEW]] int *q = new int[3]; // CHECK: call void @_ZdaPv({{.*}}) [[ATTR_BUILTIN_DELETE]] delete[] p; // expected-warning {{'delete[]' applied to a pointer that was allocated with 'new'; did you mean 'delete'?}} // CHECK: call noalias noundef ptr @_ZnamRKSt9nothrow_t(i64 noundef 3, {{.*}}) [[ATTR_NOBUILTIN_NOUNWIND_ALLOCSIZE:#[^ ]*]] (void) new (nothrow) S[3]; // CHECK: call noundef ptr @_Znwm15MyPlacementType(i64 noundef 4){{$}} (void) new (mpt) int; } // CHECK: declare noundef ptr @_ZnamRKSt9nothrow_t(i64 noundef, {{.*}}) [[ATTR_NOBUILTIN_NOUNWIND_ALLOCSIZE:#[^ ]*]] // CHECK-LABEL: define{{.*}} void @_ZN5N36641gEv void g() { // It's OK for there to be attributes here, so long as we don't have a // 'builtin' attribute. // CHECK: call noalias noundef nonnull ptr @_Znwm(i64 noundef 4) {{#[^ ]*}}{{$}} int *p = (int*)operator new(4); // CHECK: call void @_ZdlPv({{.*}}) [[ATTR_NOUNWIND:#[^ ]*]] operator delete(p); // CHECK: call noalias noundef nonnull ptr @_Znam(i64 noundef 12) {{#[^ ]*}}{{$}} int *q = (int*)operator new[](12); // CHECK: call void @_ZdaPv({{.*}}) [[ATTR_NOUNWIND]] operator delete [](p); // CHECK: call noalias noundef ptr @_ZnamRKSt9nothrow_t(i64 noundef 3, {{.*}}) [[ATTR_NOUNWIND_ALLOCSIZE:#[^ ]*]] (void) operator new[](3, nothrow); } } namespace builtins { // CHECK-LABEL: define{{.*}} void @_ZN8builtins1fEv void f() { // CHECK: call noalias noundef nonnull ptr @_Znwm(i64 noundef 4) [[ATTR_BUILTIN_NEW]] // CHECK: call void @_ZdlPv({{.*}}) [[ATTR_BUILTIN_DELETE]] __builtin_operator_delete(__builtin_operator_new(4)); } } // CHECK-DAG: attributes [[ATTR_NOBUILTIN]] = {{[{].*}} nobuiltin allocsize(0) {{.*[}]}} // CHECK-DAG: attributes [[ATTR_NOBUILTIN_NOUNWIND]] = {{[{].*}} nobuiltin nounwind {{.*[}]}} // CHECK-DAG: attributes [[ATTR_NOBUILTIN_NOUNWIND_ALLOCSIZE]] = {{[{].*}} nobuiltin nounwind allocsize(0) {{.*[}]}} // CHECK-DAG: attributes [[ATTR_BUILTIN_NEW]] = {{[{].*}} builtin {{.*[}]}} // CHECK-DAG: attributes [[ATTR_BUILTIN_DELETE]] = {{[{].*}} builtin {{.*[}]}} // The ([^b}|...) monstrosity is matching a character that's not the start of 'builtin'. // Add more letters if this matches some other attribute. // CHECK-DAG: attributes [[ATTR_NOUNWIND]] = {{([^b]|b[^u]|bu[^i]|bui[^l])*}} nounwind {{([^b]|b[^u]|bu[^i]|bui[^l])*$}} // CHECK-DAG: attributes [[ATTR_NOUNWIND_ALLOCSIZE]] = {{([^b]|b[^u]|bu[^i]|bui[^l])*}} nounwind allocsize(0) {{([^b]|b[^u]|bu[^i]|bui[^l])*$}}