[cfe-dev] Why the argument of `delete' is converted to void* ?

Jean-Daniel Dupas devlists at shadowlab.org
Wed Jul 4 08:07:34 PDT 2012


Le 4 juil. 2012 à 15:57, Enea Zaffanella a écrit :

> On 07/04/2012 03:35 PM, Jean-Daniel Dupas wrote:
>> 
>> Le 4 juil. 2012 à 14:42, Abramo Bagnara a écrit :
>> 
>>> Il 04/07/2012 14:01, Jean-Daniel Dupas ha scritto:
>>>> 
>>>> Le 4 juil. 2012 à 12:42, Enea Zaffanella a écrit :
>>>> 
>>>>> We have noticed that, in the AST produced by clang, the expression
>>>>> argument of a CXXDeleteExpr node is implicitly converted to void*:
>>>>> 
>>>>> # cat delete.cc
>>>>> struct S {};
>>>>> 
>>>>> void free(S* ps) {
>>>>> delete ps;
>>>>> }
>>>>> 
>>>>> # llvm/Debug+Asserts/bin/clang -cc1 -ast-dump delete.cc
>>>>> [...]
>>>>> void free(S *ps) (CompoundStmt 0x4822650 <delete.cc:3:18, line:5:1>
>>>>> (CXXDeleteExpr 0x4822628 <line:4:3, col:10> 'void'
>>>>>   (ImplicitCastExpr 0x4821df8 <col:10> 'void *' <BitCast>
>>>>>     (ImplicitCastExpr 0x4821de0 <col:10> 'struct S *' <LValueToRValue>
>>>>>       (DeclRefExpr 0x4821db8 <col:10> 'struct S *' lvalue ParmVar
>>>>> 0x47eeb20 'ps' 'struct S *')))))
>>>>> 
>>>>> 
>>>>> What are the reasons for introducing such an implicit cast?
>>>>> 
>>>>> Enea.
>>>> 
>>>> Just a though, but isn't it because the signature of delete is:
>>>> 
>>>> operator delete(void *);
>>> 
>>> I don't think so:
>>> 
>>> delete ptr;
>>> 
>>> is something very different from
>>> 
>>> operator delete(ptr);
>> 
>> 
>> I'm not sure it is quite different.
>> 
>> This is the IR generated by clang++ for this code with c++filt _ZdlPv =
>> operator delete(void*):
>> 
>> define void @_Z4freeP1S(%struct.S* %ps) nounwind uwtable ssp {
>> entry:
>>   %isnull = icmp eq %struct.S* %ps, null
>>   br i1 %isnull, label %delete.end, label %delete.notnull
>> 
>> delete.notnull: ; preds = %entry
>>   %0 = getelementptr inbounds %struct.S* %ps, i64 0, i32 0
>>   tail call void @_ZdlPv(i8* %0) nounwind
>>   br label %delete.end
>> 
>> delete.end: ; preds = %delete.notnull, %entry
>>   ret void
>> }
>> 
>> declare void @_ZdlPv(i8*) nounwind
>> 
>> 
>> 
>> 
>> -- Jean-Daniel
> 
> 
> Sorry for the misunderstanding, but the original question was not really meant to be restricted to classes having a trivial destructor (if you add a non-trivial destructor to class S then "delete ps" will call it, whereas "operator delete(ps)" will not).
> 
> To rephrase my question: since in the general case "delete ps" may also call the destructor, why is its argument (always) converted to void*?
> 
> Cheers,
> Enea.


AFAIK, even with a non trivial destructor, the code always end up calling the operator delete(void *) to free the memory.

It will generate something like this:

call the destructor on the struct.
call operator delete((void *)ps);

or in LLVM IR:
  tail call void @_ZN1SD1Ev(%struct.S* %ps) nounwind // ps->~S()
  %0 = getelementptr inbounds %struct.S* %ps, i64 0, i32 0
  tail call void @_ZdlPv(i8* %0) nounwind // operator delete((void *)ps)
  br label %delete.end


-- Jean-Daniel




-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20120704/4c52adca/attachment.html>


More information about the cfe-dev mailing list