diff options
Diffstat (limited to 'clang')
| -rw-r--r-- | clang/Lex/Lexer.cpp | 42 | ||||
| -rw-r--r-- | clang/Lex/Pragma.cpp | 20 | ||||
| -rw-r--r-- | clang/Lex/Preprocessor.cpp | 69 | ||||
| -rw-r--r-- | clang/include/clang/Lex/Lexer.h | 5 | ||||
| -rw-r--r-- | clang/include/clang/Lex/Preprocessor.h | 9 |
5 files changed, 92 insertions, 53 deletions
diff --git a/clang/Lex/Lexer.cpp b/clang/Lex/Lexer.cpp index 8b783d61c95..4892a21fe01 100644 --- a/clang/Lex/Lexer.cpp +++ b/clang/Lex/Lexer.cpp @@ -884,7 +884,7 @@ bool Lexer::SkipBlockComment(LexerToken &Result, const char *CurPtr) { /// LexIncludeFilename - After the preprocessor has parsed a #include, lex and /// (potentially) macro expand the filename. -std::string Lexer::LexIncludeFilename(LexerToken &FilenameTok) { +void Lexer::LexIncludeFilename(LexerToken &FilenameTok) { assert(ParsingPreprocessorDirective && ParsingFilename == false && "Must be in a preprocessing directive!"); @@ -895,46 +895,12 @@ std::string Lexer::LexIncludeFilename(LexerToken &FilenameTok) { // Lex the filename. Lex(FilenameTok); - // We should have gotten the filename now. + // We should have obtained the filename now. ParsingFilename = false; - - // No filename? - if (FilenameTok.getKind() == tok::eom) { - Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename); - return ""; - } - // Get the text form of the filename. - std::string Filename = PP.getSpelling(FilenameTok); - assert(!Filename.empty() && "Can't have tokens with empty spellings!"); - - // Make sure the filename is <x> or "x". - if (Filename[0] == '<') { - if (Filename[Filename.size()-1] != '>') { - Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename); - FilenameTok.setKind(tok::eom); - return ""; - } - } else if (Filename[0] == '"') { - if (Filename[Filename.size()-1] != '"') { - Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename); - FilenameTok.setKind(tok::eom); - return ""; - } - } else { + // No filename? + if (FilenameTok.getKind() == tok::eom) Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename); - FilenameTok.setKind(tok::eom); - return ""; - } - - // Diagnose #include "" as invalid. - if (Filename.size() == 2) { - Diag(FilenameTok.getLocation(), diag::err_pp_empty_filename); - FilenameTok.setKind(tok::eom); - return ""; - } - - return Filename; } /// ReadToEndOfLine - Read the rest of the current preprocessor line as an diff --git a/clang/Lex/Pragma.cpp b/clang/Lex/Pragma.cpp index a535cc456a2..2dd4d6f7943 100644 --- a/clang/Lex/Pragma.cpp +++ b/clang/Lex/Pragma.cpp @@ -18,6 +18,7 @@ #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" +#include "llvm/ADT/SmallVector.h" using namespace llvm; using namespace clang; @@ -246,20 +247,27 @@ void Preprocessor::HandlePragmaSystemHeader(LexerToken &SysHeaderTok) { /// void Preprocessor::HandlePragmaDependency(LexerToken &DependencyTok) { LexerToken FilenameTok; - std::string Filename = CurLexer->LexIncludeFilename(FilenameTok); + CurLexer->LexIncludeFilename(FilenameTok); // If the token kind is EOM, the error has already been diagnosed. if (FilenameTok.getKind() == tok::eom) return; - // Find out whether the filename is <x> or "x". - bool isAngled = Filename[0] == '<'; + // Reserve a buffer to get the spelling. + SmallVector<char, 128> FilenameBuffer; + FilenameBuffer.resize(FilenameTok.getLength()); + + const char *FilenameStart = &FilenameBuffer[0], *FilenameEnd; + bool isAngled = GetIncludeFilenameSpelling(FilenameTok, + FilenameStart, FilenameEnd); + // If GetIncludeFilenameSpelling set the start ptr to null, there was an + // error. + if (FilenameStart == 0) + return; // Search include directories for this file. const DirectoryLookup *CurDir; - - // Remove the quotes. - const FileEntry *File = LookupFile(&Filename[1], &Filename[Filename.size()-1], + const FileEntry *File = LookupFile(FilenameStart, FilenameEnd, isAngled, 0, CurDir); if (File == 0) return Diag(FilenameTok, diag::err_pp_file_not_found); diff --git a/clang/Lex/Preprocessor.cpp b/clang/Lex/Preprocessor.cpp index 8ee524f5b93..09fa7c1f550 100644 --- a/clang/Lex/Preprocessor.cpp +++ b/clang/Lex/Preprocessor.cpp @@ -1474,6 +1474,55 @@ void Preprocessor::HandleIdentSCCSDirective(LexerToken &Tok) { // Preprocessor Include Directive Handling. //===----------------------------------------------------------------------===// +/// GetIncludeFilenameSpelling - Turn the specified lexer token into a fully +/// checked and spelled filename, e.g. as an operand of #include. This returns +/// true if the input filename was in <>'s or false if it were in ""'s. The +/// caller is expected to provide a buffer that is large enough to hold the +/// spelling of the filename, but is also expected to handle the case when +/// this method decides to use a different buffer. +bool Preprocessor::GetIncludeFilenameSpelling(const LexerToken &FilenameTok, + const char *&BufStart, + const char *&BufEnd) { + // Get the text form of the filename. + unsigned Len = getSpelling(FilenameTok, BufStart); + BufEnd = BufStart+Len; + assert(BufStart != BufEnd && "Can't have tokens with empty spellings!"); + + // Make sure the filename is <x> or "x". + bool isAngled; + if (BufStart[0] == '<') { + if (BufEnd[-1] != '>') { + Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename); + BufStart = 0; + return true; + } + isAngled = true; + } else if (BufStart[0] == '"') { + if (BufEnd[-1] != '"') { + Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename); + BufStart = 0; + return true; + } + isAngled = false; + } else { + Diag(FilenameTok.getLocation(), diag::err_pp_expects_filename); + BufStart = 0; + return true; + } + + // Diagnose #include "" as invalid. + if (BufEnd-BufStart <= 2) { + Diag(FilenameTok.getLocation(), diag::err_pp_empty_filename); + BufStart = 0; + return ""; + } + + // Skip the brackets. + ++BufStart; + --BufEnd; + return isAngled; +} + /// HandleIncludeDirective - The "#include" tokens have just been read, read the /// file to be included from the lexer, then include it! This is a common /// routine with functionality shared between #include, #include_next and @@ -1483,12 +1532,24 @@ void Preprocessor::HandleIncludeDirective(LexerToken &IncludeTok, bool isImport) { LexerToken FilenameTok; - std::string Filename = CurLexer->LexIncludeFilename(FilenameTok); + CurLexer->LexIncludeFilename(FilenameTok); // If the token kind is EOM, the error has already been diagnosed. if (FilenameTok.getKind() == tok::eom) return; + // Reserve a buffer to get the spelling. + SmallVector<char, 128> FilenameBuffer; + FilenameBuffer.resize(FilenameTok.getLength()); + + const char *FilenameStart = &FilenameBuffer[0], *FilenameEnd; + bool isAngled = GetIncludeFilenameSpelling(FilenameTok, + FilenameStart, FilenameEnd); + // If GetIncludeFilenameSpelling set the start ptr to null, there was an + // error. + if (FilenameStart == 0) + return; + // Verify that there is nothing after the filename, other than EOM. Use the // preprocessor to lex this in case lexing the filename entered a macro. CheckEndOfDirective("#include"); @@ -1497,13 +1558,9 @@ void Preprocessor::HandleIncludeDirective(LexerToken &IncludeTok, if (IncludeMacroStack.size() == MaxAllowedIncludeStackDepth-1) return Diag(FilenameTok, diag::err_pp_include_too_deep); - // Find out whether the filename is <x> or "x". - bool isAngled = Filename[0] == '<'; - // Search include directories. const DirectoryLookup *CurDir; - // Remove the quotes from the filename. - const FileEntry *File = LookupFile(&Filename[1], &Filename[Filename.size()-1], + const FileEntry *File = LookupFile(FilenameStart, FilenameEnd, isAngled, LookupFrom, CurDir); if (File == 0) return Diag(FilenameTok, diag::err_pp_file_not_found); diff --git a/clang/include/clang/Lex/Lexer.h b/clang/include/clang/Lex/Lexer.h index 94a94d3b871..eb55331ed2a 100644 --- a/clang/include/clang/Lex/Lexer.h +++ b/clang/include/clang/Lex/Lexer.h @@ -341,9 +341,8 @@ private: /// LexIncludeFilename - After the preprocessor has parsed a #include, lex and /// (potentially) macro expand the filename. If the sequence parsed is not - /// lexically legal, emit a diagnostic and return a result EOM token. Return - /// the spelled and checked filename. - std::string LexIncludeFilename(LexerToken &Result); + /// lexically legal, emit a diagnostic and return a result EOM token. + void LexIncludeFilename(LexerToken &Result); }; diff --git a/clang/include/clang/Lex/Preprocessor.h b/clang/include/clang/Lex/Preprocessor.h index e999a8b63e5..1e52a4b98d4 100644 --- a/clang/include/clang/Lex/Preprocessor.h +++ b/clang/include/clang/Lex/Preprocessor.h @@ -403,6 +403,15 @@ private: /// start lexing tokens from it instead of the current buffer. void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir); + /// GetIncludeFilenameSpelling - Turn the specified lexer token into a fully + /// checked and spelled filename, e.g. as an operand of #include. This returns + /// true if the input filename was in <>'s or false if it were in ""'s. The + /// caller is expected to provide a buffer that is large enough to hold the + /// spelling of the filename, but is also expected to handle the case when + /// this method decides to use a different buffer. + bool GetIncludeFilenameSpelling(const LexerToken &FNTok, + const char *&BufStart, const char *&BufEnd); + /// LookupFile - Given a "foo" or <foo> reference, look up the indicated file, /// return null on failure. isAngled indicates whether the file reference is /// for system #include's or not (i.e. using <> instead of ""). |

