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,
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,
--- /dev/null
+// 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;
+};
+
--- /dev/null
+// 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;
+};
--- /dev/null
+// 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;
+};
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 }
}
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;
}
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 }
}
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;
}