]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Add -Wnrvo
authorJason Merrill <jason@redhat.com>
Tue, 6 Jun 2023 16:46:26 +0000 (12:46 -0400)
committerJason Merrill <jason@redhat.com>
Wed, 7 Jun 2023 01:32:23 +0000 (21:32 -0400)
While looking at PRs about cases where we don't perform the named return
value optimization, it occurred to me that it might be useful to have a
warning for that.

This does not fix PR58487, but might be interesting to people watching it.

PR c++/58487

gcc/c-family/ChangeLog:

* c.opt: Add -Wnrvo.

gcc/ChangeLog:

* doc/invoke.texi: Document it.

gcc/cp/ChangeLog:

* typeck.cc (want_nrvo_p): New.
(check_return_expr): Handle -Wnrvo.

gcc/testsuite/ChangeLog:

* g++.dg/opt/nrv25.C: New test.

gcc/c-family/c.opt
gcc/cp/typeck.cc
gcc/doc/invoke.texi
gcc/testsuite/g++.dg/opt/nrv25.C [new file with mode: 0644]

index 3333cddeece7e3920bd903eca7ab5e28411be1d2..cead19955611ba7b2a0c96f203e7370aaa48bee7 100644 (file)
@@ -923,6 +923,10 @@ Wnamespaces
 C++ ObjC++ Var(warn_namespaces) Warning
 Warn on namespace definition.
 
+Wnrvo
+C++ ObjC++ Var(warn_nrvo)
+Warn if the named return value optimization is not performed although it is allowed.
+
 Wpacked-not-aligned
 C ObjC C++ ObjC++ Var(warn_packed_not_aligned) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
 Warn when fields in a struct with the packed attribute are misaligned.
index 11fcc7fcd3b35df92906e0bd72811dac43ae9e9c..6b5705e806dae6f583c2685d1e9297abb5773d8e 100644 (file)
@@ -10670,6 +10670,16 @@ can_do_nrvo_p (tree retval, tree functype)
          && !TYPE_VOLATILE (TREE_TYPE (retval)));
 }
 
+/* True if we would like to perform NRVO, i.e. can_do_nrvo_p is true and we
+   would otherwise return in memory.  */
+
+static bool
+want_nrvo_p (tree retval, tree functype)
+{
+  return (can_do_nrvo_p (retval, functype)
+         && aggregate_value_p (functype, current_function_decl));
+}
+
 /* Like can_do_nrvo_p, but we check if we're trying to move a class
    prvalue.  */
 
@@ -11151,7 +11161,7 @@ check_return_expr (tree retval, bool *no_warning)
       bare_retval = tree_strip_any_location_wrapper (retval);
     }
 
-  bool named_return_value_okay_p = can_do_nrvo_p (bare_retval, functype);
+  bool named_return_value_okay_p = want_nrvo_p (bare_retval, functype);
   if (fn_returns_value_p && flag_elide_constructors)
     {
       if (named_return_value_okay_p
@@ -11159,7 +11169,18 @@ check_return_expr (tree retval, bool *no_warning)
              || current_function_return_value == bare_retval))
        current_function_return_value = bare_retval;
       else
-       current_function_return_value = error_mark_node;
+       {
+         if ((named_return_value_okay_p
+              || (current_function_return_value
+                  && current_function_return_value != error_mark_node))
+             && !warning_suppressed_p (current_function_decl, OPT_Wnrvo))
+           {
+             warning (OPT_Wnrvo, "not eliding copy on return in %qD",
+                      current_function_decl);
+             suppress_warning (current_function_decl, OPT_Wnrvo);
+           }
+         current_function_return_value = error_mark_node;
+       }
     }
 
   /* We don't need to do any conversions when there's nothing being
index 9130104af22aedcb942179cbf622e42aa19d69a7..6d08229ce403620ba8d1e3f63d770b0e69b4d5e7 100644 (file)
@@ -6678,6 +6678,25 @@ is only active when @option{-fdelete-null-pointer-checks} is active,
 which is enabled by optimizations in most targets.  The precision of
 the warnings depends on the optimization options used.
 
+@opindex Wnrvo
+@opindex Wno-nrvo
+@item -Wnrvo @r{(C++ and Objective-C++ only)}
+Warn if the compiler does not elide the copy from a local variable to
+the return value of a function in a context where it is allowed by
+[class.copy.elision].  This elision is commonly known as the Named
+Return Value Optimization.  For instance, in the example below the
+compiler cannot elide copies from both v1 and b2, so it elides neither.
+
+@smallexample
+std::vector<int> f()
+@{
+  std::vector<int> v1, v2;
+  // ...
+  if (cond) return v1;
+  else return v2; // warning: not eliding copy
+@}
+@end smallexample
+
 @opindex Winfinite-recursion
 @opindex Wno-infinite-recursion
 @item -Winfinite-recursion
diff --git a/gcc/testsuite/g++.dg/opt/nrv25.C b/gcc/testsuite/g++.dg/opt/nrv25.C
new file mode 100644 (file)
index 0000000..35c4a88
--- /dev/null
@@ -0,0 +1,15 @@
+// PR c++/58487
+// { dg-additional-options -Wnrvo }
+
+struct A {
+  A() {}
+  A(const A&);
+};
+
+A test() {
+  A a, b;
+  if (true)
+    return a;
+  else
+    return b;                  // { dg-warning Wnrvo }
+}