On Mon, Apr 25, 2016 at 9:57 PM, Jason Merrill <ja...@redhat.com> wrote:
> Hmm, this seems to assume that operator delete itself doesn't do
> anything with the object being deleted.  This is true of the default
> implementation, but I don't see anything in the standard that
> prohibits a user-supplied replacement or class-specific deallocation
> function from accessing the memory.

Hmm, but the delete expression invokes the (default) destructor which
ends the lifetime of the object and thus invalidates all memory.  Don't
we place a CLOBBER there as well nowadays (seems not).

For

struct A { A(); ~A(); int i; };

int main()
{
  A *a = new A;
  delete a;
}

I see

    struct A * a;
  <<cleanup_point <<< Unknown tree: expr_stmt
  (void) (a = TARGET_EXPR <D.2346, operator new (4)>;, try
    {
      A::A ((struct A *) D.2346);
    }
  catch
    {
      operator delete (D.2346);
    }, (struct A *) D.2346;) >>>>>;
  <<cleanup_point <<< Unknown tree: expr_stmt
  if (SAVE_EXPR <a> != 0B)
    {
      A::~A (SAVE_EXPR <a>);, operator delete ((void *) SAVE_EXPR <a>);;
    }
  else
    {
      <<< Unknown tree: void_cst >>>
    } >>>>>;

so after the destructor is invoked the objects lifetime ends.

Richard.

> Jason
>
>
> On Mon, Apr 25, 2016 at 6:08 AM, Richard Biener
> <richard.guent...@gmail.com> wrote:
>> On Fri, Apr 22, 2016 at 11:37 PM, Mikhail Maltsev <malts...@gmail.com> wrote:
>>> On 04/20/2016 05:12 PM, Richard Biener wrote:
>>>> You have
>>>>
>>>> +static tree
>>>> +handle_free_attribute (tree *node, tree name, tree /*args*/, int 
>>>> /*flags*/,
>>>> +                      bool *no_add_attrs)
>>>> +{
>>>> +  tree decl = *node;
>>>> +  if (TREE_CODE (decl) == FUNCTION_DECL
>>>> +      && type_num_arguments (TREE_TYPE (decl)) != 0
>>>> +      && POINTER_TYPE_P (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))))
>>>> +    DECL_ALLOC_FN_KIND (decl) = ALLOC_FN_FREE;
>>>> +  else
>>>> +    {
>>>> +      warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wattributes,
>>>> +                 "%qE attribute ignored", name);
>>>> +      *no_add_attrs = true;
>>>> +    }
>>>>
>>>> so one can happily apply the attribute to
>>>>
>>>>  void foo (void *, void *);
>>>>
>>>> but then
>>>>
>>>> @@ -2117,6 +2127,13 @@ call_may_clobber_ref_p_1 (gcall *call, ao_ref *ref)
>>>>           /* Fallthru to general call handling.  */;
>>>>        }
>>>>
>>>> +  if (callee != NULL_TREE
>>>> +      && (flags_from_decl_or_type (callee) & ECF_FREE) != 0)
>>>> +    {
>>>> +      tree ptr = gimple_call_arg (call, 0);
>>>> +      return ptr_deref_may_alias_ref_p_1 (ptr, ref);
>>>> +    }
>>>>
>>>> will ignore the 2nd argument.  I think it's better to ignore the attribute
>>>> if type_num_arguments () != 1.
>>>
>>> Actually, the C++ standard ([basic.stc.dynamic]/2) defines the following 4
>>> deallocation functions implicitly:
>>>
>>> void operator delete(void*);
>>> void operator delete[](void*);
>>> void operator delete(void*, std::size_t) noexcept;
>>> void operator delete[](void*, std::size_t) noexcept;
>>>
>>> And the standard library also has:
>>>
>>> void operator delete(void*, const std::nothrow_t&);
>>> void operator delete[](void*, const std::nothrow_t&);
>>> void operator delete(void*, std::size_t, const std::nothrow_t&);
>>> void operator delete[](void*, std::size_t, const std::nothrow_t&);
>>>
>>> IIUC, 'delete(void*, std::size_t)' is used by default in C++14
>>> (https://gcc.gnu.org/ml/gcc-patches/2014-12/msg01266.html). How should we 
>>> handle
>>> this?
>>
>> Hmm.  I guess by adjusting the documentation of the attribute to
>> explicitely mention
>> the behavior on the rest of the argument pointed-to memory (the
>> function is assumed
>> to neither write nor read from that memory).  Also explicitely mention
>> that 'this' is
>> always the first argument if present.
>>
>> Richard.
>>
>>> --
>>> Regards,
>>>     Mikhail Maltsev

Reply via email to