r224228 - MSVC: A wide string literal from L#macro_arg in a macro
Alexey Bataev
a.bataev at hotmail.com
Sun Dec 14 20:18:11 PST 2014
Author: abataev
Date: Sun Dec 14 22:18:11 2014
New Revision: 224228
URL: http://llvm.org/viewvc/llvm-project?rev=224228&view=rev
Log:
MSVC: A wide string literal from L#macro_arg in a macro
Clang should form a wide string literal from L#macro_arg in a function-like macro in -fms-compatibility mode.
Fix for http://llvm.org/PR9984.
Differential Revision: http://reviews.llvm.org/D6604
Added:
cfe/trunk/test/Lexer/ms-compatibility.c (with props)
Modified:
cfe/trunk/include/clang/Lex/Token.h
cfe/trunk/lib/Lex/TokenLexer.cpp
Modified: cfe/trunk/include/clang/Lex/Token.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Token.h?rev=224228&r1=224227&r2=224228&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/Token.h (original)
+++ cfe/trunk/include/clang/Lex/Token.h Sun Dec 14 22:18:11 2014
@@ -66,7 +66,7 @@ class Token {
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 @@ public:
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 @@ public:
/// 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)
Modified: cfe/trunk/lib/Lex/TokenLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/TokenLexer.cpp?rev=224228&r1=224227&r2=224228&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/TokenLexer.cpp (original)
+++ cfe/trunk/lib/Lex/TokenLexer.cpp Sun Dec 14 22:18:11 2014
@@ -206,6 +206,7 @@ void TokenLexer::ExpandFunctionArguments
ExpansionLocStart,
ExpansionLocEnd);
}
+ Res.setFlag(Token::StringifiedInMacro);
// The stringified/charified string leading space flag gets set to match
// the #/#@ operator.
@@ -405,6 +406,14 @@ void TokenLexer::ExpandFunctionArguments
}
}
+/// \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 @@ bool TokenLexer::Lex(Token &Tok) {
// 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 @@ bool TokenLexer::PasteTokens(Token &Tok)
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.
Added: cfe/trunk/test/Lexer/ms-compatibility.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Lexer/ms-compatibility.c?rev=224228&view=auto
==============================================================================
--- cfe/trunk/test/Lexer/ms-compatibility.c (added)
+++ cfe/trunk/test/Lexer/ms-compatibility.c Sun Dec 14 22:18:11 2014
@@ -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";
Propchange: cfe/trunk/test/Lexer/ms-compatibility.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: cfe/trunk/test/Lexer/ms-compatibility.c
------------------------------------------------------------------------------
svn:keywords = Author Date Id Rev URL
Propchange: cfe/trunk/test/Lexer/ms-compatibility.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
More information about the cfe-commits
mailing list