typeck.c (decl_in_std_namespace_p): Return true also for decls in inline namespaces...
authorJakub Jelinek <jakub@redhat.com>
Wed, 30 Oct 2019 21:53:37 +0000 (22:53 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 30 Oct 2019 21:53:37 +0000 (22:53 +0100)
* typeck.c (decl_in_std_namespace_p): Return true also for decls
in inline namespaces inside of std namespace.

* g++.dg/cpp0x/Wpessimizing-move6.C: New test.

From-SVN: r277648

gcc/cp/ChangeLog
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move6.C [new file with mode: 0644]

index 402d321d0e7488785d41c481b39611e031b9b4b6..46b8fe02907dffab3b96cefc50343037966b00aa 100644 (file)
@@ -1,3 +1,8 @@
+2019-10-30  Jakub Jelinek  <jakub@redhat.com>
+
+       * typeck.c (decl_in_std_namespace_p): Return true also for decls
+       in inline namespaces inside of std namespace.
+
 2019-10-30  Bernd Edlinger  <bernd.edlinger@hotmail.de>
 
        PR c++/92024
index 477c6a3995520ee8948bf2d40ac328478638cbc4..03c39b3e3b92d434074d935c1aa8c017f0748d72 100644 (file)
@@ -9395,8 +9395,19 @@ maybe_warn_about_returning_address_of_local (tree retval)
 bool
 decl_in_std_namespace_p (tree decl)
 {
-  return (decl != NULL_TREE
-         && DECL_NAMESPACE_STD_P (decl_namespace_context (decl)));
+  while (decl)
+    {
+      decl = decl_namespace_context (decl);
+      if (DECL_NAMESPACE_STD_P (decl))
+       return true;
+      /* Allow inline namespaces inside of std namespace, e.g. with
+        --enable-symvers=gnu-versioned-namespace std::forward would be
+        actually std::_8::forward.  */
+      if (!DECL_NAMESPACE_INLINE_P (decl))
+       return false;
+      decl = CP_DECL_CONTEXT (decl);
+    }
+  return false;
 }
 
 /* Returns true if FN, a CALL_EXPR, is a call to std::forward.  */
index 67de104fb1d43ee86b48846268eb3cb7c58526e3..d64275b8ea56dbc7f2ac98902669362b25e9735d 100644 (file)
@@ -1,3 +1,7 @@
+2019-10-30  Jakub Jelinek  <jakub@redhat.com>
+
+       * g++.dg/cpp0x/Wpessimizing-move6.C: New test.
+
 2019-10-30  Bernd Edlinger  <bernd.edlinger@hotmail.de>
 
        PR c++/92024
diff --git a/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move6.C b/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move6.C
new file mode 100644 (file)
index 0000000..6467556
--- /dev/null
@@ -0,0 +1,135 @@
+// PR c++/86981
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wpessimizing-move" }
+
+// Define std::move.
+namespace std {
+  inline namespace _8 { }
+  namespace _8 {
+    template<typename _Tp>
+      struct remove_reference
+      { typedef _Tp   type; };
+
+    template<typename _Tp>
+      struct remove_reference<_Tp&>
+      { typedef _Tp   type; };
+
+    template<typename _Tp>
+      struct remove_reference<_Tp&&>
+      { typedef _Tp   type; };
+
+    template<typename _Tp>
+      constexpr typename std::remove_reference<_Tp>::type&&
+      move(_Tp&& __t) noexcept
+      { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); }
+  }
+}
+
+struct T {
+  T() { }
+  T(const T&) { }
+  T(T&&) { }
+};
+struct U {
+  U() { }
+  U(const U&) { }
+  U(U&&) { }
+  U(T) { }
+};
+
+T g;
+
+T
+fn1 ()
+{
+  T t;
+  return std::move (t); // { dg-warning "moving a local object in a return statement prevents copy elision" }
+}
+
+T
+fn2 ()
+{
+  // Not a local variable.
+  return std::move (g);
+}
+
+int
+fn3 ()
+{
+  int i = 42;
+  // Not a class type.
+  return std::move (i);
+}
+
+T
+fn4 (bool b)
+{
+  T t;
+  if (b)
+    throw std::move (t);
+  return std::move (t); // { dg-warning "moving a local object in a return statement prevents copy elision" }
+}
+
+T
+fn5 (T t)
+{
+  // Function parameter; std::move is redundant but not pessimizing.
+  return std::move (t);
+}
+
+U
+fn6 (T t, U u, bool b)
+{
+  if (b)
+    return std::move (t);
+  else
+    // Function parameter; std::move is redundant but not pessimizing.
+    return std::move (u);
+}
+
+U
+fn6 (bool b)
+{
+  T t;
+  U u;
+  if (b)
+    return std::move (t);
+  else
+    return std::move (u); // { dg-warning "moving a local object in a return statement prevents copy elision" }
+}
+
+T
+fn7 ()
+{
+  static T t;
+  // Non-local; don't warn.
+  return std::move (t);
+}
+
+T
+fn8 ()
+{
+  return T();
+}
+
+T
+fn9 (int i)
+{
+  T t;
+
+  switch (i)
+    {
+    case 1:
+      return std::move ((t)); // { dg-warning "moving a local object in a return statement prevents copy elision" }
+    case 2:
+      return (std::move (t)); // { dg-warning "moving a local object in a return statement prevents copy elision" }
+    default:
+      return (std::move ((t))); // { dg-warning "moving a local object in a return statement prevents copy elision" }
+    }
+}
+
+int
+fn10 ()
+{
+  return std::move (42);
+}