On 14 June 2021 01:45:36 CEST, Jeff Law via Gcc-patches <gcc-patches@gcc.gnu.org> wrote: > > >On 6/2/2021 3:40 PM, Martin Sebor via Gcc-patches wrote: >> The two forms of placement operator new defined in <new> return their >> pointer argument and may not be displaced by user-defined functions. >> But because they are ordinary (not built-in) functions this property >> isn't reflected in their declarations alone, and there's no user- >> level attribute to annotate them with. When they are inlined >> the property is transparent in the IL but when they are not (without >> inlining such as -O0), calls to the operators appear in the IL and >> cause -Wmismatched-new-delete to try to match them with the functions >> called to deallocate memory. When the pointer to the memory was >> obtained from a function that matches the deallocator but not >> the placement new, the warning falsely triggers. >> >> The attached patch solves this by detecting calls to placement new >> and treating them the same as those to other pass-through calls (such >> as memset). In addition, it also teaches -Wfree-nonheap-object about >> placement delete, for a similar reason as above. Finally, it also >> adds a test for attribute fn spec indicating a function returns its >> argument. It's not necessary for the fix (I had initially though >> placement new might have the attribute) but it seems appropriate >> to check. >> >> Tested on x86_64-linux. >> >> Martin >> >> gcc-100876.diff >> >> PR c++/100876 - -Wmismatched-new-delete should understand placement >new when it's not inlined >> >> gcc/ChangeLog: >> >> PR c++/100876 >> * builtins.c (gimple_call_return_array): Check for attribute fn >spec. >> Handle calls to placement new. >> (ndecl_dealloc_argno): Avoid placement delete. >> >> gcc/testsuite/ChangeLog: >> >> PR c++/100876 >> * g++.dg/warn/Wmismatched-new-delete-4.C: New test. >> * g++.dg/warn/Wmismatched-new-delete-5.C: New test. >> * g++.dg/warn/Wstringop-overflow-7.C: New test. >> * g++.dg/warn/Wfree-nonheap-object-6.C: New test. >> * g++.dg/analyzer/placement-new.C: Prune out expected warning. >> >> diff --git a/gcc/builtins.c b/gcc/builtins.c >> index af1fe49bb48..fb0717a0248 100644 >> --- a/gcc/builtins.c >> +++ b/gcc/builtins.c >> @@ -5159,11 +5159,43 @@ static tree >> gimple_call_return_array (gimple *stmt, offset_int offrng[2], >> range_query *rvals) >> { >> - if (!gimple_call_builtin_p (stmt, BUILT_IN_NORMAL) >> - || gimple_call_num_args (stmt) < 1) >> + { >> + /* Check for attribute fn spec to see if the function returns >one >> + of its arguments. */ >> + attr_fnspec fnspec = gimple_call_fnspec (as_a <gcall *>(stmt)); >> + unsigned int argno; >> + if (fnspec.returns_arg (&argno)) >> + { >> + offrng[0] = offrng[1] = 0; >> + return gimple_call_arg (stmt, argno); >> + } >> + } >> + >> + if (gimple_call_num_args (stmt) < 1) >> return NULL_TREE; >Nit. You've got an unnecessary {} at the outer level of this hunk.
if (unsigned int = 1 && fnspec.returns_arg (&argno)) doesn't look too appealing though, I'd leave the curly braces, no? cheers, > >OK with the nit fixed. > >THanks, >Jeff