forked from OSchip/llvm-project
parent
ba6df9122f
commit
269c232e67
|
@ -116,8 +116,9 @@ const FileEntry *FileManager::getFile(const std::string &Filename) {
|
|||
|
||||
// Otherwise, we don't have this directory yet, add it.
|
||||
FileEntry *FE = new FileEntry();
|
||||
FE->Size = StatBuf.st_size;
|
||||
FE->Name = Filename;
|
||||
FE->Size = StatBuf.st_size;
|
||||
FE->ModTime = StatBuf.st_mtime;
|
||||
FE->Dir = DirInfo;
|
||||
FE->UID = NextFileUID++;
|
||||
return Ent = UFE = FE;
|
||||
|
|
|
@ -783,7 +783,7 @@ void Lexer::SkipBlockComment(LexerToken &Result, const char *CurPtr) {
|
|||
|
||||
/// LexIncludeFilename - After the preprocessor has parsed a #include, lex and
|
||||
/// (potentially) macro expand the filename.
|
||||
void Lexer::LexIncludeFilename(LexerToken &Result) {
|
||||
std::string Lexer::LexIncludeFilename(LexerToken &FilenameTok) {
|
||||
assert(ParsingPreprocessorDirective &&
|
||||
ParsingFilename == false &&
|
||||
"Must be in a preprocessing directive!");
|
||||
|
@ -791,33 +791,49 @@ void Lexer::LexIncludeFilename(LexerToken &Result) {
|
|||
// We are now parsing a filename!
|
||||
ParsingFilename = true;
|
||||
|
||||
// There should be exactly two tokens here if everything is good: first the
|
||||
// filename, then the EOM.
|
||||
Lex(Result);
|
||||
// Lex the filename.
|
||||
Lex(FilenameTok);
|
||||
|
||||
// We should have gotten the filename now.
|
||||
ParsingFilename = false;
|
||||
|
||||
// No filename?
|
||||
if (Result.getKind() == tok::eom) {
|
||||
PP.Diag(Result, diag::err_pp_expects_filename);
|
||||
return;
|
||||
if (FilenameTok.getKind() == tok::eom) {
|
||||
PP.Diag(FilenameTok, diag::err_pp_expects_filename);
|
||||
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.
|
||||
LexerToken EndTok;
|
||||
PP.Lex(EndTok);
|
||||
// Get the text form of the filename.
|
||||
std::string Filename = PP.getSpelling(FilenameTok);
|
||||
assert(!Filename.empty() && "Can't have tokens with empty spellings!");
|
||||
|
||||
if (EndTok.getKind() != tok::eom) {
|
||||
PP.Diag(EndTok, diag::ext_pp_extra_tokens_at_eol, "#include");
|
||||
|
||||
// Lex until the end of the preprocessor directive line.
|
||||
while (EndTok.getKind() != tok::eom)
|
||||
PP.Lex(EndTok);
|
||||
|
||||
Result.SetKind(tok::eom);
|
||||
// Make sure the filename is <x> or "x".
|
||||
if (Filename[0] == '<') {
|
||||
if (Filename[Filename.size()-1] != '>') {
|
||||
PP.Diag(FilenameTok, diag::err_pp_expects_filename);
|
||||
FilenameTok.SetKind(tok::eom);
|
||||
return "";
|
||||
}
|
||||
} else if (Filename[0] == '"') {
|
||||
if (Filename[Filename.size()-1] != '"') {
|
||||
PP.Diag(FilenameTok, diag::err_pp_expects_filename);
|
||||
FilenameTok.SetKind(tok::eom);
|
||||
return "";
|
||||
}
|
||||
} else {
|
||||
PP.Diag(FilenameTok, diag::err_pp_expects_filename);
|
||||
FilenameTok.SetKind(tok::eom);
|
||||
return "";
|
||||
}
|
||||
|
||||
// Diagnose #include "" as invalid.
|
||||
if (Filename.size() == 2) {
|
||||
PP.Diag(FilenameTok, diag::err_pp_empty_filename);
|
||||
FilenameTok.SetKind(tok::eom);
|
||||
return "";
|
||||
}
|
||||
|
||||
return Filename;
|
||||
}
|
||||
|
||||
/// ReadToEndOfLine - Read the rest of the current preprocessor line as an
|
||||
|
|
|
@ -938,41 +938,26 @@ void Preprocessor::HandleIncludeDirective(LexerToken &IncludeTok,
|
|||
bool isImport) {
|
||||
++NumIncluded;
|
||||
LexerToken FilenameTok;
|
||||
CurLexer->LexIncludeFilename(FilenameTok);
|
||||
std::string Filename = CurLexer->LexIncludeFilename(FilenameTok);
|
||||
|
||||
// If the token kind is EOM, the error has already been diagnosed.
|
||||
if (FilenameTok.getKind() == tok::eom)
|
||||
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");
|
||||
|
||||
// Check that we don't have infinite #include recursion.
|
||||
if (IncludeStack.size() == MaxAllowedIncludeStackDepth-1)
|
||||
return Diag(FilenameTok, diag::err_pp_include_too_deep);
|
||||
|
||||
// Get the text form of the filename.
|
||||
std::string Filename = getSpelling(FilenameTok);
|
||||
assert(!Filename.empty() && "Can't have tokens with empty spellings!");
|
||||
|
||||
// Make sure the filename is <x> or "x".
|
||||
bool isAngled;
|
||||
if (Filename[0] == '<') {
|
||||
isAngled = true;
|
||||
if (Filename[Filename.size()-1] != '>')
|
||||
return Diag(FilenameTok, diag::err_pp_expects_filename);
|
||||
} else if (Filename[0] == '"') {
|
||||
isAngled = false;
|
||||
if (Filename[Filename.size()-1] != '"')
|
||||
return Diag(FilenameTok, diag::err_pp_expects_filename);
|
||||
} else {
|
||||
return Diag(FilenameTok, diag::err_pp_expects_filename);
|
||||
}
|
||||
// Find out whether the filename is <x> or "x".
|
||||
bool isAngled = Filename[0] == '<';
|
||||
|
||||
// Remove the quotes.
|
||||
Filename = std::string(Filename.begin()+1, Filename.end()-1);
|
||||
|
||||
// Diagnose #include "" as invalid.
|
||||
if (Filename.empty())
|
||||
return Diag(FilenameTok, diag::err_pp_empty_filename);
|
||||
|
||||
// Search include directories.
|
||||
const DirectoryLookup *CurDir;
|
||||
const FileEntry *File = LookupFile(Filename, isAngled, LookupFrom, CurDir);
|
||||
|
@ -1325,6 +1310,8 @@ void Preprocessor::HandlePragmaPoison(LexerToken &PoisonTok) {
|
|||
}
|
||||
}
|
||||
|
||||
/// HandlePragmaSystemHeader - Implement #pragma GCC system_header. We know
|
||||
/// that the whole directive has been parsed.
|
||||
void Preprocessor::HandlePragmaSystemHeader(LexerToken &SysHeaderTok) {
|
||||
if (IncludeStack.empty()) {
|
||||
Diag(SysHeaderTok, diag::pp_pragma_sysheader_in_main_file);
|
||||
|
@ -1343,6 +1330,52 @@ void Preprocessor::HandlePragmaSystemHeader(LexerToken &SysHeaderTok) {
|
|||
SystemHeaderPragma, DirectoryLookup::SystemHeaderDir);
|
||||
}
|
||||
|
||||
/// HandlePragmaDependency - Handle #pragma GCC dependency "foo" blah.
|
||||
///
|
||||
void Preprocessor::HandlePragmaDependency(LexerToken &DependencyTok) {
|
||||
LexerToken FilenameTok;
|
||||
std::string Filename = 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] == '<';
|
||||
|
||||
// Remove the quotes.
|
||||
Filename = std::string(Filename.begin()+1, Filename.end()-1);
|
||||
|
||||
// Search include directories.
|
||||
const DirectoryLookup *CurDir;
|
||||
const FileEntry *File = LookupFile(Filename, isAngled, 0, CurDir);
|
||||
if (File == 0)
|
||||
return Diag(FilenameTok, diag::err_pp_file_not_found);
|
||||
|
||||
Lexer *TheLexer = CurLexer;
|
||||
if (TheLexer == 0) {
|
||||
assert(!IncludeStack.empty() && "No current lexer?");
|
||||
TheLexer = IncludeStack.back().TheLexer;
|
||||
}
|
||||
const FileEntry *CurFile =
|
||||
SourceMgr.getFileEntryForFileID(TheLexer->getCurFileID());
|
||||
|
||||
// If this file is older than the file it depends on, emit a diagnostic.
|
||||
if (CurFile && CurFile->getModificationTime() < File->getModificationTime()) {
|
||||
// Lex tokens at the end of the message and include them in the message.
|
||||
std::string Message;
|
||||
Lex(DependencyTok);
|
||||
while (DependencyTok.getKind() != tok::eom) {
|
||||
Message += getSpelling(DependencyTok) + " ";
|
||||
Lex(DependencyTok);
|
||||
}
|
||||
|
||||
Message.erase(Message.end()-1);
|
||||
Diag(FilenameTok, diag::pp_out_of_date_dependency, Message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// AddPragmaHandler - Add the specified pragma handler to the preprocessor.
|
||||
/// If 'Namespace' is non-null, then it is a token required to exist on the
|
||||
/// pragma line before the pragma string starts, e.g. "STDC" or "GCC".
|
||||
|
@ -1398,6 +1431,12 @@ struct PragmaSystemHeaderHandler : public PragmaHandler {
|
|||
PP.CheckEndOfDirective("#pragma");
|
||||
}
|
||||
};
|
||||
struct PragmaDependencyHandler : public PragmaHandler {
|
||||
PragmaDependencyHandler(const IdentifierTokenInfo *ID) : PragmaHandler(ID) {}
|
||||
virtual void HandlePragma(Preprocessor &PP, LexerToken &DepToken) {
|
||||
PP.HandlePragmaDependency(DepToken);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
@ -1408,4 +1447,6 @@ void Preprocessor::RegisterBuiltinPragmas() {
|
|||
AddPragmaHandler("GCC", new PragmaPoisonHandler(getIdentifierInfo("poison")));
|
||||
AddPragmaHandler("GCC", new PragmaSystemHeaderHandler(
|
||||
getIdentifierInfo("system_header")));
|
||||
AddPragmaHandler("GCC", new PragmaDependencyHandler(
|
||||
getIdentifierInfo("dependency")));
|
||||
}
|
||||
|
|
|
@ -92,6 +92,8 @@ DIAG(pp_pragma_sysheader_in_main_file, WARNING,
|
|||
"#pragma system_header ignored in main file")
|
||||
DIAG(pp_poisoning_existing_macro, WARNING,
|
||||
"poisoning existing macro")
|
||||
DIAG(pp_out_of_date_dependency, WARNING,
|
||||
"current file is older than dependency %s")
|
||||
|
||||
DIAG(ext_pp_import_directive, EXTENSION,
|
||||
"#import is a language extension")
|
||||
|
|
|
@ -38,6 +38,7 @@ public:
|
|||
class FileEntry {
|
||||
std::string Name; // Name of the directory.
|
||||
off_t Size; // File size in bytes.
|
||||
time_t ModTime; // Modification time of file.
|
||||
const DirectoryEntry *Dir; // Directory file lives in.
|
||||
unsigned UID; // A unique (small) ID for the file.
|
||||
FileEntry() {}
|
||||
|
@ -47,6 +48,7 @@ public:
|
|||
const std::string &getName() const { return Name; }
|
||||
off_t getSize() const { return Size; }
|
||||
unsigned getUID() const { return UID; }
|
||||
time_t getModificationTime() const { return ModTime; }
|
||||
|
||||
/// getDir - Return the directory the file lives in.
|
||||
///
|
||||
|
|
|
@ -288,8 +288,9 @@ 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.
|
||||
void LexIncludeFilename(LexerToken &Result);
|
||||
/// lexically legal, emit a diagnostic and return a result EOM token. Return
|
||||
/// the spelled and checked filename.
|
||||
std::string LexIncludeFilename(LexerToken &Result);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -433,6 +433,7 @@ public:
|
|||
void HandlePragmaOnce(LexerToken &OnceTok);
|
||||
void HandlePragmaPoison(LexerToken &PoisonTok);
|
||||
void HandlePragmaSystemHeader(LexerToken &SysHeaderTok);
|
||||
void HandlePragmaDependency(LexerToken &DependencyTok);
|
||||
};
|
||||
|
||||
} // end namespace clang
|
||||
|
|
Loading…
Reference in New Issue