[PATCH] Emulate MSVC handling of commas during macro arg expansion

Aaron Ballman aaron at aaronballman.com
Tue Jun 25 15:39:14 PDT 2013


> Index: test/Preprocessor/microsoft-ext.c
> ===================================================================
> --- test/Preprocessor/microsoft-ext.c (revision 184863)
> +++ test/Preprocessor/microsoft-ext.c (working copy)
> @@ -22,3 +22,14 @@
>  ACTION_TEMPLATE(InvokeArgument,
>                  HAS_1_TEMPLATE_PARAMS(int, k),
>                  AND_2_VALUE_PARAMS(p0, p1));
> +
> +
> +// This tests compatibility with behaviour needed for type_traits in VS2012
> +// Test based on _VARIADIC_EXPAND_0X macros in xstddef of VS2012
> +#define _COMMA ,
> +
> +#define MAKER(_arg1, _comma, _arg2) void func(_arg1 _comma _arg2) {}
> +#define MAKE_FUNC(_makerP1, _makerP2, _arg1, _comma, _arg2) \
> +                  _makerP1 ## _makerP2(_arg1, _comma, _arg2)
> +
> +MAKE_FUNC(MAK, ER, int a, _COMMA, int b); // CHECK: void func(int a , int b) {}
> Index: include/clang/Lex/Token.h
> ===================================================================
> --- include/clang/Lex/Token.h (revision 184863)
> +++ include/clang/Lex/Token.h (working copy)
> @@ -74,6 +74,7 @@
>      StartOfLine   = 0x01,  // At start of line or only after whitespace.
>      LeadingSpace  = 0x02,  // Whitespace exists before this token.
>      DisableExpand = 0x04,  // This identifier may never be macro expanded.
> +    IgnoredComma = 0x04,   // [reused] Comma is not an argument separator (MS)

I'm not too keen on reusing this value, even though it may be safe to do.

>      NeedsCleaning = 0x08,  // Contained an escaped newline or trigraph.
>      LeadingEmptyMacro = 0x10, // Empty macro exists before this token.
>      HasUDSuffix = 0x20,    // This string or character literal has a ud-suffix.
> Index: lib/Lex/TokenLexer.cpp
> ===================================================================
> --- lib/Lex/TokenLexer.cpp (revision 184863)
> +++ lib/Lex/TokenLexer.cpp (working copy)
> @@ -277,6 +277,14 @@
>          unsigned FirstResult = ResultToks.size();
>          unsigned NumToks = MacroArgs::getArgLength(ResultArgToks);
>          ResultToks.append(ResultArgToks, ResultArgToks+NumToks);
> +
> +        // In Microsoft-compatibility mode, we follow MSVC's preprocessing
> +        // behaviour by not considering single commas from nested macro
> +        // expansions as argument separators. Set a flag on the token so we can
> +        // test for this later when the macro expansion is processed.

Trailing whitespace.  Also, not certain if we have a preference for US
spellings or not (behavior instead of behaviour).

> +        if (PP.getLangOpts().MicrosoftMode && NumToks == 1 &&
> +            ResultToks.back().is(tok::comma))
> +          ResultToks.back().setFlag(Token::IgnoredComma);
>
>          // If the '##' came from expanding an argument, turn it into 'unknown'
>          // to avoid pasting.
> Index: lib/Lex/PPMacroExpansion.cpp
> ===================================================================
> --- lib/Lex/PPMacroExpansion.cpp (revision 184863)
> +++ lib/Lex/PPMacroExpansion.cpp (working copy)
> @@ -458,7 +458,12 @@
>          }
>        } else if (Tok.is(tok::l_paren)) {
>          ++NumParens;
> -      } else if (Tok.is(tok::comma) && NumParens == 0) {
> +      } else if (Tok.is(tok::comma) && NumParens == 0 &&
> +                 !(Tok.getFlags() & Token::IgnoredComma)) {
> +        // In Microsoft-compatibility mode, single commas from nested macro
> +        // expansions should not be considered as argument separators. We test
> +        // for this with the IgnoredComma token flag above.

Trailing whitespace

> +
>          // Comma ends this argument if there are more fixed arguments expected.
>          // However, if this is a variadic macro, and this is part of the
>          // variadic part, then the comma is just an argument token.

Other than the nitpicks, the patch LGTM and I'm very excited for it!
Thank you for working on it.  :-)

~Aaron

On Tue, Jun 25, 2013 at 5:44 PM, Will Wilson <will at indefiant.com> wrote:
> Hi All,
>
> This patch is a rework of João's original patch applied as r163022 and later
> reverted in r164672. I've spent a few (long...) days attempting to get to
> the bottom of what caused the failures that led to the original patch being
> reverted. This should fix (once and for all) the error seen when compiling
> VS2012 type_traits and by extension most of the VS2012 STL headers:
>
> In file included from C:\Program Files (x86)\Microsoft Visual Studio
> 11.0\VC\include\type_traits:1820:
> C:\Program Files (x86)\Microsoft Visual Studio
> 11.0\VC\include\xrefwrap(156,20): error : too many arguments provided to
> function-like macro invocation
>
>
> The main changes in this patch are:
>
> Tokens used as macro arguments that expand to a *single* comma have special
> treatment - the comma will not be treated as a macro argument separator in
> MicrosoftMode. Tokens that expand into multiple tokens that may include
> commas are treated normally.
> I've reused 0x04 for the IgnoredComma flag as the other case (DisableExpand)
> is exclusively used for identifiers and won't conflict with tok::comma. It
> didn't seem worth using up an entirely new value for such a rare edge case
> as this.
>
> In terms of testing, clang should now be able to compile VS2012 type_traits.
> I tested successfully against Nico's original GTest test case (PR13924) and
> against boost.python 1.42.0 which also failed with the original patch. I've
> also added a new test case based on the VS2012 xstddef macros that led to
> the patch being needed in the first place.
>
> All tests passed against latest trunk. Please review and commit if it
> LGTY...
>
> Cheers,
> Will.
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>




More information about the cfe-commits mailing list