Page MenuHome

Add support for `VA_NARGS_COUNT() == 0`
Needs ReviewPublic

Authored by Loren Osborn (linux_dr) on May 15 2022, 8:16 PM.
This revision needs review, but there are no reviewers specified.

Details

Reviewers
None
Summary

adding support for empty argument list in VA_NARGS_COUNT().

(This is not currently used, but it's a feature I'm hoping to use in an upcoming patch.)

Diff Detail

Repository
rB Blender

Event Timeline

Loren Osborn (linux_dr) requested review of this revision.May 15 2022, 8:16 PM
Loren Osborn (linux_dr) created this revision.

I'm not sure if this fix is compatible with all compilers. Please test and note your compiler and if this fails to compile. (I have added a test to make failure quick and easily detectable.)

Status Update:
This particular fix works fine for GCC and Clang. The , ## __VA_ARGS__ syntax is a preprocessor extension created by GCC. There is a standard compliant alternative, __VA_OPT__(), but is only part of the C++ standard starting with C++20. MSC/MSC++ have a similar extension to GCC (without the ## "token paste" operator, that I've been able to detect as supported, but it's rather temperamental and I was unable to get it to function correctly in this context.

I think the best strategy for handling the MSC case and the case with no similar preprocessor extension is to use an ISEMPTY() implementation similar to the one described here: https://gustedt.wordpress.com/2010/06/08/detect-empty-macro-arguments/ This all seems like a good deal of effort for a feature that is currently not used.

Recommendation: At least for now, I think the most straightforward fix for this is to rename the macro to make it clear that it only supports 1 or more argument. If we need more sophistication in the future, we can add that.

Loren Osborn (linux_dr) updated this revision to Diff 51724.EditedMay 23 2022, 3:05 AM

Updated this diff to work on all compilers I was able to test it on.

Additionally exposed the following new macros:

  • IF_ELSE(): Conditionally include one code fragment or the other
  • BOOL_NOT(): Invert the input boolean. (The result is 0 or 1.)
  • VA_IS_EMPTY(): 1 if argument list is empty, 0 otherwise.
  • VA_HAS_COMMA(): 1 if argument list contains 2 or more (comma separated) elements, 0 otherwise.

Missed edge case where GCC_VERSION isn't always defined in gcc.

This is verbose and difficult enough to predict how changes might impact different compilers, that I'd want to see the use case for it's inclusion.

We might even consider using a dummy argument as an alternative since this considerably increases the complexity of the VA_NARGS_COUNT macro.

I'd rather put this patch on hold until the use case for it is shown.

This is verbose and difficult enough to predict how changes might impact different compilers, that I'd want to see the use case for it's inclusion.

I'm actually working on a use case, fixing some memory alignment issues, but it's still in mid development. After it became apparent that this was a non-trivial fix, I brought it to @Ray Molenkamp (LazyDodo) 's attention. (He was kind of exasperated from my chasing theoretical issues.) I suggested, for now, changing the macro name (by appending _GTE1 or _AT_LEAST_ONE to the macro name) until the empty arguments case was needed. That's when he suggested I bring the diff to your attention.

We might even consider using a dummy argument as an alternative since this considerably increases the complexity of the VA_NARGS_COUNT macro.

This issue isn't that this fails to build with no arguments; it's simply that it returns the wrong value. (1 instead of 0). To the preprocessor an "empty" argument is just as valid as any other argument, so when counting the empty argument still counts as 1. From the 2010 Jens Gustedt article linked in the diff:

"So in fact NARG2 is cheating. It doesn’t count the number of arguments that it receives, but returns the number of commas plus one. In particular, even if it receives an empty argument list it will return 1. "

I'd rather put this patch on hold until the use case for it is shown.

I agree it isn't urgently needed at this time, though I've tried to include lots of tests so we have a high degree of confidence in it after it compiles. Ray also mentioned that an administrator could kick off a cross-platform build (for supported platforms) on unmerged patches. This would be helpful to know that all supported compilers are passing these tests.

As soon as I have a patch that relies on these changes, I'll let you know.

It seems thoroughly covered by tests, that i like, kicked off a build to see how all compilers like it

https://builder.blender.org/admin/#/builders/18/builds/425

I’m glad we found a failure I can fix, but from the logs, I have no idea what compiler /opt/rh/devtoolset-9/root/usr/bin/c++ is, so I’m not sure how to reproduce the problem. Do you happen to know what compiler this is?

it's gcc 9.3.1. on centos7

-- Building in CentOS 7 64bit environment
-- The C compiler identification is GNU 9.3.1
-- The CXX compiler identification is GNU 9.3.1
-- Check for working C compiler: /opt/rh/devtoolset-9/root/usr/bin/cc
-- Check for working C compiler: /opt/rh/devtoolset-9/root/usr/bin/cc - works

but no need to get picky on the gcc version by the looks of it, it seems to repro on all GCC versions

https://godbolt.org/z/6jrvbxEdn

Ok, great… that’s exactly the information I needed, I’ve seen this issue before and don’t have a fix yet, but i have a solid way forward now.

Thanks!

Loren Osborn (linux_dr) retitled this revision from Add support for `VA_NARGS_COUNT() == 0` to [BROKEN] Add support for `VA_NARGS_COUNT() == 0`.May 24 2022, 6:53 PM
Loren Osborn (linux_dr) retitled this revision from [BROKEN] Add support for `VA_NARGS_COUNT() == 0` to Add support for `VA_NARGS_COUNT() == 0`.

GCC comma token-paste detection was backwards

  • Extra argument in _VA_FEATURE_COMMA_TOKEN_PASTE_DETECT_1_OR_2_ARGS() prototype reversed detection result logic
  • Added all documented tests from 2010 article. (This exposed an issue that may only have been exposed by changes in parse-order)
  • Fixed VA_IS_EMPTY() false-positive case exposed by old documented tests.
  • Added tests for existing VA_NARGS_CALL_OVERLOAD() macro

Probably 100% irrelevant, but this delta helped me discover/report this defect: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105732 (Not blocked)

@Ray Molenkamp (LazyDodo), would you mind kicking off a build of this diff?

-Thanks