From 8b9d027701dbfe4e0dad8c0fd8a2fdc95e7bf7db Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Wed, 18 Mar 2009 21:16:16 +0000 Subject: [PATCH] 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 --- utils/TableGen/ClangDiagnosticsEmitter.cpp | 101 +++++++++++++++++++++ utils/TableGen/ClangDiagnosticsEmitter.h | 9 ++ utils/TableGen/TableGen.cpp | 6 ++ 3 files changed, 116 insertions(+) diff --git a/utils/TableGen/ClangDiagnosticsEmitter.cpp b/utils/TableGen/ClangDiagnosticsEmitter.cpp index f9501fb494d..a3f27ba75f2 100644 --- a/utils/TableGen/ClangDiagnosticsEmitter.cpp +++ b/utils/TableGen/ClangDiagnosticsEmitter.cpp @@ -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 +#include using namespace llvm; + +//===----------------------------------------------------------------------===// +// Generic routines for all Clang TableGen backens. +//===----------------------------------------------------------------------===// + typedef std::vector RecordVector; typedef std::vector SuperClassVector; typedef std::vector 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 DiagnosticSet; +typedef std::map OptionMap; +typedef llvm::DenseSet 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(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(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(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(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"; + } +} diff --git a/utils/TableGen/ClangDiagnosticsEmitter.h b/utils/TableGen/ClangDiagnosticsEmitter.h index bedfe5af8f8..b241bde521e 100644 --- a/utils/TableGen/ClangDiagnosticsEmitter.h +++ b/utils/TableGen/ClangDiagnosticsEmitter.h @@ -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 diff --git a/utils/TableGen/TableGen.cpp b/utils/TableGen/TableGen.cpp index 22c5d504155..0e356290a97 100644 --- a/utils/TableGen/TableGen.cpp +++ b/utils/TableGen/TableGen.cpp @@ -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;