Why Clang doesn't emit `builtin` attribute on :: operator delete() call sites?

Hi All,

I’m trying to write a middle-end LLVM pass and I found that Clang front-end is not emitting builtin attribute on call sites of :: operator delete().
To be more clear, for the following source code:

void MemMan::deallocation(void* p)
  :: operator delete(p);

Call site of function {_Zdlpv() or :: operator delete} in the IR doesn’t have the builtin attribute and the function _Zdlpv() has nobuiltin attribute itself. But, if I change the code to something like:

void MemMan::deallocation(void* p)
  :: delete(p);

the call site associated to the function _Zdlpv() will get the builtin attribute.
My understanding is that the cpp new expression, that is used here, also calls :: operator delete(p) under the hood, but why clang can attach attribute builtin to the call site in this case and not the case in the code written in the first block?

If we mark the call site in the first block with builtin attribute will there be any correctness issue? Or is it only a bug?


Hi Mehrnoosh,

I remember this coming up a while ago, although I can’t put my finger on the discussion (@wristow do you know?). I think the reason for not attaching builtin has to do with the global new/delete operators being replaceable; and if they have been replaced, the compiler doesn’t know all the fine points of their exact semantics (may have some behind-the-scenes logging going on, or whatever).

It does seem odd that ::operator delete and ::delete aren’t consistent, and hopefully someone who knows what they are talking about will come along with a more complete answer.

I haven’t looked it up specifically, but it wouldn’t be very surprising if using the new or delete operators had stronger semantics than calling the operator functions even if their natural code-generation was identical. So whether this would be allowed for direct calls to operator functions might really depend on what semantics you expect the builtin attribute to imply in IR.

Hi Mehrnoosh,

I remember this coming up a while ago, although I can’t put my finger on the discussion (@wristow do you know?).

I don’t have an answer, but I know a related discussion that is, in a sense, the dual of this one. Specifically, D97735 (this relates to callsites being marked as builtin, but calling nobuiltin functions). There may be some insight in the discussion there.

This is on purpose. For the call sites, the compiler could do optimizations like eliding unnecessary pairs of new/delete expressions, but this is not applicable for new/delete operator. For the definitions, @pogo59’s explanation is my understanding as well.

Thank you all; according to @pogo59 's explanation and the discussion in D97735 I can understand why the behavior is different. D97735 had some key points regarding this topic such as the following link which clarifies why only new/delete expressions gets the builtin attribute and not the new/delete operator(https://groups.google.com/g/llvm-dev/c/0HA_Td1y5Po).