diff options
author | Reid Kleckner <reid@kleckner.net> | 2013-06-26 17:16:08 +0000 |
---|---|---|
committer | Reid Kleckner <reid@kleckner.net> | 2013-06-26 17:16:08 +0000 |
commit | 596b85cc234d8f5c2fcdb23ade14535a33789c5c (patch) | |
tree | 2cd0adbca30804d2a66e33e822f6338103503fd1 | |
parent | b3f550e8cd5ff1d2304582e95dd494bf955f27d3 (diff) | |
download | bcm5719-llvm-596b85cc234d8f5c2fcdb23ade14535a33789c5c.tar.gz bcm5719-llvm-596b85cc234d8f5c2fcdb23ade14535a33789c5c.zip |
Match MSVC's handling of commas during macro argument expansion
This allows clang to parse the type_traits header in Visual Studio 2012,
which is included widely in practice.
This is a rework of r163022 by João Matos. The original patch broke
preprocessing of gtest headers, which this patch addresses.
Patch by Will Wilson!
llvm-svn: 184968
-rw-r--r-- | clang/include/clang/Lex/Token.h | 3 | ||||
-rw-r--r-- | clang/lib/Lex/PPMacroExpansion.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Lex/TokenLexer.cpp | 8 | ||||
-rw-r--r-- | clang/test/Preprocessor/microsoft-ext.c | 12 |
4 files changed, 28 insertions, 2 deletions
diff --git a/clang/include/clang/Lex/Token.h b/clang/include/clang/Lex/Token.h index bcbe9c913be..76c62fe944a 100644 --- a/clang/include/clang/Lex/Token.h +++ b/clang/include/clang/Lex/Token.h @@ -77,7 +77,8 @@ public: 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. - HasUCN = 0x40 // This identifier contains a UCN. + HasUCN = 0x40, // This identifier contains a UCN. + IgnoredComma = 0x80, // This comma is not a macro argument separator (MS). }; tok::TokenKind getKind() const { return (tok::TokenKind)Kind; } diff --git a/clang/lib/Lex/PPMacroExpansion.cpp b/clang/lib/Lex/PPMacroExpansion.cpp index 13fdf854fd1..06f14c24bdd 100644 --- a/clang/lib/Lex/PPMacroExpansion.cpp +++ b/clang/lib/Lex/PPMacroExpansion.cpp @@ -458,7 +458,12 @@ MacroArgs *Preprocessor::ReadFunctionLikeMacroArgs(Token &MacroName, } } 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. + // 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. diff --git a/clang/lib/Lex/TokenLexer.cpp b/clang/lib/Lex/TokenLexer.cpp index 4251f0ebf28..4f21995391c 100644 --- a/clang/lib/Lex/TokenLexer.cpp +++ b/clang/lib/Lex/TokenLexer.cpp @@ -278,6 +278,14 @@ void TokenLexer::ExpandFunctionArguments() { unsigned NumToks = MacroArgs::getArgLength(ResultArgToks); ResultToks.append(ResultArgToks, ResultArgToks+NumToks); + // In Microsoft-compatibility mode, we follow MSVC's preprocessing + // behavior 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. + 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. for (unsigned i = FirstResult, e = ResultToks.size(); i != e; ++i) { diff --git a/clang/test/Preprocessor/microsoft-ext.c b/clang/test/Preprocessor/microsoft-ext.c index ec10374a1d6..b03f6775429 100644 --- a/clang/test/Preprocessor/microsoft-ext.c +++ b/clang/test/Preprocessor/microsoft-ext.c @@ -22,3 +22,15 @@ class GMOCK_ACTION_CLASS_(name, value_params) {\ 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) {} |