Coverage Report

Created: 2020-02-25 14:32

/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
11.4k
  static bool isIgnored(unsigned DiagID) {
33
11.4k
    // FIXME: This feels like a hack.
34
11.4k
    static clang::DiagnosticsEngine Diags(new DiagnosticIDs,
35
11.4k
                                          new DiagnosticOptions);
36
11.4k
    return Diags.isIgnored(DiagID, SourceLocation());
37
11.4k
  }
38
39
3.30k
  static bool unimplemented(const GroupRecord &Group) {
40
3.30k
    if (!Group.diagnostics().empty())
41
2.93k
      return false;
42
371
43
371
    for (const GroupRecord &GR : Group.subgroups())
44
254
      if (!unimplemented(GR))
45
250
        return false;
46
371
47
371
    
return true121
;
48
371
  }
49
50
3.46k
  static bool enabledByDefault(const GroupRecord &Group) {
51
5.09k
    for (const DiagnosticRecord &DR : Group.diagnostics()) {
52
5.09k
      if (isIgnored(DR.DiagID))
53
1.42k
        return false;
54
5.09k
    }
55
3.46k
56
3.46k
    
for (const GroupRecord &GR : Group.subgroups())2.03k
{
57
526
      if (!enabledByDefault(GR))
58
219
        return false;
59
526
    }
60
2.03k
61
2.03k
    
return true1.81k
;
62
2.03k
  }
63
64
3.05k
  void printGroup(const GroupRecord &Group, unsigned Indent = 0) {
65
3.05k
    out.indent(Indent * 2);
66
3.05k
67
3.05k
    if (unimplemented(Group))
68
117
      out << Colors::RED;
69
2.93k
    else if (enabledByDefault(Group))
70
1.50k
      out << Colors::GREEN;
71
1.42k
    else
72
1.42k
      out << Colors::YELLOW;
73
3.05k
74
3.05k
    out << "-W" << Group.getName() << "\n" << Colors::RESET;
75
3.05k
76
3.05k
    ++Indent;
77
3.05k
    for (const GroupRecord &GR : Group.subgroups()) {
78
1.55k
      printGroup(GR, Indent);
79
1.55k
    }
80
3.05k
81
3.05k
    if (Internal) {
82
6.38k
      for (const DiagnosticRecord &DR : Group.diagnostics()) {
83
6.38k
        if (!isIgnored(DR.DiagID))
84
3.16k
          out << Colors::GREEN;
85
6.38k
        out.indent(Indent * 2);
86
6.38k
        out << DR.getName() << Colors::RESET << "\n";
87
6.38k
      }
88
2.93k
    }
89
3.05k
  }
90
91
4
  int showGroup(StringRef RootGroup) {
92
4
    ArrayRef<GroupRecord> AllGroups = getDiagnosticGroups();
93
4
94
4
    if (RootGroup.size() > UINT16_MAX) {
95
0
      llvm::errs() << "No such diagnostic group exists\n";
96
0
      return 1;
97
0
    }
98
4
99
4
    const GroupRecord *Found = llvm::lower_bound(AllGroups, RootGroup);
100
4
    if (Found == AllGroups.end() || Found->getName() != RootGroup) {
101
1
      llvm::errs() << "No such diagnostic group exists\n";
102
1
      return 1;
103
1
    }
104
3
105
3
    printGroup(*Found);
106
3
107
3
    return 0;
108
3
  }
109
110
3
  int showAll() {
111
3
    ArrayRef<GroupRecord> AllGroups = getDiagnosticGroups();
112
3
    llvm::DenseSet<unsigned> NonRootGroupIDs;
113
3
114
2.49k
    for (const GroupRecord &GR : AllGroups) {
115
3.81k
      for (auto SI = GR.subgroup_begin(), SE = GR.subgroup_end(); SI != SE;
116
2.49k
           
++SI1.32k
) {
117
1.32k
        NonRootGroupIDs.insert((unsigned)SI.getID());
118
1.32k
      }
119
2.49k
    }
120
3
121
3
    assert(NonRootGroupIDs.size() < AllGroups.size());
122
3
123
2.49k
    for (unsigned i = 0, e = AllGroups.size(); i != e; 
++i2.49k
) {
124
2.49k
      if (!NonRootGroupIDs.count(i))
125
1.49k
        printGroup(AllGroups[i]);
126
2.49k
    }
127
3
128
3
    return 0;
129
3
  }
130
131
7
  void showKey() {
132
7
    out << '\n' << Colors::GREEN << "GREEN" << Colors::RESET
133
7
        << " = enabled by default";
134
7
    out << '\n' << Colors::RED << "RED" << Colors::RESET
135
7
        << " = unimplemented (accepted for GCC compatibility)\n\n";
136
7
  }
137
};
138
139
0
static void printUsage() {
140
0
  llvm::errs() << "Usage: diagtool tree [--internal] [<diagnostic-group>]\n";
141
0
}
142
143
7
int TreeView::run(unsigned int argc, char **argv, llvm::raw_ostream &out) {
144
7
  // First check our one flag (--flags-only).
145
7
  bool Internal = false;
146
7
  if (argc > 0) {
147
7
    StringRef FirstArg(*argv);
148
7
    if (FirstArg.equals("--internal")) {
149
4
      Internal = true;
150
4
      --argc;
151
4
      ++argv;
152
4
    }
153
7
  }
154
7
155
7
  bool ShowAll = false;
156
7
  StringRef RootGroup;
157
7
158
7
  switch (argc) {
159
1
  case 0:
160
1
    ShowAll = true;
161
1
    break;
162
6
  case 1:
163
6
    RootGroup = argv[0];
164
6
    if (RootGroup.startswith("-W"))
165
5
      RootGroup = RootGroup.substr(2);
166
6
    if (RootGroup == "everything")
167
2
      ShowAll = true;
168
6
    // FIXME: Handle other special warning flags, like -pedantic.
169
6
    break;
170
0
  default:
171
0
    printUsage();
172
0
    return -1;
173
7
  }
174
7
175
7
  out.enable_colors(out.has_colors());
176
7
177
7
  TreePrinter TP(out);
178
7
  TP.Internal = Internal;
179
7
  TP.showKey();
180
7
  return ShowAll ? 
TP.showAll()3
:
TP.showGroup(RootGroup)4
;
181
7
}