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