aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2024-07-31 17:33:55 -0400
committerMarek Polacek <polacek@redhat.com>2024-08-05 12:17:02 -0400
commit34d947134403e7482ba4f153d8faabee0bc4933e (patch)
tree088a5357017e8d99f05f922004138dff7605249e /gcc
parentc26534d21159dd4c5d1472f0050b65e148161691 (diff)
downloadgcc-34d947134403e7482ba4f153d8faabee0bc4933e.zip
gcc-34d947134403e7482ba4f153d8faabee0bc4933e.tar.gz
gcc-34d947134403e7482ba4f153d8faabee0bc4933e.tar.bz2
c++: fix -Wdangling-reference false positive [PR115987]
This fixes another false positive. When a function is taking a temporary of scalar type that couldn't be bound to the return type of the function, don't warn, such a program would be ill-formed. Thanks to Jonathan for reporting the problem. PR c++/115987 gcc/cp/ChangeLog: * call.cc (do_warn_dangling_reference): Don't consider a temporary with a scalar type that cannot bind to the return type. gcc/testsuite/ChangeLog: * g++.dg/ext/attr-no-dangling6.C: Adjust. * g++.dg/ext/attr-no-dangling7.C: Likewise. * g++.dg/warn/Wdangling-reference22.C: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/call.cc14
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-no-dangling6.C22
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-no-dangling7.C8
-rw-r--r--gcc/testsuite/g++.dg/warn/Wdangling-reference22.C19
4 files changed, 46 insertions, 17 deletions
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 40cb582..a75e2e5 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -14290,8 +14290,18 @@ do_warn_dangling_reference (tree expr, bool arg_p)
/* Recurse to see if the argument is a temporary. It could also
be another call taking a temporary and returning it and
initializing this reference parameter. */
- if (do_warn_dangling_reference (arg, /*arg_p=*/true))
- return expr;
+ if ((arg = do_warn_dangling_reference (arg, /*arg_p=*/true)))
+ {
+ /* If we know the temporary could not bind to the return type,
+ don't warn. This is for scalars only because for classes
+ we can't be sure we are not returning its sub-object. */
+ if (SCALAR_TYPE_P (TREE_TYPE (arg))
+ && TYPE_REF_P (rettype)
+ && !reference_related_p (TREE_TYPE (arg),
+ TREE_TYPE (rettype)))
+ continue;
+ return expr;
+ }
/* Don't warn about member functions like:
std::any a(...);
S& s = a.emplace<S>({0}, 0);
diff --git a/gcc/testsuite/g++.dg/ext/attr-no-dangling6.C b/gcc/testsuite/g++.dg/ext/attr-no-dangling6.C
index 235a5fd..5b349e8 100644
--- a/gcc/testsuite/g++.dg/ext/attr-no-dangling6.C
+++ b/gcc/testsuite/g++.dg/ext/attr-no-dangling6.C
@@ -12,26 +12,26 @@ struct SF { static constexpr bool value = false; };
template<typename T>
[[gnu::no_dangling(T::value)]]
-const X& get (const int& i)
+const X& get (const int& i, const X&)
{
return i == 0 ? x1 : x2;
}
template<bool B = true>
[[gnu::no_dangling(B)]]
-const X& foo (const int& i)
+const X& foo (const int& i, const X&)
{
return i == 0 ? x1 : x2;
}
[[gnu::no_dangling(val ())]]
-const X& bar (const int& i)
+const X& bar (const int& i, const X&)
{
return i == 0 ? x1 : x2;
}
[[gnu::no_dangling(!val ())]]
-const X& baz (const int& i)
+const X& baz (const int& i, const X&)
{
return i == 0 ? x1 : x2;
}
@@ -52,13 +52,13 @@ auto gety() -> Span<SF>;
void
test ()
{
- [[maybe_unused]] const X& x1 = get<ST> (10); // { dg-bogus "dangling" }
- [[maybe_unused]] const X& x2 = get<SF> (10); // { dg-warning "dangling" }
- [[maybe_unused]] const X& x3 = foo<true> (10); // { dg-bogus "dangling" }
- [[maybe_unused]] const X& x4 = foo<false> (10); // { dg-warning "dangling" }
- [[maybe_unused]] const X& x7 = foo<> (10); // { dg-bogus "dangling" }
- [[maybe_unused]] const X& x5 = bar (10); // { dg-bogus "dangling" }
- [[maybe_unused]] const X& x6 = baz (10); // { dg-warning "dangling" }
+ [[maybe_unused]] const X& x1 = get<ST> (10, X{}); // { dg-bogus "dangling" }
+ [[maybe_unused]] const X& x2 = get<SF> (10, X{}); // { dg-warning "dangling" }
+ [[maybe_unused]] const X& x3 = foo<true> (10, X{}); // { dg-bogus "dangling" }
+ [[maybe_unused]] const X& x4 = foo<false> (10, X{}); // { dg-warning "dangling" }
+ [[maybe_unused]] const X& x7 = foo<> (10, X{}); // { dg-bogus "dangling" }
+ [[maybe_unused]] const X& x5 = bar (10, X{}); // { dg-bogus "dangling" }
+ [[maybe_unused]] const X& x6 = baz (10, X{}); // { dg-warning "dangling" }
[[maybe_unused]] const auto &b1 = geti()[0]; // { dg-bogus "dangling" }
[[maybe_unused]] const auto &b2 = gety()[0]; // { dg-warning "dangling" }
diff --git a/gcc/testsuite/g++.dg/ext/attr-no-dangling7.C b/gcc/testsuite/g++.dg/ext/attr-no-dangling7.C
index 3c392ed..a5fb809 100644
--- a/gcc/testsuite/g++.dg/ext/attr-no-dangling7.C
+++ b/gcc/testsuite/g++.dg/ext/attr-no-dangling7.C
@@ -16,16 +16,16 @@ const X& foo(const int& i);
bool val () { return true; }
[[gnu::no_dangling(val ())]] // { dg-error "call" }
-const X& bar (const int& i);
+const X& bar (const int& i, const X&);
-[[gnu::no_dangling(20)]] const X& fn1 (const int &);
+[[gnu::no_dangling(20)]] const X& fn1 (const int &, const X&);
void
test ()
{
- [[maybe_unused]] const X& x1 = bar (10); // { dg-warning "dangling" }
+ [[maybe_unused]] const X& x1 = bar (10, X{}); // { dg-warning "dangling" }
[[maybe_unused]] const X& x2 = foo<int> (10); // { dg-error "no matching" }
[[maybe_unused]] const X& x3 // { dg-warning "dangling" }
- = fn1 (10); // { dg-error "narrowing" }
+ = fn1 (10, X{}); // { dg-error "narrowing" }
}
diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-reference22.C b/gcc/testsuite/g++.dg/warn/Wdangling-reference22.C
new file mode 100644
index 0000000..0381f93
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wdangling-reference22.C
@@ -0,0 +1,19 @@
+// PR c++/115987
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wdangling-reference" }
+
+template <typename T>
+struct Wrapper {
+ T val;
+};
+
+template <typename T, typename FUNC>
+ const T& unwrap_2(const Wrapper<T>& r, FUNC&&) {
+ return r.val;
+}
+
+int main(int, char**) {
+ const Wrapper<int> w{1234};
+ const auto& u = unwrap_2(w, 1L); // { dg-bogus "dangling reference" }
+ __builtin_printf("Unwrapped value : %d\n", u);
+}