Change Diagnostic Category size error from runtime to compiletime

Diagnostic Categories are fairly annoying, and are only enforced
by a runtime-debug-only assert. This puts in a touch more work
to get this all done at compile-time with static asserts

Differential Revision: https://reviews.llvm.org/D37122

llvm-svn: 311905
diff --git a/clang/lib/Basic/DiagnosticIDs.cpp b/clang/lib/Basic/DiagnosticIDs.cpp
index 0cdaf8e..b74047a 100644
--- a/clang/lib/Basic/DiagnosticIDs.cpp
+++ b/clang/lib/Basic/DiagnosticIDs.cpp
@@ -68,6 +68,29 @@
   }
 };
 
+#define STRINGIFY_NAME(NAME) #NAME
+#define VALIDATE_DIAG_SIZE(NAME)                                               \
+  static_assert(                                                               \
+      static_cast<unsigned>(diag::NUM_BUILTIN_##NAME##_DIAGNOSTICS) <          \
+          static_cast<unsigned>(diag::DIAG_START_##NAME) +                     \
+              static_cast<unsigned>(diag::DIAG_SIZE_##NAME),                   \
+      STRINGIFY_NAME(                                                          \
+          DIAG_SIZE_##NAME) " is insufficient to contain all "                 \
+                            "diagnostics, it may need to be made larger in "   \
+                            "DiagnosticIDs.h.");
+VALIDATE_DIAG_SIZE(COMMON)
+VALIDATE_DIAG_SIZE(DRIVER)
+VALIDATE_DIAG_SIZE(FRONTEND)
+VALIDATE_DIAG_SIZE(SERIALIZATION)
+VALIDATE_DIAG_SIZE(LEX)
+VALIDATE_DIAG_SIZE(PARSE)
+VALIDATE_DIAG_SIZE(AST)
+VALIDATE_DIAG_SIZE(COMMENT)
+VALIDATE_DIAG_SIZE(SEMA)
+VALIDATE_DIAG_SIZE(ANALYSIS)
+#undef VALIDATE_DIAG_SIZE
+#undef STRINGIFY_NAME
+
 } // namespace anonymous
 
 static const StaticDiagInfoRec StaticDiagInfo[] = {
@@ -96,18 +119,6 @@
 /// GetDiagInfo - Return the StaticDiagInfoRec entry for the specified DiagID,
 /// or null if the ID is invalid.
 static const StaticDiagInfoRec *GetDiagInfo(unsigned DiagID) {
-  // If assertions are enabled, verify that the StaticDiagInfo array is sorted.
-#ifndef NDEBUG
-  static bool IsFirst = true; // So the check is only performed on first call.
-  if (IsFirst) {
-    assert(std::is_sorted(std::begin(StaticDiagInfo),
-                          std::end(StaticDiagInfo)) &&
-           "Diag ID conflict, the enums at the start of clang::diag (in "
-           "DiagnosticIDs.h) probably need to be increased");
-    IsFirst = false;
-  }
-#endif
-
   // Out of bounds diag. Can't be in the table.
   using namespace diag;
   if (DiagID >= DIAG_UPPER_LIMIT || DiagID <= DIAG_START_COMMON)