On 8/5/19 1:57 PM, Marc Glisse wrote: > On Mon, 5 Aug 2019, Martin Liška wrote: > >> On 8/5/19 9:07 AM, Marc Glisse wrote: >>> On Mon, 5 Aug 2019, Martin Liška wrote: >>> >>>> I'm sending fix for the ICE. The issue is that we can end up >>>> with a ctor without an argument (when not being used). >>> >>> Ah, I didn't realize that after cloning and drastically changing the >>> signature it would still count as operator new/delete. Is getting down to 0 >>> arguments the only bad thing that can happen? Can't we have an operator >>> delete (void*, void*) where the first argument gets optimized out and we >>> end up optimizing as if the second argument was actually the memory being >>> released? Should we do some sanity-checking when propagating the new/delete >>> flags to clones? >>> >> >> It can theoretically happen, but it should be properly handled in the >> following >> code: >> >> 810 if (is_delete_operator >> 811 || gimple_call_builtin_p (stmt, BUILT_IN_FREE)) >> 812 { >> 813 /* It can happen that a user delete operator has the >> pointer >> 814 argument optimized out already. */ >> 815 if (gimple_call_num_args (stmt) == 0) >> 816 continue; >> 817 >> 818 tree ptr = gimple_call_arg (stmt, 0); >> 819 gimple *def_stmt; >> 820 tree def_callee; >> 821 /* If the pointer we free is defined by an allocation >> 822 function do not add the call to the worklist. */ >> 823 if (TREE_CODE (ptr) == SSA_NAME >> 824 && is_gimple_call (def_stmt = SSA_NAME_DEF_STMT >> (ptr)) >> 825 && (def_callee = gimple_call_fndecl (def_stmt)) >> 826 && ((DECL_BUILT_IN_CLASS (def_callee) == >> BUILT_IN_NORMAL >> 827 && (DECL_FUNCTION_CODE (def_callee) == >> BUILT_IN_ALIGNED_ALLOC >> 828 || DECL_FUNCTION_CODE (def_callee) == >> BUILT_IN_MALLOC >> 829 || DECL_FUNCTION_CODE (def_callee) == >> BUILT_IN_CALLOC)) >> 830 || DECL_IS_REPLACEABLE_OPERATOR_NEW_P >> (def_callee))) >> 831 { >> 832 /* Delete operators can have alignment and (or) >> size as next >> 833 arguments. When being a SSA_NAME, they must be >> marked >> 834 as necessary. */ >> 835 if (is_delete_operator && gimple_call_num_args >> (stmt) >= 2) >> 836 for (unsigned i = 1; i < gimple_call_num_args >> (stmt); i++) >> 837 { >> 838 tree arg = gimple_call_arg (stmt, i); >> 839 if (TREE_CODE (arg) == SSA_NAME) >> 840 mark_operand_necessary (arg); >> 841 } >> >> Where we verify that first argument of delete call is defined as a LHS of a >> new operator. > > What I am saying is that it may be the wrong operator new. > > Imagine something like: > > struct A { > A(); > __attribute__((malloc)) static void* operator new(unsigned long sz, > void*,bool); > static void operator delete(void* ptr, void*,bool); > }; > int main(){ > int*p=new int; > new(p,true) A; > } > > At the beginning, it has > > D.2321 = A::operator new (1, p, 1); > > and > > A::operator delete (D.2321, p, 1); > > Now imagine we have access to the body of the functions, and the last one is > transformed into > > operator delete.clone (p)
You are right. It can really lead to confusion of the DCE. What we have is DECL_ABSTRACT_ORIGIN(decl) which we can use to indicate operators that were somehow modified by an IPA optimization. Do you believe it will be sufficient? Thanks, Martin > > (the first argument was removed) > p does come from an operator new, so we do see a matched pair new+delete, but > it is the wrong pair. > > I admit that's rather unlikely, but with clones that have a different > signature, many assumptions we could make on the functions become unsafe, and > I am not clear on the scale of this issue. >