Message ID | 0102019302eef2a1-a0296694-7644-43a4-9bef-83b862cf3566-000000@eu-west-1.amazonses.com |
---|---|
State | New |
Headers | show |
Series | c++: Fix another crash with invalid new operators [PR117463] | expand |
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. > Successfully tested on x86_64-pc-linux-gnu. > > PR c++/117463 > > gcc/cp/ChangeLog: > > * constexpr.cc (cxx_placement_new_fn): Check first_arg against > NULL_TREE. > > gcc/testsuite/ChangeLog: > > * g++.dg/init/new54.C: New test. > > --- > gcc/cp/constexpr.cc | 3 ++- > gcc/testsuite/g++.dg/init/new54.C | 14 ++++++++++++++ > 2 files changed, 16 insertions(+), 1 deletion(-) > create mode 100644 gcc/testsuite/g++.dg/init/new54.C > > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc > index 71e6dc4ef32..379700ca2c1 100644 > --- a/gcc/cp/constexpr.cc > +++ b/gcc/cp/constexpr.cc > @@ -2334,7 +2334,8 @@ cxx_placement_new_fn (tree 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 > + if (first_arg > + && TREE_VALUE (first_arg) == ptr_type_node > && TREE_CHAIN (first_arg) == void_list_node) > return true; > } > 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;
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc index 71e6dc4ef32..379700ca2c1 100644 --- a/gcc/cp/constexpr.cc +++ b/gcc/cp/constexpr.cc @@ -2334,7 +2334,8 @@ cxx_placement_new_fn (tree 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 + if (first_arg + && TREE_VALUE (first_arg) == ptr_type_node && TREE_CHAIN (first_arg) == void_list_node) return true; } 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;