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

void* operator new(std::size_t, double) throw ();
void* operator new[](std::size_t, double) throw ();

struct S {
  void *operator new(std::size_t size);
  void operator delete(void* p);
};

typedef int __attribute__((aligned(16))) i16_t;

// check if proper function is called
void test1() {
  // CHECK: @_ZL13__aligned_newjj
  int* i = new int;
  // CHECK: @_ZL17__aligned_new_arrjj
  int* arri = new int[1];
       // CHECK: @_ZL13__aligned_newjjRKSt9nothrow_t
       i = new(std::nothrow) int;
       // CHECK: @_ZL17__aligned_new_arrjjRKSt9nothrow_t
       arri = new(std::nothrow) int[1];
       // CHECK: @_ZL13__aligned_newjjPv
       i = new(i) int;
       // CHECK: @_ZL17__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: @_ZL13__aligned_newjj
     s = ::new S;

  // CHECK: @_ZL16__aligned_deletePv
  delete i;
  // CHECK: @_ZL20__aligned_delete_arrPv
  delete[] arri;
  // CHECK: @_ZN1SdlEPv
  delete s;
  // CHECK: @_ZL16__aligned_deletePv
  ::delete s;
}

// check alignment
void test2() {
  // CHECK: @_ZL13__aligned_newjj(i32 1, i32 1)
  char* c = new char;
  // CHECK: @_ZL13__aligned_newjj(i32 4, i32 16)
  i16_t* i16 = new i16_t;
  // CHECK: @_ZL17__aligned_new_arrjj(i32 4, i32 16)
  i16_t* i16arr = new i16_t[1];
}
