#include "file-prefix-map.h"
#include "cgraph.h"
#include "omp-general.h"
+#include "opts.h"
/* Forward declarations. */
case CALL_EXPR:
{
- int sv = optimize, nw = sv;
tree callee = get_callee_fndecl (x);
+ /* "Inline" calls to std::move/forward and other cast-like functions
+ by simply folding them into a corresponding cast to their return
+ type. This is cheaper than relying on the middle end to do so, and
+ also means we avoid generating useless debug info for them at all.
+
+ At this point the argument has already been converted into a
+ reference, so it suffices to use a NOP_EXPR to express the
+ cast. */
+ if ((OPTION_SET_P (flag_fold_simple_inlines)
+ ? flag_fold_simple_inlines
+ : !flag_no_inline)
+ && call_expr_nargs (x) == 1
+ && decl_in_std_namespace_p (callee)
+ && DECL_NAME (callee) != NULL_TREE
+ && (id_equal (DECL_NAME (callee), "move")
+ || id_equal (DECL_NAME (callee), "forward")
+ || id_equal (DECL_NAME (callee), "addressof")
+ /* This addressof equivalent is used heavily in libstdc++. */
+ || id_equal (DECL_NAME (callee), "__addressof")
+ || id_equal (DECL_NAME (callee), "as_const")))
+ {
+ r = CALL_EXPR_ARG (x, 0);
+ /* Check that the return and argument types are sane before
+ folding. */
+ if (INDIRECT_TYPE_P (TREE_TYPE (x))
+ && INDIRECT_TYPE_P (TREE_TYPE (r)))
+ {
+ if (!same_type_p (TREE_TYPE (x), TREE_TYPE (r)))
+ r = build_nop (TREE_TYPE (x), r);
+ x = cp_fold (r);
+ break;
+ }
+ }
+
+ int sv = optimize, nw = sv;
+
/* Some built-in function calls will be evaluated at compile-time in
fold (). Set optimize to 1 when folding __builtin_constant_p inside
a constexpr function so that fold_builtin_1 doesn't fold it to 0. */
@option{-fextern-tls-init}. On targets that do not support symbol
aliases, the default is @option{-fno-extern-tls-init}.
+@item -ffold-simple-inlines
+@itemx -fno-fold-simple-inlines
+@opindex ffold-simple-inlines
+@opindex fno-fold-simple-inlines
+Permit the C++ frontend to fold calls to @code{std::move}, @code{std::forward},
+@code{std::addressof} and @code{std::as_const}. In contrast to inlining, this
+means no debug information will be generated for such calls. Since these
+functions are rarely interesting to debug, this flag is enabled by default
+unless @option{-fno-inline} is active.
+
@item -fno-gnu-keywords
@opindex fno-gnu-keywords
@opindex fgnu-keywords
--- /dev/null
+// PR c++/96780
+// Verify calls to std::move/forward are folded away by the frontend.
+// { dg-do compile { target c++11 } }
+// { dg-additional-options "-ffold-simple-inlines -fdump-tree-gimple" }
+
+#include <utility>
+
+struct A;
+
+extern A& a;
+extern const A& ca;
+
+void f() {
+ auto&& x1 = std::move(a);
+ auto&& x2 = std::forward<A>(a);
+ auto&& x3 = std::forward<A&>(a);
+
+ auto&& x4 = std::move(ca);
+ auto&& x5 = std::forward<const A>(ca);
+ auto&& x6 = std::forward<const A&>(ca);
+
+ auto x7 = std::addressof(a);
+ auto x8 = std::addressof(ca);
+#if __GLIBCXX__
+ auto x9 = std::__addressof(a);
+ auto x10 = std::__addressof(ca);
+#endif
+#if __cpp_lib_as_const
+ auto&& x11 = std::as_const(a);
+ auto&& x12 = std::as_const(ca);
+#endif
+}
+
+// { dg-final { scan-tree-dump-not "= std::move" "gimple" } }
+// { dg-final { scan-tree-dump-not "= std::forward" "gimple" } }
+// { dg-final { scan-tree-dump-not "= std::addressof" "gimple" } }
+// { dg-final { scan-tree-dump-not "= std::__addressof" "gimple" } }
+// { dg-final { scan-tree-dump-not "= std::as_const" "gimple" } }