[clang] [clang] Implement P3144R2 "Deleting a Pointer to an Incomplete Type..." (PR #97733)
Vlad Serebrennikov via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 5 03:55:08 PDT 2024
https://github.com/Endilll updated https://github.com/llvm/llvm-project/pull/97733
>From f009148063ba41d39fc844f4432ceb51377f381c Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Thu, 4 Jul 2024 17:05:11 +0300
Subject: [PATCH 1/4] [clang] Implement P3144R2 "Deleting a Pointer to an
Incomplete Type Should be Ill-formed"
---
.../clang/Basic/DiagnosticSemaKinds.td | 2 ++
clang/lib/Sema/SemaExprCXX.cpp | 12 ++++++---
clang/test/CXX/drs/cwg5xx.cpp | 22 +++++++++-------
clang/test/SemaCXX/new-delete.cpp | 26 ++++++++++++-------
4 files changed, 41 insertions(+), 21 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 3df64b2ecef1b..5c3e311ac6382 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7991,6 +7991,8 @@ def err_ambiguous_delete_operand : Error<
def warn_delete_incomplete : Warning<
"deleting pointer to incomplete type %0 may cause undefined behavior">,
InGroup<DeleteIncomplete>;
+def err_delete_incomplete : Error<
+ "cannot delete pointer to incomplete type %0">;
def err_delete_incomplete_class_type : Error<
"deleting incomplete class type %0; no conversions to pointer type">;
def err_delete_explicit_conversion : Error<
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index 69074f92a0286..fcf2189a308a8 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -3719,8 +3719,11 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
// The C++ standard bans deleting a pointer to a non-object type, which
// effectively bans deletion of "void*". However, most compilers support
// this, so we treat it as a warning unless we're in a SFINAE context.
- Diag(StartLoc, diag::ext_delete_void_ptr_operand)
- << Type << Ex.get()->getSourceRange();
+ // But we still prohibit this since C++26.
+ Diag(StartLoc, LangOpts.CPlusPlus26 ? diag::err_delete_incomplete
+ : diag::ext_delete_void_ptr_operand)
+ << (LangOpts.CPlusPlus26 ? Pointee : Type)
+ << Ex.get()->getSourceRange();
} else if (Pointee->isFunctionType() || Pointee->isVoidType() ||
Pointee->isSizelessType()) {
return ExprError(Diag(StartLoc, diag::err_delete_operand)
@@ -3729,7 +3732,10 @@ Sema::ActOnCXXDelete(SourceLocation StartLoc, bool UseGlobal,
// FIXME: This can result in errors if the definition was imported from a
// module but is hidden.
if (!RequireCompleteType(StartLoc, Pointee,
- diag::warn_delete_incomplete, Ex.get())) {
+ LangOpts.CPlusPlus26
+ ? diag::err_delete_incomplete
+ : diag::warn_delete_incomplete,
+ Ex.get())) {
if (const RecordType *RT = PointeeElem->getAs<RecordType>())
PointeeRD = cast<CXXRecordDecl>(RT->getDecl());
}
diff --git a/clang/test/CXX/drs/cwg5xx.cpp b/clang/test/CXX/drs/cwg5xx.cpp
index 9d890f981348a..6a0bb7a196669 100644
--- a/clang/test/CXX/drs/cwg5xx.cpp
+++ b/clang/test/CXX/drs/cwg5xx.cpp
@@ -1,9 +1,10 @@
-// RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98-11,cxx98-14,cxx98-17,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx98-11,cxx98-14,cxx98-17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx98-14,cxx98-17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++17 %s -verify=expected,since-cxx17,cxx98-17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++20 %s -verify=expected,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
-// RUN: %clang_cc1 -std=c++23 %s -verify=expected,since-cxx23,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++98 %s -verify=expected,cxx98-23,cxx98-11,cxx98-14,cxx98-17,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++11 %s -verify=expected,cxx98-23,cxx98-11,cxx98-14,cxx98-17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++14 %s -verify=expected,cxx98-23,cxx98-14,cxx98-17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx98-23,since-cxx17,cxx98-17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++20 %s -verify=expected,cxx98-23,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++23 %s -verify=expected,cxx98-23,since-cxx23,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
+// RUN: %clang_cc1 -std=c++2c %s -verify=expected,since-cxx26,since-cxx23,since-cxx20,since-cxx17,since-cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
#if __cplusplus == 199711L
#define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
@@ -901,7 +902,8 @@ namespace cwg573 { // cwg573: no
void *d = reinterpret_cast<void*>(c);
// cxx98-error at -1 {{cast between pointer-to-function and pointer-to-object is an extension}}
void f() { delete a; }
- // expected-error at -1 {{cannot delete expression with pointer-to-'void' type 'void *'}}
+ // cxx98-23-error at -1 {{cannot delete expression with pointer-to-'void' type 'void *'}}
+ // since-cxx26-error at -2 {{cannot delete pointer to incomplete type 'void'}}
int n = d - a;
// expected-error at -1 {{arithmetic on pointers to void}}
// FIXME: This is ill-formed.
@@ -1238,11 +1240,13 @@ namespace cwg599 { // cwg599: partial
struct V { operator int*(); operator Fn*(); };
void f(void *p, void (*q)(), S s, T t, U u, V v) {
delete p;
- // expected-error at -1 {{cannot delete expression with pointer-to-'void' type 'void *'}}
+ // cxx98-23-error at -1 {{cannot delete expression with pointer-to-'void' type 'void *'}}
+ // since-cxx26-error at -2 {{cannot delete pointer to incomplete type 'void'}}
delete q;
// expected-error at -1 {{cannot delete expression of type 'void (*)()'}}
delete s;
- // expected-error at -1 {{cannot delete expression with pointer-to-'void' type 'void *'}}
+ // cxx98-23-error at -1 {{cannot delete expression with pointer-to-'void' type 'void *'}}
+ // since-cxx26-error at -2 {{cannot delete pointer to incomplete type 'void'}}
delete t;
// expected-error at -1 {{cannot delete expression of type 'T'}}
// FIXME: This is valid, but is rejected due to a non-conforming GNU
diff --git a/clang/test/SemaCXX/new-delete.cpp b/clang/test/SemaCXX/new-delete.cpp
index 1a99c6aac604f..ec6ad43476f94 100644
--- a/clang/test/SemaCXX/new-delete.cpp
+++ b/clang/test/SemaCXX/new-delete.cpp
@@ -1,8 +1,10 @@
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,precxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++98
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,precxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++11
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,precxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++14
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx17,precxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++17
-// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx17,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++20
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,precxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++98
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,precxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++11
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,precxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++14
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,cxx17,precxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++17
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,cxx17,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++20
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx98-23,cxx17,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++23
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,since-cxx26,cxx17,cxx20 %s -triple=i686-pc-linux-gnu -Wno-new-returns-null -std=c++2c
// FIXME Location is (frontend)
// cxx17-note@*:* {{candidate function not viable: requires 2 arguments, but 3 were provided}}
@@ -172,8 +174,12 @@ void bad_deletes()
{
delete 0; // expected-error {{cannot delete expression of type 'int'}}
delete [0] (int*)0; // expected-error {{expected variable name or 'this' in lambda capture list}}
- delete (void*)0; // expected-warning {{cannot delete expression with pointer-to-'void' type 'void *'}}
- delete (T*)0; // expected-warning {{deleting pointer to incomplete type}}
+ delete (void*)0;
+ // cxx98-23-warning at -1 {{cannot delete expression with pointer-to-'void' type 'void *'}}
+ // since-cxx26-error at -2 {{cannot delete pointer to incomplete type 'void'}}
+ delete (T*)0;
+ // cxx98-23-warning at -1 {{deleting pointer to incomplete type}}
+ // since-cxx26-error at -2 {{cannot delete pointer to incomplete type 'T'}}
::S::delete (int*)0; // expected-error {{expected unqualified-id}}
}
@@ -513,8 +519,10 @@ namespace DeleteIncompleteClass {
namespace DeleteIncompleteClassPointerError {
struct A; // expected-note {{forward declaration}}
- void f(A *x) { 1+delete x; } // expected-warning {{deleting pointer to incomplete type}} \
- // expected-error {{invalid operands to binary expression}}
+ void f(A *x) { 1+delete x; }
+ // expected-error at -1 {{invalid operands to binary expression}}
+ // cxx98-23-warning at -2 {{deleting pointer to incomplete type}}
+ // since-cxx26-error at -3 {{cannot delete pointer to incomplete type 'A'}}
}
namespace PR10504 {
>From bdcc4ab396e2ed65e23afe4409b3d1487e16e806 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Fri, 5 Jul 2024 12:07:29 +0300
Subject: [PATCH 2/4] Address feedback
---
clang/docs/ReleaseNotes.rst | 4 ++++
clang/include/clang/Basic/DiagnosticGroups.td | 2 ++
clang/include/clang/Basic/DiagnosticSemaKinds.td | 5 +++--
3 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f149684214567..3a3dec4cbc60a 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -265,6 +265,7 @@ C++2c Feature Support
- Implemented `P2809R3: Trivial infinite loops are not Undefined Behavior <https://wg21.link/P2809R3>`_.
+- Implemented `P3144R2 Deleting a Pointer to an Incomplete Type Should be Ill-formed <https://wg21.link/P3144R2>`_.
Resolutions to C++ Defect Reports
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -431,6 +432,9 @@ New Compiler Flags
Matches MSVC behaviour by defining ``__STDC__`` to ``1`` when
MSVC compatibility mode is used. It has no effect for C++ code.
+- ``-Wc++2c-compat``group was added to help migrating existing codebases
+ to C++26.
+
Deprecated Compiler Flags
-------------------------
diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td
index 9431eea1f6be2..0fc87b45ba05a 100644
--- a/clang/include/clang/Basic/DiagnosticGroups.td
+++ b/clang/include/clang/Basic/DiagnosticGroups.td
@@ -420,6 +420,8 @@ def CXX20CompatPedantic : DiagGroup<"c++20-compat-pedantic",
def : DiagGroup<"c++2a-compat", [CXX20Compat]>;
def : DiagGroup<"c++2a-compat-pedantic", [CXX20CompatPedantic]>;
+def CXX26Compat : DiagGroup<"c++2c-compat", []>;
+
def ExitTimeDestructors : DiagGroup<"exit-time-destructors">;
def FlexibleArrayExtensions : DiagGroup<"flexible-array-extensions">;
def FourByteMultiChar : DiagGroup<"four-char-constants">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 5c3e311ac6382..c0a9fa6cbacb6 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7989,8 +7989,9 @@ def ext_delete_void_ptr_operand : ExtWarn<
def err_ambiguous_delete_operand : Error<
"ambiguous conversion of delete expression of type %0 to a pointer">;
def warn_delete_incomplete : Warning<
- "deleting pointer to incomplete type %0 may cause undefined behavior">,
- InGroup<DeleteIncomplete>;
+ "deleting pointer to incomplete type %0 is incompatible with C++2c"
+ " and may cause undefined behavior">,
+ InGroup<CXX26Compat>;
def err_delete_incomplete : Error<
"cannot delete pointer to incomplete type %0">;
def err_delete_incomplete_class_type : Error<
>From 3a28e5223fe85971d2afcd27a4af6a26368f0b37 Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Fri, 5 Jul 2024 13:05:32 +0300
Subject: [PATCH 3/4] Change C++ Status page accordingly
---
clang/www/cxx_status.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index f12ce38ba3d79..0c013e6d7cb58 100755
--- a/clang/www/cxx_status.html
+++ b/clang/www/cxx_status.html
@@ -213,7 +213,7 @@ <h2 id="cxx26">C++2c implementation status</h2>
<tr>
<td>Deleting a Pointer to an Incomplete Type Should be Ill-formed</td>
<td><a href="https://wg21.link/P3144">P3144R2</a></td>
- <td class="none" align="center">No</td>
+ <td class="Unreleased" align="center">Clang 19</td>
</tr>
<tr>
<td>Ordering of constraints involving fold expressions</td>
>From 60f00a9f34af633eb64223b5c65f693ae3bc9c2a Mon Sep 17 00:00:00 2001
From: Vlad Serebrennikov <serebrennikov.vladislav at gmail.com>
Date: Fri, 5 Jul 2024 13:54:50 +0300
Subject: [PATCH 4/4] Add missing whitespace to docs that was breaking the
build
---
clang/docs/ReleaseNotes.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3a3dec4cbc60a..216e0ac0968b8 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -432,7 +432,7 @@ New Compiler Flags
Matches MSVC behaviour by defining ``__STDC__`` to ``1`` when
MSVC compatibility mode is used. It has no effect for C++ code.
-- ``-Wc++2c-compat``group was added to help migrating existing codebases
+- ``-Wc++2c-compat`` group was added to help migrating existing codebases
to C++26.
Deprecated Compiler Flags
More information about the cfe-commits
mailing list