Implement the microsoft charize extension #@

llvm-svn: 38712
This commit is contained in:
Chris Lattner 2006-07-15 06:11:25 +00:00
parent 2b271db205
commit c783d1dff9
4 changed files with 43 additions and 7 deletions

View File

@ -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?

View File

@ -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:

View File

@ -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")

View File

@ -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);