[PATCH] c++: Enhance -Wuninitialized to check private base class [PR80681]

2025-02-18 Thread xxie-xd
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 *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/

Re: [PATCH] c++: Check invalid use of constrained auto with trailing return type [PR100589]

2025-03-01 Thread xxie-xd
* Patrick Palka  [2025-02-28 10:37:37]:

> Hi,
> 
> On Fri, 28 Feb 2025, Da Xie wrote:
> 
> > This bug comes from a missing check when a function declaration has a
> > late-specified return type and a constrained auto type specifier. By
> > adding such a check, we can catch such uses and diagnose them as errors.
> > 
> > Successfully bootstrapped and regretested on x86_64-pc-linux-gnu:
> > adds 6 new test results and 4 UNSUPPORTED results to g++.sum.  The 4
> > UNSUPPORTED results are due to the fact that concepts are not supported
> > before c++20, so tests cannot pass with c++17 and lower standards.
> > 
> > PR c++/100589
> > 
> > gcc/cp/ChangeLog:
> > 
> > * decl.cc (grokdeclarator): Issue an error for a declarator with
> > constrained auto type specifier and trailing return types.
> > 
> > gcc/testsuite/ChangeLog:
> > 
> > * g++.dg/other/pr100589.C: New test.
> 
> Thanks for the patch!  Looks good to me overall, some minor comments
> below.
> 

Thank you for the review! I'll make changes to the patch based on your
advice.

> > 
> > Signed-off-by: Da Xie 
> > ---
> >  gcc/cp/decl.cc| 7 +++
> >  gcc/testsuite/g++.dg/other/pr100589.C | 7 +++
> >  2 files changed, 14 insertions(+)
> >  create mode 100644 gcc/testsuite/g++.dg/other/pr100589.C
> > 
> > diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
> > index 9ca8c6c4481..f283ed996a2 100644
> > --- a/gcc/cp/decl.cc
> > +++ b/gcc/cp/decl.cc
> > @@ -14037,6 +14037,13 @@ grokdeclarator (const cp_declarator *declarator,
> > "invalid use of %");
> > return error_mark_node;
> >   }
> > +   else if (is_constrained_auto (type))
> > + {
> > +   error_at (typespec_loc, "invalid use of "
> > + "constrained auto type specifier "
> > + "in function with trailing return type");
> 
> We should quote the 'auto' in this diagnostic by writing %
> for consistency with the other diagnostics.
> 

I have added an if statement to handle cases where the declarator
represents a named function. In such scenarios, an error will be issued,
including the function name, the use of constrained %, and the
existence of a trailing return type. For all other cases, an error
message will indicate the invalid use of constrained %.

Curiously, I found that if the same error message occurred multiple
times(In my case, the above error message does not print function names, 
so every function/type declartions issues the same error message), 
a single dg-error will catch all of them, even if these messages
are issued on different lines of code. I think this is the bug mentioned
in GCC Wiki (https://gcc.gnu.org/wiki/HowToPrepareATestcase#TODO).
Thankfully, in the updated testcase, the error messages are issued for a
function declaration and type declaration each. I have updated the
dg-error regex pattern to capture error messages separately for
functions and types. This ensures more precise matching and handling of
the respective error cases.

> > +   return error_mark_node;
> > + }
> > tree tmpl = CLASS_PLACEHOLDER_TEMPLATE (auto_node);
> > if (!tmpl)
> >   if (tree late_auto = type_uses_auto (late_return_type))
> > diff --git a/gcc/testsuite/g++.dg/other/pr100589.C 
> > b/gcc/testsuite/g++.dg/other/pr100589.C
> > new file mode 100644
> > index 000..3fa054ed34d
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/other/pr100589.C
> 
> Since this is a concepts-specific test let's name it
> 
>   g++.dg/cpp2a/concepts-pr100589.C
> 

Renamed.

> > @@ -0,0 +1,7 @@
> > +// PR c++/100589
> > +// { dg-do compile { target c++20 } }
> > +
> > +template
> > +concept false_concept = false;
> > +
> > +false_concept auto f() -> int; // { dg-error "constrained auto type 
> > specifier.* trailing return type" }
> 
> It'd be good to also test a bare function type:
> 
>  using type = false_concept auto() -> int;
> 

Test added.

> > \ No newline at end of file
> > -- 
> > 2.34.1
> > 
> > 

Thanks again for your reply. I will send updated patch when the
bootstrap and regression tests are finished.