// RUN: %clang -fstrict-aligned -S -emit-llvm %s -o - | FileCheck %s

// Check substitutions for standard non-placement new/delete. These declarations
// are synthesized by clang and should be seen without any inclusions
void test1() {
  // CHECK: __aligned_newjj
  int* i = new int;
  // CHECK: __aligned_new_arrjj
  int* arri = new int[1];
  // CHECK: __aligned_deletePv
  delete i;
  // CHECK: __aligned_delete_arrPv
  delete[] arri;
}

#include <aligned_new.h>

// replaced standard operators - should be substituted
void* operator new(std::size_t) throw (std::bad_alloc) { return NULL; };
void* operator new[](std::size_t) throw (std::bad_alloc) { return NULL; };
void  operator delete(void* ptr) throw () {};
void  operator delete[](void* ptr) throw () {};

// overloaded operators - should not be substituted
void* operator new(std::size_t, double) throw ();
void* operator new[](std::size_t, double) throw ();

struct S {
  // standard operators in the class scope - should not be substituted
  void *operator new(std::size_t size) { return NULL; };
  void operator delete(void* p) {};
};

typedef int __attribute__((aligned(64))) i64_t;

// check the rest of the substitutions
void test2() {
       // CHECK: __aligned_newjjRKSt9nothrow_t
  int* i = new(std::nothrow) int;
       // CHECK: __aligned_new_arrjjRKSt9nothrow_t
  int* arri = new(std::nothrow) int[1];
       // CHECK: __aligned_newjjPv
       i = new(i) int;
       // CHECK: __aligned_new_arrjjPv
       arri = new(i) int[1];

       // CHECK: @_Znwjd
       i = new(1.0f) int;
       // CHECK: @_Znajd
       arri = new(1.0f) int[1];

  // CHECK: @_ZN1SnwEj
  S* s = new S;
     // CHECK: __aligned_newjj
     s = ::new S;

  // CHECK: @_ZN1SdlEPv
  delete s;
  // CHECK: __aligned_deletePv
  ::delete s;
}

// check alignment
void test3() {
  // CHECK: __aligned_newjj(i32 1, i32 1)
  char* c = new char;
  // CHECK: __aligned_newjj(i32 4, i32 64)
  i64_t* i64 = new i64_t;
  // CHECK: __aligned_new_arrjj(i32 4, i32 64)
  i64_t* i64arr = new i64_t[1];
}
