summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp')
-rw-r--r--contrib/llvm/tools/clang/utils/TableGen/ClangDiagnosticsEmitter.cpp332
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];
OpenPOWER on IntegriCloud