Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?

-- >8 --
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/warn/Wdangling-reference22.C: New test.
---
 gcc/cp/call.cc                                | 15 +++++++++++++--
 .../g++.dg/warn/Wdangling-reference22.C       | 19 +++++++++++++++++++
 2 files changed, 32 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/warn/Wdangling-reference22.C

diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 40cb582acc7..375256ebcc4 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -14290,8 +14290,19 @@ 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)
+                   && SCALAR_TYPE_P (TREE_TYPE (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/warn/Wdangling-reference22.C 
b/gcc/testsuite/g++.dg/warn/Wdangling-reference22.C
new file mode 100644
index 00000000000..0381f9313fb
--- /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);
+}

base-commit: 1f53319cae81aea438b6c0ba55f49e5669acf1c8
-- 
2.45.2

Reply via email to