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.
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