2024-07-02 Jakub Jelinek <ja...@redhat.com>
Jason Merrill <ja...@redhat.com>
PR c++/115747
gcc/cp/
* init.cc: Implement C++26 P3144R2 - Deleting a Pointer to an
Incomplete Type Should be Ill-formed.
(build_vec_delete_1): Emit permerror_at and return error_mark_node
for delete [] on incomplete type.
(build_delete): Similarly for delete.
gcc/testsuite/
* g++.dg/init/delete1.C: Adjust expected diagnostics for C++26.
* g++.dg/warn/Wdelete-incomplete-1.C: Likewise.
* g++.dg/warn/incomplete1.C: Likewise.
* g++.dg/ipa/pr85607.C: Likewise.
* g++.dg/cpp26/delete1.C: New test.
* g++.dg/cpp26/delete2.C: New test.
* g++.dg/cpp26/delete3.C: New test.
--- gcc/cp/init.cc.jj 2024-06-04 13:19:03.706604998 +0200
+++ gcc/cp/init.cc 2024-07-02 19:16:57.596412502 +0200
@@ -4114,7 +4114,24 @@ build_vec_delete_1 (location_t loc, tree
if (!COMPLETE_TYPE_P (type))
{
- if (complain & tf_warning)
+ if (cxx_dialect > cxx23)
+ {
+ if (complain & tf_error)
+ {
+ int saved_errorcount = errorcount;
+ if (permerror_opt (loc, OPT_Wdelete_incomplete,
+ "operator %<delete []%> used on "
+ "incomplete type"))
+ {
+ cxx_incomplete_type_inform (type);
+ if (errorcount != saved_errorcount)
+ return error_mark_node;
+ }
+ }
+ else
+ return error_mark_node;
+ }
+ else if (complain & tf_warning)
{
auto_diagnostic_group d;
if (warning_at (loc, OPT_Wdelete_incomplete,
@@ -5178,7 +5195,24 @@ build_delete (location_t loc, tree otype
if (!COMPLETE_TYPE_P (type))
{
- if (complain & tf_warning)
+ if (cxx_dialect > cxx23)
+ {
+ if (complain & tf_error)
+ {
+ int saved_errorcount = errorcount;
+ if (permerror_opt (loc, OPT_Wdelete_incomplete,
+ "operator %<delete%> used on "
+ "incomplete type"))
+ {
+ cxx_incomplete_type_inform (type);
+ if (errorcount != saved_errorcount)
+ return error_mark_node;
+ }
+ }
+ else
+ return error_mark_node;
+ }
+ else if (complain & tf_warning)
{
auto_diagnostic_group d;
if (warning_at (loc, OPT_Wdelete_incomplete,
--- gcc/testsuite/g++.dg/init/delete1.C.jj 2020-01-12 11:54:37.185401761
+0100
+++ gcc/testsuite/g++.dg/init/delete1.C 2024-07-02 17:38:58.742393502 +0200
@@ -3,7 +3,8 @@
class C; // { dg-message "7:forward" }
void foo(void *p) {
- delete [] ((C*)p) ; // { dg-warning "3:possible problem detected in invocation of
operator .delete \\\[\\\]." }
- // { dg-message "3:neither the destructor nor the class-specific" "note" {
target *-*-* } .-1 }
- // { dg-warning "invalid use of incomplete type" "" { target *-*-* } .-2 }
+ delete [] ((C*)p) ; // { dg-warning "3:possible problem detected in invocation of operator
.delete \\\[\\\]." "" { target c++23_down } }
+ // { dg-message "3:neither the destructor nor the class-specific" "note" {
target c++23_down } .-1 }
+ // { dg-warning "invalid use of incomplete type" "" { target c++23_down }
.-2 }
+ // { dg-error "operator 'delete \\\[\\\]' used on incomplete type" "" {
target c++26 } .-3 }
}
--- gcc/testsuite/g++.dg/warn/Wdelete-incomplete-1.C.jj 2020-01-12
11:54:37.282400298 +0100
+++ gcc/testsuite/g++.dg/warn/Wdelete-incomplete-1.C 2024-07-02
17:37:39.326397364 +0200
@@ -2,7 +2,8 @@
class Foo; // { dg-message "7:forward declaration" }
int main() {
- Foo* p; // { dg-warning "9:.p. has incomplete type" }
- delete [] p; // { dg-warning "4:possible problem detected in invocation of
operator .delete \\\[\\\]." }
- // { dg-message "4:neither the destructor nor the class-specific" "note" {
target *-*-* } .-1 }
+ Foo* p; // { dg-warning "9:.p. has incomplete type" "" { target
c++23_down } }
+ delete [] p; // { dg-warning "4:possible problem detected in invocation of operator
.delete \\\[\\\]." "" { target c++23_down } }
+ // { dg-message "4:neither the destructor nor the class-specific" "note" {
target c++23_down } .-1 }
+ // { dg-error "operator 'delete \\\[\\\]' used on incomplete type" "" {
target c++26 } .-2 }
}
--- gcc/testsuite/g++.dg/warn/incomplete1.C.jj 2020-01-12 11:54:37.290400177
+0100
+++ gcc/testsuite/g++.dg/warn/incomplete1.C 2024-07-02 17:38:27.988782244
+0200
@@ -11,12 +11,13 @@
class A; // { dg-message "7:forward declaration of 'class A'" }
-A *a; // { dg-warning "4:'a' has incomplete type" }
+A *a; // { dg-warning "4:'a' has incomplete type" "" { target
c++23_down } }
int
main (int argc, char **argv)
{
- delete a; // { dg-warning "3:possible problem detected in invocation of .operator
delete." "warn" }
- // { dg-message "3:neither the destructor nor the class-specific" "note" {
target *-*-* } .-1 }
+ delete a; // { dg-warning "3:possible problem detected in invocation of .operator
delete." "warn" { target c++23_down } }
+ // { dg-message "3:neither the destructor nor the class-specific" "note" {
target c++23_down } .-1 }
+ // { dg-error "operator 'delete' used on incomplete type" "" { target c++26
} .-2 }
return 0;
}
--- gcc/testsuite/g++.dg/ipa/pr85607.C.jj 2020-01-12 11:54:37.193401641
+0100
+++ gcc/testsuite/g++.dg/ipa/pr85607.C 2024-07-02 17:39:20.601117195 +0200
@@ -3,12 +3,13 @@
class A; // { dg-message "7:forward declaration of 'class A'" }
-A *a; // { dg-warning "4:'a' has incomplete type" }
+A *a; // { dg-warning "4:'a' has incomplete type" "" { target
c++23_down } }
int
main (int argc, char **argv)
{
- delete a; // { dg-warning "3:possible problem detected in invocation of .operator
delete." "warn" }
- // { dg-message "3:neither the destructor nor the class-specific" "note" {
target *-*-* } .-1 }
+ delete a; // { dg-warning "3:possible problem detected in invocation of .operator
delete." "warn" { target c++23_down } }
+ // { dg-message "3:neither the destructor nor the class-specific" "note" {
target c++23_down } .-1 }
+ // { dg-error "operator 'delete' used on incomplete type" "" { target c++26
} .-2 }
return 0;
}
--- gcc/testsuite/g++.dg/cpp26/delete1.C.jj 2024-07-02 12:08:55.547027171
+0200
+++ gcc/testsuite/g++.dg/cpp26/delete1.C 2024-07-02 17:41:14.089682637
+0200
@@ -0,0 +1,36 @@
+// C++26 P3144R2 - Deleting a Pointer to an Incomplete Type Should be
Ill-formed
+// { dg-do compile { target c++26 } }
+
+struct S; // { dg-message "forward declaration of 'struct S'" }
+struct T; // { dg-message "forward declaration of 'struct T'" }
+struct U; // { dg-message "forward declaration of 'struct U'" }
+
+void
+foo (S *p, T *q, U *r, S *s, T *t, U *u)
+{
+ delete p; // { dg-error "operator 'delete' used on incomplete type" }
+ delete q; // { dg-error "operator 'delete' used on incomplete type" }
+ delete r; // { dg-error "operator 'delete' used on incomplete type" }
+ delete[] s; // { dg-error "operator 'delete \\\[\\\]' used on incomplete
type" }
+ delete[] t; // { dg-error "operator 'delete \\\[\\\]' used on incomplete
type" }
+ delete[] u; // { dg-error "operator 'delete \\\[\\\]' used on incomplete
type" }
+}
+
+struct S
+{
+ int s;
+};
+
+struct T
+{
+ int t;
+ ~T () {}
+};
+
+struct U
+{
+ int u;
+ void operator delete (void *) noexcept;
+ void operator delete[] (void *) noexcept;
+};
+
--- gcc/testsuite/g++.dg/cpp26/delete2.C.jj 2024-07-02 17:39:49.549751269
+0200
+++ gcc/testsuite/g++.dg/cpp26/delete2.C 2024-07-02 17:41:19.943608640
+0200
@@ -0,0 +1,36 @@
+// C++26 P3144R2 - Deleting a Pointer to an Incomplete Type Should be
Ill-formed
+// { dg-do compile { target c++26 } }
+// { dg-options "-Wno-delete-incomplete" }
+
+struct S;
+struct T;
+struct U;
+
+void
+foo (S *p, T *q, U *r, S *s, T *t, U *u)
+{
+ delete p; // { dg-bogus "operator 'delete' used on incomplete type" }
+ delete q; // { dg-bogus "operator 'delete' used on incomplete type" }
+ delete r; // { dg-bogus "operator 'delete' used on incomplete type" }
+ delete[] s; // { dg-bogus "operator 'delete \\\[\\\]' used on incomplete
type" }
+ delete[] t; // { dg-bogus "operator 'delete \\\[\\\]' used on incomplete
type" }
+ delete[] u; // { dg-bogus "operator 'delete \\\[\\\]' used on incomplete
type" }
+}
+
+struct S
+{
+ int s;
+};
+
+struct T
+{
+ int t;
+ ~T () {}
+};
+
+struct U
+{
+ int u;
+ void operator delete (void *) noexcept;
+ void operator delete[] (void *) noexcept;
+};
--- gcc/testsuite/g++.dg/cpp26/delete3.C.jj 2024-07-02 17:41:29.026493828
+0200
+++ gcc/testsuite/g++.dg/cpp26/delete3.C 2024-07-02 17:52:13.829368589
+0200
@@ -0,0 +1,36 @@
+// C++26 P3144R2 - Deleting a Pointer to an Incomplete Type Should be
Ill-formed
+// { dg-do compile { target c++26 } }
+// { dg-options "-fpermissive" }
+
+struct S; // { dg-message "forward declaration of 'struct S'" }
+struct T; // { dg-message "forward declaration of 'struct T'" }
+struct U; // { dg-message "forward declaration of 'struct U'" }
+
+void
+foo (S *p, T *q, U *r, S *s, T *t, U *u)
+{
+ delete p; // { dg-warning "operator 'delete' used on incomplete type" }
+ delete q; // { dg-warning "operator 'delete' used on incomplete type" }
+ delete r; // { dg-warning "operator 'delete' used on incomplete type" }
+ delete[] s; // { dg-warning "operator 'delete \\\[\\\]' used on incomplete
type" }
+ delete[] t; // { dg-warning "operator 'delete \\\[\\\]' used on incomplete
type" }
+ delete[] u; // { dg-warning "operator 'delete \\\[\\\]' used on incomplete
type" }
+}
+
+struct S
+{
+ int s;
+};
+
+struct T
+{
+ int t;
+ ~T () {}
+};
+
+struct U
+{
+ int u;
+ void operator delete (void *) noexcept;
+ void operator delete[] (void *) noexcept;
+};
Jakub