Issue 177890
Summary [Clang] Clang sometimes incorrectly makes not-exactly-matching deallocation functions cause ambiguity
Labels clang:frontend, diverges-from:gcc, diverges-from:msvc
Assignees
Reporter frederick-vs-ja
    In the following example, both MSVC and GCC doesn't think the deleted deallocation function overloads cause ambiguity and correctly call corresponding deallocation functions when an exception is thrown on initialization. But Clang thinks the deleted overloads cause ambiguity.

Per [[expr.new]/29](https://eel.is/c++draft/expr.new#29), perhaps MSVC and GCC are correct and Clang is wrong.

Link: https://godbolt.org/z/xf4qrqcME

```C++
#include <cstdio>
#include <cstdlib>
#include <new>

template<class...Args>
void operator delete(void*, Args&&...) = delete;

template<class...Args>
void operator delete[](void*, Args&&...) = delete;

struct ThrowingDefaultCtor {
 struct UniqueException {};

  ThrowingDefaultCtor() { throw UniqueException{}; }
};

void f() {
  if (auto p = new (std::nothrow) ThrowingDefaultCtor)
    delete p;
}

void g() {
  if (auto p = new (std::nothrow) ThrowingDefaultCtor[2])
    delete[] p;
}

void* operator new(std::size_t n, const std::nothrow_t&) noexcept { // replacing version
 if (n == 0)
    ++n;
  auto p = std::malloc(n);
  std::puts("operator new(size_t, nothrow_t)");
  return p;
}

void* operator new[](std::size_t n, const std::nothrow_t&) noexcept { // replacing version
 if (n == 0)
    ++n;
  auto p = std::malloc(n);
  std::puts("operator new[](size_t, nothrow_t)");
  return p;
}

void operator delete(void* p) noexcept { // replacing version
  std::puts("operator delete(void*)");
 std::free(p);
}

void operator delete(void* p, std::size_t) noexcept { // replacing version
  std::puts("operator delete(void*, size_t)");
 std::free(p);
}

void operator delete(void* p, const std::nothrow_t&) noexcept { // replacing version
  std::puts("operator delete(void*, nothrow_t)");
  std::free(p);
}

void operator delete[](void* p) noexcept { // replacing version
  std::puts("operator delete[](void*)");
 std::free(p);
}

void operator delete[](void* p, std::size_t) noexcept { // replacing version
  std::puts("operator delete[](void*, size_t)");
 std::free(p);
}

void operator delete[](void* p, const std::nothrow_t&) noexcept { // replacing version
  std::puts("operator delete[](void*, nothrow_t)");
  std::free(p);
}

int main() {
  try {
    f();
  } catch(const ThrowingDefaultCtor::UniqueException&) {
  }
  try {
 g();
  } catch(const ThrowingDefaultCtor::UniqueException&) {
  }
}
```
_______________________________________________
llvm-bugs mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs

Reply via email to