forked from OSchip/llvm-project
Implement the microsoft charize extension #@
llvm-svn: 38712
This commit is contained in:
parent
2b271db205
commit
c783d1dff9
|
@ -39,7 +39,7 @@ MacroFormalArgs::MacroFormalArgs(const MacroInfo *MI) {
|
|||
/// preprocessor operator.
|
||||
///
|
||||
static LexerToken StringifyArgument(const std::vector<LexerToken> &Toks,
|
||||
Preprocessor &PP) {
|
||||
Preprocessor &PP, bool Charify = false) {
|
||||
LexerToken Tok;
|
||||
Tok.StartToken();
|
||||
Tok.SetKind(tok::string_literal);
|
||||
|
@ -78,9 +78,32 @@ static LexerToken StringifyArgument(const std::vector<LexerToken> &Toks,
|
|||
Result.erase(Result.end()-1); // remove one of the \'s.
|
||||
}
|
||||
}
|
||||
|
||||
Result += '"';
|
||||
|
||||
// If this is the charify operation and the result is not a legal character
|
||||
// constant, diagnose it.
|
||||
if (Charify) {
|
||||
// First step, turn double quotes into single quotes:
|
||||
Result[0] = '\'';
|
||||
Result[Result.size()-1] = '\'';
|
||||
|
||||
// Check for bogus character.
|
||||
bool isBad = false;
|
||||
if (Result.size() == 2) {
|
||||
Result = "' '"; // #@empty -> ' '.
|
||||
} else if (Result.size() == 3) {
|
||||
isBad = Result[1] == '\''; // ''' is not legal. '\' already fixed above.
|
||||
} else {
|
||||
isBad = (Result.size() != 4 || Result[1] != '\\'); // Not '\x'
|
||||
}
|
||||
|
||||
if (isBad) {
|
||||
assert(!Toks.empty() && "No tokens to charize?");
|
||||
PP.Diag(Toks[0], diag::err_invalid_character_to_charify);
|
||||
Result = "' '";
|
||||
}
|
||||
}
|
||||
|
||||
Tok.SetLength(Result.size());
|
||||
Tok.SetLocation(PP.CreateString(&Result[0], Result.size()));
|
||||
return Tok;
|
||||
|
@ -143,11 +166,17 @@ void MacroExpander::ExpandFunctionArguments() {
|
|||
// preprocessor already verified that the following token is a macro name
|
||||
// when the #define was parsed.
|
||||
const LexerToken &CurTok = (*MacroTokens)[i];
|
||||
if (CurTok.getKind() == tok::hash) {
|
||||
if (CurTok.getKind() == tok::hash || CurTok.getKind() == tok::hashat) {
|
||||
int ArgNo = Macro.getArgumentNum((*MacroTokens)[i+1].getIdentifierInfo());
|
||||
assert(ArgNo != -1 && "Token following # is not an argument?");
|
||||
|
||||
ResultToks.push_back(FormalArgs->getStringifiedArgument(ArgNo, PP));
|
||||
if (CurTok.getKind() == tok::hash) // Stringify
|
||||
ResultToks.push_back(FormalArgs->getStringifiedArgument(ArgNo, PP));
|
||||
else {
|
||||
// 'charify': don't bother caching these.
|
||||
ResultToks.push_back(StringifyArgument(
|
||||
FormalArgs->getUnexpArgument(ArgNo), PP, true));
|
||||
}
|
||||
|
||||
// FIXME: Should the stringified string leading space flag get set to
|
||||
// match the # or the identifier?
|
||||
|
|
|
@ -47,8 +47,6 @@ Preprocessor:
|
|||
* Function-style #define & macro expansion
|
||||
* #line / #file directives
|
||||
* -C output mode in -E mode.
|
||||
* MSExtension: #@param 'stringizes' into a character (charize?):
|
||||
#define A(x) #@x / A(z) -> 'z'
|
||||
* MSExtension: "L#param" stringizes to a wide string literal.
|
||||
|
||||
Traditional Preprocessor:
|
||||
|
|
|
@ -73,6 +73,8 @@ DIAG(err_empty_character, ERROR,
|
|||
"empty character constant")
|
||||
DIAG(err_unterminated_block_comment, ERROR,
|
||||
"unterminated /* comment")
|
||||
DIAG(err_invalid_character_to_charify, ERROR,
|
||||
"invalid argument to convert to character")
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Preprocessor Diagnostics
|
||||
|
@ -101,7 +103,7 @@ DIAG(pp_redef_builtin_macro, WARNING,
|
|||
DIAG(pp_macro_not_used, WARNING, // -Wunused-macros
|
||||
"macro is not used")
|
||||
DIAG(pp_invalid_string_literal, WARNING,
|
||||
"invalid string literal, ignoring final '\'")
|
||||
"invalid string literal, ignoring final '\\'")
|
||||
|
||||
DIAG(ext_pp_import_directive, EXTENSION,
|
||||
"#import is a language extension")
|
||||
|
|
|
@ -41,6 +41,13 @@ public:
|
|||
ArgTokens.back().swap(ArgToks);
|
||||
}
|
||||
|
||||
/// getUnexpArgument - Return the unexpanded tokens for the specified formal.
|
||||
///
|
||||
const std::vector<LexerToken> &getUnexpArgument(unsigned Arg) const {
|
||||
assert(Arg < ArgTokens.size() && "Invalid ArgNo");
|
||||
return ArgTokens[Arg];
|
||||
}
|
||||
|
||||
/// getStringifiedArgument - Compute, cache, and return the specified argument
|
||||
/// that has been 'stringified' as required by the # operator.
|
||||
const LexerToken &getStringifiedArgument(unsigned ArgNo, Preprocessor &PP);
|
||||
|
|
Loading…
Reference in New Issue