1//===- DiagnosticNames.cpp - Defines a table of all builtin diagnostics ----==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "DiagnosticNames.h"
10#include "clang/Basic/AllDiagnostics.h"
11#include "llvm/ADT/STLExtras.h"
12#include "llvm/ADT/StringTable.h"
13#include <array>
14#include <cstddef>
15#include <cstdint>
16
17using namespace clang;
18using namespace diagtool;
19
20struct BuiltinDiagnosticNameStorage {
21#define DIAG_NAME_INDEX(ENUM) char ENUM[sizeof(#ENUM)];
22#include "clang/Basic/DiagnosticIndexName.inc"
23#undef DIAG_NAME_INDEX
24};
25
26static_assert(sizeof(BuiltinDiagnosticNameStorage) <= uint64_t(1) << 24);
27
28static constexpr BuiltinDiagnosticNameStorage BuiltinDiagnosticNames = {
29#define DIAG_NAME_INDEX(ENUM) #ENUM,
30#include "clang/Basic/DiagnosticIndexName.inc"
31#undef DIAG_NAME_INDEX
32};
33
34#define DIAGNOSTIC_RECORD(ENUM) \
35 {diag::ENUM, uint16_t(offsetof(BuiltinDiagnosticNameStorage, ENUM)), \
36 uint8_t(offsetof(BuiltinDiagnosticNameStorage, ENUM) >> 16), \
37 STR_SIZE(#ENUM, uint8_t)}
38
39static constexpr DiagnosticRecord BuiltinDiagnosticsByName[] = {
40#define DIAG_NAME_INDEX(ENUM) DIAGNOSTIC_RECORD(ENUM),
41#include "clang/Basic/DiagnosticIndexName.inc"
42#undef DIAG_NAME_INDEX
43};
44static_assert(std::size(BuiltinDiagnosticsByName) < (1U << 16));
45#undef DIAGNOSTIC_RECORD
46
47llvm::ArrayRef<DiagnosticRecord> diagtool::getBuiltinDiagnosticsByName() {
48 return llvm::ArrayRef(BuiltinDiagnosticsByName);
49}
50
51static constexpr auto BuiltinDiagnosticIndexByID = [] {
52 std::array<uint16_t, diag::DIAG_UPPER_LIMIT> Result = {};
53 uint16_t Index = 0;
54#define DIAG_NAME_INDEX(ENUM) Result[diag::ENUM] = ++Index;
55#include "clang/Basic/DiagnosticIndexName.inc"
56#undef DIAG_NAME_INDEX
57 return Result;
58}();
59
60llvm::StringRef DiagnosticRecord::getName() const {
61 const char *Names = reinterpret_cast<const char *>(&BuiltinDiagnosticNames);
62 uint32_t NameOffset =
63 uint32_t(NameOffsetLow) | (uint32_t(NameOffsetHigh) << 16);
64 return llvm::StringRef(Names + NameOffset, NameLen);
65}
66
67const DiagnosticRecord &diagtool::getDiagnosticForID(short DiagID) {
68 assert(DiagID >= 0 &&
69 static_cast<unsigned>(DiagID) < BuiltinDiagnosticIndexByID.size() &&
70 BuiltinDiagnosticIndexByID[DiagID] != 0 && "diagnostic not found");
71 return BuiltinDiagnosticsByName[BuiltinDiagnosticIndexByID[DiagID] - 1];
72}
73
74#define GET_DIAG_ARRAYS
75#include "clang/Basic/DiagnosticGroups.inc"
76#undef GET_DIAG_ARRAYS
77
78// Second the table of options, sorted by name for fast binary lookup.
79static const GroupRecord OptionTable[] = {
80#define DIAG_ENTRY(GroupName, FlagNameOffset, Members, SubGroups, Docs) \
81 {FlagNameOffset, Members, SubGroups},
82#include "clang/Basic/DiagnosticGroups.inc"
83#undef DIAG_ENTRY
84};
85
86llvm::StringRef GroupRecord::getName() const {
87 return DiagGroupNames[NameOffset];
88}
89
90GroupRecord::subgroup_iterator GroupRecord::subgroup_begin() const {
91 return DiagSubGroups + SubGroups;
92}
93
94GroupRecord::subgroup_iterator GroupRecord::subgroup_end() const {
95 return nullptr;
96}
97
98llvm::iterator_range<diagtool::GroupRecord::subgroup_iterator>
99GroupRecord::subgroups() const {
100 return llvm::make_range(x: subgroup_begin(), y: subgroup_end());
101}
102
103GroupRecord::diagnostics_iterator GroupRecord::diagnostics_begin() const {
104 return DiagArrays + Members;
105}
106
107GroupRecord::diagnostics_iterator GroupRecord::diagnostics_end() const {
108 return nullptr;
109}
110
111llvm::iterator_range<diagtool::GroupRecord::diagnostics_iterator>
112GroupRecord::diagnostics() const {
113 return llvm::make_range(x: diagnostics_begin(), y: diagnostics_end());
114}
115
116llvm::ArrayRef<GroupRecord> diagtool::getDiagnosticGroups() {
117 return llvm::ArrayRef(OptionTable);
118}
119