/* 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);
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;
}
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" }
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" }
}
--- /dev/null
+// 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);
+}