Index: cfe/trunk/include/clang/Lex/Token.h =================================================================== --- cfe/trunk/include/clang/Lex/Token.h +++ cfe/trunk/include/clang/Lex/Token.h @@ -66,7 +66,7 @@ tok::TokenKind Kind; /// Flags - Bits we track about this token, members of the TokenFlags enum. - unsigned char Flags; + unsigned short Flags; public: // Various flags set per token: @@ -80,7 +80,9 @@ 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. - IgnoredComma = 0x80 // This comma is not a macro argument separator (MS). + IgnoredComma = 0x80, // This comma is not a macro argument separator (MS). + StringifiedInMacro = 0x100, // This string or character literal is formed by + // macro stringizing or charizing operator. }; tok::TokenKind getKind() const { return Kind; } @@ -262,6 +264,12 @@ /// Returns true if this token contains a universal character name. bool hasUCN() const { return (Flags & HasUCN) ? true : false; } + + /// Returns true if this token is formed by macro by stringizing or charizing + /// operator. + bool stringifiedInMacro() const { + return (Flags & StringifiedInMacro) ? true : false; + } }; /// \brief Information about the conditional stack (\#if directives) Index: cfe/trunk/lib/Lex/TokenLexer.cpp =================================================================== --- cfe/trunk/lib/Lex/TokenLexer.cpp +++ cfe/trunk/lib/Lex/TokenLexer.cpp @@ -206,6 +206,7 @@ ExpansionLocStart, ExpansionLocEnd); } + Res.setFlag(Token::StringifiedInMacro); // The stringified/charified string leading space flag gets set to match // the #/#@ operator. @@ -405,6 +406,14 @@ } } +/// \brief Checks if two tokens form wide string literal. +static bool isWideStringLiteralFromMacro(const Token &FirstTok, + const Token &SecondTok) { + return FirstTok.is(tok::identifier) && + FirstTok.getIdentifierInfo()->isStr("L") && SecondTok.isLiteral() && + SecondTok.stringifiedInMacro(); +} + /// Lex - Lex and return a token from this macro stream. /// bool TokenLexer::Lex(Token &Tok) { @@ -435,7 +444,13 @@ // If this token is followed by a token paste (##) operator, paste the tokens! // Note that ## is a normal token when not expanding a macro. - if (!isAtEnd() && Tokens[CurToken].is(tok::hashhash) && Macro) { + if (!isAtEnd() && Macro && + (Tokens[CurToken].is(tok::hashhash) || + // Special processing of L#x macros in -fms-compatibility mode. + // Microsoft compiler is able to form a wide string literal from + // 'L#macro_arg' construct in a function-like macro. + (PP.getLangOpts().MSVCCompat && + isWideStringLiteralFromMacro(Tok, Tokens[CurToken])))) { // When handling the microsoft /##/ extension, the final token is // returned by PasteTokens, not the pasted token. if (PasteTokens(Tok)) @@ -511,9 +526,10 @@ SourceLocation StartLoc = Tok.getLocation(); SourceLocation PasteOpLoc; do { - // Consume the ## operator. + // Consume the ## operator if any. PasteOpLoc = Tokens[CurToken].getLocation(); - ++CurToken; + if (Tokens[CurToken].is(tok::hashhash)) + ++CurToken; assert(!isAtEnd() && "No token on the RHS of a paste operator!"); // Get the RHS token. Index: cfe/trunk/test/Lexer/ms-compatibility.c =================================================================== --- cfe/trunk/test/Lexer/ms-compatibility.c +++ cfe/trunk/test/Lexer/ms-compatibility.c @@ -0,0 +1,11 @@ +// RUN: %clang_cc1 -fsyntax-only -E -fms-compatibility %s | FileCheck --check-prefix=CHECK-MS-COMPAT %s +// RUN: %clang_cc1 -fsyntax-only -E %s | FileCheck --check-prefix=CHECK-NO-MS-COMPAT %s + +#define FN(x) L#x +#define F L "aaa" +void *v1 = FN(aaa); +void *v2 = F; +// CHECK-MS-COMPAT: void *v1 = L"aaa"; +// CHECK-MS-COMPAT: void *v2 = L "aaa"; +// CHECK-NO-MS-COMPAT: void *v1 = L "aaa"; +// CHECK-NO-MS-COMPAT: void *v2 = L "aaa";