diff options
author | Jason Merrill <jason@redhat.com> | 2024-09-15 13:50:04 +0200 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2024-09-18 08:58:52 -0400 |
commit | 8733d5d3873977d6ca82d71b28728650f988e9c8 (patch) | |
tree | 1430a816602f810b813da7b2599a91f7a5a41f78 | |
parent | 6f3b6a451771cd54c98768e7db3c5d58aab2b6aa (diff) | |
download | gcc-8733d5d3873977d6ca82d71b28728650f988e9c8.zip gcc-8733d5d3873977d6ca82d71b28728650f988e9c8.tar.gz gcc-8733d5d3873977d6ca82d71b28728650f988e9c8.tar.bz2 |
c++: -Wdangling-reference and empty class [PR115361]
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.
-rw-r--r-- | gcc/cp/call.cc | 12 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/attr-no-dangling6.C | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/attr-no-dangling7.C | 6 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/attr-no-dangling8.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/attr-no-dangling9.C | 1 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/Wdangling-reference1.C | 1 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/Wdangling-reference2.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/Wdangling-reference23.C | 14 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/warn/Wdangling-reference3.C | 1 |
9 files changed, 33 insertions, 12 deletions
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 664088e..1ecf3aa 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 5b349e8..1fc426d 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 a5fb809..04c6bad 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 8208d75..aa196315 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 65b4f71..d7fd897 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 1718c28..a184317 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 dafdb43..a3d5ad6 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 0000000..e59ccc5 --- /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 4bc20c1..7db1dc8 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(); }; |