diff options
Diffstat (limited to 'contrib/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp | 332 |
1 files changed, 224 insertions, 108 deletions
diff --git a/contrib/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp b/contrib/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp index db159d1..e517755 100644 --- a/contrib/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp +++ b/contrib/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp @@ -135,7 +135,7 @@ namespace { const Record *ExplicitDef; - GroupInfo() : ExplicitDef(0) {} + GroupInfo() : ExplicitDef(nullptr) {} }; } // end anonymous namespace. @@ -170,7 +170,8 @@ static void groupDiagnostics(const std::vector<Record*> &Diags, for (unsigned i = 0, e = Diags.size(); i != e; ++i) { const Record *R = Diags[i]; DefInit *DI = dyn_cast<DefInit>(R->getValueInit("Group")); - if (DI == 0) continue; + if (!DI) + continue; assert(R->getValueAsDef("Class")->getName() != "CLASS_NOTE" && "Note can't be in a DiagGroup"); std::string GroupName = DI->getDef()->getValueAsString("GroupName"); @@ -357,8 +358,9 @@ bool InferPedantic::isExtension(const Record *Diag) { } bool InferPedantic::isOffByDefault(const Record *Diag) { - const std::string &DefMap = Diag->getValueAsDef("DefaultMapping")->getName(); - return DefMap == "MAP_IGNORE"; + const std::string &DefSeverity = + Diag->getValueAsDef("DefaultSeverity")->getValueAsString("Name"); + return DefSeverity == "Ignored"; } bool InferPedantic::groupInPedantic(const Record *Group, bool increment) { @@ -472,6 +474,11 @@ static bool isError(const Record &Diag) { return ClsName == "CLASS_ERROR"; } +static bool isRemark(const Record &Diag) { + const std::string &ClsName = Diag.getValueAsDef("Class")->getName(); + return ClsName == "CLASS_REMARK"; +} + /// ClangDiagsDefsEmitter - The top-level class emits .def files containing /// declarations of Clang diagnostics. namespace clang { @@ -502,7 +509,7 @@ void EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS, // Compute the set of diagnostics that are in -Wpedantic. RecordSet DiagsInPedantic; InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup); - inferPedantic.compute(&DiagsInPedantic, (RecordVec*)0); + inferPedantic.compute(&DiagsInPedantic, (RecordVec*)nullptr); for (unsigned i = 0, e = Diags.size(); i != e; ++i) { const Record &R = *Diags[i]; @@ -518,13 +525,22 @@ void EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS, } } + // Check that all remarks have an associated diagnostic group. + if (isRemark(R)) { + if (!isa<DefInit>(R.getValueInit("Group"))) { + PrintFatalError(R.getLoc(), "Error " + R.getName() + + " not in any diagnostic group"); + } + } + // Filter by component. if (!Component.empty() && Component != R.getValueAsString("Component")) continue; OS << "DIAG(" << R.getName() << ", "; OS << R.getValueAsDef("Class")->getName(); - OS << ", diag::" << R.getValueAsDef("DefaultMapping")->getName(); + OS << ", (unsigned)diag::Severity::" + << R.getValueAsDef("DefaultSeverity")->getValueAsString("Name"); // Description string. OS << ", \""; @@ -555,8 +571,7 @@ void EmitClangDiagsDefs(RecordKeeper &Records, raw_ostream &OS, else OS << ", false"; - // Default warning show in system header bit. - if (R.getValueAsBit("WarningShowInSystemHeader")) + if (R.getValueAsBit("ShowInSystemHeader")) OS << ", true"; else OS << ", false"; @@ -581,76 +596,42 @@ static std::string getDiagCategoryEnum(llvm::StringRef name) { return enumName.str(); } -namespace clang { -void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) { - // Compute a mapping from a DiagGroup to all of its parents. - DiagGroupParentMap DGParentMap(Records); - - std::vector<Record*> Diags = - Records.getAllDerivedDefinitions("Diagnostic"); - - std::vector<Record*> DiagGroups - = Records.getAllDerivedDefinitions("DiagGroup"); - - std::map<std::string, GroupInfo> DiagsInGroup; - groupDiagnostics(Diags, DiagGroups, DiagsInGroup); - - // All extensions are implicitly in the "pedantic" group. Record the - // implicit set of groups in the "pedantic" group, and use this information - // later when emitting the group information for Pedantic. - RecordVec DiagsInPedantic; - RecordVec GroupsInPedantic; - InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup); - inferPedantic.compute(&DiagsInPedantic, &GroupsInPedantic); - - // Walk through the groups emitting an array for each diagnostic of the diags - // that are mapped to. - OS << "\n#ifdef GET_DIAG_ARRAYS\n"; - unsigned MaxLen = 0; - OS << "static const int16_t DiagArrays[] = {\n" - << " /* Empty */ -1,\n"; - for (std::map<std::string, GroupInfo>::const_iterator - I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) { - MaxLen = std::max(MaxLen, (unsigned)I->first.size()); - const bool IsPedantic = I->first == "pedantic"; - - const std::vector<const Record*> &V = I->second.DiagsInGroup; - if (!V.empty() || (IsPedantic && !DiagsInPedantic.empty())) { - OS << " /* DiagArray" << I->second.IDNo << " */ "; - for (unsigned i = 0, e = V.size(); i != e; ++i) - OS << "diag::" << V[i]->getName() << ", "; - // Emit the diagnostics implicitly in "pedantic". - if (IsPedantic) { - for (unsigned i = 0, e = DiagsInPedantic.size(); i != e; ++i) - OS << "diag::" << DiagsInPedantic[i]->getName() << ", "; - } - OS << "-1,\n"; - } - } - OS << "};\n\n"; - +/// \brief Emit the array of diagnostic subgroups. +/// +/// The array of diagnostic subgroups contains for each group a list of its +/// subgroups. The individual lists are separated by '-1'. Groups with no +/// subgroups are skipped. +/// +/// \code +/// static const int16_t DiagSubGroups[] = { +/// /* Empty */ -1, +/// /* DiagSubGroup0 */ 142, -1, +/// /* DiagSubGroup13 */ 265, 322, 399, -1 +/// } +/// \endcode +/// +static void emitDiagSubGroups(std::map<std::string, GroupInfo> &DiagsInGroup, + RecordVec &GroupsInPedantic, raw_ostream &OS) { OS << "static const int16_t DiagSubGroups[] = {\n" << " /* Empty */ -1,\n"; - for (std::map<std::string, GroupInfo>::const_iterator - I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) { - const bool IsPedantic = I->first == "pedantic"; + for (auto const &I : DiagsInGroup) { + const bool IsPedantic = I.first == "pedantic"; - const std::vector<std::string> &SubGroups = I->second.SubGroups; + const std::vector<std::string> &SubGroups = I.second.SubGroups; if (!SubGroups.empty() || (IsPedantic && !GroupsInPedantic.empty())) { - OS << " /* DiagSubGroup" << I->second.IDNo << " */ "; - for (unsigned i = 0, e = SubGroups.size(); i != e; ++i) { + OS << " /* DiagSubGroup" << I.second.IDNo << " */ "; + for (auto const &SubGroup : SubGroups) { std::map<std::string, GroupInfo>::const_iterator RI = - DiagsInGroup.find(SubGroups[i]); + DiagsInGroup.find(SubGroup); assert(RI != DiagsInGroup.end() && "Referenced without existing?"); OS << RI->second.IDNo << ", "; } // Emit the groups implicitly in "pedantic". if (IsPedantic) { - for (unsigned i = 0, e = GroupsInPedantic.size(); i != e; ++i) { - const std::string &GroupName = - GroupsInPedantic[i]->getValueAsString("GroupName"); + for (auto const &Group : GroupsInPedantic) { + const std::string &GroupName = Group->getValueAsString("GroupName"); std::map<std::string, GroupInfo>::const_iterator RI = - DiagsInGroup.find(GroupName); + DiagsInGroup.find(GroupName); assert(RI != DiagsInGroup.end() && "Referenced without existing?"); OS << RI->second.IDNo << ", "; } @@ -660,48 +641,140 @@ void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) { } } OS << "};\n\n"; +} - StringToOffsetTable GroupNames; - for (std::map<std::string, GroupInfo>::const_iterator - I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) { - // Store a pascal-style length byte at the beginning of the string. - std::string Name = char(I->first.size()) + I->first; - GroupNames.GetOrAddStringOffset(Name, false); +/// \brief Emit the list of diagnostic arrays. +/// +/// This data structure is a large array that contains itself arrays of varying +/// size. Each array represents a list of diagnostics. The different arrays are +/// separated by the value '-1'. +/// +/// \code +/// static const int16_t DiagArrays[] = { +/// /* Empty */ -1, +/// /* DiagArray1 */ diag::warn_pragma_message, +/// -1, +/// /* DiagArray2 */ diag::warn_abs_too_small, +/// diag::warn_unsigned_abs, +/// diag::warn_wrong_absolute_value_type, +/// -1 +/// }; +/// \endcode +/// +static void emitDiagArrays(std::map<std::string, GroupInfo> &DiagsInGroup, + RecordVec &DiagsInPedantic, raw_ostream &OS) { + OS << "static const int16_t DiagArrays[] = {\n" + << " /* Empty */ -1,\n"; + for (auto const &I : DiagsInGroup) { + const bool IsPedantic = I.first == "pedantic"; + + const std::vector<const Record *> &V = I.second.DiagsInGroup; + if (!V.empty() || (IsPedantic && !DiagsInPedantic.empty())) { + OS << " /* DiagArray" << I.second.IDNo << " */ "; + for (auto *Record : V) + OS << "diag::" << Record->getName() << ", "; + // Emit the diagnostics implicitly in "pedantic". + if (IsPedantic) { + for (auto const &Diag : DiagsInPedantic) + OS << "diag::" << Diag->getName() << ", "; + } + OS << "-1,\n"; + } } + OS << "};\n\n"; +} +/// \brief Emit a list of group names. +/// +/// This creates a long string which by itself contains a list of pascal style +/// strings, which consist of a length byte directly followed by the string. +/// +/// \code +/// static const char DiagGroupNames[] = { +/// \000\020#pragma-messages\t#warnings\020CFString-literal" +/// }; +/// \endcode +static void emitDiagGroupNames(StringToOffsetTable &GroupNames, + raw_ostream &OS) { OS << "static const char DiagGroupNames[] = {\n"; GroupNames.EmitString(OS); OS << "};\n\n"; +} +/// \brief Emit diagnostic arrays and related data structures. +/// +/// This creates the actual diagnostic array, an array of diagnostic subgroups +/// and an array of subgroup names. +/// +/// \code +/// #ifdef GET_DIAG_ARRAYS +/// static const int16_t DiagArrays[]; +/// static const int16_t DiagSubGroups[]; +/// static const char DiagGroupNames[]; +/// #endif +/// \endcode +static void emitAllDiagArrays(std::map<std::string, GroupInfo> &DiagsInGroup, + RecordVec &DiagsInPedantic, + RecordVec &GroupsInPedantic, + StringToOffsetTable &GroupNames, + raw_ostream &OS) { + OS << "\n#ifdef GET_DIAG_ARRAYS\n"; + emitDiagArrays(DiagsInGroup, DiagsInPedantic, OS); + emitDiagSubGroups(DiagsInGroup, GroupsInPedantic, OS); + emitDiagGroupNames(GroupNames, OS); OS << "#endif // GET_DIAG_ARRAYS\n\n"; +} + +/// \brief Emit diagnostic table. +/// +/// The table is sorted by the name of the diagnostic group. Each element +/// consists of the name of the diagnostic group (given as offset in the +/// group name table), a reference to a list of diagnostics (optional) and a +/// reference to a set of subgroups (optional). +/// +/// \code +/// #ifdef GET_DIAG_TABLE +/// {/* abi */ 159, /* DiagArray11 */ 19, /* Empty */ 0}, +/// {/* aggregate-return */ 180, /* Empty */ 0, /* Empty */ 0}, +/// {/* all */ 197, /* Empty */ 0, /* DiagSubGroup13 */ 3}, +/// {/* deprecated */ 1981,/* DiagArray1 */ 348, /* DiagSubGroup3 */ 9}, +/// #endif +/// \endcode +static void emitDiagTable(std::map<std::string, GroupInfo> &DiagsInGroup, + RecordVec &DiagsInPedantic, + RecordVec &GroupsInPedantic, + StringToOffsetTable &GroupNames, raw_ostream &OS) { + unsigned MaxLen = 0; + + for (auto const &I: DiagsInGroup) + MaxLen = std::max(MaxLen, (unsigned)I.first.size()); - // Emit the table now. OS << "\n#ifdef GET_DIAG_TABLE\n"; unsigned SubGroupIndex = 1, DiagArrayIndex = 1; - for (std::map<std::string, GroupInfo>::const_iterator - I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I) { + for (auto const &I: DiagsInGroup) { // Group option string. OS << " { /* "; - if (I->first.find_first_not_of("abcdefghijklmnopqrstuvwxyz" + if (I.first.find_first_not_of("abcdefghijklmnopqrstuvwxyz" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - "0123456789!@#$%^*-+=:?")!=std::string::npos) - PrintFatalError("Invalid character in diagnostic group '" + - I->first + "'"); - OS << I->first << " */ " << std::string(MaxLen-I->first.size(), ' '); + "0123456789!@#$%^*-+=:?") != + std::string::npos) + PrintFatalError("Invalid character in diagnostic group '" + I.first + + "'"); + OS << I.first << " */ " << std::string(MaxLen - I.first.size(), ' '); // Store a pascal-style length byte at the beginning of the string. - std::string Name = char(I->first.size()) + I->first; + std::string Name = char(I.first.size()) + I.first; OS << GroupNames.GetOrAddStringOffset(Name, false) << ", "; // Special handling for 'pedantic'. - const bool IsPedantic = I->first == "pedantic"; + const bool IsPedantic = I.first == "pedantic"; // Diagnostics in the group. - const std::vector<const Record*> &V = I->second.DiagsInGroup; - const bool hasDiags = !V.empty() || - (IsPedantic && !DiagsInPedantic.empty()); + const std::vector<const Record *> &V = I.second.DiagsInGroup; + const bool hasDiags = + !V.empty() || (IsPedantic && !DiagsInPedantic.empty()); if (hasDiags) { - OS << "/* DiagArray" << I->second.IDNo << " */ " - << DiagArrayIndex << ", "; + OS << "/* DiagArray" << I.second.IDNo << " */ " << DiagArrayIndex + << ", "; if (IsPedantic) DiagArrayIndex += DiagsInPedantic.size(); DiagArrayIndex += V.size() + 1; @@ -710,29 +783,81 @@ void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) { } // Subgroups. - const std::vector<std::string> &SubGroups = I->second.SubGroups; - const bool hasSubGroups = !SubGroups.empty() || - (IsPedantic && !GroupsInPedantic.empty()); + const std::vector<std::string> &SubGroups = I.second.SubGroups; + const bool hasSubGroups = + !SubGroups.empty() || (IsPedantic && !GroupsInPedantic.empty()); if (hasSubGroups) { - OS << "/* DiagSubGroup" << I->second.IDNo << " */ " << SubGroupIndex; + OS << "/* DiagSubGroup" << I.second.IDNo << " */ " << SubGroupIndex; if (IsPedantic) SubGroupIndex += GroupsInPedantic.size(); SubGroupIndex += SubGroups.size() + 1; } else { OS << "/* Empty */ 0"; } + OS << " },\n"; } OS << "#endif // GET_DIAG_TABLE\n\n"; +} - // Emit the category table next. +/// \brief Emit the table of diagnostic categories. +/// +/// The table has the form of macro calls that have two parameters. The +/// category's name as well as an enum that represents the category. The +/// table can be used by defining the macro 'CATEGORY' and including this +/// table right after. +/// +/// \code +/// #ifdef GET_CATEGORY_TABLE +/// CATEGORY("Semantic Issue", DiagCat_Semantic_Issue) +/// CATEGORY("Lambda Issue", DiagCat_Lambda_Issue) +/// #endif +/// \endcode +static void emitCategoryTable(RecordKeeper &Records, raw_ostream &OS) { DiagCategoryIDMap CategoriesByID(Records); OS << "\n#ifdef GET_CATEGORY_TABLE\n"; - for (DiagCategoryIDMap::const_iterator I = CategoriesByID.begin(), - E = CategoriesByID.end(); I != E; ++I) - OS << "CATEGORY(\"" << *I << "\", " << getDiagCategoryEnum(*I) << ")\n"; + for (auto const &C : CategoriesByID) + OS << "CATEGORY(\"" << C << "\", " << getDiagCategoryEnum(C) << ")\n"; OS << "#endif // GET_CATEGORY_TABLE\n\n"; } + +namespace clang { +void EmitClangDiagGroups(RecordKeeper &Records, raw_ostream &OS) { + // Compute a mapping from a DiagGroup to all of its parents. + DiagGroupParentMap DGParentMap(Records); + + std::vector<Record *> Diags = Records.getAllDerivedDefinitions("Diagnostic"); + + std::vector<Record *> DiagGroups = + Records.getAllDerivedDefinitions("DiagGroup"); + + std::map<std::string, GroupInfo> DiagsInGroup; + groupDiagnostics(Diags, DiagGroups, DiagsInGroup); + + // All extensions are implicitly in the "pedantic" group. Record the + // implicit set of groups in the "pedantic" group, and use this information + // later when emitting the group information for Pedantic. + RecordVec DiagsInPedantic; + RecordVec GroupsInPedantic; + InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup); + inferPedantic.compute(&DiagsInPedantic, &GroupsInPedantic); + + StringToOffsetTable GroupNames; + for (std::map<std::string, GroupInfo>::const_iterator + I = DiagsInGroup.begin(), + E = DiagsInGroup.end(); + I != E; ++I) { + // Store a pascal-style length byte at the beginning of the string. + std::string Name = char(I->first.size()) + I->first; + GroupNames.GetOrAddStringOffset(Name, false); + } + + emitAllDiagArrays(DiagsInGroup, DiagsInPedantic, GroupsInPedantic, GroupNames, + OS); + emitDiagTable(DiagsInGroup, DiagsInPedantic, GroupsInPedantic, GroupNames, + OS); + emitCategoryTable(Records, OS); +} } // end namespace clang //===----------------------------------------------------------------------===// @@ -748,17 +873,6 @@ struct RecordIndexElement std::string Name; }; - -struct RecordIndexElementSorter : - public std::binary_function<RecordIndexElement, RecordIndexElement, bool> { - - bool operator()(RecordIndexElement const &Lhs, - RecordIndexElement const &Rhs) const { - return Lhs.Name < Rhs.Name; - } - -}; - } // end anonymous namespace. namespace clang { @@ -773,7 +887,9 @@ void EmitClangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS) { Index.push_back(RecordIndexElement(R)); } - std::sort(Index.begin(), Index.end(), RecordIndexElementSorter()); + std::sort(Index.begin(), Index.end(), + [](const RecordIndexElement &Lhs, + const RecordIndexElement &Rhs) { return Lhs.Name < Rhs.Name; }); for (unsigned i = 0, e = Index.size(); i != e; ++i) { const RecordIndexElement &R = Index[i]; |