From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1734) id 55D8E3858420; Tue, 23 Jan 2024 21:36:03 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 55D8E3858420 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1706045763; bh=vhVzVnTbR+cZ32VNDwpT2OgigVvlWkBXE4VNCLcXBsQ=; h=From:To:Subject:Date:From; b=YfpepDljLroTvsVeAl+vJL7sh0G/lJDqkhK1uw637dY+AUIGS9k6hZLY9Hwj1pNL0 pAIuWwwZstQIyNEEnVKCONgImV7tQcisQy2jJIG4/IfiTYDi5xX8yDAoy0vzNyghO9 D2m+8LCJqUxfNsB7SXcCv/stu//ldMQYUO4ep9oo= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Marek Polacek To: gcc-cvs@gcc.gnu.org Subject: [gcc r14-8375] c++: -Wdangling-reference and lambda false warning [PR109640] X-Act-Checkin: gcc X-Git-Author: Marek Polacek X-Git-Refname: refs/heads/trunk X-Git-Oldrev: ed4c7893de2cbae0a07bb4984e408d57e6db06f3 X-Git-Newrev: 9010fdba68063beccfbab0aa9ec8739f232ca2f4 Message-Id: <20240123213603.55D8E3858420@sourceware.org> Date: Tue, 23 Jan 2024 21:36:03 +0000 (GMT) List-Id: https://gcc.gnu.org/g:9010fdba68063beccfbab0aa9ec8739f232ca2f4 commit r14-8375-g9010fdba68063beccfbab0aa9ec8739f232ca2f4 Author: Marek Polacek Date: Fri Jan 19 13:59:41 2024 -0500 c++: -Wdangling-reference and lambda false warning [PR109640] -Wdangling-reference checks if a function receives a temporary as its argument, and only warns if any of the arguments was a temporary. But we should not warn when the temporary represents a lambda or we generate false positives as in the attached testcases. PR c++/113256 PR c++/111607 PR c++/109640 gcc/cp/ChangeLog: * call.cc (do_warn_dangling_reference): Don't warn if the temporary is of lambda type. gcc/testsuite/ChangeLog: * g++.dg/warn/Wdangling-reference14.C: New test. * g++.dg/warn/Wdangling-reference15.C: New test. * g++.dg/warn/Wdangling-reference16.C: New test. Diff: --- gcc/cp/call.cc | 9 ++++--- gcc/testsuite/g++.dg/warn/Wdangling-reference14.C | 22 ++++++++++++++++ gcc/testsuite/g++.dg/warn/Wdangling-reference15.C | 31 +++++++++++++++++++++++ gcc/testsuite/g++.dg/warn/Wdangling-reference16.C | 13 ++++++++++ 4 files changed, 72 insertions(+), 3 deletions(-) diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 1f5ff417c81..77f51bacce3 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -14123,7 +14123,10 @@ do_warn_dangling_reference (tree expr, bool arg_p) tree e = expr; while (handled_component_p (e)) e = TREE_OPERAND (e, 0); - if (!reference_like_class_p (TREE_TYPE (e))) + tree type = TREE_TYPE (e); + /* If the temporary represents a lambda, we don't really know + what's going on here. */ + if (!reference_like_class_p (type) && !LAMBDA_TYPE_P (type)) return expr; } @@ -14180,10 +14183,10 @@ do_warn_dangling_reference (tree expr, bool arg_p) initializing this reference parameter. */ if (do_warn_dangling_reference (arg, /*arg_p=*/true)) return expr; - /* Don't warn about member function like: + /* Don't warn about member functions like: std::any a(...); S& s = a.emplace({0}, 0); - which constructs a new object and returns a reference to it, but + which construct a new object and return a reference to it, but we still want to detect: struct S { const S& self () { return *this; } }; const S& s = S().self(); diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-reference14.C b/gcc/testsuite/g++.dg/warn/Wdangling-reference14.C new file mode 100644 index 00000000000..92b38a965e0 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wdangling-reference14.C @@ -0,0 +1,22 @@ +// PR c++/113256 +// { dg-do compile { target c++14 } } +// { dg-options "-Wdangling-reference" } + +#include +#include + +template auto bind(M T::* pm, A) +{ + return [=]( auto&& x ) -> M const& { return x.*pm; }; +} + +template struct arg {}; + +arg<1> _1; + +int main() +{ + std::pair pair; + int const& x = bind( &std::pair::first, _1 )( pair ); // { dg-bogus "dangling reference" } + assert( &x == &pair.first ); +} diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-reference15.C b/gcc/testsuite/g++.dg/warn/Wdangling-reference15.C new file mode 100644 index 00000000000..c39577db64a --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wdangling-reference15.C @@ -0,0 +1,31 @@ +// PR c++/111607 +// { dg-do compile { target c++20 } } +// { dg-options "-Wdangling-reference" } + +#include + +struct S { + constexpr S(int i_) : i(i_) {} + S(S const &) = delete; + S & operator=(S const &) = delete; + S(S &&) = delete; + S & operator=(S &&) = delete; + int i; +}; + +struct A { + S s{0}; +}; + +using V = std::variant; + +consteval auto f(V const & v) { + auto const & s = std::visit([](auto const & v) -> S const & { return v.s; }, v); // { dg-bogus "dangling reference" } + return s.i; +} + +int main() { + constexpr V a{std::in_place_type}; + constexpr auto i = f(a); + return i; +} diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-reference16.C b/gcc/testsuite/g++.dg/warn/Wdangling-reference16.C new file mode 100644 index 00000000000..91996922291 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wdangling-reference16.C @@ -0,0 +1,13 @@ +// PR c++/109640 +// { dg-do compile { target c++11 } } +// { dg-options "-Wdangling-reference" } + +bool +fn0 () +{ + int a; + int&& i = [](int& r) -> int&& { return static_cast(r); }(a); // { dg-bogus "dangling reference" } + auto const l = [](int& r) -> int&& { return static_cast(r); }; + int&& j = l(a); + return &i == &j; +}