TreeView.cpp revision 354f20a8720732aa1745d1ff9595382cee324ee2
1//===- TreeView.cpp - diagtool tool for printing warning flags ------------===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9// 10// This diagnostic tool 11// 12//===----------------------------------------------------------------------===// 13 14#include "DiagTool.h" 15#include "DiagnosticNames.h" 16#include "clang/AST/ASTDiagnostic.h" 17#include "clang/Basic/AllDiagnostics.h" 18#include "clang/Basic/Diagnostic.h" 19#include "clang/Basic/DiagnosticOptions.h" 20#include "llvm/ADT/DenseSet.h" 21#include "llvm/ADT/StringMap.h" 22#include "llvm/Support/Format.h" 23#include "llvm/Support/Process.h" 24 25DEF_DIAGTOOL("tree", 26 "Show warning flags in a tree view", 27 TreeView) 28 29using namespace clang; 30using namespace diagtool; 31 32static void printUsage() { 33 llvm::errs() << "Usage: diagtool tree [--flags-only] [<diagnostic-group>]\n"; 34} 35 36static bool showColors(llvm::raw_ostream &out) { 37 if (&out != &llvm::errs() && &out != &llvm::outs()) 38 return false; 39 return llvm::errs().is_displayed() && llvm::outs().is_displayed(); 40} 41 42static void setColor(bool ShowColors, llvm::raw_ostream &out, 43 llvm::raw_ostream::Colors Color) { 44 if (ShowColors) 45 out << llvm::sys::Process::OutputColor(Color, false, false); 46} 47 48static void resetColor(bool ShowColors, llvm::raw_ostream &out) { 49 if (ShowColors) 50 out << llvm::sys::Process::ResetColor(); 51} 52 53static clang::DiagnosticsEngine::Level getLevel(unsigned DiagID) { 54 // FIXME: This feels like a hack. 55 static clang::DiagnosticsEngine Diags(new DiagnosticIDs, 56 new DiagnosticOptions); 57 return Diags.getDiagnosticLevel(DiagID, SourceLocation()); 58} 59 60static void printGroup(llvm::raw_ostream &out, const GroupRecord &Group, 61 bool FlagsOnly, unsigned Indent = 0) { 62 out.indent(Indent * 2); 63 64 bool ShowColors = showColors(out); 65 setColor(ShowColors, out, llvm::raw_ostream::YELLOW); 66 out << "-W" << Group.getName() << "\n"; 67 resetColor(ShowColors, out); 68 69 ++Indent; 70 for (GroupRecord::subgroup_iterator I = Group.subgroup_begin(), 71 E = Group.subgroup_end(); 72 I != E; ++I) { 73 printGroup(out, *I, FlagsOnly, Indent); 74 } 75 76 if (!FlagsOnly) { 77 for (GroupRecord::diagnostics_iterator I = Group.diagnostics_begin(), 78 E = Group.diagnostics_end(); 79 I != E; ++I) { 80 if (ShowColors) { 81 if (getLevel(I->DiagID) != DiagnosticsEngine::Ignored) { 82 setColor(ShowColors, out, llvm::raw_ostream::GREEN); 83 } 84 } 85 out.indent(Indent * 2); 86 out << I->getName(); 87 resetColor(ShowColors, out); 88 out << "\n"; 89 } 90 } 91} 92 93static int showGroup(llvm::raw_ostream &out, StringRef RootGroup, 94 bool FlagsOnly) { 95 ArrayRef<GroupRecord> AllGroups = getDiagnosticGroups(); 96 97 if (RootGroup.size() > UINT16_MAX) { 98 llvm::errs() << "No such diagnostic group exists\n"; 99 return 1; 100 } 101 102 const GroupRecord *Found = 103 std::lower_bound(AllGroups.begin(), AllGroups.end(), RootGroup); 104 105 if (Found == AllGroups.end() || Found->getName() != RootGroup) { 106 llvm::errs() << "No such diagnostic group exists\n"; 107 return 1; 108 } 109 110 printGroup(out, *Found, FlagsOnly); 111 112 return 0; 113} 114 115static int showAll(llvm::raw_ostream &out, bool FlagsOnly) { 116 ArrayRef<GroupRecord> AllGroups = getDiagnosticGroups(); 117 llvm::DenseSet<unsigned> NonRootGroupIDs; 118 119 for (ArrayRef<GroupRecord>::iterator I = AllGroups.begin(), 120 E = AllGroups.end(); 121 I != E; ++I) { 122 for (GroupRecord::subgroup_iterator SI = I->subgroup_begin(), 123 SE = I->subgroup_end(); 124 SI != SE; ++SI) { 125 NonRootGroupIDs.insert((unsigned)SI.getID()); 126 } 127 } 128 129 assert(NonRootGroupIDs.size() < AllGroups.size()); 130 131 for (unsigned i = 0, e = AllGroups.size(); i != e; ++i) { 132 if (!NonRootGroupIDs.count(i)) 133 printGroup(out, AllGroups[i], FlagsOnly); 134 } 135 136 return 0; 137} 138 139int TreeView::run(unsigned int argc, char **argv, llvm::raw_ostream &out) { 140 // First check our one flag (--flags-only). 141 bool FlagsOnly = false; 142 if (argc > 0) { 143 StringRef FirstArg(*argv); 144 if (FirstArg.equals("--flags-only")) { 145 FlagsOnly = true; 146 --argc; 147 ++argv; 148 } 149 } 150 151 bool ShowAll = false; 152 StringRef RootGroup; 153 154 switch (argc) { 155 case 0: 156 ShowAll = true; 157 break; 158 case 1: 159 RootGroup = argv[0]; 160 if (RootGroup.startswith("-W")) 161 RootGroup = RootGroup.substr(2); 162 if (RootGroup == "everything") 163 ShowAll = true; 164 // FIXME: Handle other special warning flags, like -pedantic. 165 break; 166 default: 167 printUsage(); 168 return -1; 169 } 170 171 if (showColors(out)) { 172 out << '\n'; 173 setColor(true, out, llvm::raw_ostream::GREEN); 174 out << "GREEN"; 175 resetColor(true, out); 176 out << " = enabled by default\n\n"; 177 } 178 179 if (ShowAll) 180 return showAll(out, FlagsOnly); 181 182 return showGroup(out, RootGroup, FlagsOnly); 183} 184 185