]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: -Wdangling-reference and empty class [PR115361]
authorJason Merrill <jason@redhat.com>
Sun, 15 Sep 2024 11:50:04 +0000 (13:50 +0200)
committerJason Merrill <jason@redhat.com>
Wed, 18 Sep 2024 12:58:52 +0000 (08:58 -0400)
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
gcc/testsuite/g++.dg/ext/attr-no-dangling6.C
gcc/testsuite/g++.dg/ext/attr-no-dangling7.C
gcc/testsuite/g++.dg/ext/attr-no-dangling8.C
gcc/testsuite/g++.dg/ext/attr-no-dangling9.C
gcc/testsuite/g++.dg/warn/Wdangling-reference1.C
gcc/testsuite/g++.dg/warn/Wdangling-reference2.C
gcc/testsuite/g++.dg/warn/Wdangling-reference23.C [new file with mode: 0644]
gcc/testsuite/g++.dg/warn/Wdangling-reference3.C

index 664088eed9c79a4c0df950d22b81f4ef1ba27bd2..1ecf3aac7051f067fa043d0ae8de15bca4b72e65 100644 (file)
@@ -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;
              }
index 5b349e8e6827fe92b0dd1e8e9f5c542fc1cb80f6..1fc426d20d3df16dd89c4607bbc183b8f04f5e5e 100644 (file)
@@ -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; };
index a5fb809e6bdbede0c0db408138787365cddad884..04c6badf0b6f23e7fea5cce59a70ff71a2108f2f 100644 (file)
@@ -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" }
index 8208d751a4bb3c736b22b1199efa2ea40399b5a8..aa196315a38adda99d53fa7c94cdf0337881bbcc 100644 (file)
@@ -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 &);
   };
 };
index 65b4f7145a9265e240102fcc18a3ce6f2ff71479..d7fd897de539b7db21885490b90bc1ae92664675 100644 (file)
@@ -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 &);
 };
index 1718c28165e9878fe3535fad782d5fe02b32f4db..a184317dd5c375187881c210f9324bb48c79683b 100644 (file)
@@ -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&);
index dafdb43f1b931abb02ae59ff40466aa12d7fd2c0..a3d5ad6d8676d93efcc9c521c5046e2790c1388b 100644 (file)
@@ -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 (file)
index 0000000..e59ccc5
--- /dev/null
@@ -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);
+}
index 4bc20c13b3f714efe2039747877d8c7ee1c219f6..7db1dc86855d126741fc83a0ab8597648affb5a6 100644 (file)
@@ -18,6 +18,7 @@ struct G {
 };
 
 struct F {
+  int i;
   G& f();
 };