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.
This commit is contained in:
parent
ed4c7893de
commit
9010fdba68
4 changed files with 72 additions and 3 deletions
|
@ -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();
|
||||
|
|
22
gcc/testsuite/g++.dg/warn/Wdangling-reference14.C
Normal file
22
gcc/testsuite/g++.dg/warn/Wdangling-reference14.C
Normal file
|
@ -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 );
|
||||
}
|
31
gcc/testsuite/g++.dg/warn/Wdangling-reference15.C
Normal file
31
gcc/testsuite/g++.dg/warn/Wdangling-reference15.C
Normal file
|
@ -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;
|
||||
}
|
13
gcc/testsuite/g++.dg/warn/Wdangling-reference16.C
Normal file
13
gcc/testsuite/g++.dg/warn/Wdangling-reference16.C
Normal file
|
@ -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;
|
||||
}
|
Loading…
Add table
Reference in a new issue