r352980 - Fix handling of usual deallocation functions in various configuratios.

Eric Fiselier via cfe-commits cfe-commits at lists.llvm.org
Sat Feb 2 19:44:31 PST 2019


Author: ericwf
Date: Sat Feb  2 19:44:31 2019
New Revision: 352980

URL: http://llvm.org/viewvc/llvm-project?rev=352980&view=rev
Log:
Fix handling of usual deallocation functions in various configuratios.

Clang allows users to enable or disable various types of allocation
and deallocation regardless of the C++ dialect. When extended new/delete
overloads are enabled in older dialects, we need to treat them as if
they're usual.

Also, disabling one usual deallocation form shouldn't
disable any others. For example, disabling aligned allocation in C++2a
should have no effect on destroying delete.

Added:
    cfe/trunk/test/SemaCXX/extended-usual-deallocation-functions.cpp
Modified:
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/test/SemaCXX/cxx2a-destroying-delete.cpp

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=352980&r1=352979&r2=352980&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Sat Feb  2 19:44:31 2019
@@ -2091,8 +2091,13 @@ bool CXXMethodDecl::isUsualDeallocationF
     return false;
 
   // In C++17 onwards, all potential usual deallocation functions are actual
-  // usual deallocation functions.
-  if (Context.getLangOpts().AlignedAllocation)
+  // usual deallocation functions. Honor this behavior when post-C++14
+  // deallocation functions are offered as extensions too.
+  // FIXME(EricWF): Destrying Delete should be a language option. How do we
+  // handle when destroying delete is used prior to C++17?
+  if (Context.getLangOpts().CPlusPlus17 ||
+      Context.getLangOpts().AlignedAllocation ||
+      isDestroyingOperatorDelete())
     return true;
 
   // This function is a usual deallocation function if there are no

Modified: cfe/trunk/test/SemaCXX/cxx2a-destroying-delete.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx2a-destroying-delete.cpp?rev=352980&r1=352979&r2=352980&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx2a-destroying-delete.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx2a-destroying-delete.cpp Sat Feb  2 19:44:31 2019
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -std=c++2a -verify %s
+// RUN: %clang_cc1 -std=c++2a -fexceptions -verify %s
+// RUN: %clang_cc1 -std=c++2a  -verify %s
 
 namespace std {
   using size_t = decltype(sizeof(0));
@@ -58,11 +59,13 @@ namespace delete_selection {
     C();
     void *operator new(std::size_t);
     void operator delete(void*) = delete;
-    void operator delete(C *, std::destroying_delete_t) = delete;
+    void operator delete(C *, std::destroying_delete_t) = delete; // expected-note 0-1 {{deleted here}}
   };
-  // FIXME: This should be ill-formed, but we incorrectly decide that overload
-  // resolution failed (because it selected a deleted function) and thus no
-  // 'operator delete' should be called.
+  // TODO: We only diagnose the use of a deleted operator delete when exceptions
+  // are enabled. Otherwise we don't bother doing the lookup.
+#ifdef __EXCEPTIONS
+  // expected-error at +2 {{attempt to use a deleted function}}
+#endif
   C *new_C() { return new C; }
 
   struct D {

Added: cfe/trunk/test/SemaCXX/extended-usual-deallocation-functions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/extended-usual-deallocation-functions.cpp?rev=352980&view=auto
==============================================================================
--- cfe/trunk/test/SemaCXX/extended-usual-deallocation-functions.cpp (added)
+++ cfe/trunk/test/SemaCXX/extended-usual-deallocation-functions.cpp Sat Feb  2 19:44:31 2019
@@ -0,0 +1,69 @@
+// RUN: %clang_cc1 -fexceptions -std=c++2a -fsized-deallocation -fno-aligned-allocation -verify %s
+// RUN: %clang_cc1 -fexceptions -std=c++17 -fsized-deallocation -fno-aligned-allocation -verify %s
+// RUN: %clang_cc1 -fexceptions -std=c++14 -fsized-deallocation -faligned-allocation -DHAS_ALIGN -verify %s
+// RUN: %clang_cc1 -fexceptions -std=c++11 -fsized-deallocation -faligned-allocation -DHAS_ALIGN -verify %s
+
+// Test that we handle aligned deallocation, sized deallocation, and destroying
+// delete as usual deallocation functions even if they are used as extensions
+// prior to C++17.
+
+namespace std {
+using size_t = decltype(sizeof(0));
+enum class align_val_t : size_t;
+
+struct destroying_delete_t {
+  struct __construct { explicit __construct() = default; };
+  explicit destroying_delete_t(__construct) {}
+};
+
+inline constexpr destroying_delete_t destroying_delete(destroying_delete_t::__construct());
+}
+
+// FIXME: Should destroying delete really be on in all dialects by default?
+struct A {
+  void operator delete(void*) = delete;
+  void operator delete(A*, std::destroying_delete_t) = delete; // expected-note {{deleted}}
+};
+void ATest(A* a) { delete a; } // expected-error {{deleted}}
+
+struct B {
+  void operator delete(void*) = delete; // expected-note {{deleted}}
+  void operator delete(void*, std::size_t) = delete;
+};
+void BTest(B *b) { delete b; }// expected-error {{deleted}}
+
+
+struct alignas(32) C {
+#ifndef HAS_ALIGN
+  // expected-note at +2 {{deleted}}
+#endif
+  void operator delete(void*) = delete;
+#ifdef HAS_ALIGN
+  // expected-note at +2 {{deleted}}
+#endif
+  void operator delete(void*, std::align_val_t) = delete;
+};
+void CTest(C *c) { delete c; } // expected-error {{deleted}}
+
+struct D {
+  void operator delete(void*) = delete;
+  void operator delete(D*, std::destroying_delete_t) = delete; // expected-note {{deleted}}
+  void operator delete(D*, std::destroying_delete_t, std::size_t) = delete;
+  void operator delete(D*, std::destroying_delete_t, std::align_val_t) = delete;
+  void operator delete(D*, std::destroying_delete_t, std::size_t, std::align_val_t) = delete;
+};
+void DTest(D *d) { delete d; } // expected-error {{deleted}}
+
+struct alignas(64) E {
+  void operator delete(void*) = delete;
+  void operator delete(E*, std::destroying_delete_t) = delete;
+  void operator delete(E*, std::destroying_delete_t, std::size_t) = delete;
+  void operator delete(E*, std::destroying_delete_t, std::align_val_t) = delete;
+  void operator delete(E*, std::destroying_delete_t, std::size_t, std::align_val_t) = delete;
+#ifdef HAS_ALIGN
+  // expected-note at -3 {{deleted}}
+#else
+  // expected-note at -7 {{deleted}}
+#endif
+};
+void ETest(E *e) { delete e; } // expected-error {{deleted}}




More information about the cfe-commits mailing list