aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/class.cc2
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl.cc23
-rw-r--r--gcc/testsuite/g++.dg/warn/Wuse-after-free3.C4
4 files changed, 25 insertions, 5 deletions
diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index 4766b7c..6fdb56a 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -5053,6 +5053,8 @@ build_clone (tree fn, tree name, bool need_vtt_parm_p,
clone = copy_fndecl_with_name (fn, name, ERROR_MARK,
need_vtt_parm_p, omit_inherited_parms_p);
DECL_CLONED_FUNCTION (clone) = fn;
+
+ maybe_prepare_return_this (clone);
}
/* Remember where this function came from. */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7b0b7c6..5614b71 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6979,6 +6979,7 @@ extern tree lookup_enumerator (tree, tree);
extern bool start_preparsed_function (tree, tree, int);
extern bool start_function (cp_decl_specifier_seq *,
const cp_declarator *, tree);
+extern tree maybe_prepare_return_this (tree);
extern void maybe_return_this (void);
extern tree begin_function_body (void);
extern void finish_function_body (tree);
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index e269f68..bce8068 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -17926,16 +17926,31 @@ store_parm_decls (tree current_function_parms)
}
+/* Mark CDTOR's implicit THIS argument for returning, if required by
+ the ABI.. Return the decl for THIS, if it is to be returned, and
+ NULL otherwise. */
+
+tree
+maybe_prepare_return_this (tree cdtor)
+{
+ if (targetm.cxx.cdtor_returns_this ())
+ if (tree val = DECL_ARGUMENTS (cdtor))
+ {
+ suppress_warning (val, OPT_Wuse_after_free);
+ return val;
+ }
+
+ return NULL_TREE;
+}
+
/* Set the return value of the [cd]tor if the ABI wants that. */
void
-maybe_return_this (void)
+maybe_return_this ()
{
- if (targetm.cxx.cdtor_returns_this ())
+ if (tree val = maybe_prepare_return_this (current_function_decl))
{
/* Return the address of the object. */
- tree val = DECL_ARGUMENTS (current_function_decl);
- suppress_warning (val, OPT_Wuse_after_free);
val = fold_convert (TREE_TYPE (DECL_RESULT (current_function_decl)), val);
val = build2 (MODIFY_EXPR, TREE_TYPE (val),
DECL_RESULT (current_function_decl), val);
diff --git a/gcc/testsuite/g++.dg/warn/Wuse-after-free3.C b/gcc/testsuite/g++.dg/warn/Wuse-after-free3.C
index e5b1578..8ef8202 100644
--- a/gcc/testsuite/g++.dg/warn/Wuse-after-free3.C
+++ b/gcc/testsuite/g++.dg/warn/Wuse-after-free3.C
@@ -11,5 +11,7 @@ struct A
A::~A ()
{
operator delete (this);
- f (); // { dg-warning "used after" }
+ f (); // { dg-warning "used after" "" { xfail arm_eabi } }
+ // arm_eabi's cdtors return this, which disables -Wuse-after-free
+ // warnings for cdtors' "this".
}