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