Page MenuHomePhabricator

[NFC, Refactor] Convert FunctionDefinitionKind from DeclSpech.h to a scoped enum

Authored by faisalv on Nov 8 2020, 9:38 AM.



[NFC, Refactor] Convert FunctionDefinitionKind from DeclSpech.h to a scoped enum

Diff Detail

Unit TestsFailed

390 mslinux > HWAddressSanitizer-x86_64.TestCases::sizes.cpp
Script: -- : 'RUN: at line 3'; /mnt/disks/ssd0/agent/llvm-project/build/./bin/clang --driver-mode=g++ -m64 -gline-tables-only -fsanitize=hwaddress -fuse-ld=lld -mcmodel=large -mllvm -hwasan-globals -mllvm -hwasan-use-short-granules -mllvm -hwasan-instrument-landing-pads=0 -mllvm -hwasan-instrument-personality-functions /mnt/disks/ssd0/agent/llvm-project/compiler-rt/test/hwasan/TestCases/sizes.cpp -nostdlib++ -lstdc++ -o /mnt/disks/ssd0/agent/llvm-project/build/projects/compiler-rt/test/hwasan/X86_64/TestCases/Output/sizes.cpp.tmp
50 mslinux > SanitizerCommon-Unit._/Sanitizer-x86_64-Test::SanitizerCommon.StackDepotPrint
Note: Google Test filter = SanitizerCommon.StackDepotPrint [==========] Running 1 test from 1 test case. [----------] Global test environment set-up.

Event Timeline

faisalv requested review of this revision.Nov 8 2020, 9:38 AM
faisalv created this revision.
aaron.ballman added inline comments.Nov 9 2020, 6:00 AM

I think we need to keep this as unsigned because some compilers struggle with bit-fields of enumeration types (even when the enumeration underlying type is fixed):

Generally agree with this direction; Are there plans for migrating in a similar fashion, for consistency?

Generally agree with this direction; Are there plans for migrating in a similar fashion, for consistency?

yup - i plan to get around to many of these - assuming time cooperates.

Am currently working on Decl::Kind...


As Barry had reminded me - this warning was deemed a bug: Are you sure we should still tailor our code to appease it? Is there a config file we can use to #define an ENUM_UNSIGNED_BITFIELD(x) or some such - that does the right thing for most compilers - (and are we even comfortable from a style-guide perpective, with such a conditional-define strategy?

Your thoughts?


aaron.ballman added inline comments.Nov 9 2020, 12:42 PM

The warning in GCC was a bug, but the fact that GCC issues the warning means -Werror builds will not be able to handle it. GCC 9.2 is really recent, so we can't just bump the supported version of GCC to 9.3 to avoid the issue. We could use macros to work around it for GCC, but IIRC, MSVC also had some hiccups over the years with using an enumeration as a bit-field member (I seem to recall it not wanting to pack the bits with surrounding fields, but I could be remembering incorrectly). I'm not certain whether macros are worth the effort, but my personal inclination is to just stick with unsigned unless there's a really big win from coming up with something more complex.

faisalv added inline comments.Nov 11 2020, 5:26 AM

Well - the biggest downside of making it unsigned (vs leaving it as an enum) is that each assignment or initialization now requires a static_cast.

What would you folks suggest:

  1. do not modernize such enums into scoped enums
  2. scope these enums - sticking to unsigned bit-fields - and add static_casts
  3. teach the bots to ignore that gcc warning? (is this even an option)

Thank you!

aaron.ballman added inline comments.Nov 11 2020, 5:51 AM

For #2, do you have an idea of how often we'd need to insert the static_casts for this particular enum? I don't think we assign to this field all that often in a place where we only have an integer rather than an enumeration value, so my preference is for #2 on a case-by-case basis (for instance, we could add a helper function to set unsigned bit-fields to an enum value -- we already have one here with setFunctionDefinitionKind()).

faisalv updated this revision to Diff 305020.Nov 12 2020, 8:59 PM

This revision includes the following changes to the initial patch:

  • revert the bit-field to unsigned from enum (so as to avoid that nettlesome gcc warning)
  • specified a fixed underlying type of 'unsigned char' for the enum FunctionDefinitionKind
  • added static_casts when initiatilizing or assigning to the bit-field (which as Aaron astutely noticed was confined to the ctor and setter)

Thank you!

rsmith added a subscriber: rsmith.Nov 12 2020, 9:09 PM
rsmith added inline comments.

I don't think it's OK to have an initialism like this in the clang namespace scope -- generally-speaking, the larger the scope of a name, the longer and more descriptive the name needs to be. Is spelling out the full name of the enumeration everywhere it appears unacceptably verbose?


We should be very wary of having bit-fields of enumeration type anyway, because the MS ABI layout rule for bit-fields doesn't pack adjacent bit-fields together if they don't have the same storage type. (That's why we use unsigned : 1 bit-fields for flags most of the time -- so they'll pack with adjacent unsigned : 2 bitfields under the MS ABI.)

aaron.ballman added inline comments.Nov 13 2020, 6:02 AM

That will change uses like this:




which repeats the enumeration name twice (once for the function and once for the enumerator) and is rather unfortunate. I'm not certain it's more unfortunate than putting an initialism into the clang namespace though.


Thank you for the reminder -- that was the MSVC oddity I was mentioning but couldn't recall the details of!

This comment was removed by wchilders.
wchilders added inline comments.Nov 13 2020, 12:30 PM

Lost my original comment... I guess I still don't know how to use Phabricator :(

I see both arguments here, I think I agree more with @rsmith as I generally prefer less "mental indirection"/clarity over less typing.

That said, there's also a potential middle ground here. There is a fair bit of inconsistency in enum naming, looking at Specifiers.h for instance, sometimes "Specifier" is spelled "Specifier" and other times it's spelled "Spec" or "Specifiers" (and actually looking closer, it doesn't appear that TypeSpecifiersPipe is ever used). Perhaps it would be good to standardize the short names, and perhaps use something like FnDefKind or FunctionDefKind -- both of which are notably shortly, but still reasonably understandable and specific names. Just a thought :)

wchilders added inline comments.Nov 13 2020, 12:36 PM

Correction TypeSpecifiersPipe is used, just a bit strangely -- one value, TSP_pipe is assigned to a bit field as a flag, rather than true.

Also notably shorter* (whoops)

faisalv updated this revision to Diff 305317.Nov 14 2020, 8:55 AM

This diff makes the following changes to the previous patch (based on feedback from Richard, Aaron and Wyatt):

  • avoid introducing an initialism (FDK) into the clang namespace and unabbreviated each corresponding use to 'FunctionDefinitionKind'. Let me know if it seems too verbose - if so, perhaps a compromise along Wyatt's suggestion might behoove our source.
  • changed the destination type from 'unsigned' to 'unsigned char' in our static_casts.
    • is that preferred, or should i have left it as 'unsigned'?
    • is there any real benefit here to specifying an underlying type of 'unsigned char' for our enum (that is never used as an opaque enum).

Richard, thanks for stepping in and enlightening us as to why the world is still not ready for type-safe enum bit-fields! (spoiler: MSVC's outré ABI choice in layout)

P.S. Also, for those of you like me, who tend to be sloppy with their English (unlike Richard in all his meticulous glory ;) - and were unfamiliar with the nuances behind the term 'initialism' - let me direct you to a lesson from one of the greatest broadcasters of our time:

I started with specifiers.h here:, but it is not yet committed.

faisalv marked 2 inline comments as done.Nov 14 2020, 9:32 AM
faisalv added subscribers: aaron.ballman, BRevzin, Rakete1111 and 4 others.


Thanks Thorsten - if no one else does it - i'll try and commit this for you
later today :)

Faisal Vali

aaron.ballman added inline comments.Nov 20 2020, 7:38 AM

We don't gain a whole lot by making this unsigned char since we're not storing it anywhere -- leave as the default int and change the static_cast<>s?


Might as well hit these formatting fixes since we're touching the lines anyway.

wchilders accepted this revision.Nov 20 2020, 8:36 AM
This revision is now accepted and ready to land.Nov 20 2020, 8:36 AM