[cfe-commits] r67413 - in /cfe/trunk: include/clang/Basic/Diagnostic.h lib/Basic/Diagnostic.cpp lib/Sema/Sema.cpp lib/Sema/Sema.h lib/Sema/SemaTemplateInstantiate.cpp

Douglas Gregor dgregor at apple.com
Fri Mar 20 15:48:49 PDT 2009


Author: dgregor
Date: Fri Mar 20 17:48:49 2009
New Revision: 67413

URL: http://llvm.org/viewvc/llvm-project?rev=67413&view=rev
Log:
Eliminate post-diagnostic hooks. Instead, implement a Sema-specific
variant of DiagnosticBuilder that emits the template instantiation
backtrace when needed.

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

Modified: cfe/trunk/include/clang/Basic/Diagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diagnostic.h?rev=67413&r1=67412&r2=67413&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/Diagnostic.h (original)
+++ cfe/trunk/include/clang/Basic/Diagnostic.h Fri Mar 20 17:48:49 2009
@@ -125,33 +125,6 @@
   }
 };
 
-/// \brief A hook function that will be invoked after we have
-/// completed processing of the current diagnostic.
-///
-/// Hook functions are typically used to emit further diagnostics
-/// (typically notes) that give more information about this
-/// diagnostic.
-struct PostDiagnosticHook {
-  /// \brief The type of the hook function itself.
-  ///
-  /// DiagID is the ID of the diagnostic to which the hook was
-  /// attached, and Cookie is a user-specified value that can be used
-  /// to store extra data for the hook.
-  typedef void (*HookTy)(unsigned DiagID, void *Cookie);
-
-  PostDiagnosticHook() {}
-
-  PostDiagnosticHook(HookTy Hook, void *Cookie) : Hook(Hook), Cookie(Cookie) {
-    assert(Hook && "No hook provided!");
-  }
-
-  /// \brief The hook function.
-  HookTy Hook;
-
-  /// \brief The cookie that will be passed along to the hook function.
-  void *Cookie;
-};
-
 /// Diagnostic - This concrete class is used by the front-end to report
 /// problems and issues.  It massages the diagnostics (e.g. handling things like
 /// "report warnings as errors" and passes them off to the DiagnosticClient for
@@ -363,9 +336,6 @@
   /// \brief The number of code modifications hints in the
   /// CodeModificationHints array.
   unsigned char NumCodeModificationHints;
-  /// \brief The number of post-diagnostic hooks in the
-  /// PostDiagnosticHooks array.
-  unsigned char NumPostDiagnosticHooks;
 
   /// DiagArgumentsKind - This is an array of ArgumentKind::ArgumentKind enum
   /// values, with one for each argument.  This specifies whether the argument
@@ -393,15 +363,6 @@
   /// to insert, remove, or modify at a particular position.
   CodeModificationHint CodeModificationHints[MaxCodeModificationHints];
 
-  enum { MaxPostDiagnosticHooks = 10 };
-  
-  /// \brief Functions that will be invoked after the diagnostic has
-  /// been emitted.
-  PostDiagnosticHook PostDiagnosticHooks[MaxPostDiagnosticHooks];
-
-  /// \brief Whether we're already within a post-diagnostic hook.
-  bool InPostDiagnosticHook;
-
   /// ProcessDiag - This is the method used to report a diagnostic that is
   /// finally fully formed.
   void ProcessDiag();
@@ -424,14 +385,13 @@
 /// for example.
 class DiagnosticBuilder {
   mutable Diagnostic *DiagObj;
-  mutable unsigned NumArgs, NumRanges, NumCodeModificationHints, 
-                   NumPostDiagnosticHooks;
+  mutable unsigned NumArgs, NumRanges, NumCodeModificationHints;
   
   void operator=(const DiagnosticBuilder&); // DO NOT IMPLEMENT
   friend class Diagnostic;
   explicit DiagnosticBuilder(Diagnostic *diagObj)
     : DiagObj(diagObj), NumArgs(0), NumRanges(0), 
-      NumCodeModificationHints(0), NumPostDiagnosticHooks(0) {}
+      NumCodeModificationHints(0) {}
 
 public:  
   /// Copy constructor.  When copied, this "takes" the diagnostic info from the
@@ -439,19 +399,25 @@
   DiagnosticBuilder(const DiagnosticBuilder &D) {
     DiagObj = D.DiagObj;
     D.DiagObj = 0;
+    NumArgs = D.NumArgs;
+    NumRanges = D.NumRanges;
+    NumCodeModificationHints = D.NumCodeModificationHints;
   }
-  
-  /// Destructor - The dtor emits the diagnostic.
-  ~DiagnosticBuilder() {
-    // If DiagObj is null, then its soul was stolen by the copy ctor.
+
+  /// \brief Force the diagnostic builder to emit the diagnostic now.
+  ///
+  /// Once this function has been called, the DiagnosticBuilder object
+  /// should not be used again before it is destroyed.
+  void Emit() {
+    // If DiagObj is null, then its soul was stolen by the copy ctor
+    // or the user called Emit().
     if (DiagObj == 0) return;
 
-    // When destroyed, the ~DiagnosticBuilder sets the final argument count into
+    // When emitting diagnostics, we set the final argument count into
     // the Diagnostic object.
     DiagObj->NumDiagArgs = NumArgs;
     DiagObj->NumDiagRanges = NumRanges;
     DiagObj->NumCodeModificationHints = NumCodeModificationHints;
-    DiagObj->NumPostDiagnosticHooks = NumPostDiagnosticHooks;
 
     // Process the diagnostic, sending the accumulated information to the
     // DiagnosticClient.
@@ -459,7 +425,14 @@
 
     // This diagnostic is no longer in flight.
     DiagObj->CurDiagID = ~0U;
+
+    // This diagnostic is dead.
+    DiagObj = 0;
   }
+
+  /// Destructor - The dtor emits the diagnostic if it hasn't already
+  /// been emitted.
+  ~DiagnosticBuilder() { Emit(); }
   
   /// Operator bool: conversion of DiagnosticBuilder to bool always returns
   /// true.  This allows is to be used in boolean error contexts like:
@@ -492,15 +465,6 @@
            "Too many code modification hints!");
     DiagObj->CodeModificationHints[NumCodeModificationHints++] = Hint;
   }
-
-  void AddPostDiagnosticHook(const PostDiagnosticHook &Hook) const {
-    assert(!DiagObj->InPostDiagnosticHook &&
-           "Can't add a post-diagnostic hook to a diagnostic inside "
-           "a post-diagnostic hook");
-    assert(NumPostDiagnosticHooks < Diagnostic::MaxPostDiagnosticHooks &&
-           "Too many post-diagnostic hooks");
-    DiagObj->PostDiagnosticHooks[NumPostDiagnosticHooks++] = Hook;
-  }
 };
 
 inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
@@ -551,13 +515,6 @@
   return DB;
 }
 
-inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB,
-                                           const PostDiagnosticHook &Hook) {
-  DB.AddPostDiagnosticHook(Hook);
-  return DB;
-}
-  
-
 /// Report - Issue the message to the client.  DiagID is a member of the
 /// diag::kind enum.  This actually returns a new instance of DiagnosticBuilder
 /// which emits the diagnostics (through ProcessDiag) when it is destroyed.

Modified: cfe/trunk/lib/Basic/Diagnostic.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Diagnostic.cpp?rev=67413&r1=67412&r2=67413&view=diff

==============================================================================
--- cfe/trunk/lib/Basic/Diagnostic.cpp (original)
+++ cfe/trunk/lib/Basic/Diagnostic.cpp Fri Mar 20 17:48:49 2009
@@ -221,8 +221,6 @@
   
   ArgToStringFn = DummyArgToStringFn;
   ArgToStringCookie = 0;
-
-  InPostDiagnosticHook = false;
 }
 
 Diagnostic::~Diagnostic() {
@@ -411,15 +409,7 @@
   Client->HandleDiagnostic(DiagLevel, Info);
   if (Client->IncludeInDiagnosticCounts()) ++NumDiagnostics;
 
-  // Invoke any post-diagnostic hooks.
-  unsigned LastDiag = CurDiagID;
   CurDiagID = ~0U;
-  
-  InPostDiagnosticHook = true;
-  for (unsigned Hook = 0; Hook < NumPostDiagnosticHooks; ++Hook)
-    PostDiagnosticHooks[Hook].Hook(LastDiag, 
-                                   PostDiagnosticHooks[Hook].Cookie);
-  InPostDiagnosticHook = false;
 }
 
 

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=67413&r1=67412&r2=67413&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Fri Mar 20 17:48:49 2009
@@ -295,3 +295,19 @@
   return 0;
 }
 
+Sema::SemaDiagnosticBuilder::~SemaDiagnosticBuilder() {
+  this->Emit();
+  
+  // If this is not a note, and we're in a template instantiation
+  // that is different from the last template instantiation where
+  // we emitted an error, print a template instantiation
+  // backtrace.
+  if (!SemaRef.Diags.isBuiltinNote(DiagID) &&
+      !SemaRef.ActiveTemplateInstantiations.empty() &&
+      SemaRef.ActiveTemplateInstantiations.back() 
+        != SemaRef.LastTemplateInstantiationErrorContext) {
+    SemaRef.PrintInstantiationStack();
+    SemaRef.LastTemplateInstantiationErrorContext 
+      = SemaRef.ActiveTemplateInstantiations.back();
+  }
+}

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=67413&r1=67412&r2=67413&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Fri Mar 20 17:48:49 2009
@@ -241,15 +241,30 @@
   Diagnostic &getDiagnostics() const { return Diags; }
   SourceManager &getSourceManager() const { return SourceMgr; }
 
-  /// The primitive diagnostic helpers.
-  DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
+  /// \brief Helper class that creates diagnostics with optional
+  /// template instantiation stacks.
+  ///
+  /// This class provides a wrapper around the basic DiagnosticBuilder
+  /// class that emits diagnostics. SemaDiagnosticBuilder is
+  /// responsible for emitting the diagnostic (as DiagnosticBuilder
+  /// does) and, if the diagnostic comes from inside a template
+  /// instantiation, printing the template instantiation stack as
+  /// well.
+  class SemaDiagnosticBuilder : public DiagnosticBuilder {
+    Sema &SemaRef;
+    unsigned DiagID;
+
+  public:
+    SemaDiagnosticBuilder(DiagnosticBuilder &DB, Sema &SemaRef, unsigned DiagID)
+      : DiagnosticBuilder(DB), SemaRef(SemaRef), DiagID(DiagID) { }
+
+    ~SemaDiagnosticBuilder();
+  };
+
+  /// \brief Emit a diagnostic.
+  SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) {
     DiagnosticBuilder DB = Diags.Report(FullSourceLoc(Loc, SourceMgr), DiagID);
-    if (!Diags.isBuiltinNote(DiagID) && 
-        !ActiveTemplateInstantiations.empty() &&
-        ActiveTemplateInstantiations.back() 
-          != LastTemplateInstantiationErrorContext)
-      DB << PostDiagnosticHook(PrintInstantiationStackHook, this);
-    return DB;
+    return SemaDiagnosticBuilder(DB, *this, DiagID);
   }
 
   virtual void DeleteExpr(ExprTy *E);
@@ -1858,7 +1873,6 @@
     operator=(const InstantiatingTemplate&); // not implemented
   };
 
-  static void PrintInstantiationStackHook(unsigned DiagID, void *Cookie);
   void PrintInstantiationStack();
 
   QualType InstantiateType(QualType T, const TemplateArgument *TemplateArgs,

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=67413&r1=67412&r2=67413&view=diff

==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Fri Mar 20 17:48:49 2009
@@ -93,14 +93,6 @@
   return true;
 }
 
-/// \brief Post-diagnostic hook for printing the instantiation stack.
-void Sema::PrintInstantiationStackHook(unsigned, void *Cookie) {
-  Sema &SemaRef = *static_cast<Sema*>(Cookie);
-  SemaRef.PrintInstantiationStack();
-  SemaRef.LastTemplateInstantiationErrorContext 
-    = SemaRef.ActiveTemplateInstantiations.back();
-}
-
 /// \brief Prints the current instantiation stack through a series of
 /// notes.
 void Sema::PrintInstantiationStack() {





More information about the cfe-commits mailing list