aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/typeck.c26
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/warn/effc2.C39
4 files changed, 73 insertions, 3 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8b0bc21..8aa6b1c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2004-07-08 Giovanni Bajo <giovannibajo@gcc.gnu.org>
+
+ PR c++/16169
+ * typeck.c (check_return_expr): Improve -Weffc++ warning: handle
+ returning CALL_EXPR, and non-reference return type.
+
2004-07-08 Nathan Sidwell <nathan@codesourcery.com>
* name-lookup.c (push_binding): Use VEC_reserve.
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 1588cbc..55b3ef3 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -5989,9 +5989,29 @@ check_return_expr (tree retval)
/* Effective C++ rule 15. See also start_function. */
if (warn_ecpp
- && DECL_NAME (current_function_decl) == ansi_assopname(NOP_EXPR)
- && retval != current_class_ref)
- warning ("`operator=' should return a reference to `*this'");
+ && DECL_NAME (current_function_decl) == ansi_assopname(NOP_EXPR))
+ {
+ bool warn = true;
+
+ /* The function return type must be a reference to the current
+ class. */
+ if (TREE_CODE (valtype) == REFERENCE_TYPE
+ && same_type_ignoring_top_level_qualifiers_p
+ (TREE_TYPE (valtype), TREE_TYPE (current_class_ref)))
+ {
+ /* Returning '*this' is obviously OK. */
+ if (retval == current_class_ref)
+ warn = false;
+ /* If we are calling a function whose return type is the same of
+ the current class reference, it is ok. */
+ else if (TREE_CODE (retval) == INDIRECT_REF
+ && TREE_CODE (TREE_OPERAND (retval, 0)) == CALL_EXPR)
+ warn = false;
+ }
+
+ if (warn)
+ warning ("`operator=' should return a reference to `*this'");
+ }
/* The fabled Named Return Value optimization, as per [class.copy]/15:
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 54be7f9..1a3e2c0 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2004-07-08 Giovanni Bajo <giovannibajo@gcc.gnu.org>
+
+ PR c++/16169
+ * g++.dg/warn/effc2.C: New test.
+
2004-07-08 Joseph S. Myers <jsm@polyomino.org.uk>
* gcc.c-torture/execute/bitfld-1.x: Remove.
diff --git a/gcc/testsuite/g++.dg/warn/effc2.C b/gcc/testsuite/g++.dg/warn/effc2.C
new file mode 100644
index 0000000..fb765f0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/effc2.C
@@ -0,0 +1,39 @@
+// { dg-do compile }
+// { dg-options "-Weffc++" }
+// Contributed by Benjamin Kosnik <bkoz at redhat dot com>
+// PR c++/16169 : Improve -Weffc++ rule 15
+
+struct A {
+ const A& foo();
+ const A& operator=(int)
+ { return foo(); }
+};
+
+struct B {
+ B& foo();
+ B& operator=(int)
+ { return foo(); }
+};
+
+struct C {
+ C& operator=(int)
+ { return *this; }
+};
+
+struct D {
+ D operator=(int)
+ { return *this; } // { dg-warning "should return a reference" }
+};
+
+struct E {
+ E& foo();
+ E operator=(int)
+ { return foo(); } // { dg-warning "should return a reference" }
+};
+
+struct F
+{
+ operator float();
+ float operator=(int)
+ { return *this; } // { dg-warning "should return a reference" }
+};