From 0e7e3fc1307d2b5b274ce3438bccd7f9488b4c84 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Mon, 21 Nov 2011 00:01:14 +0000 Subject: [PATCH] Delete the depfile if we could not open a header file. We cannot generate any reasonable depfile if a header is missing. llvm-svn: 145019 --- clang/lib/Frontend/DependencyFile.cpp | 64 ++++++++++++++----------- clang/test/Driver/output-file-cleanup.c | 7 +++ 2 files changed, 43 insertions(+), 28 deletions(-) diff --git a/clang/lib/Frontend/DependencyFile.cpp b/clang/lib/Frontend/DependencyFile.cpp index ff3a12392c9f..21f5daa9ee39 100644 --- a/clang/lib/Frontend/DependencyFile.cpp +++ b/clang/lib/Frontend/DependencyFile.cpp @@ -31,11 +31,12 @@ class DependencyFileCallback : public PPCallbacks { std::vector Files; llvm::StringSet<> FilesSet; const Preprocessor *PP; + std::string OutputFile; std::vector Targets; - raw_ostream *OS; bool IncludeSystemHeaders; bool PhonyTarget; bool AddMissingHeaderDeps; + bool SeenMissingHeader; private: bool FileMatchesDepCriteria(const char *Filename, SrcMgr::CharacteristicKind FileType); @@ -44,12 +45,12 @@ private: public: DependencyFileCallback(const Preprocessor *_PP, - raw_ostream *_OS, const DependencyOutputOptions &Opts) - : PP(_PP), Targets(Opts.Targets), OS(_OS), + : PP(_PP), OutputFile(Opts.OutputFile), Targets(Opts.Targets), IncludeSystemHeaders(Opts.IncludeSystemHeaders), PhonyTarget(Opts.UsePhonyTargets), - AddMissingHeaderDeps(Opts.AddMissingHeaderDeps) {} + AddMissingHeaderDeps(Opts.AddMissingHeaderDeps), + SeenMissingHeader(false) {} virtual void FileChanged(SourceLocation Loc, FileChangeReason Reason, SrcMgr::CharacteristicKind FileType, @@ -65,8 +66,6 @@ public: virtual void EndOfMainFile() { OutputDependencyFile(); - delete OS; - OS = 0; } }; } @@ -78,19 +77,11 @@ void clang::AttachDependencyFileGen(Preprocessor &PP, return; } - std::string Err; - raw_ostream *OS(new llvm::raw_fd_ostream(Opts.OutputFile.c_str(), Err)); - if (!Err.empty()) { - PP.getDiagnostics().Report(diag::err_fe_error_opening) - << Opts.OutputFile << Err; - return; - } - // Disable the "file not found" diagnostic if the -MG option was given. if (Opts.AddMissingHeaderDeps) PP.SetSuppressIncludeNotFoundError(true); - PP.addPPCallbacks(new DependencyFileCallback(&PP, OS, Opts)); + PP.addPPCallbacks(new DependencyFileCallback(&PP, Opts)); } /// FileMatchesDepCriteria - Determine whether the given Filename should be @@ -145,8 +136,12 @@ void DependencyFileCallback::InclusionDirective(SourceLocation HashLoc, SourceLocation EndLoc, StringRef SearchPath, StringRef RelativePath) { - if (AddMissingHeaderDeps && !File) - AddFilename(FileName); + if (!File) { + if (AddMissingHeaderDeps) + AddFilename(FileName); + else + SeenMissingHeader = true; + } } void DependencyFileCallback::AddFilename(StringRef Filename) { @@ -165,6 +160,19 @@ static void PrintFilename(raw_ostream &OS, StringRef Filename) { } void DependencyFileCallback::OutputDependencyFile() { + if (SeenMissingHeader) { + llvm::sys::Path(OutputFile).eraseFromDisk(); + return; + } + + std::string Err; + llvm::raw_fd_ostream OS(OutputFile.c_str(), Err); + if (!Err.empty()) { + PP->getDiagnostics().Report(diag::err_fe_error_opening) + << OutputFile << Err; + return; + } + // Write out the dependency targets, trying to avoid overly long // lines when possible. We try our best to emit exactly the same // dependency file as GCC (4.2), assuming the included files are the @@ -179,16 +187,16 @@ void DependencyFileCallback::OutputDependencyFile() { Columns += N; } else if (Columns + N + 2 > MaxColumns) { Columns = N + 2; - *OS << " \\\n "; + OS << " \\\n "; } else { Columns += N + 1; - *OS << ' '; + OS << ' '; } // Targets already quoted as needed. - *OS << *I; + OS << *I; } - *OS << ':'; + OS << ':'; Columns += 1; // Now add each dependency in the order it was seen, but avoiding @@ -200,23 +208,23 @@ void DependencyFileCallback::OutputDependencyFile() { // break the line on the next iteration. unsigned N = I->length(); if (Columns + (N + 1) + 2 > MaxColumns) { - *OS << " \\\n "; + OS << " \\\n "; Columns = 2; } - *OS << ' '; - PrintFilename(*OS, *I); + OS << ' '; + PrintFilename(OS, *I); Columns += N + 1; } - *OS << '\n'; + OS << '\n'; // Create phony targets if requested. if (PhonyTarget && !Files.empty()) { // Skip the first entry, this is always the input file itself. for (std::vector::iterator I = Files.begin() + 1, E = Files.end(); I != E; ++I) { - *OS << '\n'; - PrintFilename(*OS, *I); - *OS << ":\n"; + OS << '\n'; + PrintFilename(OS, *I); + OS << ":\n"; } } } diff --git a/clang/test/Driver/output-file-cleanup.c b/clang/test/Driver/output-file-cleanup.c index b4745e224733..7bc17af20303 100644 --- a/clang/test/Driver/output-file-cleanup.c +++ b/clang/test/Driver/output-file-cleanup.c @@ -3,6 +3,11 @@ // RUN: test ! -f %t.o // RUN: test ! -f %t.d +// RUN: touch %t.o +// RUN: not %clang -DMISSING -o %t.o -MMD -MF %t.d %s +// RUN: test ! -f %t.o +// RUN: test ! -f %t.d + // RUN: touch %t.o // RUN: not %clang -o %t.o -MMD -MF %t.d %s // RUN: test ! -f %t.o @@ -15,6 +20,8 @@ #ifdef CRASH #pragma clang __debug crash +#elif defined(MISSING) +#include "nonexistent.h" #else invalid C code #endif