diff options
Diffstat (limited to 'lib/Basic')
-rw-r--r-- | lib/Basic/Diagnostic.cpp | 47 | ||||
-rw-r--r-- | lib/Basic/SourceManager.cpp | 17 |
2 files changed, 61 insertions, 3 deletions
diff --git a/lib/Basic/Diagnostic.cpp b/lib/Basic/Diagnostic.cpp index f7ec873e4c..227c175dc0 100644 --- a/lib/Basic/Diagnostic.cpp +++ b/lib/Basic/Diagnostic.cpp @@ -222,6 +222,8 @@ Diagnostic::Diagnostic(DiagnosticClient *client) : Client(client) { ArgToStringFn = DummyArgToStringFn; ArgToStringCookie = 0; + DelayedDiagID = 0; + // Set all mappings to 'unset'. DiagMappings BlankDiags(diag::DIAG_UPPER_LIMIT/2, 0); DiagMappingsStack.push_back(BlankDiags); @@ -289,6 +291,23 @@ const char *Diagnostic::getDescription(unsigned DiagID) const { return CustomDiagInfo->getDescription(DiagID); } +void Diagnostic::SetDelayedDiagnostic(unsigned DiagID, llvm::StringRef Arg1, + llvm::StringRef Arg2) { + if (DelayedDiagID) + return; + + DelayedDiagID = DiagID; + DelayedDiagArg1 = Arg1; + DelayedDiagArg1 = Arg2; +} + +void Diagnostic::ReportDelayed() { + Report(DelayedDiagID) << DelayedDiagArg1 << DelayedDiagArg2; + DelayedDiagID = 0; + DelayedDiagArg1.clear(); + DelayedDiagArg2.clear(); +} + /// getDiagnosticLevel - Based on the way the client configured the Diagnostic /// object, classify the specified diagnostic ID into a Level, consumable by /// the DiagnosticClient. @@ -532,6 +551,34 @@ bool Diagnostic::ProcessDiag() { return true; } +bool DiagnosticBuilder::Emit() { + // If DiagObj is null, then its soul was stolen by the copy ctor + // or the user called Emit(). + if (DiagObj == 0) return false; + + // When emitting diagnostics, we set the final argument count into + // the Diagnostic object. + DiagObj->NumDiagArgs = NumArgs; + DiagObj->NumDiagRanges = NumRanges; + DiagObj->NumCodeModificationHints = NumCodeModificationHints; + + // Process the diagnostic, sending the accumulated information to the + // DiagnosticClient. + bool Emitted = DiagObj->ProcessDiag(); + + // Clear out the current diagnostic object. + DiagObj->Clear(); + + // If there was a delayed diagnostic, emit it now. + if (DiagObj->DelayedDiagID) + DiagObj->ReportDelayed(); + + // This diagnostic is dead. + DiagObj = 0; + + return Emitted; +} + DiagnosticClient::~DiagnosticClient() {} diff --git a/lib/Basic/SourceManager.cpp b/lib/Basic/SourceManager.cpp index c34f3e2543..27cb9bebde 100644 --- a/lib/Basic/SourceManager.cpp +++ b/lib/Basic/SourceManager.cpp @@ -89,15 +89,26 @@ const llvm::MemoryBuffer *ContentCache::getBuffer(Diagnostic &Diag, char *Ptr = const_cast<char*>(Buffer.getPointer()->getBufferStart()); for (unsigned i = 0, e = Entry->getSize(); i != e; ++i) Ptr[i] = FillStr[i % FillStr.size()]; - Diag.Report(diag::err_cannot_open_file) - << Entry->getName() << ErrorStr; + + if (Diag.isDiagnosticInFlight()) + Diag.SetDelayedDiagnostic(diag::err_cannot_open_file, + Entry->getName(), ErrorStr); + else + Diag.Report(diag::err_cannot_open_file) + << Entry->getName() << ErrorStr; + Buffer.setInt(true); } else if (FileInfo.st_size != Entry->getSize() || FileInfo.st_mtime != Entry->getModificationTime()) { // Check that the file's size, modification time, and inode are // the same as in the file entry (which may have come from a // stat cache). - Diag.Report(diag::err_file_modified) << Entry->getName(); + if (Diag.isDiagnosticInFlight()) + Diag.SetDelayedDiagnostic(diag::err_file_modified, + Entry->getName()); + else + Diag.Report(diag::err_file_modified) << Entry->getName(); + Buffer.setInt(true); } } |