//===- TreeView.cpp - diagtool tool for printing warning flags ------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This diagnostic tool // //===----------------------------------------------------------------------===// #include "DiagTool.h" #include "DiagnosticNames.h" #include "clang/AST/ASTDiagnostic.h" #include "clang/Basic/AllDiagnostics.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticOptions.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/StringMap.h" #include "llvm/Support/Format.h" #include "llvm/Support/Process.h" DEF_DIAGTOOL("tree", "Show warning flags in a tree view", TreeView) using namespace clang; using namespace diagtool; static void printUsage() { llvm::errs() << "Usage: diagtool tree [--flags-only] [<diagnostic-group>]\n"; } static bool showColors(llvm::raw_ostream &out) { if (&out != &llvm::errs() && &out != &llvm::outs()) return false; return llvm::errs().is_displayed() && llvm::outs().is_displayed(); } static void setColor(bool ShowColors, llvm::raw_ostream &out, llvm::raw_ostream::Colors Color) { if (ShowColors) out << llvm::sys::Process::OutputColor(Color, false, false); } static void resetColor(bool ShowColors, llvm::raw_ostream &out) { if (ShowColors) out << llvm::sys::Process::ResetColor(); } static clang::DiagnosticsEngine::Level getLevel(unsigned DiagID) { // FIXME: This feels like a hack. static clang::DiagnosticsEngine Diags(new DiagnosticIDs, new DiagnosticOptions); return Diags.getDiagnosticLevel(DiagID, SourceLocation()); } static void printGroup(llvm::raw_ostream &out, const GroupRecord &Group, bool FlagsOnly, unsigned Indent = 0) { out.indent(Indent * 2); bool ShowColors = showColors(out); setColor(ShowColors, out, llvm::raw_ostream::YELLOW); out << "-W" << Group.getName() << "\n"; resetColor(ShowColors, out); ++Indent; for (GroupRecord::subgroup_iterator I = Group.subgroup_begin(), E = Group.subgroup_end(); I != E; ++I) { printGroup(out, *I, FlagsOnly, Indent); } if (!FlagsOnly) { for (GroupRecord::diagnostics_iterator I = Group.diagnostics_begin(), E = Group.diagnostics_end(); I != E; ++I) { if (ShowColors) { if (getLevel(I->DiagID) != DiagnosticsEngine::Ignored) { setColor(ShowColors, out, llvm::raw_ostream::GREEN); } } out.indent(Indent * 2); out << I->getName(); resetColor(ShowColors, out); out << "\n"; } } } static int showGroup(llvm::raw_ostream &out, StringRef RootGroup, bool FlagsOnly) { ArrayRef<GroupRecord> AllGroups = getDiagnosticGroups(); GroupRecord Key = { RootGroup.size(), RootGroup.data(), 0, 0 }; const GroupRecord *Found = std::lower_bound(AllGroups.begin(), AllGroups.end(), Key); if (Found == AllGroups.end() || Found->getName() != RootGroup) { llvm::errs() << "No such diagnostic group exists\n"; return 1; } printGroup(out, *Found, FlagsOnly); return 0; } static int showAll(llvm::raw_ostream &out, bool FlagsOnly) { ArrayRef<GroupRecord> AllGroups = getDiagnosticGroups(); llvm::DenseSet<unsigned> NonRootGroupIDs; for (ArrayRef<GroupRecord>::iterator I = AllGroups.begin(), E = AllGroups.end(); I != E; ++I) { for (GroupRecord::subgroup_iterator SI = I->subgroup_begin(), SE = I->subgroup_end(); SI != SE; ++SI) { NonRootGroupIDs.insert((unsigned)SI.getID()); } } assert(NonRootGroupIDs.size() < AllGroups.size()); for (unsigned i = 0, e = AllGroups.size(); i != e; ++i) { if (!NonRootGroupIDs.count(i)) printGroup(out, AllGroups[i], FlagsOnly); } return 0; } int TreeView::run(unsigned int argc, char **argv, llvm::raw_ostream &out) { // First check our one flag (--flags-only). bool FlagsOnly = false; if (argc > 0) { StringRef FirstArg(*argv); if (FirstArg.equals("--flags-only")) { FlagsOnly = true; --argc; ++argv; } } bool ShowAll = false; StringRef RootGroup; switch (argc) { case 0: ShowAll = true; break; case 1: RootGroup = argv[0]; if (RootGroup.startswith("-W")) RootGroup = RootGroup.substr(2); if (RootGroup == "everything") ShowAll = true; // FIXME: Handle other special warning flags, like -pedantic. break; default: printUsage(); return -1; } if (showColors(out)) { out << '\n'; setColor(true, out, llvm::raw_ostream::GREEN); out << "GREEN"; resetColor(true, out); out << " = enabled by default\n\n"; } if (ShowAll) return showAll(out, FlagsOnly); return showGroup(out, RootGroup, FlagsOnly); }