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