mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-06 05:23:55 +00:00
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 llvm-svn: 224228
This commit is contained in:
parent
c175dd2ea5
commit
583b076223
@ -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)
|
||||
|
@ -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.
|
||||
|
11
clang/test/Lexer/ms-compatibility.c
Normal file
11
clang/test/Lexer/ms-compatibility.c
Normal file
@ -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";
|
Loading…
Reference in New Issue
Block a user