The issue described in PR80681 highlights a problem that:
g++'s -Wuninitialized option does not warn when a privately inherited
base class contains public const data or reference members, and the
derived class does not have a user-provided constructor.

Similarly, the same issue occurs when the privately inherited base
class contains protected const data or reference members. In both
cases, the derived class is unable to initialize these members in the
base class.

For private const data or reference members in privately inherited
base classes, these members are inherently inaccessible to the derived
class and cannot be initialized. Therefore, they are not considered as
a condition for issuing a warning.

In my proposed patch, under the condition that the current class
does not have a user-provided constructor and the -Wuninitialized option
is enabled, I traverse all directly privately inherited base classes
of the current class. For each base class, I check whether it contains
any non-private const data or reference members. If such members are
found, a warning is issued at the declaration location of the
current class. Additionally, supplementary information is provided to
indicate the declaration location of the non-private const data or
reference members in the base class.

Successfully bootstrapped and regretested on x86_64-pc-linux-gnu:
adds 21 PASS results to g++.sum.

        PR c++/80681

gcc/cp/ChangeLog:

        * class.cc (check_bases_and_members): Enhanced -Wuninitialized to
        warn for classes without user-provided constructors that privately
        inherit base classes with non-private const data or reference members.

gcc/testsuite/ChangeLog:

        * g++.dg/warn/Wuninitialized-pr80681-1.C: New test.
---
 gcc/cp/class.cc                               | 61 +++++++++++++++++++
 .../g++.dg/warn/Wuninitialized-pr80681-1.C    | 19 ++++++
 2 files changed, 80 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/warn/Wuninitialized-pr80681-1.C

diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc
index d5ae69b0fdf..49c4ef08f33 100644
--- a/gcc/cp/class.cc
+++ b/gcc/cp/class.cc
@@ -6500,6 +6500,67 @@ check_bases_and_members (tree t)
                        OPT_Wuninitialized, "non-static const member %q#D "
                        "in class without a constructor", field);
        }
+      /* If the class privately inherited from a class with public
+       or protected non-static const or reference data members,
+       these members can never be initialized.  */
+
+      tree binfo = TYPE_BINFO (t);
+      vec<tree, va_gc> *accesses = BINFO_BASE_ACCESSES (binfo);
+      tree base_binfo;
+      unsigned i;
+
+      for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+       {
+         tree basetype = TREE_TYPE (base_binfo);
+
+         if ((*accesses)[i] == access_private_node)
+           {
+             tree base_field;
+
+             for (base_field = TYPE_FIELDS (basetype); base_field;
+                  base_field = DECL_CHAIN (base_field))
+               {
+                 tree field_type;
+
+                 if (TREE_CODE (base_field) != FIELD_DECL
+                     || DECL_INITIAL (base_field) != NULL_TREE)
+                   continue;
+
+                 field_type = TREE_TYPE (base_field);
+
+                 if (!TREE_PRIVATE (base_field))
+                   {
+                     if (TYPE_REF_P (field_type))
+                       {
+                         warning (OPT_Wuninitialized,
+                                  "private inheritance of base class "
+                                  "%q#T with non-private "
+                                  "non-static reference in class "
+                                  "without a constructor",
+                                  basetype);
+                         inform (DECL_SOURCE_LOCATION (base_field),
+                                 "non-static reference %q#D here:",
+                                 base_field);
+                       }
+                     else if (CP_TYPE_CONST_P (field_type)
+                              && (!CLASS_TYPE_P (field_type)
+                                  || !TYPE_HAS_DEFAULT_CONSTRUCTOR (
+                                    field_type)))
+                       {
+                         warning (OPT_Wuninitialized,
+                                  "private inheritance of base class "
+                                  "%q#T with non-private "
+                                  "non-static const member in class "
+                                  "without a constructor",
+                                  basetype);
+                         inform (DECL_SOURCE_LOCATION (base_field),
+                                 "non-static const member %q#D here:",
+                                 base_field);
+                       }
+                   }
+               }
+           }
+       }
     }
 
   /* Synthesize any needed methods.  */
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-pr80681-1.C 
b/gcc/testsuite/g++.dg/warn/Wuninitialized-pr80681-1.C
new file mode 100644
index 00000000000..a5103d2a3f4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-pr80681-1.C
@@ -0,0 +1,19 @@
+// PR c++/80681
+/* { dg-do compile } */
+/* { dg-options "-Wuninitialized" } */
+
+struct B1 { const int j; };             // no warning, good
+
+struct C1 : private B1 { }; // { dg-warning "non-private non-static const 
member" }
+
+struct B2 { const int &j; };            // no warning, good
+
+struct C2: private B2 { };  // { dg-warning "non-private non-static reference" 
}
+
+struct D1 { const int j; D1(int _j) : j(_j) {} };        
+
+struct E1: private D1 { E1(int _j) : D1(_j) {} };     // Should not warn.  
+
+struct D2 { const int &j; D2(int& _j) : j(_j) {} };        
+
+struct E2: private D2 { E2(int& _j) : D2(_j) {} };   // Should not warn.  
\ No newline at end of file
-- 
2.34.1

Reply via email to