aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2011-11-13 00:09:36 -0500
committerJason Merrill <jason@gcc.gnu.org>2011-11-13 00:09:36 -0500
commit2c6f792709071cd3492a10b79924674924f7fb1c (patch)
treed4bb198a43ba892c06b25855372885a1f92e3520 /gcc
parentafe5cf219076d5f529ce767563aa36ea07970356 (diff)
downloadgcc-2c6f792709071cd3492a10b79924674924f7fb1c.zip
gcc-2c6f792709071cd3492a10b79924674924f7fb1c.tar.gz
gcc-2c6f792709071cd3492a10b79924674924f7fb1c.tar.bz2
re PR c++/986 (g++ misses warning for reference on temporary that invokes undefined behaviour)
PR c++/986 * call.c (set_up_extended_ref_temp): Warn about references bound to non-static reference members. * init.c (perform_member_init): Pass in the member. From-SVN: r181334
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/call.c8
-rw-r--r--gcc/cp/init.c2
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/g++.dg/warn/ref-temp1.C11
5 files changed, 28 insertions, 1 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 21f6447..a33332c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,10 @@
2011-11-12 Jason Merrill <jason@redhat.com>
+ PR c++/986
+ * call.c (set_up_extended_ref_temp): Warn about references
+ bound to non-static reference members.
+ * init.c (perform_member_init): Pass in the member.
+
PR c++/51060
* cp-gimplify.c (cp_gimplify_expr): Leave clobbers alone.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index e81950c..ab06542 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -8607,6 +8607,14 @@ set_up_extended_ref_temp (tree decl, tree expr, VEC(tree,gc) **cleanups,
if (TREE_CODE (expr) != TARGET_EXPR)
expr = get_target_expr (expr);
+ if (TREE_CODE (decl) == FIELD_DECL
+ && extra_warnings && !TREE_NO_WARNING (decl))
+ {
+ warning (OPT_Wextra, "a temporary bound to %qD only persists "
+ "until the constructor exits", decl);
+ TREE_NO_WARNING (decl) = true;
+ }
+
/* Recursively extend temps in this initializer. */
TARGET_EXPR_INITIAL (expr)
= extend_ref_init_temps (decl, TARGET_EXPR_INITIAL (expr), cleanups);
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 77fe42e..5c20e32 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -599,7 +599,7 @@ perform_member_init (tree member, tree init)
if (init == error_mark_node)
return;
/* Use 'this' as the decl, as it has the lifetime we want. */
- init = extend_ref_init_temps (current_class_ptr, init, &cleanups);
+ init = extend_ref_init_temps (member, init, &cleanups);
if (TREE_CODE (type) == ARRAY_TYPE
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (type)))
init = build_vec_init_expr (type, init, tf_warning_or_error);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 0582e49..4c44603 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,5 +1,8 @@
2011-11-12 Jason Merrill <jason@redhat.com>
+ PR c++/986
+ * g++.dg/warn/ref-temp1.C: New.
+
PR c++/51060
* g++.dg/opt/stack2.C: New.
diff --git a/gcc/testsuite/g++.dg/warn/ref-temp1.C b/gcc/testsuite/g++.dg/warn/ref-temp1.C
new file mode 100644
index 0000000..26f1ca5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/ref-temp1.C
@@ -0,0 +1,11 @@
+// PR c++/986
+// { dg-options "-Wall -Wextra" }
+
+struct X { X (int); };
+
+struct Y {
+ Y ();
+ const X &x; // note the ampersand
+};
+
+Y::Y () : x(1) {} // { dg-warning "temporary" }