aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2024-09-15 13:50:04 +0200
committerJason Merrill <jason@redhat.com>2024-09-18 08:58:52 -0400
commit8733d5d3873977d6ca82d71b28728650f988e9c8 (patch)
tree1430a816602f810b813da7b2599a91f7a5a41f78 /gcc
parent6f3b6a451771cd54c98768e7db3c5d58aab2b6aa (diff)
downloadgcc-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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/call.cc12
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-no-dangling6.C6
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-no-dangling7.C6
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-no-dangling8.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/attr-no-dangling9.C1
-rw-r--r--gcc/testsuite/g++.dg/warn/Wdangling-reference1.C1
-rw-r--r--gcc/testsuite/g++.dg/warn/Wdangling-reference2.C2
-rw-r--r--gcc/testsuite/g++.dg/warn/Wdangling-reference23.C14
-rw-r--r--gcc/testsuite/g++.dg/warn/Wdangling-reference3.C1
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();
};