https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77542
Martin Sebor <msebor at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|UNCONFIRMED |RESOLVED CC| |msebor at gcc dot gnu.org Known to work| |7.3.0, 8.2.0, 9.0 Resolution|--- |FIXED Known to fail| |5.3.0, 6.4.0 --- Comment #4 from Martin Sebor <msebor at gcc dot gnu.org> --- After fixing the test in attachment 39608 I get the output below which I think is what the reporter expected. Resolving as fixed. $ cat t.C && xg++ -S -Wall t.C #include <memory> class Foo { public: void close() { } private: int foo; }; struct FooDeleter { void operator()(Foo *foo) { foo->close(); } }; class Test { public: typedef std::unique_ptr<Foo, FooDeleter> BindScope; template <typename... Args> BindScope bind(Args&&... args) __attribute__((warn_unused_result)); BindScope checkWarningInt(int arg) __attribute__((warn_unused_result)); BindScope checkWarningFoo(int arg) __attribute__((warn_unused_result)); operator Foo*() { return m_ptr.get(); } private: std::unique_ptr<Foo> m_ptr; }; template <typename... Args> Test::BindScope Test::bind(Args&&... args) { BindScope bindScope(*this); return std::move(bindScope); } Test::BindScope Test::checkWarningFoo(int arg) { BindScope bindScope(*this); return std::move(bindScope); } Test::BindScope Test::checkWarningInt(int arg) { return 0; } int main(int argc, char *argv[]) { Test t; t.bind(1, "foo"); // no warning <--- that's my bug t.checkWarningFoo(1); // emits warning t.checkWarningInt(1); // emits warning } t.C: In member function ‘Test::BindScope Test::checkWarningFoo(int)’: t.C:38:19: warning: moving a local object in a return statement prevents copy elision [-Wpessimizing-move] 38 | return std::move(bindScope); | ~~~~~~~~~^~~~~~~~~~~ t.C:38:19: note: remove ‘std::move’ call t.C: In function ‘int main(int, char**)’: t.C:47:19: warning: ignoring return value of ‘Test::BindScope Test::bind(Args&& ...) [with Args = {int, const char (&)[4]}; Test::BindScope = std::unique_ptr<Foo, FooDeleter>]’, declared with attribute warn_unused_result [-Wunused-result] 47 | t.bind(1, "foo"); // no warning <--- that's my bug | ^ t.C:31:17: note: declared here 31 | Test::BindScope Test::bind(Args&&... args) { | ^~~~ t.C:48:23: warning: ignoring return value of ‘Test::BindScope Test::checkWarningFoo(int)’, declared with attribute warn_unused_result [-Wunused-result] 48 | t.checkWarningFoo(1); // emits warning | ^ t.C:36:17: note: declared here 36 | Test::BindScope Test::checkWarningFoo(int arg) { | ^~~~ t.C:49:23: warning: ignoring return value of ‘Test::BindScope Test::checkWarningInt(int)’, declared with attribute warn_unused_result [-Wunused-result] 49 | t.checkWarningInt(1); // emits warning | ^ t.C:41:17: note: declared here 41 | Test::BindScope Test::checkWarningInt(int arg) { | ^~~~ t.C: In instantiation of ‘Test::BindScope Test::bind(Args&& ...) [with Args = {int, const char (&)[4]}; Test::BindScope = std::unique_ptr<Foo, FooDeleter>]’: t.C:47:18: required from here t.C:33:29: warning: moving a local object in a return statement prevents copy elision [-Wpessimizing-move] 33 | return std::move(bindScope); | ^ t.C:33:29: note: remove ‘std::move’ call