Tested x86_64-pc-linux-gnu. Marek, any concerns? -- 8< --
We can't have a dangling reference to an empty class unless it's specifically to that class or one of its bases. This was giving a false positive on the _ExtractKey pattern in libstdc++ hashtable.h. This also adjusts the order of arguments to reference_related_p, which is relevant for empty classes (unlike scalars). Several of the classes in the testsuite needed to gain data members to continue to warn. PR c++/115361 gcc/cp/ChangeLog: * call.cc (do_warn_dangling_reference): Check is_empty_class. gcc/testsuite/ChangeLog: * g++.dg/ext/attr-no-dangling6.C: * g++.dg/ext/attr-no-dangling7.C: * g++.dg/ext/attr-no-dangling8.C: * g++.dg/ext/attr-no-dangling9.C: * g++.dg/warn/Wdangling-reference1.C: * g++.dg/warn/Wdangling-reference2.C: * g++.dg/warn/Wdangling-reference3.C: Make classes non-empty. * g++.dg/warn/Wdangling-reference23.C: New test. --- gcc/cp/call.cc | 12 +++++++----- gcc/testsuite/g++.dg/ext/attr-no-dangling6.C | 6 +++--- gcc/testsuite/g++.dg/ext/attr-no-dangling7.C | 6 +++--- gcc/testsuite/g++.dg/ext/attr-no-dangling8.C | 2 ++ gcc/testsuite/g++.dg/ext/attr-no-dangling9.C | 1 + gcc/testsuite/g++.dg/warn/Wdangling-reference1.C | 1 + gcc/testsuite/g++.dg/warn/Wdangling-reference2.C | 2 +- gcc/testsuite/g++.dg/warn/Wdangling-reference23.C | 14 ++++++++++++++ gcc/testsuite/g++.dg/warn/Wdangling-reference3.C | 1 + 9 files changed, 33 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/g++.dg/warn/Wdangling-reference23.C diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 664088eed9c..1ecf3aac705 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -14356,12 +14356,14 @@ do_warn_dangling_reference (tree expr, bool arg_p) 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)) + don't warn. This is for scalars and empty classes only + because for other classes we can't be sure we are not + returning its sub-object. */ + if ((SCALAR_TYPE_P (TREE_TYPE (arg)) + || is_empty_class (TREE_TYPE (arg))) && TYPE_REF_P (rettype) - && !reference_related_p (TREE_TYPE (arg), - TREE_TYPE (rettype))) + && !reference_related_p (TREE_TYPE (rettype), + TREE_TYPE (arg))) continue; return expr; } diff --git a/gcc/testsuite/g++.dg/ext/attr-no-dangling6.C b/gcc/testsuite/g++.dg/ext/attr-no-dangling6.C index 5b349e8e682..1fc426d20d3 100644 --- a/gcc/testsuite/g++.dg/ext/attr-no-dangling6.C +++ b/gcc/testsuite/g++.dg/ext/attr-no-dangling6.C @@ -2,9 +2,9 @@ // { dg-do compile { target c++20 } } // { dg-options "-Wdangling-reference" } -class X { }; -const X x1; -const X x2; +class X { int i; }; +const X x1 {}; +const X x2 {}; constexpr bool val () { return true; } struct ST { static constexpr bool value = true; }; diff --git a/gcc/testsuite/g++.dg/ext/attr-no-dangling7.C b/gcc/testsuite/g++.dg/ext/attr-no-dangling7.C index a5fb809e6bd..04c6badf0b6 100644 --- a/gcc/testsuite/g++.dg/ext/attr-no-dangling7.C +++ b/gcc/testsuite/g++.dg/ext/attr-no-dangling7.C @@ -2,9 +2,9 @@ // { dg-do compile { target c++20 } } // { dg-options "-Wdangling-reference" } -class X { }; -const X x1; -const X x2; +class X { int i; }; +const X x1 {}; +const X x2 {}; template<bool... N> [[gnu::no_dangling(N)]] const X& get(const int& i); // { dg-error "parameter packs not expanded" } diff --git a/gcc/testsuite/g++.dg/ext/attr-no-dangling8.C b/gcc/testsuite/g++.dg/ext/attr-no-dangling8.C index 8208d751a4b..aa196315a38 100644 --- a/gcc/testsuite/g++.dg/ext/attr-no-dangling8.C +++ b/gcc/testsuite/g++.dg/ext/attr-no-dangling8.C @@ -8,6 +8,7 @@ template<class T> constexpr bool is_reference_v<T&&> = true; template <typename T> struct [[gnu::no_dangling(is_reference_v<T>)]] S { + int i; int &foo (const int &); }; @@ -15,6 +16,7 @@ template <typename T1, typename T2> struct X { template <typename U1 = T1, typename U2 = T2> struct [[gnu::no_dangling(is_reference_v<U1> && is_reference_v<U2>)]] Y { + int i; int &foo (const int &); }; }; diff --git a/gcc/testsuite/g++.dg/ext/attr-no-dangling9.C b/gcc/testsuite/g++.dg/ext/attr-no-dangling9.C index 65b4f7145a9..d7fd897de53 100644 --- a/gcc/testsuite/g++.dg/ext/attr-no-dangling9.C +++ b/gcc/testsuite/g++.dg/ext/attr-no-dangling9.C @@ -12,6 +12,7 @@ using true_type = bool_constant<true>; using false_type = bool_constant<false>; struct S { + int i; template<bool B> [[gnu::no_dangling(B)]] int &foo (const int &); }; diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-reference1.C b/gcc/testsuite/g++.dg/warn/Wdangling-reference1.C index 1718c28165e..a184317dd5c 100644 --- a/gcc/testsuite/g++.dg/warn/Wdangling-reference1.C +++ b/gcc/testsuite/g++.dg/warn/Wdangling-reference1.C @@ -131,6 +131,7 @@ int n = 1; const int& refmax = max(n - 1, n + 1); // { dg-warning "dangling reference" } struct Y { + int i; operator int&(); operator int&&(); const int& foo(const int&); diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-reference2.C b/gcc/testsuite/g++.dg/warn/Wdangling-reference2.C index dafdb43f1b9..a3d5ad6d867 100644 --- a/gcc/testsuite/g++.dg/warn/Wdangling-reference2.C +++ b/gcc/testsuite/g++.dg/warn/Wdangling-reference2.C @@ -3,7 +3,7 @@ // { dg-options "-Wdangling-reference" } namespace std { -struct any {}; +struct any { void *p; ~any(); }; template <typename _ValueType> _ValueType any_cast(any &&); template <typename _Tp> struct remove_reference { using type = _Tp; }; template <typename _Tp> _Tp forward(typename remove_reference<_Tp>::type); diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-reference23.C b/gcc/testsuite/g++.dg/warn/Wdangling-reference23.C new file mode 100644 index 00000000000..e59ccc5057b --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wdangling-reference23.C @@ -0,0 +1,14 @@ +// PR c++/115361 +// { dg-additional-options -Wdangling-reference } + +struct B { int i; }; + +struct A { + const int & operator()(const B& b) { return b.i; } +}; + +int main() +{ + B b = {}; + const int &r = A()(b); +} diff --git a/gcc/testsuite/g++.dg/warn/Wdangling-reference3.C b/gcc/testsuite/g++.dg/warn/Wdangling-reference3.C index 4bc20c13b3f..7db1dc86855 100644 --- a/gcc/testsuite/g++.dg/warn/Wdangling-reference3.C +++ b/gcc/testsuite/g++.dg/warn/Wdangling-reference3.C @@ -18,6 +18,7 @@ struct G { }; struct F { + int i; G& f(); }; base-commit: a9f9391e1eeccb9d062b9e73ef27ac577b23ed64 -- 2.46.0