* [pushed] c++: Add -Wnrvo
@ 2023-06-07 1:33 Jason Merrill
0 siblings, 0 replies; only message in thread
From: Jason Merrill @ 2023-06-07 1:33 UTC (permalink / raw)
To: gcc-patches
Tested x86_64-pc-linux-gnu, applying to trunk.
-- 8< --
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/doc/invoke.texi | 19 +++++++++++++++++++
gcc/c-family/c.opt | 4 ++++
gcc/cp/typeck.cc | 25 +++++++++++++++++++++++--
gcc/testsuite/g++.dg/opt/nrv25.C | 15 +++++++++++++++
4 files changed, 61 insertions(+), 2 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/opt/nrv25.C
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 9130104af22..6d08229ce40 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -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/c-family/c.opt b/gcc/c-family/c.opt
index 3333cddeece..cead1995561 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -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.
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 11fcc7fcd3b..6b5705e806d 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -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
diff --git a/gcc/testsuite/g++.dg/opt/nrv25.C b/gcc/testsuite/g++.dg/opt/nrv25.C
new file mode 100644
index 00000000000..35c4a88a088
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/nrv25.C
@@ -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 }
+}
base-commit: 29c82c6ca929e0f5eccfe038dea71177d814c6b7
prerequisite-patch-id: aed53cdac161144c31cb1433282e1ad1d49d3770
prerequisite-patch-id: 1098cb4457a5eff90fa8176f9b0d8d2e9477596e
prerequisite-patch-id: 823f2ce422455c6c7ccbaa9938b670a600b376df
prerequisite-patch-id: 964ab37ff6b24b8fbdc942ff338100c5f5ee6a59
prerequisite-patch-id: fadb6db55b6de5d7d467edeb485770af9f9e0772
--
2.31.1
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2023-06-07 1:33 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-07 1:33 [pushed] c++: Add -Wnrvo Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).