Nice to see this finally fixed!<br><br><div class="gmail_quote">On Wed, Jun 26, 2013 at 6:16 PM, Reid Kleckner <span dir="ltr"><<a href="mailto:reid@kleckner.net" target="_blank">reid@kleckner.net</a>></span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rnk<br>
Date: Wed Jun 26 12:16:08 2013<br>
New Revision: 184968<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=184968&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=184968&view=rev</a><br>
Log:<br>
Match MSVC's handling of commas during macro argument expansion<br>
<br>
This allows clang to parse the type_traits header in Visual Studio 2012,<br>
which is included widely in practice.<br>
<br>
This is a rework of r163022 by João Matos.  The original patch broke<br>
preprocessing of gtest headers, which this patch addresses.<br>
<br>
Patch by Will Wilson!<br>
<br>
Modified:<br>
    cfe/trunk/include/clang/Lex/Token.h<br>
    cfe/trunk/lib/Lex/PPMacroExpansion.cpp<br>
    cfe/trunk/lib/Lex/TokenLexer.cpp<br>
    cfe/trunk/test/Preprocessor/microsoft-ext.c<br>
<br>
Modified: cfe/trunk/include/clang/Lex/Token.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Token.h?rev=184968&r1=184967&r2=184968&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Token.h?rev=184968&r1=184967&r2=184968&view=diff</a><br>


==============================================================================<br>
--- cfe/trunk/include/clang/Lex/Token.h (original)<br>
+++ cfe/trunk/include/clang/Lex/Token.h Wed Jun 26 12:16:08 2013<br>
@@ -77,7 +77,8 @@ public:<br>
     NeedsCleaning = 0x08,  // Contained an escaped newline or trigraph.<br>
     LeadingEmptyMacro = 0x10, // Empty macro exists before this token.<br>
     HasUDSuffix = 0x20,    // This string or character literal has a ud-suffix.<br>
-    HasUCN = 0x40          // This identifier contains a UCN.<br>
+    HasUCN = 0x40,         // This identifier contains a UCN.<br>
+    IgnoredComma = 0x80,   // This comma is not a macro argument separator (MS).<br>
   };<br>
<br>
   tok::TokenKind getKind() const { return (tok::TokenKind)Kind; }<br>
<br>
Modified: cfe/trunk/lib/Lex/PPMacroExpansion.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=184968&r1=184967&r2=184968&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPMacroExpansion.cpp?rev=184968&r1=184967&r2=184968&view=diff</a><br>


==============================================================================<br>
--- cfe/trunk/lib/Lex/PPMacroExpansion.cpp (original)<br>
+++ cfe/trunk/lib/Lex/PPMacroExpansion.cpp Wed Jun 26 12:16:08 2013<br>
@@ -458,7 +458,12 @@ MacroArgs *Preprocessor::ReadFunctionLik<br>
         }<br>
       } else if (Tok.is(tok::l_paren)) {<br>
         ++NumParens;<br>
-      } else if (Tok.is(tok::comma) && NumParens == 0) {<br>
+      } else if (Tok.is(tok::comma) && NumParens == 0 &&<br>
+                 !(Tok.getFlags() & Token::IgnoredComma)) {<br>
+        // In Microsoft-compatibility mode, single commas from nested macro<br>
+        // expansions should not be considered as argument separators. We test<br>
+        // for this with the IgnoredComma token flag above.<br>
+<br>
         // Comma ends this argument if there are more fixed arguments expected.<br>
         // However, if this is a variadic macro, and this is part of the<br>
         // variadic part, then the comma is just an argument token.<br>
<br>
Modified: cfe/trunk/lib/Lex/TokenLexer.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/TokenLexer.cpp?rev=184968&r1=184967&r2=184968&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/TokenLexer.cpp?rev=184968&r1=184967&r2=184968&view=diff</a><br>


==============================================================================<br>
--- cfe/trunk/lib/Lex/TokenLexer.cpp (original)<br>
+++ cfe/trunk/lib/Lex/TokenLexer.cpp Wed Jun 26 12:16:08 2013<br>
@@ -278,6 +278,14 @@ void TokenLexer::ExpandFunctionArguments<br>
         unsigned NumToks = MacroArgs::getArgLength(ResultArgToks);<br>
         ResultToks.append(ResultArgToks, ResultArgToks+NumToks);<br>
<br>
+        // In Microsoft-compatibility mode, we follow MSVC's preprocessing<br>
+        // behavior by not considering single commas from nested macro<br>
+        // expansions as argument separators. Set a flag on the token so we can<br>
+        // test for this later when the macro expansion is processed.<br>
+        if (PP.getLangOpts().MicrosoftMode && NumToks == 1 &&<br>
+            ResultToks.back().is(tok::comma))<br>
+          ResultToks.back().setFlag(Token::IgnoredComma);<br>
+<br>
         // If the '##' came from expanding an argument, turn it into 'unknown'<br>
         // to avoid pasting.<br>
         for (unsigned i = FirstResult, e = ResultToks.size(); i != e; ++i) {<br>
<br>
Modified: cfe/trunk/test/Preprocessor/microsoft-ext.c<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/microsoft-ext.c?rev=184968&r1=184967&r2=184968&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/microsoft-ext.c?rev=184968&r1=184967&r2=184968&view=diff</a><br>


==============================================================================<br>
--- cfe/trunk/test/Preprocessor/microsoft-ext.c (original)<br>
+++ cfe/trunk/test/Preprocessor/microsoft-ext.c Wed Jun 26 12:16:08 2013<br>
@@ -22,3 +22,15 @@ class GMOCK_ACTION_CLASS_(name, value_pa<br>
 ACTION_TEMPLATE(InvokeArgument,<br>
                 HAS_1_TEMPLATE_PARAMS(int, k),<br>
                 AND_2_VALUE_PARAMS(p0, p1));<br>
+<br>
+// This tests compatibility with behaviour needed for type_traits in VS2012<br>
+// Test based on _VARIADIC_EXPAND_0X macros in xstddef of VS2012<br>
+#define _COMMA ,<br>
+<br>
+#define MAKER(_arg1, _comma, _arg2)                                            \<br>
+  void func(_arg1 _comma _arg2) {}<br>
+#define MAKE_FUNC(_makerP1, _makerP2, _arg1, _comma, _arg2)                    \<br>
+  _makerP1##_makerP2(_arg1, _comma, _arg2)<br>
+<br>
+MAKE_FUNC(MAK, ER, int a, _COMMA, int b);<br>
+// CHECK: void func(int a , int b) {}<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br><br clear="all"><div><br></div>-- <br>João Matos