https://gcc.gnu.org/g:417b4cc9bf218083838aeab458bbb7510e36375a

commit r15-5109-g417b4cc9bf218083838aeab458bbb7510e36375a
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Mon Nov 11 19:54:32 2024 +0100

    c++: Add __builtin_operator_{new,delete} support
    
    clang++ adds __builtin_operator_{new,delete} builtins which as documented
    work similarly to ::operator {new,delete}, except that it is an error
    if the called ::operator {new,delete} is not a replaceable global operator
    and allow optimizations which C++ normally allows just when those are used
    from new/delete expressions https://eel.is/c++draft/expr.new#14
    When using these builtins, the same optimizations can be done even when
    using those builtins.
    
    For GCC we note that in the CALL_FROM_NEW_OR_DELETE_P flag on CALL_EXPRs.
    The following patch implements it as a C++ FE keyword (because passing
    references through ... changes the argument and so BUILT_IN_FRONTEND
    builtin can't be used), just attempts to call the ::operator {new,delete}
    and if it isn't replaceable, diagnoses it.
    
    libstdc++ already uses the builtin in some cases.
    
    2024-11-11  Jakub Jelinek  <ja...@redhat.com>
    
    gcc/c-family/
            * c-common.h (enum rid): Add RID_BUILTIN_OPERATOR_NEW
            and RID_BUILTIN_OPERATOR_DELETE.
            (names_builtin_p): Change return type from bool to int.
            * c-common.cc (c_common_reswords): Add __builtin_operator_new
            and __builtin_operator_delete.
    gcc/c/
            * c-decl.cc (names_builtin_p): Change return type from
            bool to int, adjust return statments.
    gcc/cp/
            * parser.cc (cp_parser_postfix_expression): Handle
            RID_BUILTIN_OPERATOR_NEW and RID_BUILTIN_OPERATOR_DELETE.
            * cp-objcp-common.cc (names_builtin_p): Change return type from
            bool to int, adjust return statments.  Handle
            RID_BUILTIN_OPERATOR_NEW and RID_BUILTIN_OPERATOR_DELETE.
            * pt.cc (tsubst_expr) <case CALL_EXPR>: Handle
            CALL_FROM_NEW_OR_DELETE_P.
    gcc/
            * doc/extend.texi (New/Delete Builtins): Document
            __builtin_operator_new and __builtin_operator_delete.
    gcc/testsuite/
            * g++.dg/ext/builtin-operator-new-1.C: New test.
            * g++.dg/ext/builtin-operator-new-2.C: New test.
            * g++.dg/ext/builtin-operator-new-3.C: New test.

Diff:
---
 gcc/c-family/c-common.cc                          |   2 +
 gcc/c-family/c-common.h                           |   3 +-
 gcc/c/c-decl.cc                                   |  10 +-
 gcc/cp/cp-objcp-common.cc                         |  21 +++--
 gcc/cp/parser.cc                                  |  35 +++++++
 gcc/cp/pt.cc                                      |  24 +++++
 gcc/doc/extend.texi                               |  28 ++++++
 gcc/testsuite/g++.dg/ext/builtin-operator-new-1.C | 106 ++++++++++++++++++++++
 gcc/testsuite/g++.dg/ext/builtin-operator-new-2.C |  49 ++++++++++
 gcc/testsuite/g++.dg/ext/builtin-operator-new-3.C |  47 ++++++++++
 10 files changed, 310 insertions(+), 15 deletions(-)

diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index 06be2a37b4f6..dae5f5e1c27e 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -434,6 +434,8 @@ const struct c_common_resword c_common_reswords[] =
   { "__builtin_counted_by_ref", RID_BUILTIN_COUNTED_BY_REF, D_CONLY },
   { "__builtin_has_attribute", RID_BUILTIN_HAS_ATTRIBUTE, 0 },
   { "__builtin_launder", RID_BUILTIN_LAUNDER, D_CXXONLY },
+  { "__builtin_operator_new", RID_BUILTIN_OPERATOR_NEW, D_CXXONLY },
+  { "__builtin_operator_delete", RID_BUILTIN_OPERATOR_DELETE, D_CXXONLY },
   { "__builtin_shuffle", RID_BUILTIN_SHUFFLE, 0 },
   { "__builtin_shufflevector", RID_BUILTIN_SHUFFLEVECTOR, 0 },
   { "__builtin_stdc_bit_ceil", RID_BUILTIN_STDC, D_CONLY },
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 46099b635146..3c3da66272bd 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -168,6 +168,7 @@ enum rid
   RID_ADDRESSOF,
   RID_BUILTIN_LAUNDER,
   RID_BUILTIN_BIT_CAST,
+  RID_BUILTIN_OPERATOR_NEW, RID_BUILTIN_OPERATOR_DELETE,
 
   /* C++11 */
   RID_CONSTEXPR, RID_DECLTYPE, RID_NOEXCEPT, RID_NULLPTR, RID_STATIC_ASSERT,
@@ -840,7 +841,7 @@ extern bool in_late_binary_op;
 extern const char *c_addr_space_name (addr_space_t as);
 extern tree identifier_global_value (tree);
 extern tree identifier_global_tag (tree);
-extern bool names_builtin_p (const char *);
+extern int names_builtin_p (const char *);
 extern tree c_linkage_bindings (tree);
 extern void record_builtin_type (enum rid, const char *, tree);
 extern void start_fname_decls (void);
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index ac47ef24a3de..e5045c636736 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -11750,10 +11750,10 @@ identifier_global_tag (tree t)
   return NULL_TREE;
 }
 
-/* Returns true if NAME refers to a built-in function or function-like
-   operator.  */
+/* Returns non-zero (result of __has_builtin) if NAME refers to a built-in
+   function or function-like operator.  */
 
-bool
+int
 names_builtin_p (const char *name)
 {
   tree id = get_identifier (name);
@@ -11774,12 +11774,12 @@ names_builtin_p (const char *name)
     case RID_CHOOSE_EXPR:
     case RID_OFFSETOF:
     case RID_TYPES_COMPATIBLE_P:
-      return true;
+      return 1;
     default:
       break;
     }
 
-  return false;
+  return 0;
 }
 
 /* In C, the only C-linkage public declaration is at file scope.  */
diff --git a/gcc/cp/cp-objcp-common.cc b/gcc/cp/cp-objcp-common.cc
index 1e43db31db8c..921931b9846a 100644
--- a/gcc/cp/cp-objcp-common.cc
+++ b/gcc/cp/cp-objcp-common.cc
@@ -545,10 +545,10 @@ identifier_global_tag (tree name)
   return ret;
 }
 
-/* Returns true if NAME refers to a built-in function or function-like
-   operator.  */
+/* Returns non-zero (result of __has_builtin) if NAME refers to a built-in
+   function or function-like operator.  */
 
-bool
+int
 names_builtin_p (const char *name)
 {
   tree id = get_identifier (name);
@@ -556,23 +556,23 @@ names_builtin_p (const char *name)
     {
       if (TREE_CODE (binding) == FUNCTION_DECL
          && DECL_IS_UNDECLARED_BUILTIN (binding))
-       return true;
+       return 1;
 
       /* Handle the case when an overload for a  built-in name exists.  */
       if (TREE_CODE (binding) != OVERLOAD)
-       return false;
+       return 0;
 
       for (ovl_iterator it (binding); it; ++it)
        {
          tree decl = *it;
          if (DECL_IS_UNDECLARED_BUILTIN (decl))
-           return true;
+           return 1;
        }
     }
 
   /* Check for built-in traits.  */
   if (IDENTIFIER_TRAIT_P (id))
-    return true;
+    return 1;
 
   /* Also detect common reserved C++ words that aren't strictly built-in
      functions.  */
@@ -587,12 +587,15 @@ names_builtin_p (const char *name)
     case RID_BUILTIN_ASSOC_BARRIER:
     case RID_BUILTIN_BIT_CAST:
     case RID_OFFSETOF:
-      return true;
+      return 1;
+    case RID_BUILTIN_OPERATOR_NEW:
+    case RID_BUILTIN_OPERATOR_DELETE:
+      return 201802L;
     default:
       break;
     }
 
-  return false;
+  return 0;
 }
 
 /* Register c++-specific dumps.  */
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index c1375ecdbb5f..07b12224615a 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -7733,6 +7733,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool 
address_p, bool cast_p,
     case RID_BUILTIN_SHUFFLEVECTOR:
     case RID_BUILTIN_LAUNDER:
     case RID_BUILTIN_ASSOC_BARRIER:
+    case RID_BUILTIN_OPERATOR_NEW:
+    case RID_BUILTIN_OPERATOR_DELETE:
       {
        vec<tree, va_gc> *vec;
 
@@ -7819,6 +7821,39 @@ cp_parser_postfix_expression (cp_parser *parser, bool 
address_p, bool cast_p,
              }
            break;
 
+         case RID_BUILTIN_OPERATOR_NEW:
+         case RID_BUILTIN_OPERATOR_DELETE:
+           tree fn;
+           fn = ovl_op_identifier (keyword == RID_BUILTIN_OPERATOR_NEW
+                                   ? NEW_EXPR : DELETE_EXPR);
+           fn = lookup_qualified_name (global_namespace, fn);
+           postfix_expression = finish_call_expr (fn, &vec, true, false,
+                                                  tf_warning_or_error);
+           if (postfix_expression != error_mark_node)
+             {
+               tree call = extract_call_expr (postfix_expression);
+               fn = cp_get_callee_fndecl_nofold (call);
+               if (fn ? !DECL_IS_REPLACEABLE_OPERATOR (fn)
+                      : !processing_template_decl)
+                 {
+                   auto_diagnostic_group d;
+                   if (keyword == RID_BUILTIN_OPERATOR_NEW)
+                     error_at (loc, "call to %<__builtin_operator_new%> "
+                                    "does not select replaceable global "
+                                    "allocation function");
+                   else 
+                     error_at (loc, "call to %<__builtin_operator_delete%> "
+                                    "does not select replaceable global "
+                                    "deallocation function");
+                   if (fn)
+                     inform (DECL_SOURCE_LOCATION (fn),
+                             "selected function declared here");
+                 }
+               else if (call && TREE_CODE (call) == CALL_EXPR)
+                 CALL_FROM_NEW_OR_DELETE_P (call) = 1;
+             }
+           break;
+
          default:
            gcc_unreachable ();
          }
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index f4213f88b99f..35ec7eba0bad 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -21242,6 +21242,30 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl)
                  else if (TREE_CODE (call) == AGGR_INIT_EXPR)
                    AGGR_INIT_EXPR_MUST_TAIL (call) = mtc;
                }
+           if (CALL_FROM_NEW_OR_DELETE_P (t))
+             {
+               tree call = extract_call_expr (ret);
+               tree fn = cp_get_callee_fndecl_nofold (call);
+               if (fn ? !DECL_IS_REPLACEABLE_OPERATOR (fn)
+                      : !processing_template_decl)
+                 {
+                   auto_diagnostic_group d;
+                   location_t loc = cp_expr_loc_or_input_loc (t);
+                   if (!fn || IDENTIFIER_NEW_OP_P (DECL_NAME (fn)))
+                     error_at (loc, "call to %<__builtin_operator_new%> "
+                                    "does not select replaceable global "
+                                    "allocation function");
+                   else 
+                     error_at (loc, "call to %<__builtin_operator_delete%> "
+                                    "does not select replaceable global "
+                                    "deallocation function");
+                   if (fn)
+                     inform (DECL_SOURCE_LOCATION (fn),
+                             "selected function declared here");
+                 }
+               else if (call && TREE_CODE (call) == CALL_EXPR)
+                 CALL_FROM_NEW_OR_DELETE_P (call) = 1;
+             }
            if (warning_suppressed_p (t, OPT_Wpessimizing_move))
              /* This also suppresses -Wredundant-move.  */
              suppress_warning (ret, OPT_Wpessimizing_move);
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index ba8004e8979c..c566474074d7 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -90,6 +90,7 @@ extensions, accepted by GCC in C90 mode and in C++.
 * x86 specific memory model extensions for transactional memory:: x86 memory 
models.
 * Object Size Checking:: Built-in functions for limited buffer overflow
                         checking.
+* New/Delete Builtins:: Built-in functions for C++ allocations and 
deallocations.
 * Other Builtins::      Other built-in functions.
 * Target Builtins::     Built-in functions specific to particular targets.
 * Target Format Checks:: Format checks specific to particular targets.
@@ -14313,6 +14314,33 @@ format string @var{fmt}.  If the compiler is able to 
optimize them to
 is called and the @var{flag} argument passed to it.
 @enddefbuiltin
 
+@node New/Delete Builtins
+@section Built-in functions for C++ allocations and deallocations
+@findex __builtin_operator_new
+@findex __builtin_operator_delete
+Calling these C++ built-in functions is similar to calling
+@code{::operator new} or @code{::operator delete} with the same arguments,
+except that it is an error if the selected @code{::operator new} or
+@code{::operator delete} overload is not a replaceable global operator
+and for optimization purposes calls to pairs of these functions can be
+omitted if access to the allocation is optimized out, or could be replaced
+with implementation provided buffer on the stack, or multiple allocation
+calls can be merged into a single allocation.  In C++ such optimizations
+are normally allowed just for calls to such replaceable global operators
+from @code{new} and @code{delete} expressions.
+
+@smallexample
+void foo () @{
+  int *a = new int;
+  delete a; // This pair of allocation/deallocation operators can be omitted
+           // or replaced with int _temp; int *a = &_temp; etc.@:
+  void *b = ::operator new (32);
+  ::operator delete (b); // This one cannnot.
+  void *c = __builtin_operator_new (32);
+  __builtin_operator_delete (c); // This one can.
+@}
+@end smallexample
+
 @node Other Builtins
 @section Other Built-in Functions Provided by GCC
 @cindex built-in functions
diff --git a/gcc/testsuite/g++.dg/ext/builtin-operator-new-1.C 
b/gcc/testsuite/g++.dg/ext/builtin-operator-new-1.C
new file mode 100644
index 000000000000..7adffc202064
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/builtin-operator-new-1.C
@@ -0,0 +1,106 @@
+// { dg-do compile }
+// { dg-options "-O2 -fdump-tree-gimple -fdump-tree-optimized" }
+// { dg-final { scan-tree-dump " = operator new \\\(" "gimple" } }
+// { dg-final { scan-tree-dump "operator delete \\\(" "gimple" } }
+// { dg-final { scan-tree-dump-not "operator new \\\(" "optimized" } }
+// { dg-final { scan-tree-dump-not "operator delete \\\(" "optimized" } }
+
+#include <new>
+
+#if __has_builtin (__builtin_operator_new) != 201802L
+#error "Unexpected value of __has_builtin (__builtin_operator_new)"
+#endif
+#if __has_builtin (__builtin_operator_delete) != 201802L
+#error "Unexpected value of __has_builtin (__builtin_operator_delete)"
+#endif
+
+void
+foo ()
+{
+  void *a = __builtin_operator_new (32);
+  __builtin_operator_delete (a);
+#if __cpp_sized_deallocation
+  a = __builtin_operator_new (32);
+  __builtin_operator_delete (a, 32);
+#endif
+#if __cpp_aligned_new
+  void *b = __builtin_operator_new (32, std::align_val_t(32));
+  __builtin_operator_delete (b, std::align_val_t(32));
+#if __cpp_sized_deallocation
+  b = __builtin_operator_new (32, std::align_val_t(32));
+  __builtin_operator_delete (b, 32, std::align_val_t(32));
+#endif
+#endif
+  void *c = __builtin_operator_new (32, std::nothrow);
+  __builtin_operator_delete (c, std::nothrow);
+#if __cpp_aligned_new
+  void *d = __builtin_operator_new (32, std::align_val_t(32), std::nothrow);
+  __builtin_operator_delete (d, std::align_val_t(32), std::nothrow);
+#endif
+  void *e = __builtin_operator_new (1.f);
+  __builtin_operator_delete (e);
+}
+
+template <int N>
+void
+bar ()
+{
+  void *a = __builtin_operator_new (32);
+  __builtin_operator_delete (a);
+#if __cpp_sized_deallocation
+  a = __builtin_operator_new (32);
+  __builtin_operator_delete (a, 32);
+#endif
+#if __cpp_aligned_new
+  void *b = __builtin_operator_new (32, std::align_val_t(32));
+  __builtin_operator_delete (b, std::align_val_t(32));
+#if __cpp_sized_deallocation
+  b = __builtin_operator_new (32, std::align_val_t(32));
+  __builtin_operator_delete (b, 32, std::align_val_t(32));
+#endif
+#endif
+  void *c = __builtin_operator_new (32, std::nothrow);
+  __builtin_operator_delete (c, std::nothrow);
+#if __cpp_aligned_new
+  void *d = __builtin_operator_new (32, std::align_val_t(32), std::nothrow);
+  __builtin_operator_delete (d, std::align_val_t(32), std::nothrow);
+#endif
+  void *e = __builtin_operator_new (1.f);
+  __builtin_operator_delete (e);
+}
+
+template <typename T, typename U, typename V, typename W>
+void
+baz (T sz, V v, W w)
+{
+  U a = __builtin_operator_new (sz);
+  __builtin_operator_delete (a);
+#if __cpp_sized_deallocation
+  a = __builtin_operator_new (sz);
+  __builtin_operator_delete (a, sz);
+#endif
+#if __cpp_aligned_new
+  U b = __builtin_operator_new (sz, std::align_val_t(sz));
+  __builtin_operator_delete (b, std::align_val_t(sz));
+#if __cpp_sized_deallocation
+  b = __builtin_operator_new (sz, std::align_val_t(sz));
+  __builtin_operator_delete (b, sz, std::align_val_t(sz));
+#endif
+#endif
+  U c = __builtin_operator_new (sz, v);
+  __builtin_operator_delete (c, v);
+#if __cpp_aligned_new
+  U d = __builtin_operator_new (sz, std::align_val_t(sz), v);
+  __builtin_operator_delete (d, std::align_val_t(sz), v);
+#endif
+  U e = __builtin_operator_new (w);
+  __builtin_operator_delete (e);
+}
+
+void
+qux ()
+{
+  bar <0> ();
+  baz <std::size_t, void *, const std::nothrow_t &, float> (32, std::nothrow,
+                                                           1.f);
+}
diff --git a/gcc/testsuite/g++.dg/ext/builtin-operator-new-2.C 
b/gcc/testsuite/g++.dg/ext/builtin-operator-new-2.C
new file mode 100644
index 000000000000..e0196a57b148
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/builtin-operator-new-2.C
@@ -0,0 +1,49 @@
+// { dg-do compile }
+
+#include <new>
+
+void *operator new (std::size_t, float, double);       // { dg-message 
"selected function declared here" }
+void operator delete (void *, float, double);          // { dg-message 
"selected function declared here" }
+
+void
+foo (void *x)
+{
+  void *a = __builtin_operator_new (32, 1.f, 32.);     // { dg-error "call to 
'__builtin_operator_new' does not select replaceable global allocation 
function" }
+  __builtin_operator_delete (a, 1.f, 32.);             // { dg-error "call to 
'__builtin_operator_delete' does not select replaceable global deallocation 
function" }
+  void *b = __builtin_operator_new (32, x);            // { dg-error "call to 
'__builtin_operator_new' does not select replaceable global allocation 
function" }
+  void *c = __builtin_operator_new (32, 1LL, 1L, 1);   // { dg-error "no 
matching function for call to 'operator new\\\(int, long long int, long int, 
int\\\)'" }
+  __builtin_operator_delete (c, 1LL, 1L, 1);           // { dg-error "no 
matching function for call to 'operator delete\\\(void\\\*&, long long int, 
long int, int\\\)'" }
+  void *d = __builtin_operator_new ();                 // { dg-error "no 
matching function for call to 'operator new\\\(\\\)'" }
+  __builtin_operator_delete ();                                // { dg-error 
"no matching function for call to 'operator delete\\\(\\\)'" }
+}
+
+template <int N>
+void
+bar (void *x)
+{
+  void *a = __builtin_operator_new (32, 1.f, 32.);     // { dg-error "call to 
'__builtin_operator_new' does not select replaceable global allocation 
function" }
+  __builtin_operator_delete (a, 1.f, 32.);             // { dg-error "call to 
'__builtin_operator_delete' does not select replaceable global deallocation 
function" }
+  void *b = __builtin_operator_new (32, x);            // { dg-error "call to 
'__builtin_operator_new' does not select replaceable global allocation 
function" }
+  void *c = __builtin_operator_new (32, 1LL, 1L, 1);   // { dg-error "no 
matching function for call to 'operator new\\\(int, long long int, long int, 
int\\\)'" }
+  __builtin_operator_delete (c, 1LL, 1L, 1);           // { dg-error "no 
matching function for call to 'operator delete\\\(void\\\*&, long long int, 
long int, int\\\)'" }
+  void *d = __builtin_operator_new ();                 // { dg-error "no 
matching function for call to 'operator new\\\(\\\)'" }
+  __builtin_operator_delete ();                                // { dg-error 
"no matching function for call to 'operator delete\\\(\\\)'" }
+}
+
+template <typename T, typename U, typename V>
+void
+baz (void *x, T sz, V v)
+{
+  U a = __builtin_operator_new (sz, 1.f, 32.);         // { dg-error "call to 
'__builtin_operator_new' does not select replaceable global allocation 
function" }
+  __builtin_operator_delete (a, 1.f, 32.);             // { dg-error "call to 
'__builtin_operator_delete' does not select replaceable global deallocation 
function" }
+  U b = __builtin_operator_new (sz, x);                        // { dg-error 
"call to '__builtin_operator_new' does not select replaceable global allocation 
function" }
+  U c = __builtin_operator_new (sz, v, 1L, 1);         // { dg-error "no 
matching function for call to 'operator new\\\(int&, long long int&, long int, 
int\\\)'" }
+  __builtin_operator_delete (c, v, 1L, 1);             // { dg-error "no 
matching function for call to 'operator delete\\\(void\\\*&, long long int&, 
long int, int\\\)'" }
+}
+
+void
+qux (void *x, void *y)
+{
+  bar <0> (x);
+  baz <int, void *, long long> (y, 32, 1LL);
+}
diff --git a/gcc/testsuite/g++.dg/ext/builtin-operator-new-3.C 
b/gcc/testsuite/g++.dg/ext/builtin-operator-new-3.C
new file mode 100644
index 000000000000..f83e8ef0732c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/builtin-operator-new-3.C
@@ -0,0 +1,47 @@
+// { dg-do run }
+
+#include <new>
+
+void
+use (void *p)
+{
+  int *volatile q = new (p) int;
+  *q = 42;
+  (*q)++;
+  if (*q != 43)
+    __builtin_abort ();
+}
+
+int
+main ()
+{
+  void *volatile a = __builtin_operator_new (sizeof (int));
+  use (a);
+  __builtin_operator_delete (a);
+#if __cpp_sized_deallocation
+  a = __builtin_operator_new (sizeof (int));
+  use (a);
+  __builtin_operator_delete (a, sizeof (int));
+#endif
+#if __cpp_aligned_new
+  void *volatile b = __builtin_operator_new (sizeof (int), 
std::align_val_t(alignof (int) * 4));
+  use (b);
+  __builtin_operator_delete (b, std::align_val_t(alignof (int) * 4));
+#if __cpp_sized_deallocation
+  b = __builtin_operator_new (sizeof (int), std::align_val_t(alignof (int) * 
4));
+  use (b);
+  __builtin_operator_delete (b, sizeof (int), std::align_val_t(alignof (int) * 
4));
+#endif
+#endif
+  void *volatile c = __builtin_operator_new (sizeof (int), std::nothrow);
+  use (c);
+  __builtin_operator_delete (c, std::nothrow);
+#if __cpp_aligned_new
+  void *volatile d = __builtin_operator_new (sizeof (int), 
std::align_val_t(alignof (int) * 4), std::nothrow);
+  use (d);
+  __builtin_operator_delete (d, std::align_val_t(sizeof (int)), std::nothrow);
+#endif
+  void *volatile e = __builtin_operator_new (1.f);
+  use (e);
+  __builtin_operator_delete (e);
+}

Reply via email to