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