Coverage Report

Created: 2022-07-16 07:03

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/tools/diagtool/TreeView.cpp
Line
Count
Source (jump to first uncovered line)
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
//===----------------------------------------------------------------------===//
8
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"
17
18
DEF_DIAGTOOL("tree", "Show warning flags in a tree view", TreeView)
19
20
using namespace clang;
21
using namespace diagtool;
22
23
class TreePrinter {
24
  using Colors = llvm::raw_ostream::Colors;
25
26
public:
27
  llvm::raw_ostream &out;
28
  bool Internal;
29
30
7
  TreePrinter(llvm::raw_ostream &out) : out(out), Internal(false) {}
31
32
13.9k
  static bool isIgnored(unsigned DiagID) {
33
    // FIXME: This feels like a hack.
34
13.9k
    static clang::DiagnosticsEngine Diags(new DiagnosticIDs,
35
13.9k
                                          new DiagnosticOptions);
36
13.9k
    return Diags.isIgnored(DiagID, SourceLocation());
37
13.9k
  }
38
39
3.88k
  static bool unimplemented(const GroupRecord &Group) {
40
3.88k
    if (!Group.diagnostics().empty())
41
3.44k
      return false;
42
43
438
    return llvm::all_of(Group.subgroups(), unimplemented);
44
3.88k
  }
45
46
4.08k
  static bool enabledByDefault(const GroupRecord &Group) {
47
6.02k
    for (const DiagnosticRecord &DR : Group.diagnostics()) {
48
6.02k
      if (isIgnored(DR.DiagID))
49
1.74k
        return false;
50
6.02k
    }
51
52
2.34k
    for (const GroupRecord &GR : Group.subgroups()) {
53
647
      if (!enabledByDefault(GR))
54
285
        return false;
55
647
    }
56
57
2.05k
    return true;
58
2.34k
  }
59
60
3.56k
  void printGroup(const GroupRecord &Group, unsigned Indent = 0) {
61
3.56k
    out.indent(Indent * 2);
62
63
3.56k
    if (unimplemented(Group))
64
124
      out << Colors::RED;
65
3.44k
    else if (enabledByDefault(Group))
66
1.69k
      out << Colors::GREEN;
67
1.74k
    else
68
1.74k
      out << Colors::YELLOW;
69
70
3.56k
    out << "-W" << Group.getName() << "\n" << Colors::RESET;
71
72
3.56k
    ++Indent;
73
3.56k
    for (const GroupRecord &GR : Group.subgroups()) {
74
1.88k
      printGroup(GR, Indent);
75
1.88k
    }
76
77
3.56k
    if (Internal) {
78
7.94k
      for (const DiagnosticRecord &DR : Group.diagnostics()) {
79
7.94k
        if (!isIgnored(DR.DiagID))
80
3.62k
          out << Colors::GREEN;
81
7.94k
        out.indent(Indent * 2);
82
7.94k
        out << DR.getName() << Colors::RESET << "\n";
83
7.94k
      }
84
3.43k
    }
85
3.56k
  }
86
87
4
  int showGroup(StringRef RootGroup) {
88
4
    ArrayRef<GroupRecord> AllGroups = getDiagnosticGroups();
89
90
4
    if (RootGroup.size() > UINT16_MAX) {
91
0
      llvm::errs() << "No such diagnostic group exists\n";
92
0
      return 1;
93
0
    }
94
95
4
    const GroupRecord *Found = llvm::lower_bound(AllGroups, RootGroup);
96
4
    if (Found == AllGroups.end() || Found->getName() != RootGroup) {
97
1
      llvm::errs() << "No such diagnostic group exists\n";
98
1
      return 1;
99
1
    }
100
101
3
    printGroup(*Found);
102
103
3
    return 0;
104
4
  }
105
106
3
  int showAll() {
107
3
    ArrayRef<GroupRecord> AllGroups = getDiagnosticGroups();
108
3
    llvm::DenseSet<unsigned> NonRootGroupIDs;
109
110
2.84k
    for (const GroupRecord &GR : AllGroups) {
111
4.41k
      for (auto SI = GR.subgroup_begin(), SE = GR.subgroup_end(); SI != SE;
112
2.84k
           
++SI1.57k
) {
113
1.57k
        NonRootGroupIDs.insert((unsigned)SI.getID());
114
1.57k
      }
115
2.84k
    }
116
117
3
    assert(NonRootGroupIDs.size() < AllGroups.size());
118
119
2.84k
    for (unsigned i = 0, e = AllGroups.size(); i != e; 
++i2.84k
) {
120
2.84k
      if (!NonRootGroupIDs.count(i))
121
1.67k
        printGroup(AllGroups[i]);
122
2.84k
    }
123
124
3
    return 0;
125
3
  }
126
127
7
  void showKey() {
128
7
    out << '\n' << Colors::GREEN << "GREEN" << Colors::RESET
129
7
        << " = enabled by default";
130
7
    out << '\n' << Colors::RED << "RED" << Colors::RESET
131
7
        << " = unimplemented (accepted for GCC compatibility)\n\n";
132
7
  }
133
};
134
135
0
static void printUsage() {
136
0
  llvm::errs() << "Usage: diagtool tree [--internal] [<diagnostic-group>]\n";
137
0
}
138
139
7
int TreeView::run(unsigned int argc, char **argv, llvm::raw_ostream &out) {
140
  // First check our one flag (--flags-only).
141
7
  bool Internal = false;
142
7
  if (argc > 0) {
143
7
    StringRef FirstArg(*argv);
144
7
    if (FirstArg.equals("--internal")) {
145
4
      Internal = true;
146
4
      --argc;
147
4
      ++argv;
148
4
    }
149
7
  }
150
151
7
  bool ShowAll = false;
152
7
  StringRef RootGroup;
153
154
7
  switch (argc) {
155
1
  case 0:
156
1
    ShowAll = true;
157
1
    break;
158
6
  case 1:
159
6
    RootGroup = argv[0];
160
6
    if (RootGroup.startswith("-W"))
161
5
      RootGroup = RootGroup.substr(2);
162
6
    if (RootGroup == "everything")
163
2
      ShowAll = true;
164
    // FIXME: Handle other special warning flags, like -pedantic.
165
6
    break;
166
0
  default:
167
0
    printUsage();
168
0
    return -1;
169
7
  }
170
171
7
  out.enable_colors(out.has_colors());
172
173
7
  TreePrinter TP(out);
174
7
  TP.Internal = Internal;
175
7
  TP.showKey();
176
7
  return ShowAll ? 
TP.showAll()3
:
TP.showGroup(RootGroup)4
;
177
7
}