diff options
author | Jakub Jelinek <jakub@redhat.com> | 2019-10-30 22:53:37 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2019-10-30 22:53:37 +0100 |
commit | 97ccc60e0c8590e22488e909464fc591eb8b0534 (patch) | |
tree | 6d7895cc261bb7068a1a75e285b8cd06adf2cfdf /gcc | |
parent | e0d91792eec490d1bddb4a095a3da2c5b4c270e2 (diff) | |
download | gcc-97ccc60e0c8590e22488e909464fc591eb8b0534.zip gcc-97ccc60e0c8590e22488e909464fc591eb8b0534.tar.gz gcc-97ccc60e0c8590e22488e909464fc591eb8b0534.tar.bz2 |
typeck.c (decl_in_std_namespace_p): Return true also for decls in inline namespaces inside of std namespace.
* 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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 15 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move6.C | 135 |
4 files changed, 157 insertions, 2 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 402d321..46b8fe0 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 477c6a3..03c39b3 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 67de104..d64275b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..6467556 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/Wpessimizing-move6.C @@ -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); +} |