This is an archive of the discontinued LLVM Phabricator instance.

Fix Microsoft compatibility handling of commas in nested macro expansions.
ClosedPublic

Authored by epastor on Oct 30 2019, 9:56 AM.

Details

Summary

In Microsoft-compatibility mode, we currently emulate MSVC's patterns in unpacking VA_ARGS by deliberately not treating single commas from macro expansion as argument separators, marking them to be ignored. However, in MSVC's preprocessor, subsequent expansions DO treat these commas as argument separators. Libraries (e.g., Boost, GoogleTest) routinely use this as a workaround for MSVC's non-compliant preprocessor by adding an additional layer of indirection to force recognition of argument separators.

To match this behavior, we now ignore each comma at most once.

Includes a small unit test that validates we match MSVC's behavior as shown in https://gcc.godbolt.org/z/y0twaq

Diff Detail

Event Timeline

epastor created this revision.Oct 30 2019, 9:56 AM
Herald added a project: Restricted Project. · View Herald TranscriptOct 30 2019, 9:56 AM
Herald added a subscriber: cfe-commits. · View Herald Transcript

Is this needed to parse system headers?

In general, we try to emulate only warts we must emulate, and if feasible we try to emit some -Wmicrosoft warning when the compat path is taken.

(MSVC added /experimental:preprocessor like 2 years ago, but it hasn't made it to a /Zc: flag yet so I suppose standard headers might keep needing these tweaks.)

(See https://docs.google.com/presentation/d/1oxNHaVjA9Gn_rTzX6HIpJHP7nXRua_0URXxxJ3oYRq0/edit#slide=id.g71ecd450e_2_843 slide 23-27)

Is this needed to parse system headers?

Interesting question. This change isn't - but I presume the (pre-existing) introduction of IgnoredComma was.

In general, we try to emulate only warts we must emulate, and if feasible we try to emit some -Wmicrosoft warning when the compat path is taken.

Sure - this change actually brings the preprocessor closer to compliance. I think the prior use of IgnoredComma had overshot MSVC by a bit. For an illustration, see
https://gcc.godbolt.org/z/XakAYf (same code as above, but in MSVC, clang, and clang -fms-compatibility)
MSVC shows it's non-compliant on TEST, and -fms-compatibility matches it there. However, MSVC matches clang's behavior for WRAPPED_TEST, as adding another layer of macro expansion is a standard trick for forcing MSVC's preprocessor to act compliant... but clang -fms-compatibility still gives the non-compliant result, since that trick doesn't work to remove IgnoredCommas.

If we wanted to detect use of the compatibility feature, we might need to apply the preprocessor both ways and see if the results were different; I'm not sure all IgnoredCommas will actually make a difference in the parsing. As is, we'd need to emit a -Wmicrosoft warning any time we saw an isolated comma as a macro parameter... which I think might get confusing?

epastor edited the summary of this revision. (Show Details)Oct 31 2019, 9:02 AM
rnk accepted this revision.Oct 31 2019, 2:38 PM

lgtm

Based on the comments it looks like you confirmed this matches MSVC's behavior, at least in this regard. I haven't stared at this deeply to think of all the corner cases, though.

To Nico's point, I think this change doesn't move us away from conformance, it's a bug in our compatibility. We've created a bad situation here were we are buggily implementing MSVC pre-processor rules, and nobody should have to add a third set of ifdefs to deal with that.

This revision is now accepted and ready to land.Oct 31 2019, 2:38 PM

Thanks, Reid; I'm not 100% sure I've checked all the corner cases either, but this at least seems like a step forward.

As a reminder: I don't have commit access. Could someone else commit this for me?

This revision was automatically updated to reflect the committed changes.