@@ -17315,6 +17315,7 @@ finish_constructor_body (void)
add_stmt (build_stmt (input_location, LABEL_EXPR, cdtor_label));
val = DECL_ARGUMENTS (current_function_decl);
+ suppress_warning (val, OPT_Wuse_after_free);
val = build2 (MODIFY_EXPR, TREE_TYPE (val),
DECL_RESULT (current_function_decl), val);
/* Return the address of the object. */
@@ -17408,6 +17409,7 @@ finish_destructor_body (void)
tree val;
val = DECL_ARGUMENTS (current_function_decl);
+ suppress_warning (val, OPT_Wuse_after_free);
val = build2 (MODIFY_EXPR, TREE_TYPE (val),
DECL_RESULT (current_function_decl), val);
/* Return the address of the object. */
@@ -166,6 +166,7 @@ build_delete_destructor_body (tree delete_dtor, tree complete_dtor)
if (targetm.cxx.cdtor_returns_this ())
{
tree val = DECL_ARGUMENTS (delete_dtor);
+ suppress_warning (val, OPT_Wuse_after_free);
val = build2 (MODIFY_EXPR, TREE_TYPE (val),
DECL_RESULT (delete_dtor), val);
add_stmt (build_stmt (0, RETURN_EXPR, val));
@@ -3880,9 +3880,17 @@ pass_waccess::warn_invalid_pointer (tree ref, gimple *use_stmt,
bool maybe, bool equality /* = false */)
{
/* Avoid printing the unhelpful "<unknown>" in the diagnostics. */
- if (ref && TREE_CODE (ref) == SSA_NAME
- && (!SSA_NAME_VAR (ref) || DECL_ARTIFICIAL (SSA_NAME_VAR (ref))))
- ref = NULL_TREE;
+ if (ref && TREE_CODE (ref) == SSA_NAME)
+ {
+ tree var = SSA_NAME_VAR (ref);
+ if (!var)
+ ref = NULL_TREE;
+ /* Don't warn for cases like when a cdtor returns 'this' on ARM. */
+ else if (warning_suppressed_p (var, OPT_Wuse_after_free))
+ return;
+ else if (DECL_ARTIFICIAL (var))
+ ref = NULL_TREE;
+ }
location_t use_loc = gimple_location (use_stmt);
if (use_loc == UNKNOWN_LOCATION)
new file mode 100644
@@ -0,0 +1,10 @@
+// PR target/104213
+// { dg-do compile }
+// { dg-options "-Wuse-after-free" }
+
+class C
+{
+ virtual ~C();
+};
+
+C::~C() {} // { dg-bogus "used after" }
new file mode 100644
@@ -0,0 +1,16 @@
+// PR target/104213
+// { dg-do compile }
+// { dg-options "-Wuse-after-free" }
+// FIXME: We should not output the warning twice.
+
+struct A
+{
+ virtual ~A ();
+ void f ();
+};
+
+A::~A ()
+{
+ operator delete (this);
+ f (); // { dg-warning "used after" }
+} // { dg-warning "used after" }