Message ID | 010201931b9ba887-d833ec77-35ef-44c3-99aa-6dcbbd36050b-000000@eu-west-1.amazonses.com |
---|---|
State | New |
Headers | show |
Series | [v2] c++: Fix another crash with invalid new operators [PR117463] | expand |
On 11/11/24 9:23 AM, Simon Martin wrote: > Hi Jason, > > On 6 Nov 2024, at 20:47, Jason Merrill wrote: > >> On 11/6/24 2:23 PM, Simon Martin wrote: >>> Even though this PR is very close to PR117101, it's not addressed by >>> the >>> fix I made through r15-4958-g5821f5c8c89a05 because >>> cxx_placement_new_fn >>> has the very same issue as std_placement_new_fn_p used to have. >>> >>> This patch fixes the issue exactly the same, by checking the first >>> parameter against NULL_TREE. I considered somehow sharing code >>> between >>> the two *_placement_new_fn* static functions, but it looked pointless >>> since the shared part ("the second parameter is the last one, and a >>> pointer") is unlikely to be useful elsewhere. >> >> It seems those two functions are intended to test the exact same >> thing: whether the argument is ::operator new(size_t, void*). >> >> I think cxx_placement_new_fn should just be >> >> return (cxx_dialect >= cxx20 && std_placement_new_fn_p (fndecl)); >> >> and some of the tests in cxx_placement_new_fn move into >> std_placement_new_fn_p to accommodate callers that e.g. don't already >> know we're dealing with operator new. > Thanks for the suggestion, makes sense. > > I did not realise that some of the tests in those functions were > actually redundant (like the tree code or global namespace ones, implied > by DECL_NAMESPACE_SCOPE_P and IDENTIFIER_NEW_OP_P) and made them look > more different than they really are. > > The attached patch has been successfully tested on x86_64-pc-linux-gnu. > OK for trunk? OK.
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index 71e6dc4ef32..c097860e655 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -2327,18 +2327,7 @@ cxx_replaceable_global_alloc_fn (tree fndecl) static inline bool cxx_placement_new_fn (tree fndecl) { - if (cxx_dialect >= cxx20 - && IDENTIFIER_NEW_OP_P (DECL_NAME (fndecl)) - && CP_DECL_CONTEXT (fndecl) == global_namespace - && !DECL_IS_REPLACEABLE_OPERATOR_NEW_P (fndecl) - && TREE_CODE (TREE_TYPE (fndecl)) == FUNCTION_TYPE) - { - tree first_arg = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (fndecl))); - if (TREE_VALUE (first_arg) == ptr_type_node - && TREE_CHAIN (first_arg) == void_list_node) - return true; - } - return false; + return (cxx_dialect >= cxx20 && std_placement_new_fn_p (fndecl)); } /* Return true if FNDECL is std::construct_at. */ diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 92d1dba6a5c..fb04b6f1ae0 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7281,6 +7281,7 @@ extern tree build_offset_ref (tree, tree, bool, extern tree throw_bad_array_new_length (void); extern bool type_has_new_extended_alignment (tree); extern unsigned malloc_alignment (void); +extern bool std_placement_new_fn_p (tree); extern tree build_new_constexpr_heap_type (tree, tree, tree); extern tree build_new (location_t, vec<tree, va_gc> **, tree, diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc index 62b3d6f6ce9..a11701002c8 100644 --- a/gcc/cp/init.cc +++ b/gcc/cp/init.cc @@ -2976,10 +2976,12 @@ malloc_alignment () /* Determine whether an allocation function is a namespace-scope non-replaceable placement new function. See DR 1748. */ -static bool +bool std_placement_new_fn_p (tree alloc_fn) { - if (DECL_NAMESPACE_SCOPE_P (alloc_fn)) + if (DECL_NAMESPACE_SCOPE_P (alloc_fn) + && IDENTIFIER_NEW_OP_P (DECL_NAME (alloc_fn)) + && !DECL_IS_REPLACEABLE_OPERATOR_NEW_P (alloc_fn)) { tree first_arg = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (alloc_fn))); if (first_arg diff --git a/gcc/testsuite/g++.dg/init/new54.C b/gcc/testsuite/g++.dg/init/new54.C new file mode 100644 index 00000000000..fdff1b55f0d --- /dev/null +++ b/gcc/testsuite/g++.dg/init/new54.C @@ -0,0 +1,14 @@ +// PR c++/117463 +// { dg-do "compile" { target c++20 } } + +struct S {}; +void *operator new[] (unsigned long, // { dg-bogus "first parameter" "" { xfail *-*-* } } + void void *volatile p); // { dg-error "two or more" } +S *fun(void *p) { + return new(p) S[10]; +} + +void *operator new (decltype(sizeof(0)), // { dg-bogus "first parameter" "" { xfail *-*-* } } + void void * p); // { dg-error "two or more" } +void *p; +auto t = new(p) int;