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