diff options
author | Marek Polacek <polacek@redhat.com> | 2024-01-19 13:59:41 -0500 |
---|---|---|
committer | Marek Polacek <polacek@redhat.com> | 2024-01-23 16:35:31 -0500 |
commit | 9010fdba68063beccfbab0aa9ec8739f232ca2f4 (patch) | |
tree | 28a49f0ba5a0ff17670eeb1a57173309e5f6997a /gcc | |
parent | ed4c7893de2cbae0a07bb4984e408d57e6db06f3 (diff) | |
download | gcc-9010fdba68063beccfbab0aa9ec8739f232ca2f4.zip gcc-9010fdba68063beccfbab0aa9ec8739f232ca2f4.tar.gz gcc-9010fdba68063beccfbab0aa9ec8739f232ca2f4.tar.bz2 |
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.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/call.cc | 9 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/Wdangling-reference14.C | 22 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/Wdangling-reference15.C | 31 | ||||
-rw-r--r-- | 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 1f5ff41..77f51ba 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<S>({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 0000000..92b38a9 --- /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 <utility> +#include <cassert> + +template<class M, class T, class A> auto bind(M T::* pm, A) +{ + return [=]( auto&& x ) -> M const& { return x.*pm; }; +} + +template<int I> struct arg {}; + +arg<1> _1; + +int main() +{ + std::pair<int, int> pair; + int const& x = bind( &std::pair<int, int>::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 0000000..c39577d --- /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 <variant> + +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<A>; + +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<A>}; + 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 0000000..9199692 --- /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<int&&>(r); }(a); // { dg-bogus "dangling reference" } + auto const l = [](int& r) -> int&& { return static_cast<int&&>(r); }; + int&& j = l(a); + return &i == &j; +} |