aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2024-01-19 13:59:41 -0500
committerMarek Polacek <polacek@redhat.com>2024-01-23 16:35:31 -0500
commit9010fdba68063beccfbab0aa9ec8739f232ca2f4 (patch)
tree28a49f0ba5a0ff17670eeb1a57173309e5f6997a
parented4c7893de2cbae0a07bb4984e408d57e6db06f3 (diff)
downloadgcc-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.
-rw-r--r--gcc/cp/call.cc9
-rw-r--r--gcc/testsuite/g++.dg/warn/Wdangling-reference14.C22
-rw-r--r--gcc/testsuite/g++.dg/warn/Wdangling-reference15.C31
-rw-r--r--gcc/testsuite/g++.dg/warn/Wdangling-reference16.C13
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;
+}