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. */
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. */
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));
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)
--- /dev/null
+// PR target/104213
+// { dg-do compile }
+// { dg-options "-Wuse-after-free" }
+
+class C
+{
+ virtual ~C();
+};
+
+C::~C() {} // { dg-bogus "used after" }
--- /dev/null
+// 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" }