https://gcc.gnu.org/g:f32e7339871beec0e4d49698f7e34d77ee882088

commit r15-5110-gf32e7339871beec0e4d49698f7e34d77ee882088
Author: Simon Martin <si...@nasilyan.com>
Date:   Mon Nov 11 20:22:32 2024 +0100

    c++: Fix another crash with invalid new operators [PR117463]
    
    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.
    
    As suggested by Jason, this patch changes both functions so that
    cxx_placement_new_fn leverages std_placement_new_fn_p which reduces code
    duplication and fixes the PR.
    
            PR c++/117463
    
    gcc/cp/ChangeLog:
    
            * constexpr.cc (cxx_placement_new_fn): Implement in terms of
            std_placement_new_fn_p.
            * cp-tree.h (std_placement_new_fn_p): Declare.
            * init.cc (std_placement_new_fn_p): Add missing checks to ensure
            that fndecl is a non-replaceable ::operator new.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/init/new54.C: New test.

Diff:
---
 gcc/cp/constexpr.cc               | 13 +------------
 gcc/cp/cp-tree.h                  |  1 +
 gcc/cp/init.cc                    |  6 ++++--
 gcc/testsuite/g++.dg/init/new54.C | 14 ++++++++++++++
 4 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 71e6dc4ef326..c097860e6551 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 1a0d5349749d..b3c909b05c41 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 62b3d6f6ce91..a11701002c8d 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 000000000000..fdff1b55f0d0
--- /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;

Reply via email to