Add another Clang TableGen-backend (-gen-clang-diags-options) for emitting

declarations for controlling groups of warnings. Currently this transforms:

  def UnusedMacrosDiags : Option<"unused-macros", [pp_macro_not_used]>;
  
into:

  static const diag::kind UnusedMacrosDiags[] = { diag::pp_macro_not_used };



git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@67239 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Ted Kremenek 2009-03-18 21:16:16 +00:00
parent d4771828ca
commit 8b9d027701
3 changed files with 116 additions and 0 deletions

View File

@ -16,8 +16,16 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/Streams.h"
#include "llvm/ADT/VectorExtras.h"
#include "llvm/ADT/DenseSet.h"
#include <set>
#include <map>
using namespace llvm;
//===----------------------------------------------------------------------===//
// Generic routines for all Clang TableGen backens.
//===----------------------------------------------------------------------===//
typedef std::vector<Record*> RecordVector;
typedef std::vector<Record*> SuperClassVector;
typedef std::vector<RecordVal> RecordValVector;
@ -54,6 +62,10 @@ static void EmitAllCaps(std::ostream& OS, const std::string &s) {
OS << char(toupper(*I));
}
//===----------------------------------------------------------------------===//
// Warning Tables (.inc file) generation.
//===----------------------------------------------------------------------===//
static void ProcessDiag(std::ostream& OS, const Record* DiagClass,
const Record& R) {
@ -106,3 +118,92 @@ void ClangDiagsDefsEmitter::run(std::ostream &OS) {
ProcessDiag(OS, DiagClass, **I);
}
}
//===----------------------------------------------------------------------===//
// Warning Group Tables generation.
//===----------------------------------------------------------------------===//
typedef std::set<const Record*> DiagnosticSet;
typedef std::map<const Record*, DiagnosticSet> OptionMap;
typedef llvm::DenseSet<const ListInit*> VisitedLists;
static void BuildGroup(DiagnosticSet& DS, VisitedLists &Visited, const Init* X);
static void BuildGroup(DiagnosticSet &DS, VisitedLists &Visited,
const ListInit* LV) {
// Simple hack to prevent including a list multiple times. This may be useful
// if one declares an Option by including a bunch of other Options that
// include other Options, etc.
if (Visited.count(LV))
return;
Visited.insert(LV);
// Iterate through the list and grab all DiagnosticControlled.
for (ListInit::const_iterator I = LV->begin(), E = LV->end(); I!=E; ++I)
BuildGroup(DS, Visited, *I);
}
static void BuildGroup(DiagnosticSet& DS, VisitedLists &Visited,
const Record *Def) {
// If an Option includes another Option, inline the Diagnostics of the
// included Option.
if (Def->isSubClassOf("Option")) {
if (const RecordVal* V = findRecordVal(*Def, "Members"))
if (const ListInit* LV = dynamic_cast<const ListInit*>(V->getValue()))
BuildGroup(DS, Visited, LV);
return;
}
if (Def->isSubClassOf("DiagnosticControlled"))
DS.insert(Def);
}
static void BuildGroup(DiagnosticSet& DS, VisitedLists &Visited,
const Init* X) {
if (const DefInit *D = dynamic_cast<const DefInit*>(X))
BuildGroup(DS, Visited, D->getDef());
// We may have some other cases here in the future.
}
void ClangOptionsEmitter::run(std::ostream &OS) {
// Build up a map from options to controlled diagnostics.
OptionMap OM;
const RecordVector &Opts = Records.getAllDerivedDefinitions("Option");
for (RecordVector::const_iterator I=Opts.begin(), E=Opts.end(); I!=E; ++I)
if (const RecordVal* V = findRecordVal(**I, "Members"))
if (const ListInit* LV = dynamic_cast<const ListInit*>(V->getValue())) {
VisitedLists Visited;
BuildGroup(OM[*I], Visited, LV);
}
// Iterate through the OptionMap and emit the declarations.
for (OptionMap::iterator I = OM.begin(), E = OM.end(); I!=E; ++I) {
// const RecordVal *V = findRecordVal(*I->first, "Name");
// assert(V && "Options must have a 'Name' value.");
// const StringInit* SV = dynamic_cast<const StringInit*>(V->getValue());
// assert(SV && "'Name' entry must be a string.");
// Output the option.
OS << "static const diag::kind " << I->first->getName() << "[] = { ";
DiagnosticSet &DS = I->second;
bool first = true;
for (DiagnosticSet::iterator I2 = DS.begin(), E2 = DS.end(); I2!=E2; ++I2) {
if (first)
first = false;
else
OS << ", ";
OS << "diag::" << (*I2)->getName();
}
OS << " };\n";
}
}

View File

@ -32,6 +32,15 @@ public:
void run(std::ostream &OS);
};
class ClangOptionsEmitter : public TableGenBackend {
RecordKeeper &Records;
public:
explicit ClangOptionsEmitter(RecordKeeper &R) : Records(R) {}
void run(std::ostream &OS);
};
} // End llvm namespace
#endif

View File

@ -48,6 +48,7 @@ enum ActionType {
GenInstrEnums, GenInstrs, GenAsmWriter,
GenCallingConv,
GenClangDiagsDefs,
GenClangDiagsOptions,
GenDAGISel,
GenFastISel,
GenSubtarget,
@ -90,6 +91,8 @@ namespace {
"Generate target intrinsic information"),
clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs",
"Generate Clang diagnostics definitions"),
clEnumValN(GenClangDiagsOptions, "gen-clang-diags-options",
"Generate options for Clang diagnostics"),
clEnumValN(GenLLVMCConf, "gen-llvmc",
"Generate LLVMC configuration library"),
clEnumValN(PrintEnums, "print-enums",
@ -209,6 +212,9 @@ int main(int argc, char **argv) {
case GenClangDiagsDefs:
ClangDiagsDefsEmitter(Records, ClangComponent).run(*Out);
break;
case GenClangDiagsOptions:
ClangOptionsEmitter(Records).run(*Out);
break;
case GenDAGISel:
DAGISelEmitter(Records).run(*Out);
break;