[cfe-commits] r99175 - in /cfe/trunk: include/clang/Basic/Diagnostic.h lib/Basic/Diagnostic.cpp lib/Basic/SourceManager.cpp

Douglas Gregor dgregor at apple.com
Mon Mar 22 08:10:57 PDT 2010


Author: dgregor
Date: Mon Mar 22 10:10:57 2010
New Revision: 99175

URL: http://llvm.org/viewvc/llvm-project?rev=99175&view=rev
Log:
Introduce the notion of a single "delayed" diagnostic into the
Diagnostic subsystem, which is used in the rare case where we find a
serious problem (i.e., an inconsistency in the file system) while
we're busy formatting another diagnostic. In this case, the delayed
diagnostic will be emitted after we're done with the other
diagnostic. This is only to be used for fatal conditions detected at
very inconvenient times, where we can neither stop the current
diagnostic in flight nor can we suppress the second error.


Modified:
    cfe/trunk/include/clang/Basic/Diagnostic.h
    cfe/trunk/lib/Basic/Diagnostic.cpp
    cfe/trunk/lib/Basic/SourceManager.cpp

Modified: cfe/trunk/include/clang/Basic/Diagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diagnostic.h?rev=99175&r1=99174&r2=99175&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Diagnostic.h (original)
+++ cfe/trunk/include/clang/Basic/Diagnostic.h Mon Mar 22 10:10:57 2010
@@ -234,6 +234,18 @@
                                   void *Cookie);
   void *ArgToStringCookie;
   ArgToStringFnTy ArgToStringFn;
+
+  /// \brief ID of the "delayed" diagnostic, which is a (typically
+  /// fatal) diagnostic that had to be delayed because it was found
+  /// while emitting another diagnostic.
+  unsigned DelayedDiagID;
+
+  /// \brief First string argument for the delayed diagnostic.
+  std::string DelayedDiagArg1;
+
+  /// \brief Second string argument for the delayed diagnostic.
+  std::string DelayedDiagArg2;
+
 public:
   explicit Diagnostic(DiagnosticClient *client = 0);
   ~Diagnostic();
@@ -400,10 +412,41 @@
   inline DiagnosticBuilder Report(FullSourceLoc Pos, unsigned DiagID);
   inline DiagnosticBuilder Report(unsigned DiagID);
 
+  /// \brief Determine whethere there is already a diagnostic in flight.
+  bool isDiagnosticInFlight() const { return CurDiagID != 0; }
+
+  /// \brief Set the "delayed" diagnostic that will be emitted once
+  /// the current diagnostic completes.
+  ///
+  ///  If a diagnostic is already in-flight but the front end must
+  ///  report a problem (e.g., with an inconsistent file system
+  ///  state), this routine sets a "delayed" diagnostic that will be
+  ///  emitted after the current diagnostic completes. This should
+  ///  only be used for fatal errors detected at inconvenient
+  ///  times. If emitting a delayed diagnostic causes a second delayed
+  ///  diagnostic to be introduced, that second delayed diagnostic
+  ///  will be ignored.
+  ///
+  /// \param DiagID The ID of the diagnostic being delayed.
+  ///
+  /// \param Arg1 A string argument that will be provided to the
+  /// diagnostic. A copy of this string will be stored in the
+  /// Diagnostic object itself.
+  ///
+  /// \param Arg2 A string argument that will be provided to the
+  /// diagnostic. A copy of this string will be stored in the
+  /// Diagnostic object itself.
+  void SetDelayedDiagnostic(unsigned DiagID, llvm::StringRef Arg1 = "",
+                            llvm::StringRef Arg2 = "");
+  
   /// \brief Clear out the current diagnostic.
   void Clear() { CurDiagID = ~0U; }
 
 private:
+  /// \brief Report the delayed diagnostic.
+  void ReportDelayed();
+
+
   /// getDiagnosticMappingInfo - Return the mapping info currently set for the
   /// specified builtin diagnostic.  This returns the high bit encoding, or zero
   /// if the field is completely uninitialized.
@@ -543,29 +586,7 @@
   ///
   /// \returns true if a diagnostic was emitted, false if the
   /// diagnostic was suppressed.
-  bool 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();
-
-    // This diagnostic is dead.
-    DiagObj = 0;
-
-    return Emitted;
-  }
+  bool Emit();
 
   /// Destructor - The dtor emits the diagnostic if it hasn't already
   /// been emitted.

Modified: cfe/trunk/lib/Basic/Diagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Diagnostic.cpp?rev=99175&r1=99174&r2=99175&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Diagnostic.cpp (original)
+++ cfe/trunk/lib/Basic/Diagnostic.cpp Mon Mar 22 10:10:57 2010
@@ -222,6 +222,8 @@
   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 @@
   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 @@
   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() {}
 

Modified: cfe/trunk/lib/Basic/SourceManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/SourceManager.cpp?rev=99175&r1=99174&r2=99175&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/SourceManager.cpp (original)
+++ cfe/trunk/lib/Basic/SourceManager.cpp Mon Mar 22 10:10:57 2010
@@ -89,15 +89,26 @@
       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);
     }
   }





More information about the cfe-commits mailing list