[cfe-commits] r61769 - /cfe/trunk/lib/Lex/MacroArgs.cpp
Chris Lattner
sabre at nondot.org
Mon Jan 5 15:04:18 PST 2009
Author: lattner
Date: Mon Jan 5 17:04:18 2009
New Revision: 61769
URL: http://llvm.org/viewvc/llvm-project?rev=61769&view=rev
Log:
Optimize stringification a bit to avoid std::string thrashing and
avoid the version of Preprocessor::getSpelling that returns an
std::string.
Modified:
cfe/trunk/lib/Lex/MacroArgs.cpp
Modified: cfe/trunk/lib/Lex/MacroArgs.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/MacroArgs.cpp?rev=61769&r1=61768&r2=61769&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/MacroArgs.cpp (original)
+++ cfe/trunk/lib/Lex/MacroArgs.cpp Mon Jan 5 17:04:18 2009
@@ -145,8 +145,9 @@
const Token *ArgTokStart = ArgToks;
// Stringify all the tokens.
- std::string Result = "\"";
- // FIXME: Optimize this loop to not use std::strings.
+ llvm::SmallString<128> Result;
+ Result += "\"";
+
bool isFirst = true;
for (; ArgToks->isNot(tok::eof); ++ArgToks) {
const Token &Tok = *ArgToks;
@@ -159,16 +160,30 @@
if (Tok.is(tok::string_literal) || // "foo"
Tok.is(tok::wide_string_literal) || // L"foo"
Tok.is(tok::char_constant)) { // 'x' and L'x'.
- Result += Lexer::Stringify(PP.getSpelling(Tok));
+ std::string Str = Lexer::Stringify(PP.getSpelling(Tok));
+ Result.append(Str.begin(), Str.end());
} else {
- // Otherwise, just append the token.
- Result += PP.getSpelling(Tok);
+ // Otherwise, just append the token. Do some gymnastics to get the token
+ // in place and avoid copies where possible.
+ unsigned CurStrLen = Result.size();
+ Result.resize(CurStrLen+Tok.getLength());
+ const char *BufPtr = &Result[CurStrLen];
+ unsigned ActualTokLen = PP.getSpelling(Tok, BufPtr);
+
+ // If getSpelling returned a pointer to an already uniqued version of the
+ // string instead of filling in BufPtr, memcpy it onto our string.
+ if (BufPtr != &Result[CurStrLen])
+ memcpy(&Result[CurStrLen], BufPtr, ActualTokLen);
+
+ // If the token was dirty, the spelling may be shorter than the token.
+ if (ActualTokLen != Tok.getLength())
+ Result.resize(CurStrLen+ActualTokLen);
}
}
// If the last character of the string is a \, and if it isn't escaped, this
// is an invalid string literal, diagnose it as specified in C99.
- if (Result[Result.size()-1] == '\\') {
+ if (Result.back() == '\\') {
// Count the number of consequtive \ characters. If even, then they are
// just escaped backslashes, otherwise it's an error.
unsigned FirstNonSlash = Result.size()-2;
@@ -178,7 +193,7 @@
if ((Result.size()-1-FirstNonSlash) & 1) {
// Diagnose errors for things like: #define F(X) #X / F(\)
PP.Diag(ArgToks[-1], diag::pp_invalid_string_literal);
- Result.erase(Result.end()-1); // remove one of the \'s.
+ Result.pop_back(); // remove one of the \'s.
}
}
Result += '"';
@@ -192,11 +207,10 @@
// Check for bogus character.
bool isBad = false;
- if (Result.size() == 3) {
+ if (Result.size() == 3)
isBad = Result[1] == '\''; // ''' is not legal. '\' already fixed above.
- } else {
+ else
isBad = (Result.size() != 4 || Result[1] != '\\'); // Not '\x'
- }
if (isBad) {
PP.Diag(ArgTokStart[0], diag::err_invalid_character_to_charify);
More information about the cfe-commits
mailing list