xref: /openbsd-src/gnu/llvm/clang/tools/diagtool/TreeView.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===- TreeView.cpp - diagtool tool for printing warning flags ------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick 
9e5dd7070Spatrick #include "DiagTool.h"
10e5dd7070Spatrick #include "DiagnosticNames.h"
11e5dd7070Spatrick #include "clang/Basic/AllDiagnostics.h"
12e5dd7070Spatrick #include "clang/Basic/Diagnostic.h"
13e5dd7070Spatrick #include "clang/Basic/DiagnosticOptions.h"
14e5dd7070Spatrick #include "llvm/ADT/DenseSet.h"
15e5dd7070Spatrick #include "llvm/Support/Format.h"
16e5dd7070Spatrick #include "llvm/Support/Process.h"
17e5dd7070Spatrick 
18e5dd7070Spatrick DEF_DIAGTOOL("tree", "Show warning flags in a tree view", TreeView)
19e5dd7070Spatrick 
20e5dd7070Spatrick using namespace clang;
21e5dd7070Spatrick using namespace diagtool;
22e5dd7070Spatrick 
23e5dd7070Spatrick class TreePrinter {
24e5dd7070Spatrick   using Colors = llvm::raw_ostream::Colors;
25e5dd7070Spatrick 
26e5dd7070Spatrick public:
27e5dd7070Spatrick   llvm::raw_ostream &out;
28e5dd7070Spatrick   bool Internal;
29e5dd7070Spatrick 
TreePrinter(llvm::raw_ostream & out)30e5dd7070Spatrick   TreePrinter(llvm::raw_ostream &out) : out(out), Internal(false) {}
31e5dd7070Spatrick 
isIgnored(unsigned DiagID)32e5dd7070Spatrick   static bool isIgnored(unsigned DiagID) {
33e5dd7070Spatrick     // FIXME: This feels like a hack.
34e5dd7070Spatrick     static clang::DiagnosticsEngine Diags(new DiagnosticIDs,
35e5dd7070Spatrick                                           new DiagnosticOptions);
36e5dd7070Spatrick     return Diags.isIgnored(DiagID, SourceLocation());
37e5dd7070Spatrick   }
38e5dd7070Spatrick 
unimplemented(const GroupRecord & Group)39ec727ea7Spatrick   static bool unimplemented(const GroupRecord &Group) {
40ec727ea7Spatrick     if (!Group.diagnostics().empty())
41ec727ea7Spatrick       return false;
42ec727ea7Spatrick 
43*12c85518Srobert     return llvm::all_of(Group.subgroups(), unimplemented);
44ec727ea7Spatrick   }
45ec727ea7Spatrick 
enabledByDefault(const GroupRecord & Group)46e5dd7070Spatrick   static bool enabledByDefault(const GroupRecord &Group) {
47e5dd7070Spatrick     for (const DiagnosticRecord &DR : Group.diagnostics()) {
48e5dd7070Spatrick       if (isIgnored(DR.DiagID))
49e5dd7070Spatrick         return false;
50e5dd7070Spatrick     }
51e5dd7070Spatrick 
52e5dd7070Spatrick     for (const GroupRecord &GR : Group.subgroups()) {
53e5dd7070Spatrick       if (!enabledByDefault(GR))
54e5dd7070Spatrick         return false;
55e5dd7070Spatrick     }
56e5dd7070Spatrick 
57e5dd7070Spatrick     return true;
58e5dd7070Spatrick   }
59e5dd7070Spatrick 
printGroup(const GroupRecord & Group,unsigned Indent=0)60e5dd7070Spatrick   void printGroup(const GroupRecord &Group, unsigned Indent = 0) {
61e5dd7070Spatrick     out.indent(Indent * 2);
62e5dd7070Spatrick 
63ec727ea7Spatrick     if (unimplemented(Group))
64ec727ea7Spatrick       out << Colors::RED;
65ec727ea7Spatrick     else if (enabledByDefault(Group))
66e5dd7070Spatrick       out << Colors::GREEN;
67e5dd7070Spatrick     else
68e5dd7070Spatrick       out << Colors::YELLOW;
69e5dd7070Spatrick 
70e5dd7070Spatrick     out << "-W" << Group.getName() << "\n" << Colors::RESET;
71e5dd7070Spatrick 
72e5dd7070Spatrick     ++Indent;
73e5dd7070Spatrick     for (const GroupRecord &GR : Group.subgroups()) {
74e5dd7070Spatrick       printGroup(GR, Indent);
75e5dd7070Spatrick     }
76e5dd7070Spatrick 
77e5dd7070Spatrick     if (Internal) {
78e5dd7070Spatrick       for (const DiagnosticRecord &DR : Group.diagnostics()) {
79e5dd7070Spatrick         if (!isIgnored(DR.DiagID))
80e5dd7070Spatrick           out << Colors::GREEN;
81e5dd7070Spatrick         out.indent(Indent * 2);
82e5dd7070Spatrick         out << DR.getName() << Colors::RESET << "\n";
83e5dd7070Spatrick       }
84e5dd7070Spatrick     }
85e5dd7070Spatrick   }
86e5dd7070Spatrick 
showGroup(StringRef RootGroup)87e5dd7070Spatrick   int showGroup(StringRef RootGroup) {
88e5dd7070Spatrick     ArrayRef<GroupRecord> AllGroups = getDiagnosticGroups();
89e5dd7070Spatrick 
90e5dd7070Spatrick     if (RootGroup.size() > UINT16_MAX) {
91e5dd7070Spatrick       llvm::errs() << "No such diagnostic group exists\n";
92e5dd7070Spatrick       return 1;
93e5dd7070Spatrick     }
94e5dd7070Spatrick 
95e5dd7070Spatrick     const GroupRecord *Found = llvm::lower_bound(AllGroups, RootGroup);
96e5dd7070Spatrick     if (Found == AllGroups.end() || Found->getName() != RootGroup) {
97e5dd7070Spatrick       llvm::errs() << "No such diagnostic group exists\n";
98e5dd7070Spatrick       return 1;
99e5dd7070Spatrick     }
100e5dd7070Spatrick 
101e5dd7070Spatrick     printGroup(*Found);
102e5dd7070Spatrick 
103e5dd7070Spatrick     return 0;
104e5dd7070Spatrick   }
105e5dd7070Spatrick 
showAll()106e5dd7070Spatrick   int showAll() {
107e5dd7070Spatrick     ArrayRef<GroupRecord> AllGroups = getDiagnosticGroups();
108e5dd7070Spatrick     llvm::DenseSet<unsigned> NonRootGroupIDs;
109e5dd7070Spatrick 
110e5dd7070Spatrick     for (const GroupRecord &GR : AllGroups) {
111e5dd7070Spatrick       for (auto SI = GR.subgroup_begin(), SE = GR.subgroup_end(); SI != SE;
112e5dd7070Spatrick            ++SI) {
113e5dd7070Spatrick         NonRootGroupIDs.insert((unsigned)SI.getID());
114e5dd7070Spatrick       }
115e5dd7070Spatrick     }
116e5dd7070Spatrick 
117e5dd7070Spatrick     assert(NonRootGroupIDs.size() < AllGroups.size());
118e5dd7070Spatrick 
119e5dd7070Spatrick     for (unsigned i = 0, e = AllGroups.size(); i != e; ++i) {
120e5dd7070Spatrick       if (!NonRootGroupIDs.count(i))
121e5dd7070Spatrick         printGroup(AllGroups[i]);
122e5dd7070Spatrick     }
123e5dd7070Spatrick 
124e5dd7070Spatrick     return 0;
125e5dd7070Spatrick   }
126e5dd7070Spatrick 
showKey()127e5dd7070Spatrick   void showKey() {
128e5dd7070Spatrick     out << '\n' << Colors::GREEN << "GREEN" << Colors::RESET
129ec727ea7Spatrick         << " = enabled by default";
130ec727ea7Spatrick     out << '\n' << Colors::RED << "RED" << Colors::RESET
131ec727ea7Spatrick         << " = unimplemented (accepted for GCC compatibility)\n\n";
132e5dd7070Spatrick   }
133e5dd7070Spatrick };
134e5dd7070Spatrick 
printUsage()135e5dd7070Spatrick static void printUsage() {
136e5dd7070Spatrick   llvm::errs() << "Usage: diagtool tree [--internal] [<diagnostic-group>]\n";
137e5dd7070Spatrick }
138e5dd7070Spatrick 
run(unsigned int argc,char ** argv,llvm::raw_ostream & out)139e5dd7070Spatrick int TreeView::run(unsigned int argc, char **argv, llvm::raw_ostream &out) {
140e5dd7070Spatrick   // First check our one flag (--flags-only).
141e5dd7070Spatrick   bool Internal = false;
142e5dd7070Spatrick   if (argc > 0) {
143e5dd7070Spatrick     StringRef FirstArg(*argv);
144e5dd7070Spatrick     if (FirstArg.equals("--internal")) {
145e5dd7070Spatrick       Internal = true;
146e5dd7070Spatrick       --argc;
147e5dd7070Spatrick       ++argv;
148e5dd7070Spatrick     }
149e5dd7070Spatrick   }
150e5dd7070Spatrick 
151e5dd7070Spatrick   bool ShowAll = false;
152e5dd7070Spatrick   StringRef RootGroup;
153e5dd7070Spatrick 
154e5dd7070Spatrick   switch (argc) {
155e5dd7070Spatrick   case 0:
156e5dd7070Spatrick     ShowAll = true;
157e5dd7070Spatrick     break;
158e5dd7070Spatrick   case 1:
159e5dd7070Spatrick     RootGroup = argv[0];
160e5dd7070Spatrick     if (RootGroup.startswith("-W"))
161e5dd7070Spatrick       RootGroup = RootGroup.substr(2);
162e5dd7070Spatrick     if (RootGroup == "everything")
163e5dd7070Spatrick       ShowAll = true;
164e5dd7070Spatrick     // FIXME: Handle other special warning flags, like -pedantic.
165e5dd7070Spatrick     break;
166e5dd7070Spatrick   default:
167e5dd7070Spatrick     printUsage();
168e5dd7070Spatrick     return -1;
169e5dd7070Spatrick   }
170e5dd7070Spatrick 
171e5dd7070Spatrick   out.enable_colors(out.has_colors());
172e5dd7070Spatrick 
173e5dd7070Spatrick   TreePrinter TP(out);
174e5dd7070Spatrick   TP.Internal = Internal;
175e5dd7070Spatrick   TP.showKey();
176e5dd7070Spatrick   return ShowAll ? TP.showAll() : TP.showGroup(RootGroup);
177e5dd7070Spatrick }
178