From dbf8ee630e4c86e5150492eaf8dbceea3c718ee1 Mon Sep 17 00:00:00 2001 From: Douglas Gregor <dgregor@apple.com> Date: Wed, 17 Mar 2010 15:44:30 +0000 Subject: [PATCH] Entering the main source file in the preprocessor can fail if the source file has been changed. Handle that failure more gracefully. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@98727 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Lex/Preprocessor.h | 2 +- lib/Frontend/CacheTokens.cpp | 3 ++- lib/Frontend/FrontendActions.cpp | 12 ++++++++---- lib/Frontend/PrintPreprocessedOutput.cpp | 6 ++++-- lib/Frontend/RewriteMacros.cpp | 3 ++- lib/Lex/Preprocessor.cpp | 9 ++++----- lib/Sema/ParseAST.cpp | 3 ++- test/Misc/changed-files.c | 3 +++ 8 files changed, 26 insertions(+), 15 deletions(-) create mode 100644 test/Misc/changed-files.c diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 3ef1fcdbda3..a4910f714fd 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -350,7 +350,7 @@ public: /// EnterMainSourceFile - Enter the specified FileID as the main source file, /// which implicitly adds the builtin defines etc. - void EnterMainSourceFile(); + bool EnterMainSourceFile(); /// EnterSourceFile - Add a source file to the top of the include stack and /// start lexing tokens from it instead of the current buffer. Return true diff --git a/lib/Frontend/CacheTokens.cpp b/lib/Frontend/CacheTokens.cpp index 02d6cec8fca..199be3d5438 100644 --- a/lib/Frontend/CacheTokens.cpp +++ b/lib/Frontend/CacheTokens.cpp @@ -549,7 +549,8 @@ void clang::CacheTokens(Preprocessor &PP, llvm::raw_fd_ostream* OS) { // Lex through the entire file. This will populate SourceManager with // all of the header information. Token Tok; - PP.EnterMainSourceFile(); + if (PP.EnterMainSourceFile()) + return; do { PP.Lex(Tok); } while (Tok.isNot(tok::eof)); // Generate the PTH file. diff --git a/lib/Frontend/FrontendActions.cpp b/lib/Frontend/FrontendActions.cpp index 1e210b42e6d..1077f9eb341 100644 --- a/lib/Frontend/FrontendActions.cpp +++ b/lib/Frontend/FrontendActions.cpp @@ -185,7 +185,8 @@ void DumpTokensAction::ExecuteAction() { Preprocessor &PP = getCompilerInstance().getPreprocessor(); // Start preprocessing the specified input file. Token Tok; - PP.EnterMainSourceFile(); + if (PP.EnterMainSourceFile()) + return; do { PP.Lex(Tok); PP.DumpToken(Tok, true); @@ -213,7 +214,8 @@ void ParseOnlyAction::ExecuteAction() { llvm::OwningPtr<Action> PA(new MinimalAction(PP)); Parser P(PP, *PA); - PP.EnterMainSourceFile(); + if (PP.EnterMainSourceFile()) + return; P.ParseTranslationUnit(); } @@ -222,7 +224,8 @@ void PreprocessOnlyAction::ExecuteAction() { Token Tok; // Start parsing the specified input file. - PP.EnterMainSourceFile(); + if (PP.EnterMainSourceFile()) + return; do { PP.Lex(Tok); } while (Tok.isNot(tok::eof)); @@ -237,7 +240,8 @@ void PrintParseAction::ExecuteAction() { llvm::OwningPtr<Action> PA(CreatePrintParserActionsAction(PP, OS)); Parser P(PP, *PA); - PP.EnterMainSourceFile(); + if (PP.EnterMainSourceFile()) + return; P.ParseTranslationUnit(); } diff --git a/lib/Frontend/PrintPreprocessedOutput.cpp b/lib/Frontend/PrintPreprocessedOutput.cpp index 44e0e139060..02afd24c246 100644 --- a/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/lib/Frontend/PrintPreprocessedOutput.cpp @@ -448,7 +448,8 @@ static int MacroIDCompare(const void* a, const void* b) { static void DoPrintMacros(Preprocessor &PP, llvm::raw_ostream *OS) { // -dM mode just scans and ignores all tokens in the files, then dumps out // the macro table at the end. - PP.EnterMainSourceFile(); + if (PP.EnterMainSourceFile()) + return; Token Tok; do PP.Lex(Tok); @@ -495,7 +496,8 @@ void clang::DoPrintPreprocessedInput(Preprocessor &PP, llvm::raw_ostream *OS, PP.addPPCallbacks(Callbacks); // After we have configured the preprocessor, enter the main file. - PP.EnterMainSourceFile(); + if (PP.EnterMainSourceFile()) + return; // Consume all of the tokens that come from the predefines buffer. Those // should not be emitted into the output and are guaranteed to be at the diff --git a/lib/Frontend/RewriteMacros.cpp b/lib/Frontend/RewriteMacros.cpp index 954e8e23cac..4ffb2978db7 100644 --- a/lib/Frontend/RewriteMacros.cpp +++ b/lib/Frontend/RewriteMacros.cpp @@ -101,7 +101,8 @@ void clang::RewriteMacrosInInput(Preprocessor &PP, llvm::raw_ostream *OS) { // Get the first preprocessing token. - PP.EnterMainSourceFile(); + if (PP.EnterMainSourceFile()) + return; Token PPTok; PP.Lex(PPTok); diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index a86799aafae..917a2e7412f 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -488,7 +488,7 @@ SourceLocation Preprocessor::getLocForEndOfToken(SourceLocation Loc, /// EnterMainSourceFile - Enter the specified FileID as the main source file, /// which implicitly adds the builtin defines etc. -void Preprocessor::EnterMainSourceFile() { +bool Preprocessor::EnterMainSourceFile() { // We do not allow the preprocessor to reenter the main file. Doing so will // cause FileID's to accumulate information from both runs (e.g. #line // information) and predefined macros aren't guaranteed to be set properly. @@ -497,8 +497,8 @@ void Preprocessor::EnterMainSourceFile() { // Enter the main file source buffer. std::string ErrorStr; - bool Res = EnterSourceFile(MainFileID, 0, ErrorStr); - assert(!Res && "Entering main file should not fail!"); + if (EnterSourceFile(MainFileID, 0, ErrorStr)) + return true; // Tell the header info that the main file was entered. If the file is later // #imported, it won't be re-entered. @@ -515,8 +515,7 @@ void Preprocessor::EnterMainSourceFile() { assert(!FID.isInvalid() && "Could not create FileID for predefines?"); // Start parsing the predefines. - Res = EnterSourceFile(FID, 0, ErrorStr); - assert(!Res && "Entering predefines should not fail!"); + return EnterSourceFile(FID, 0, ErrorStr); } diff --git a/lib/Sema/ParseAST.cpp b/lib/Sema/ParseAST.cpp index 898b3c230e8..7cd39895f6f 100644 --- a/lib/Sema/ParseAST.cpp +++ b/lib/Sema/ParseAST.cpp @@ -44,7 +44,8 @@ void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer, Sema S(PP, Ctx, *Consumer, CompleteTranslationUnit, CompletionConsumer); Parser P(PP, S); - PP.EnterMainSourceFile(); + if (PP.EnterMainSourceFile()) + return; // Initialize the parser. P.Initialize(); diff --git a/test/Misc/changed-files.c b/test/Misc/changed-files.c new file mode 100644 index 00000000000..deeb02a38a6 --- /dev/null +++ b/test/Misc/changed-files.c @@ -0,0 +1,3 @@ +// RUN: touch %t.c +// RUN: not %clang -E %t.c -o %t.c 2> %t.stderr +// RUN: grep "modified" %t.stderr -- GitLab