Clang defines the __cpp_impl_destroying_delete macro unconditionally, so
that the feature is supported whenever the library type is defined. This
is incompatible with the current definition in libstdc++ because we use
constexpr and inline variables, which will give an error for older -std
modes.

This patch defines the destroying_delete_t type and destroying_delete
variable independently of the __cpp_impl_destroying_delete macro, but
only for C++2a (because the names aren't reserved for previous
standards). The __cpp_lib_destroying_delete macro is only defined when
both the library type and compiler macro are defined (i.e. when the type
can actually be used as intended).

        PR libstdc++/89345
        * include/std/version [__cpp_impl_destroying_delete]
        (__cpp_lib_destroying_delete): Only define for C++2a and later.
        * libsupc++/new [__cpp_impl_destroying_delete]
        (__cpp_lib_destroying_delete): Likewise.
        (destroying_delete_t, destroying_delete): Likewise, but define even
        when __cpp_impl_destroying_delete is not defined.
        * testsuite/18_support/destroying_delete.cc: New test.

Tested powerpc64le-linux, committed to trunk.


commit cd37f0f4c5d82dffee9d51e0c3b9b26405114547
Author: Jonathan Wakely <jwak...@redhat.com>
Date:   Wed Feb 13 21:24:13 2019 +0000

    PR libstdc++/89345 Only define std::destroying_delete for C++2a
    
    Clang defines the __cpp_impl_destroying_delete macro unconditionally, so
    that the feature is supported whenever the library type is defined. This
    is incompatible with the current definition in libstdc++ because we use
    constexpr and inline variables, which will give an error for older -std
    modes.
    
    This patch defines the destroying_delete_t type and destroying_delete
    variable independently of the __cpp_impl_destroying_delete macro, but
    only for C++2a (because the names aren't reserved for previous
    standards). The __cpp_lib_destroying_delete macro is only defined when
    both the library type and compiler macro are defined (i.e. when the type
    can actually be used as intended).
    
            PR libstdc++/89345
            * include/std/version [__cpp_impl_destroying_delete]
            (__cpp_lib_destroying_delete): Only define for C++2a and later.
            * libsupc++/new [__cpp_impl_destroying_delete]
            (__cpp_lib_destroying_delete): Likewise.
            (destroying_delete_t, destroying_delete): Likewise, but define even
            when __cpp_impl_destroying_delete is not defined.
            * testsuite/18_support/destroying_delete.cc: New test.

diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version
index 38277b9ecf2..fa3d473759b 100644
--- a/libstdc++-v3/include/std/version
+++ b/libstdc++-v3/include/std/version
@@ -42,10 +42,6 @@
 # define __cpp_lib_uncaught_exceptions 201411L
 #endif
 
-#if __cpp_impl_destroying_delete
-# define __cpp_lib_destroying_delete 201806L
-#endif
-
 #if __cplusplus >= 201103L
 // c++11
 #define __cpp_lib_allocator_is_always_equal 201411
@@ -152,6 +148,9 @@
 
 #if __cplusplus > 201703L
 // c++2a
+#if __cpp_impl_destroying_delete
+# define __cpp_lib_destroying_delete 201806L
+#endif
 #define __cpp_lib_erase_if 201900L
 #ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED
 # define __cpp_lib_is_constant_evaluated 201811L
diff --git a/libstdc++-v3/libsupc++/new b/libstdc++-v3/libsupc++/new
index 6347d21b26f..24d897a8f22 100644
--- a/libstdc++-v3/libsupc++/new
+++ b/libstdc++-v3/libsupc++/new
@@ -208,8 +208,7 @@ namespace std
 #endif // _GLIBCXX_HAVE_BUILTIN_LAUNDER
 #endif // C++17
 
-#if __cpp_impl_destroying_delete
-#define __cpp_lib_destroying_delete 201806L
+#if __cplusplus > 201703L
 namespace std
 {
   struct destroying_delete_t
@@ -218,7 +217,11 @@ namespace std
   };
   inline constexpr destroying_delete_t destroying_delete{};
 }
-#endif // destroying delete
+// Only define the feature test macro if the compiler supports the feature:
+#if __cpp_impl_destroying_delete
+# define __cpp_lib_destroying_delete 201806L
+#endif
+#endif // C++20
 
 #pragma GCC visibility pop
 
diff --git a/libstdc++-v3/testsuite/18_support/destroying_delete.cc 
b/libstdc++-v3/testsuite/18_support/destroying_delete.cc
new file mode 100644
index 00000000000..8682ccce9fd
--- /dev/null
+++ b/libstdc++-v3/testsuite/18_support/destroying_delete.cc
@@ -0,0 +1,58 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <new>
+#include <testsuite_hooks.h>
+
+#ifndef __cpp_lib_destroying_delete
+# error "Feature-test macro for destroying_delete missing"
+#elif __cpp_lib_destroying_delete != 201806L
+# error "Feature-test macro for destroying_delete has wrong value"
+#endif
+
+const std::destroying_delete_t d{};
+static_assert(std::is_same_v<decltype(d), decltype(std::destroying_delete)>);
+
+struct X
+{
+  static bool called;
+
+  void operator delete(X* p, std::destroying_delete_t)
+  {
+    called = true;
+    p->~X();
+    ::operator delete(p);
+  }
+};
+
+bool X::called = false;
+
+void
+test01()
+{
+  X* x = new X;
+  delete x;
+  VERIFY( X::called );
+}
+
+int main()
+{
+  test01();
+}

Reply via email to