Fix a couple of bugs, add some new cool stuff.

1. Fix a todo in Parser::ParseTag, to recover better.  On code like
   that in test/Sema/decl-invalid.c it causes us to return a single
   error instead of multiple.
2. Fix an error in Sema::ParseDeclarator, where it would crash if the
   declarator didn't have an identifier.  Instead, diagnose the problem.
3. Start adding infrastructure to track the range of locations covered
   by a declspec or declarator.  This is mostly implemented for declspec,
   but could be improved, it is missing for declarator.

Thanks to Neil for pointing out this crash.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@40482 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Driver/TextDiagnostics.cpp b/Driver/TextDiagnostics.cpp
new file mode 100644
index 0000000..3c29cca
--- /dev/null
+++ b/Driver/TextDiagnostics.cpp
@@ -0,0 +1,58 @@
+//===--- TextDiagnostics.cpp - Text Diagnostics Parent Class --------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Bill Wendling and is distributed under the
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is the parent class for all text diagnostics.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TextDiagnostics.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Lex/HeaderSearch.h"
+using namespace clang;
+
+TextDiagnostics:: ~TextDiagnostics() {}
+
+std::string TextDiagnostics::FormatDiagnostic(Diagnostic::Level Level,
+                                              diag::kind ID,
+                                              const std::string *Strs,
+                                              unsigned NumStrs) {
+  std::string Msg = Diagnostic::getDescription(ID);
+  
+  // Replace all instances of %0 in Msg with 'Extra'.
+  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>>>") +
+            std::string(Msg.begin() + i + 2, Msg.end());
+    }
+  }
+
+  return Msg;
+}
+
+bool TextDiagnostics::IgnoreDiagnostic(Diagnostic::Level Level,
+                                       SourceLocation Pos) {
+  if (Pos.isValid()) {
+    // If this is a warning or note, and if it a system header, suppress the
+    // diagnostic.
+    if (Level == Diagnostic::Warning ||
+        Level == Diagnostic::Note) {
+      if (const FileEntry *F = SourceMgr.getFileEntryForLoc(Pos)) {
+        DirectoryLookup::DirType DirInfo = TheHeaderSearch->getFileDirFlavor(F);
+        if (DirInfo == DirectoryLookup::SystemHeaderDir ||
+            DirInfo == DirectoryLookup::ExternCSystemHeaderDir)
+          return true;
+      }
+    }
+  }
+
+  return false;
+}