]> granicus.if.org Git - clang/commitdiff
This reworks some of the Diagnostic interfaces a bit to change how diagnostics
authorChris Lattner <sabre@nondot.org>
Tue, 18 Nov 2008 07:04:44 +0000 (07:04 +0000)
committerChris Lattner <sabre@nondot.org>
Tue, 18 Nov 2008 07:04:44 +0000 (07:04 +0000)
are formed.  In particular, a diagnostic with all its strings and ranges is now
packaged up and sent to DiagnosticClients as a DiagnosticInfo instead of as a
ton of random stuff.  This has the benefit of simplifying the interface, making
it more extensible, and allowing us to do more checking for things like access
past the end of the various arrays passed in.

In addition to introducing DiagnosticInfo, this also substantially changes how
Diagnostic::Report works.  Instead of being passed in all of the info required
to issue a diagnostic, Report now takes only the required info (a location and
ID) and returns a fresh DiagnosticInfo *by value*.  The caller is then free to
stuff strings and ranges into the DiagnosticInfo with the << operator.  When
the dtor runs on the DiagnosticInfo object (which should happen at the end of
the statement), the diagnostic is actually emitted with all of the accumulated
information.  This is a somewhat tricky dance, but it means that the
accumulated DiagnosticInfo is allowed to keep pointers to other expression
temporaries without those pointers getting invalidated.

This is just the minimal change to get this stuff working, but this will allow
us to eliminate the zillions of variant "Diag" methods scattered throughout
(e.g.) sema.  For example, instead of calling:

  Diag(BuiltinLoc, diag::err_overload_no_match, typeNames,
       SourceRange(BuiltinLoc, RParenLoc));

We will soon be able to just do:

  Diag(BuiltinLoc, diag::err_overload_no_match)
      << typeNames << SourceRange(BuiltinLoc, RParenLoc));

This scales better to support arbitrary types being passed in (not just
strings) in a type-safe way.  Go operator overloading?!

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59502 91177308-0d34-0410-b5e6-96231b3b80d8

17 files changed:
Driver/RewriteObjC.cpp
include/clang/Analysis/PathDiagnostic.h
include/clang/Analysis/PathSensitive/BugReporter.h
include/clang/Basic/Diagnostic.h
include/clang/Driver/TextDiagnosticBuffer.h
include/clang/Driver/TextDiagnosticPrinter.h
lib/Analysis/BugReporter.cpp
lib/Analysis/PathDiagnostic.cpp
lib/Basic/Diagnostic.cpp
lib/CodeGen/CGObjC.cpp
lib/CodeGen/CodeGenModule.cpp
lib/Driver/TextDiagnosticBuffer.cpp
lib/Driver/TextDiagnosticPrinter.cpp
lib/Lex/Preprocessor.cpp
lib/Parse/DeclSpec.cpp
lib/Parse/Parser.cpp
lib/Sema/Sema.cpp

index 69aedcc2dd85962dd179fd935de4150c03e5efcb..804a891f6b6c45383954a459fb45adb7fcde66e6 100644 (file)
@@ -132,9 +132,8 @@ namespace {
       if (!Rewrite.ReplaceStmt(Old, New) || SilenceRewriteMacroWarning)
         return;
 
-      SourceRange Range = Old->getSourceRange();
-      Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag,
-                   0, 0, &Range, 1);
+      Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
+                   << Old->getSourceRange();
     }
     
     void InsertText(SourceLocation Loc, const char *StrData, unsigned StrLen,
index 6183a7c3a68af1225b2e20a01054dd7b0a52831d..bedc6da40f7fb00d4440e1fc0119899c97f308ef 100644 (file)
@@ -197,14 +197,8 @@ public:
   PathDiagnosticClient() {}
   virtual ~PathDiagnosticClient() {}
     
-  virtual void HandleDiagnostic(Diagnostic &Diags, 
-                                Diagnostic::Level DiagLevel,
-                                FullSourceLoc Pos,
-                                diag::kind ID,
-                                const std::string **Strs,
-                                unsigned NumStrs,
-                                const SourceRange *Ranges, 
-                                unsigned NumRanges);
+  virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
+                                const DiagnosticInfo &Info);
     
   virtual void HandlePathDiagnostic(const PathDiagnostic* D) = 0;
 };
index 6ab2a4e713d25600ccae3391a02df5ef7b67f2c4..71d3ccae4135a723fafb205fb0a34886c9dfd06f 100644 (file)
@@ -303,26 +303,20 @@ public:
   
   virtual ~DiagCollector() {}
   
-  virtual void HandleDiagnostic(Diagnostic &Diags, 
-                                Diagnostic::Level DiagLevel,
-                                FullSourceLoc Pos,
-                                diag::kind ID,
-                                const std::string **Strs,
-                                unsigned NumStrs,
-                                const SourceRange *Ranges, 
-                                unsigned NumRanges) {
+  virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
+                                const DiagnosticInfo &Info) {
     
     // FIXME: Use a map from diag::kind to BugType, instead of having just
     //  one BugType.
-    
-    Reports.push_back(DiagBugReport(Diags.getDescription(ID), D, Pos));
+    const char *Desc = Info.getDiags()->getDescription(Info.getID());
+    Reports.push_back(DiagBugReport(Desc, D, Info.getLocation()));
     DiagBugReport& R = Reports.back();
     
-    for ( ; NumRanges ; --NumRanges, ++Ranges)
-      R.addRange(*Ranges);
+    for (unsigned i = 0, e = Info.getNumRanges(); i != e; ++i)
+      R.addRange(Info.getRange(i));
     
-    for ( ; NumStrs ; --NumStrs, ++Strs)
-      R.addString(**Strs);    
+    for (unsigned i = 0, e = Info.getNumArgs(); i != e; ++i)
+      R.addString(Info.getArgStr(i));
   }
   
   // Iterators.
index b9bbcb2831f8dbfa516280a01f9a95d39a9502ad..566b5e3d480e4059b7532504c8c10c98f4a0d5d1 100644 (file)
@@ -22,6 +22,7 @@ namespace clang {
   class DiagnosticClient;
   class SourceRange;
   class SourceManager;
+  class DiagnosticInfo;
   
   // Import the diagnostic enums themselves.
   namespace diag {
@@ -150,7 +151,7 @@ public:
 
   /// getDescription - Given a diagnostic ID, return a description of the
   /// issue.
-  const char *getDescription(unsigned DiagID);
+  const char *getDescription(unsigned DiagID) const;
   
   /// isBuiltinNoteWarningOrExtension - Return true if the unmapped diagnostic
   /// level of the specified diagnostic ID is a Note, Warning, or Extension.
@@ -162,41 +163,146 @@ public:
   /// the DiagnosticClient.
   Level getDiagnosticLevel(unsigned DiagID) const;
   
+  
   /// Report - Issue the message to the client.  DiagID is a member of the
-  /// diag::kind enum.  
-  void Report(FullSourceLoc Pos, unsigned DiagID,
-              const std::string **Strs = 0, unsigned NumStrs = 0,
-              const SourceRange *Ranges = 0, unsigned NumRanges = 0) {
-    Report(NULL, Pos, DiagID, Strs, NumStrs, Ranges, NumRanges);
-  }                                                                      
-  
-  /// Report - Issue the message to the specified client. 
-  ///  DiagID is a member of the diag::kind enum.
-  void Report(DiagnosticClient* C, FullSourceLoc Pos, unsigned DiagID,
-              const std::string **Strs = 0, unsigned NumStrs = 0,
-              const SourceRange *Ranges = 0, unsigned NumRanges = 0);
+  /// diag::kind enum.  This actually returns a new instance of DiagnosticInfo
+  /// which emits the diagnostics (through ProcessDiag) when it is destroyed.
+  inline DiagnosticInfo Report(FullSourceLoc Pos, unsigned DiagID);
+  
+private:
+  // This is private state used by DiagnosticInfo.  We put it here instead of
+  // in DiagnosticInfo in order to keep DiagnosticInfo a small light-weight
+  // object.  This implementation choice means that we can only have one
+  // diagnostic "in flight" at a time, but this seems to be a reasonable
+  // tradeoff to keep these objects small.  Assertions verify that only one
+  // diagnostic is in flight at a time.
+  friend class DiagnosticInfo;
+  
+  /// DiagArguments - The values for the various substitution positions.  It
+  /// currently only support 10 arguments (%0-%9).
+  const std::string *DiagArguments[10];
+  /// DiagRanges - The list of ranges added to this diagnostic.  It currently
+  /// only support 10 ranges, could easily be extended if needed.
+  const SourceRange *DiagRanges[10];
+  
+  /// NumDiagArgs - This is set to -1 when no diag is in flight.  Otherwise it
+  /// is the number of entries in Arguments.
+  signed char NumDiagArgs;
+  /// NumRanges - This is the number of ranges in the DiagRanges array.
+  unsigned char NumDiagRanges;
+  
+  /// ProcessDiag - This is the method used to report a diagnostic that is
+  /// finally fully formed.
+  void ProcessDiag(const DiagnosticInfo &Info);
+};
+  
+/// DiagnosticInfo - This is a little helper class used to produce diagnostics.
+/// This is constructed with an ID and location, and then has some number of
+/// arguments (for %0 substitution) and SourceRanges added to it with the
+/// overloaded operator<<.  Once it is destroyed, it emits the diagnostic with
+/// the accumulated information.
+///
+/// Note that many of these will be created as temporary objects (many call
+/// sites), so we want them to be small to reduce stack space usage etc.  For
+/// this reason, we stick state in the Diagnostic class, see the comment there
+/// for more info.
+class DiagnosticInfo {
+  Diagnostic *DiagObj;
+  FullSourceLoc Loc;
+  unsigned DiagID;
+  void operator=(const DiagnosticInfo&); // DO NOT IMPLEMENT
+public:
+  DiagnosticInfo(Diagnostic *diagObj, FullSourceLoc loc, unsigned diagID) :
+    DiagObj(diagObj), Loc(loc), DiagID(diagID) {
+    assert(DiagObj->NumDiagArgs == -1 &&
+           "Multiple diagnostics in flight at once!");
+    DiagObj->NumDiagArgs = DiagObj->NumDiagRanges = 0;
+  }
+  
+  /// Copy constructor.  When copied, this "takes" the diagnostic info from the
+  /// input and neuters it.
+  DiagnosticInfo(DiagnosticInfo &D) {
+    DiagObj = D.DiagObj;
+    Loc = D.Loc;
+    DiagID = D.DiagID;
+    D.DiagObj = 0;
+  }
+  
+  /// Destructor - The dtor emits the diagnostic.
+  ~DiagnosticInfo() {
+    // If DiagObj is null, then its soul was stolen by the copy ctor.
+    if (!DiagObj) return;
+    
+    DiagObj->ProcessDiag(*this);
+
+    // This diagnostic is no longer in flight.
+    DiagObj->NumDiagArgs = -1;
+  }
+  
+  const Diagnostic *getDiags() const { return DiagObj; }
+  unsigned getID() const { return DiagID; }
+  const FullSourceLoc &getLocation() const { return Loc; }
+
+  unsigned getNumArgs() const { return DiagObj->NumDiagArgs; }
+  
+  /// getArgStr - Return the provided argument string specified by Idx.
+  const std::string &getArgStr(unsigned Idx) const {
+    assert((signed char)Idx < DiagObj->NumDiagArgs &&
+           "Argument out of range!");
+    return *DiagObj->DiagArguments[Idx];
+  }
+  
+  /// getNumRanges - Return the number of source ranges associated with this
+  /// diagnostic.
+  unsigned getNumRanges() const {
+    return DiagObj->NumDiagRanges;
+  }
+  
+  const SourceRange &getRange(unsigned Idx) const {
+    assert(Idx < DiagObj->NumDiagRanges && "Invalid diagnostic range index!");
+    return *DiagObj->DiagRanges[Idx];
+  }
+
+  DiagnosticInfo &operator<<(const std::string &S) {
+    assert((unsigned)DiagObj->NumDiagArgs < 
+           sizeof(DiagObj->DiagArguments)/sizeof(DiagObj->DiagArguments[0]) &&
+           "Too many arguments to diagnostic!");
+    DiagObj->DiagArguments[DiagObj->NumDiagArgs++] = &S;
+    return *this;
+  }
+  
+  DiagnosticInfo &operator<<(const SourceRange &R) {
+    assert((unsigned)DiagObj->NumDiagArgs < 
+           sizeof(DiagObj->DiagRanges)/sizeof(DiagObj->DiagRanges[0]) &&
+           "Too many arguments to diagnostic!");
+    DiagObj->DiagRanges[DiagObj->NumDiagRanges++] = &R;
+    return *this;
+  }
+  
 };
 
+
+/// Report - Issue the message to the client.  DiagID is a member of the
+/// diag::kind enum.  This actually returns a new instance of DiagnosticInfo
+/// which emits the diagnostics (through ProcessDiag) when it is destroyed.
+inline DiagnosticInfo Diagnostic::Report(FullSourceLoc Pos, unsigned DiagID) {
+  DiagnosticInfo D(this, Pos, DiagID);
+  return D;
+}
+  
+
 /// DiagnosticClient - This is an abstract interface implemented by clients of
 /// the front-end, which formats and prints fully processed diagnostics.
 class DiagnosticClient {
 protected:
-  std::string FormatDiagnostic(Diagnostic &Diags, Diagnostic::Level Level,
-                               diag::kind ID,
-                               const std::string **Strs, unsigned NumStrs);
+  std::string FormatDiagnostic(const DiagnosticInfo &Info);
 public:
   virtual ~DiagnosticClient();
 
   /// HandleDiagnostic - Handle this diagnostic, reporting it to the user or
   /// capturing it to a log as needed.
-  virtual void HandleDiagnostic(Diagnostic &Diags, 
-                                Diagnostic::Level DiagLevel,
-                                FullSourceLoc Pos,
-                                diag::kind ID,
-                                const std::string **Strs,
-                                unsigned NumStrs,
-                                const SourceRange *Ranges, 
-                                unsigned NumRanges) = 0;
+  virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
+                                const DiagnosticInfo &Info) = 0;
 };
 
 }  // end namespace clang
index 9933308368b166253f3595dd348a0793c6ef41b0..e803475ae0b7bfd28090958ba290626e15c42bd3 100644 (file)
@@ -39,14 +39,8 @@ public:
   const_iterator note_begin() const { return Notes.begin(); }
   const_iterator note_end() const   { return Notes.end(); }
 
-  virtual void HandleDiagnostic(Diagnostic &Diags,
-                                Diagnostic::Level DiagLevel,
-                                FullSourceLoc Pos,
-                                diag::kind ID,
-                                const std::string **Strs,
-                                unsigned NumStrs,
-                                const SourceRange *Ranges, 
-                                unsigned NumRanges);
+  virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
+                                const DiagnosticInfo &Info);
 };
 
 } // end namspace clang
index 7c6bce58bbb13e88b06cb99ca1dfadacc8786a1b..e5ef9fca824b27f440f6155307b3a5938eed96e1 100644 (file)
@@ -36,19 +36,13 @@ public:
   void PrintIncludeStack(FullSourceLoc Pos);
 
   void HighlightRange(const SourceRange &R,
-                      SourceManager& SrcMgr,
+                      const SourceManager& SrcMgr,
                       unsigned LineNo, unsigned FileID,
                       std::string &CaretLine,
                       const std::string &SourceLine);
 
-  virtual void HandleDiagnostic(Diagnostic &Diags,
-                                Diagnostic::Level DiagLevel,
-                                FullSourceLoc Pos,
-                                diag::kind ID,
-                                const std::string **Strs,
-                                unsigned NumStrs,
-                                const SourceRange *Ranges, 
-                                unsigned NumRanges);
+  virtual void HandleDiagnostic(Diagnostic::Level DiagLevel,
+                                const DiagnosticInfo &Info);
 };
 
 } // end namspace clang
index bf99e6ba637fbead52b061755a17b6107425d74e..0074a93b5bca314f5d8f3cb50778763ddc842d49 100644 (file)
@@ -773,21 +773,26 @@ void BugReporter::EmitWarning(BugReport& R) {
 
     D->push_back(piece);
     PD->HandlePathDiagnostic(D.take());
+    return;
   }
   else {
-    std::ostringstream os;
+    std::string str;
 
     if (D->empty())
-      os << R.getDescription();
+      str = R.getDescription();
     else
-      os << D->back()->getString();
-
+      str = D->back()->getString();
 
     Diagnostic& Diag = getDiagnostic();
-    unsigned ErrorDiag = Diag.getCustomDiagID(Diagnostic::Warning,
-                                              os.str().c_str());
-
-    Diag.Report(L, ErrorDiag, NULL, 0, Beg, End - Beg);
+    unsigned ErrorDiag = Diag.getCustomDiagID(Diagnostic::Warning, str.c_str());
+
+    switch (End-Beg) {
+    default: assert(0 && "Don't handle this many ranges yet!");
+    case 0: Diag.Report(L, ErrorDiag); break;
+    case 1: Diag.Report(L, ErrorDiag) << Beg[0]; break;
+    case 2: Diag.Report(L, ErrorDiag) << Beg[0] << Beg[1]; break;
+    case 3: Diag.Report(L, ErrorDiag) << Beg[0] << Beg[1] << Beg[2]; break;
+    }
   }
 }
 
@@ -807,9 +812,17 @@ void BugReporter::EmitBasicReport(const char* name, const char* category,
   
   DiagnosticClient *OldClient = Diag.getClient();
   Diag.setClient(&C);
-  Diag.Report(getContext().getFullLoc(Loc),
-              Diag.getCustomDiagID(Diagnostic::Warning, str),
-              0, 0, RBeg, NumRanges);
+  FullSourceLoc L = getContext().getFullLoc(Loc);
+  unsigned DiagID = Diag.getCustomDiagID(Diagnostic::Warning, str);
+  
+  switch (NumRanges) {
+  default: assert(0 && "Don't handle this many ranges yet!");
+  case 0: Diag.Report(L, DiagID); break;
+  case 1: Diag.Report(L, DiagID) << RBeg[0]; break;
+  case 2: Diag.Report(L, DiagID) << RBeg[0] << RBeg[1]; break;
+  case 3: Diag.Report(L, DiagID) << RBeg[0] << RBeg[1] << RBeg[2]; break;
+  }
+  
   Diag.setClient(OldClient);
   
   for (DiagCollector::iterator I = C.begin(), E = C.end(); I != E; ++I)
index 02cfe1e341b8ce0660cf8051aa70d8a6b28ea770..aed83ea84fb48e1fa9a664747e0a9bac649a79f6 100644 (file)
@@ -20,14 +20,8 @@ PathDiagnostic::~PathDiagnostic() {
   for (iterator I = begin(), E = end(); I != E; ++I) delete &*I;
 }
 
-void PathDiagnosticClient::HandleDiagnostic(Diagnostic &Diags, 
-                                            Diagnostic::Level DiagLevel,
-                                            FullSourceLoc Pos,
-                                            diag::kind ID,
-                                            const std::string **Strs,
-                                            unsigned NumStrs,
-                                            const SourceRange *Ranges, 
-                                            unsigned NumRanges) {
+void PathDiagnosticClient::HandleDiagnostic(Diagnostic::Level DiagLevel,
+                                            const DiagnosticInfo &Info) {
   
   // Create a PathDiagnostic with a single piece.
   
@@ -42,16 +36,13 @@ void PathDiagnosticClient::HandleDiagnostic(Diagnostic &Diags,
   case Diagnostic::Fatal:   LevelStr = "fatal error: "; break;
   }
 
-  std::string Msg = FormatDiagnostic(Diags, DiagLevel, ID, Strs, NumStrs);
+  std::string Msg = FormatDiagnostic(Info);
   
-  PathDiagnosticPiece* P = new PathDiagnosticPiece(Pos, LevelStr+Msg);
-  
-  while (NumRanges) {
-    P->addRange(*Ranges);
-    --NumRanges;
-    ++Ranges;
-  }
+  PathDiagnosticPiece *P =
+    new PathDiagnosticPiece(Info.getLocation(), LevelStr+Msg);
   
+  for (unsigned i = 0, e = Info.getNumRanges(); i != e; ++i)
+    P->addRange(Info.getRange(i));
   D->push_front(P);
 
   HandlePathDiagnostic(D);  
index 2076b16db08ad2aafd1a634a2b345aa5084be3c5..a202a55f268e9f2370251fd1a4b301f614df5ecd 100644 (file)
@@ -127,6 +127,7 @@ Diagnostic::Diagnostic(DiagnosticClient *client) : Client(client) {
   NumDiagnostics = 0;
   NumErrors = 0;
   CustomDiagInfo = 0;
+  NumDiagArgs = -1;
 }
 
 Diagnostic::~Diagnostic() {
@@ -154,7 +155,7 @@ bool Diagnostic::isBuiltinNoteWarningOrExtension(unsigned DiagID) {
 
 /// getDescription - Given a diagnostic ID, return a description of the
 /// issue.
-const char *Diagnostic::getDescription(unsigned DiagID) {
+const char *Diagnostic::getDescription(unsigned DiagID) const {
   if (DiagID < diag::NUM_BUILTIN_DIAGNOSTICS)
     return DiagnosticText[DiagID];
   else 
@@ -210,66 +211,51 @@ Diagnostic::Level Diagnostic::getDiagnosticLevel(unsigned DiagID) const {
   }
 }
 
-/// Report - Issue the message to the client.
-///  DiagID is a member of the diag::kind enum.  
-void Diagnostic::Report(DiagnosticClient* C,
-                        FullSourceLoc Loc, unsigned DiagID,
-                        const std::string **Strs, unsigned NumStrs,
-                        const SourceRange *Ranges, unsigned NumRanges) {
-  
+/// ProcessDiag - This is the method used to report a diagnostic that is
+/// finally fully formed.
+void Diagnostic::ProcessDiag(const DiagnosticInfo &Info) {
   // Figure out the diagnostic level of this message.
-  Diagnostic::Level DiagLevel = getDiagnosticLevel(DiagID);
+  Diagnostic::Level DiagLevel = getDiagnosticLevel(Info.getID());
   
   // If the client doesn't care about this message, don't issue it.
   if (DiagLevel == Diagnostic::Ignored)
     return;
 
-  // Set the diagnostic client if it isn't set already.
-  if (!C) C = Client;
-
   // If this is not an error and we are in a system header, ignore it.  We
-  // have to check on the original DiagID here, because we also want to
+  // have to check on the original Diag ID here, because we also want to
   // ignore extensions and warnings in -Werror and -pedantic-errors modes,
   // which *map* warnings/extensions to errors.
   if (SuppressSystemWarnings &&
-      DiagID < diag::NUM_BUILTIN_DIAGNOSTICS &&
-      getBuiltinDiagClass(DiagID) != ERROR &&
-      Loc.isValid() && Loc.getPhysicalLoc().isInSystemHeader())
+      Info.getID() < diag::NUM_BUILTIN_DIAGNOSTICS &&
+      getBuiltinDiagClass(Info.getID()) != ERROR &&
+      Info.getLocation().isValid() &&
+      Info.getLocation().getPhysicalLoc().isInSystemHeader())
     return;
   
   if (DiagLevel >= Diagnostic::Error) {
     ErrorOccurred = true;
 
-    if (C != 0 && C == Client)
-      ++NumErrors;
+    ++NumErrors;
   }
 
   // Finally, report it.
-  if (C != 0)
-    C->HandleDiagnostic(*this, DiagLevel, Loc, (diag::kind)DiagID,
-                        Strs, NumStrs, Ranges, NumRanges);
-
-  if (C != 0 && C == Client)
-    ++NumDiagnostics;
+  Client->HandleDiagnostic(DiagLevel, Info);
+  ++NumDiagnostics;
 }
 
 
 DiagnosticClient::~DiagnosticClient() {}
 
-std::string DiagnosticClient::FormatDiagnostic(Diagnostic &Diags,
-                                               Diagnostic::Level Level,
-                                               diag::kind ID,
-                                               const std::string **Strs,
-                                               unsigned NumStrs) {
-  std::string Msg = Diags.getDescription(ID);
+std::string DiagnosticClient::FormatDiagnostic(const DiagnosticInfo &Info) {
+  std::string Msg = Info.getDiags()->getDescription(Info.getID());
   
-  // Replace all instances of %0 in Msg with 'Extra'.
+  // Replace all instances of %0 in Msg with 'Extra'.  This is a pretty horrible
+  // and inefficient way to do this, we could improve this a lot if we care.
   for (unsigned i = 0; i < Msg.size() - 1; ++i) {
     if (Msg[i] == '%' && isdigit(Msg[i + 1])) {
       unsigned StrNo = Msg[i + 1] - '0';
       Msg = std::string(Msg.begin(), Msg.begin() + i) +
-            (StrNo < NumStrs ? *Strs[StrNo] : "<<<INTERNAL ERROR>>>") +
+            Info.getArgStr(StrNo) +
             std::string(Msg.begin() + i + 2, Msg.end());
     }
   }
index 058278cfa4ea67040750921c4f23364719dcec78..044368c6998c098b06c8abdd719a5e6ef2d28815 100644 (file)
@@ -303,10 +303,9 @@ void CodeGenFunction::EmitObjCPropertySet(const ObjCPropertyRefExpr *E,
       S = Setter->getSelector();
     } else {
       // FIXME: This should be diagnosed by sema.
-      SourceRange Range = E->getSourceRange();
       CGM.getDiags().Report(getContext().getFullLoc(E->getLocStart()),
-                            diag::err_typecheck_assign_const, 0, 0,
-                            &Range, 1);
+                            diag::err_typecheck_assign_const)
+        << E->getSourceRange();
       return;
     }
   } else {
index d7d732997b603a61568c292e2ead614d753d0987..3e146215f487939143f8bed9a24cc6fbea639a42 100644 (file)
@@ -106,11 +106,9 @@ void CodeGenModule::ErrorUnsupported(const Stmt *S, const char *Type,
     return;
   unsigned DiagID = getDiags().getCustomDiagID(Diagnostic::Error, 
                                                "cannot codegen this %0 yet");
-  SourceRange Range = S->getSourceRange();
   std::string Msg = Type;
-  const std::string *Strs[] = { &Msg };
-  getDiags().Report(Context.getFullLoc(S->getLocStart()), DiagID,
-                    Strs, 1, &Range, 1);
+  getDiags().Report(Context.getFullLoc(S->getLocStart()), DiagID)
+    << Msg << S->getSourceRange();
 }
 
 /// ErrorUnsupported - Print out an error that codegen doesn't support the
@@ -122,8 +120,7 @@ void CodeGenModule::ErrorUnsupported(const Decl *D, const char *Type,
   unsigned DiagID = getDiags().getCustomDiagID(Diagnostic::Error, 
                                                "cannot codegen this %0 yet");
   std::string Msg = Type;
-  const std::string *Strs[] = { &Msg };
-  getDiags().Report(Context.getFullLoc(D->getLocation()), DiagID, Strs, 1);
+  getDiags().Report(Context.getFullLoc(D->getLocation()), DiagID) << Msg;
 }
 
 /// setGlobalVisibility - Set the visibility for the given LLVM
index ef7ac6d408c29feec809ebc9b10a46e978d949fe..b138b1a24d2e412bc435010ce8f806a96c7d0347 100644 (file)
@@ -17,30 +17,21 @@ using namespace clang;
 /// HandleDiagnostic - Store the errors, warnings, and notes that are
 /// reported.
 /// 
-void TextDiagnosticBuffer::HandleDiagnostic(Diagnostic &Diags,
-                                            Diagnostic::Level Level,
-                                            FullSourceLoc Pos,
-                                            diag::kind ID,
-                                            const std::string **Strs,
-                                            unsigned NumStrs,
-                                            const SourceRange *,
-                                            unsigned) {
+void TextDiagnosticBuffer::HandleDiagnostic(Diagnostic::Level Level,
+                                            const DiagnosticInfo &Info) {
   switch (Level) {
   default: assert(0 && "Diagnostic not handled during diagnostic buffering!");
   case Diagnostic::Note:
-    Notes.push_back(std::make_pair(Pos.getLocation(),
-                                   FormatDiagnostic(Diags, Level, ID, 
-                                                    Strs, NumStrs)));
+    Notes.push_back(std::make_pair(Info.getLocation().getLocation(),
+                                   FormatDiagnostic(Info)));
     break;
   case Diagnostic::Warning:
-    Warnings.push_back(std::make_pair(Pos.getLocation(),
-                                      FormatDiagnostic(Diags, Level, ID, 
-                                                       Strs, NumStrs)));
+    Warnings.push_back(std::make_pair(Info.getLocation().getLocation(),
+                                      FormatDiagnostic(Info)));
     break;
   case Diagnostic::Error:
-    Errors.push_back(std::make_pair(Pos.getLocation(),
-                                    FormatDiagnostic(Diags, Level, ID,
-                                                     Strs, NumStrs)));
+    Errors.push_back(std::make_pair(Info.getLocation().getLocation(),
+                                    FormatDiagnostic(Info)));
     break;
   }
 }
index e03588b98996a7139ea00d20cf1f584f61d47e76..3b8ec10ec81c7323b19764b8275142a2c4f95c89 100644 (file)
@@ -34,7 +34,7 @@ PrintIncludeStack(FullSourceLoc Pos) {
 /// HighlightRange - Given a SourceRange and a line number, highlight (with ~'s)
 /// any characters in LineNo that intersect the SourceRange.
 void TextDiagnosticPrinter::HighlightRange(const SourceRange &R,
-                                           SourceManager& SourceMgr,
+                                           const SourceManager& SourceMgr,
                                            unsigned LineNo, unsigned FileID,
                                            std::string &CaretLine,
                                            const std::string &SourceLine) {
@@ -92,17 +92,12 @@ void TextDiagnosticPrinter::HighlightRange(const SourceRange &R,
     CaretLine[i] = '~';
 }
 
-void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic &Diags,
-                                             Diagnostic::Level Level, 
-                                             FullSourceLoc Pos,
-                                             diag::kind ID,
-                                             const std::string **Strs,
-                                             unsigned NumStrs,
-                                             const SourceRange *Ranges,
-                                             unsigned NumRanges) {
+void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic::Level Level, 
+                                             const DiagnosticInfo &Info) {
   unsigned LineNo = 0, ColNo = 0;
   unsigned FileID = 0;
   const char *LineStart = 0, *LineEnd = 0;
+  const FullSourceLoc &Pos = Info.getLocation();
   
   if (Pos.isValid()) {
     FullSourceLoc LPos = Pos.getLogicalLoc();
@@ -146,9 +141,10 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic &Diags,
     break;
   }
   
-  OS << FormatDiagnostic(Diags, Level, ID, Strs, NumStrs) << "\n";
+  OS << FormatDiagnostic(Info) << "\n";
   
-  if (CaretDiagnostics && Pos.isValid() && ((LastLoc != Pos) || Ranges)) {
+  if (CaretDiagnostics && Pos.isValid() && ((LastLoc != Pos) ||
+                                            Info.getNumRanges())) {
     // Cache the LastLoc, it allows us to omit duplicate source/caret spewage.
     LastLoc = Pos;
     
@@ -160,8 +156,8 @@ void TextDiagnosticPrinter::HandleDiagnostic(Diagnostic &Diags,
     std::string CaretLine(LineEnd-LineStart, ' ');
     
     // Highlight all of the characters covered by Ranges with ~ characters.
-    for (unsigned i = 0; i != NumRanges; ++i)
-      HighlightRange(Ranges[i], Pos.getManager(), LineNo, FileID,
+    for (unsigned i = 0; i != Info.getNumRanges(); ++i)
+      HighlightRange(Info.getRange(i), Pos.getManager(), LineNo, FileID,
                      CaretLine, SourceLine);
     
     // Next, insert the caret itself.
index dc4dd877b67390451f4fe88a7d72977ccf479514..3357791b6cb617fad93d94c0a65e2fffa1a54304 100644 (file)
@@ -124,28 +124,24 @@ void Preprocessor::Diag(SourceLocation Loc, unsigned DiagID) {
 
 void Preprocessor::Diag(SourceLocation Loc, unsigned DiagID, 
                         const std::string &Msg) {
-  const std::string *Strs[] = { &Msg };
-  Diags.Report(getFullLoc(Loc), DiagID, Strs, 1);
+  Diags.Report(getFullLoc(Loc), DiagID) << Msg;
 }
 
 void Preprocessor::Diag(SourceLocation Loc, unsigned DiagID,
                         const std::string &Msg,
                         const SourceRange &R1, const SourceRange &R2) {
-  const std::string *Strs[] = { &Msg };
-  SourceRange R[] = {R1, R2};
-  Diags.Report(getFullLoc(Loc), DiagID, Strs, 1, R, 2);
+  Diags.Report(getFullLoc(Loc), DiagID) << Msg << R1 << R2;
 }
 
 
 void Preprocessor::Diag(SourceLocation Loc, unsigned DiagID,
                         const SourceRange &R) {
-  Diags.Report(getFullLoc(Loc), DiagID, 0, 0, &R, 1);
+  Diags.Report(getFullLoc(Loc), DiagID) << R;
 }
 
 void Preprocessor::Diag(SourceLocation Loc, unsigned DiagID,
                         const SourceRange &R1, const SourceRange &R2) {
-  SourceRange R[] = {R1, R2};
-  Diags.Report(getFullLoc(Loc), DiagID, 0, 0, R, 2);
+  Diags.Report(getFullLoc(Loc), DiagID) << R1 << R2;
 }
 
 
index 733c37cb4f99d83c0c443e47a0ed2d495e18f1ea..c4971084710d7ada0327e75cb6df47906a33b0aa 100644 (file)
@@ -311,7 +311,6 @@ void DeclSpec::Diag(Diagnostic &D, SourceLocation Loc, SourceManager& SrcMgr,
 }
   
 void DeclSpec::Diag(Diagnostic &D, SourceLocation Loc, SourceManager& SrcMgr,
-          unsigned DiagID, const std::string &Info) {
-  const std::string *Strs[] = { &Info };
-  D.Report(FullSourceLoc(Loc,SrcMgr), DiagID, Strs, 1);
+                    unsigned DiagID, const std::string &Info) {
+  D.Report(FullSourceLoc(Loc,SrcMgr), DiagID) << Info;
 }
index dfabc9b16a50f08cb88937d6db53b1e7ef1ca6e9..a9ce22d047021d888a740563b0fe6e13615e09d1 100644 (file)
@@ -43,21 +43,18 @@ Action::~Action() {}
 
 bool Parser::Diag(SourceLocation Loc, unsigned DiagID,
                   const std::string &Msg) {
-  const std::string *Strs[] = { &Msg };
-  Diags.Report(FullSourceLoc(Loc,PP.getSourceManager()), DiagID, Strs, 1);
+  Diags.Report(FullSourceLoc(Loc,PP.getSourceManager()), DiagID) << Msg;
   return true;
 }
 
 bool Parser::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg,
                   const SourceRange& Range) {
-  const std::string *Strs[] = { &Msg };
-  Diags.Report(PP.getFullLoc(Loc), DiagID, Strs, 1, &Range,1);
+  Diags.Report(PP.getFullLoc(Loc), DiagID) << Msg << Range;
   return true;
 }
 
 bool Parser::Diag(SourceLocation Loc, unsigned DiagID, const SourceRange &R) {
-  Diags.Report(FullSourceLoc(Loc,PP.getSourceManager()), DiagID, 0, 0,
-               &R, 1);
+  Diags.Report(FullSourceLoc(Loc,PP.getSourceManager()), DiagID) << R;
   return true;
 }
 
index 5ea27c979b14d0ce606f8d733d51526cf3040b40..c064e2448b2cf678aed61379785c1cac1a7d99c7 100644 (file)
 #include "clang/AST/Expr.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Basic/Diagnostic.h"
-
 using namespace clang;
 
-static inline RecordDecl *CreateStructDecl(ASTContext &C, const char *Name)
-{
+static inline RecordDecl *CreateStructDecl(ASTContext &C, const char *Name) {
   if (C.getLangOptions().CPlusPlus)
     return CXXRecordDecl::Create(C, TagDecl::TK_struct, 
                                  C.getTranslationUnitDecl(),
@@ -176,66 +174,58 @@ bool Sema::Diag(SourceLocation Loc, unsigned DiagID) {
 }
 
 bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg) {
-  const std::string *Strs[] = { &Msg };
-  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, Strs, 1);
+  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID) << Msg;
   return true;
 }
 
 bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1,
                 const std::string &Msg2) {
-  const std::string *MsgArr[] = { &Msg1, &Msg2 };
-  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID,  MsgArr, 2);
+  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID) << Msg1 << Msg2;
   return true;
 }
 
 bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const SourceRange& Range) {
-  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, 0, 0, &Range,1);
+  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID) << Range;
   return true;
 }
 
 bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg,
                 const SourceRange& Range) {
-  const std::string *Strs[] = { &Msg };
-  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, Strs, 1, &Range,1);
+  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID) << Msg << Range;
   return true;
 }
 
 bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1,
-                const std::string &Msg2, const SourceRange& Range) {
-  const std::string *MsgArr[] = { &Msg1, &Msg2 };
-  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, MsgArr, 2, &Range, 1);
+                const std::string &Msg2, const SourceRange &R) {
+  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID) << Msg1 << Msg2 << R;
   return true;
 }
 
 bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg1, 
                 const std::string &Msg2, const std::string &Msg3, 
                 const SourceRange &R1) {
-  const std::string *MsgArr[] = { &Msg1, &Msg2, &Msg3 };
-  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, MsgArr, 3, &R1, 1);
+  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID)
+    << Msg1 << Msg2 << Msg3 << R1;
   return true;
 }
 
 bool Sema::Diag(SourceLocation Loc, unsigned DiagID,
                 const SourceRange& R1, const SourceRange& R2) {
-  SourceRange RangeArr[] = { R1, R2 };
-  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, 0, 0, RangeArr, 2);
+  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID) << R1 << R2;
   return true;
 }
 
 bool Sema::Diag(SourceLocation Loc, unsigned DiagID, const std::string &Msg,
                 const SourceRange& R1, const SourceRange& R2) {
-  SourceRange RangeArr[] = { R1, R2 };
-  const std::string *Strs[] = { &Msg };
-  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID, Strs, 1, RangeArr, 2);
+  PP.getDiagnostics().Report(PP.getFullLoc(Loc), DiagID) << Msg << R1 << R2;
   return true;
 }
 
 bool Sema::Diag(SourceLocation Range, unsigned DiagID, const std::string &Msg1,
                 const std::string &Msg2, const SourceRange& R1,
                 const SourceRange& R2) {
-  const std::string *MsgArr[] = { &Msg1, &Msg2 };
-  SourceRange RangeArr[] = { R1, R2 };
-  PP.getDiagnostics().Report(PP.getFullLoc(Range),DiagID, MsgArr,2,RangeArr, 2);
+  PP.getDiagnostics().Report(PP.getFullLoc(Range),DiagID)
+    << Msg1 << Msg2 << R1 << R2;
   return true;
 }