re PR c++/16169 (-Weffc++ item 15 improvements)
authorGiovanni Bajo <giovannibajo@gcc.gnu.org>
Thu, 8 Jul 2004 10:03:59 +0000 (10:03 +0000)
committerGiovanni Bajo <giovannibajo@gcc.gnu.org>
Thu, 8 Jul 2004 10:03:59 +0000 (10:03 +0000)
PR c++/16169
* typeck.c (check_return_expr): Improve -Weffc++ warning: handle
returning CALL_EXPR, and non-reference return type.

PR c++/16169
* g++.dg/warn/effc2.C: New test.

From-SVN: r84283

gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/warn/effc2.C [new file with mode: 0644]

index 8b0bc21a1fe719e859de28bbaf1bbf88e395b944..8aa6b1c34b9bdb69bf8e56b03ebbf82974556c54 100644 (file)
@@ -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.
index 1588cbceebe27be87d794f1d8397c51640396d1d..55b3ef3bc57574017f17cdd40089abd9976fe15c 100644 (file)
@@ -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;\r
+       }
+
+      if (warn)
+       warning ("`operator=' should return a reference to `*this'");
+    }
 
   /* The fabled Named Return Value optimization, as per [class.copy]/15:
 
index 54be7f9605d4f0ff3efef45ab0a90bbeccb184a7..1a3e2c09e711a12e248b9d65dfe4d94a9cd52f5a 100644 (file)
@@ -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 (file)
index 0000000..fb765f0
--- /dev/null
@@ -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" }
+};