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
This commit is contained in:
Erich Keane 2017-08-28 18:53:17 +00:00
parent a7b041748d
commit 0a539b5859
2 changed files with 47 additions and 23 deletions

View File

@ -26,19 +26,32 @@ namespace clang {
// Import the diagnostic enums themselves.
namespace diag {
// Size of each of the diagnostic categories.
enum {
DIAG_SIZE_COMMON = 300,
DIAG_SIZE_DRIVER = 200,
DIAG_SIZE_FRONTEND = 100,
DIAG_SIZE_SERIALIZATION = 120,
DIAG_SIZE_LEX = 400,
DIAG_SIZE_PARSE = 500,
DIAG_SIZE_AST = 110,
DIAG_SIZE_COMMENT = 100,
DIAG_SIZE_SEMA = 3500,
DIAG_SIZE_ANALYSIS = 100
};
// Start position for diagnostics.
enum {
DIAG_START_COMMON = 0,
DIAG_START_DRIVER = DIAG_START_COMMON + 300,
DIAG_START_FRONTEND = DIAG_START_DRIVER + 200,
DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + 100,
DIAG_START_LEX = DIAG_START_SERIALIZATION + 120,
DIAG_START_PARSE = DIAG_START_LEX + 400,
DIAG_START_AST = DIAG_START_PARSE + 500,
DIAG_START_COMMENT = DIAG_START_AST + 110,
DIAG_START_SEMA = DIAG_START_COMMENT + 100,
DIAG_START_ANALYSIS = DIAG_START_SEMA + 3500,
DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100
DIAG_START_COMMON = 0,
DIAG_START_DRIVER = DIAG_START_COMMON + DIAG_SIZE_COMMON,
DIAG_START_FRONTEND = DIAG_START_DRIVER + DIAG_SIZE_DRIVER,
DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + DIAG_SIZE_FRONTEND,
DIAG_START_LEX = DIAG_START_SERIALIZATION + DIAG_SIZE_SERIALIZATION,
DIAG_START_PARSE = DIAG_START_LEX + DIAG_SIZE_LEX,
DIAG_START_AST = DIAG_START_PARSE + DIAG_SIZE_PARSE,
DIAG_START_COMMENT = DIAG_START_AST + DIAG_SIZE_AST,
DIAG_START_SEMA = DIAG_START_COMMENT + DIAG_SIZE_COMMENT,
DIAG_START_ANALYSIS = DIAG_START_SEMA + DIAG_SIZE_SEMA,
DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + DIAG_SIZE_ANALYSIS
};
class CustomDiagInfo;

View File

@ -68,6 +68,29 @@ struct StaticDiagInfoRec {
}
};
#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 @@ static const unsigned StaticDiagInfoSize = llvm::array_lengthof(StaticDiagInfo);
/// 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)