From ef9eae1c444ae1ecd7a5dd5d9e937d420343b3e1 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Tue, 4 Jul 2006 22:33:12 +0000 Subject: [PATCH] Change the Preprocessor::getSpelling interface to let it be zero-copy in the common case. llvm-svn: 38671 --- clang/Driver/PrintPreprocessedOutput.cpp | 6 +++--- clang/Lex/Lexer.cpp | 2 +- clang/Lex/Preprocessor.cpp | 21 ++++++++++++--------- clang/include/clang/Lex/Preprocessor.h | 8 +++++++- 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/clang/Driver/PrintPreprocessedOutput.cpp b/clang/Driver/PrintPreprocessedOutput.cpp index 8485354c8791..1ca31c4bcd63 100644 --- a/clang/Driver/PrintPreprocessedOutput.cpp +++ b/clang/Driver/PrintPreprocessedOutput.cpp @@ -297,9 +297,9 @@ void clang::DoPrintPreprocessedInput(Preprocessor &PP) { } if (Tok.getLength() < 256) { - unsigned Len = PP.getSpelling(Tok, Buffer); - Buffer[Len] = 0; - OutputString(Buffer, Len); + const char *TokPtr = Buffer; + unsigned Len = PP.getSpelling(Tok, TokPtr); + OutputString(TokPtr, Len); } else { std::string S = PP.getSpelling(Tok); OutputString(&S[0], S.size()); diff --git a/clang/Lex/Lexer.cpp b/clang/Lex/Lexer.cpp index 325c013cdee9..d54ecf0fbe7f 100644 --- a/clang/Lex/Lexer.cpp +++ b/clang/Lex/Lexer.cpp @@ -360,7 +360,7 @@ FinishIdentifier: II = PP.getIdentifierInfo(IdStart, IdEnd); } else { // Cleaning needed, alloca a buffer, clean into it, then use the buffer. - char *TmpBuf = (char*)alloca(Result.getLength()); + const char *TmpBuf = (char*)alloca(Result.getLength()); unsigned Size = PP.getSpelling(Result, TmpBuf); II = PP.getIdentifierInfo(TmpBuf, TmpBuf+Size); } diff --git a/clang/Lex/Preprocessor.cpp b/clang/Lex/Preprocessor.cpp index b5cae2df2f66..b161263423d1 100644 --- a/clang/Lex/Preprocessor.cpp +++ b/clang/Lex/Preprocessor.cpp @@ -218,10 +218,10 @@ std::string Preprocessor::getSpelling(const LexerToken &Tok) const { if (!Tok.needsCleaning()) return std::string(TokStart, TokStart+Tok.getLength()); - // Otherwise, hard case, relex the characters into the string. std::string Result; Result.reserve(Tok.getLength()); + // Otherwise, hard case, relex the characters into the string. for (const char *Ptr = TokStart, *End = TokStart+Tok.getLength(); Ptr != End; ) { unsigned CharSize; @@ -237,7 +237,14 @@ std::string Preprocessor::getSpelling(const LexerToken &Tok) const { /// preallocated buffer, instead of as an std::string. The caller is required /// to allocate enough space for the token, which is guaranteed to be at least /// Tok.getLength() bytes long. The actual length of the token is returned. -unsigned Preprocessor::getSpelling(const LexerToken &Tok, char *Buffer) const { +/// +/// Note that this method may do two possible things: it may either fill in +/// the buffer specified with characters, or it may *change the input pointer* +/// to point to a constant buffer with the data already in it (avoiding a +/// copy). The caller is not allowed to modify the returned buffer pointer +/// if an internal buffer is returned. +unsigned Preprocessor::getSpelling(const LexerToken &Tok, + const char *&Buffer) const { assert((int)Tok.getLength() >= 0 && "Token character range is bogus!"); const char *TokStart = SourceMgr.getCharacterData(Tok.getLocation()); @@ -245,15 +252,11 @@ unsigned Preprocessor::getSpelling(const LexerToken &Tok, char *Buffer) const { // If this token contains nothing interesting, return it directly. if (!Tok.needsCleaning()) { - unsigned Size = Tok.getLength(); - memcpy(Buffer, TokStart, Size); - return Size; + Buffer = TokStart; + return Tok.getLength(); } // Otherwise, hard case, relex the characters into the string. - std::string Result; - Result.reserve(Tok.getLength()); - - char *OutBuf = Buffer; + char *OutBuf = const_cast(Buffer); for (const char *Ptr = TokStart, *End = TokStart+Tok.getLength(); Ptr != End; ) { unsigned CharSize; diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index 8ad55c1ee908..8b70274d47d2 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -365,7 +365,13 @@ public: /// preallocated buffer, instead of as an std::string. The caller is required /// to allocate enough space for the token, which is guaranteed to be at least /// Tok.getLength() bytes long. The length of the actual result is returned. - unsigned getSpelling(const LexerToken &Tok, char *Buffer) const; + /// + /// Note that this method may do two possible things: it may either fill in + /// the buffer specified with characters, or it may *change the input pointer* + /// to point to a constant buffer with the data already in it (avoiding a + /// copy). The caller is not allowed to modify the returned buffer pointer + /// if an internal buffer is returned. + unsigned getSpelling(const LexerToken &Tok, const char *&Buffer) const; /// DumpToken - Print the token to stderr, used for debugging. ///