summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/Lex/Lexer.cpp42
-rw-r--r--clang/Lex/Pragma.cpp20
-rw-r--r--clang/Lex/Preprocessor.cpp69
-rw-r--r--clang/include/clang/Lex/Lexer.h5
-rw-r--r--clang/include/clang/Lex/Preprocessor.h9
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 "").
OpenPOWER on IntegriCloud