Re: enabling -Werror=assign-enum for kernel

Gleb Smirnoff <[email protected]>
Newsgroups gmane.os.freebsd.current
Message-ID <ao8hCSBhqJijBivk__37128.9434305922$1787765050$gmane$org@cell.glebi.us>
  John,

On Wed, Aug 26, 2026 at 01:15:27PM -0400, John Baldwin wrote:
J> > J> Note that C++ doesn't allow this at the language level.  When I converted ctld to
J> > J> C++ I had to adjust some enums to be simple #define's instead in the ctl headers.
J> > 
J> > Noted.  I can't make a judgement if it is a smart restriction by C++ or not.
J> > In our case using enums as flags is common and handy and Werror=assign-enum in
J> > combination with __attribute__((flag_enum)) will make this use fortified
J> > against mistakes.
J> 
J> Mostly my point is that over time we may be forced to convert away from enums to
J> plain constants if more of the base system starts using C++ anyway.  At least for
J> enums exposed to userspace.

But if C++ doesn't allow flag enums in principle, then they just can't go into
userspace headers, no matter how we compile the kernel.  Basically we already
are there, and enabling Werror=assign-enum for kernel won't change anything,
will it?

J> > Question: what is our policy of adding attributes into code?  The convetion is
J> > that compilers warn and don't fail on unknown attributes, so adding them as
J> > bare words definitely works.  I personally prefer to avoid use of preprocessor
J> > when it is possible, so I'm for adding the __attribute__((flag_enum)) as is.
J> > However, few people who compile with gcc may be unhappy about lots of warnings.
J> > The best practice to shut these warning is:
J> > 
J> > #ifndef __flag_enum
J> > #ifdef __clang__
J> > #define	__flag_enum	__attribute__((flag_enum))
J> > #else
J> > #define	__flag_enum
J> > #endif
J> > #endif
J> > 
J> > This would require us use FreeBSD-specific keyword in the code.  Which one is
J> > the preferred way to move forward?
J> 
J> Normally we define a new wrapper in <sys/cdefs.h> so that the only #ifdef's are in
J> that header, and the rest of the code uses the wrapper macro unconditionally.

So your answer is that I need to add the above to <sys/cdefs.h> and rewrite my
branch to use a defined keyword instead of __attribute__((flag_enum))?  What
would be the keyword? __flag_enum or any other spelling?

J> > J> > This seems like a nice enforcement of a good code.  I already found a few
J> > J> > hamrless bugs with it and one in e1000 that could be a real bug.  It also
J> > J> > highlights some sketchy code that better be refactored.
J> > J> >
J> > J> > I have a branch where LINT is compilable with -Werror=assign-enum:
J> > J> >
J> > J> > https://github.com/freebsd/freebsd-src/compare/main...glebius:FreeBSD:Werror%3Dassign-enum
J> > J> >
J> > J> > There are basically three parts that require work:
J> > J> >
J> > J> > 1) The most common violators are SYSINIT(9)s that use (SI_SUB_FOO + 1) as
J> > J> > argument.  I have posted a pack of reviews to cover that.
J> > J>
J> > J> So I think this is probably sensible for SI_SUB_* to define new values.  I
J> > J> worry about SI_ORDER_*.  Possibly we should use plain #define's for SI_ORDER_*
J> > J> instead of an enum if we aren't already.  I wonder if you ran into any cases
J> > J> where we use an SI_ORDER_* value that is an expression?
J> > 
J> > Nope.  Everything in SYSINIT(9) that was violating Werror=assign-enum is
J> > already in main, except ipfw.  One bit left is ipfw's sysinits, which I left
J> > for later, since I wanted more changes to it.
J> > 
J> > I don't agree we should use plain #define for SI_ORDER_*.  The current code
J> > combined with Werror=assign-enum will enforce intentionality and thoughtfulness
J> > when adding new sysinits.  Would prevent quick adhoc additions in the "works
J> > for me" style.
J> 
J> At some point 'SI_ORDER_<ENGLISH ORDINAL TERM>' isn't really more readable than
J> just using an integer.  In particular for offsets relative to SI_ORDER_FIRST.
J> Today we probably don't have more than SI_ORDER_THIRD, but something like
J> SI_ORDER_FOUR_HUNDRED_FIFTY_SEVENTH would be a mouthful compared to
J> 'SI_ORDER_FIRST + 456'.  For SI_SUB_* the names are generally descriptive of
J> some subsystem, but SI_ORDER are inherently a range of explicitly numbered values
J> along with a few special cases such as SI_ORDER_ANY/LAST.  The special cases
J> make sense as names.  The numeric range makes less sense as names.  However, if
J> we all fit fine today with just SI_ORDER_THIRD then it's probably ok.  I worried
J> we might have a broader range than just FIRST/SECOND/THIRD.

So far we are good with FIRST/SECOND/THIRD.  IMHO, if we really really want to
improve SYSINIT substantially, not just fix daily problems, we should
unironically use rcorder(8) as kernel compilation tool.

-- 
Gleb Smirnoff
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.