Coverage Report

Created: 2022-05-14 11:35

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/tools/diagtool/ShowEnabledWarnings.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- ShowEnabledWarnings - diagtool tool for printing enabled 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/LLVM.h"
12
#include "clang/Frontend/CompilerInstance.h"
13
#include "clang/Frontend/TextDiagnosticBuffer.h"
14
#include "clang/Frontend/TextDiagnosticPrinter.h"
15
#include "clang/Frontend/Utils.h"
16
#include "llvm/Support/TargetSelect.h"
17
18
DEF_DIAGTOOL("show-enabled",
19
             "Show which warnings are enabled for a given command line",
20
             ShowEnabledWarnings)
21
22
using namespace clang;
23
using namespace diagtool;
24
25
namespace {
26
  struct PrettyDiag {
27
    StringRef Name;
28
    StringRef Flag;
29
    DiagnosticsEngine::Level Level;
30
31
    PrettyDiag(StringRef name, StringRef flag, DiagnosticsEngine::Level level)
32
8.21k
    : Name(name), Flag(flag), Level(level) {}
33
34
0
    bool operator<(const PrettyDiag &x) const { return Name < x.Name; }
35
  };
36
}
37
38
0
static void printUsage() {
39
0
  llvm::errs() << "Usage: diagtool show-enabled [<flags>] <single-input.c>\n";
40
0
}
41
42
1.18k
static char getCharForLevel(DiagnosticsEngine::Level Level) {
43
1.18k
  switch (Level) {
44
0
  case DiagnosticsEngine::Ignored: return ' ';
45
0
  case DiagnosticsEngine::Note:    return '-';
46
0
  case DiagnosticsEngine::Remark:  return 'R';
47
1.13k
  case DiagnosticsEngine::Warning: return 'W';
48
48
  case DiagnosticsEngine::Error:   return 'E';
49
1
  case DiagnosticsEngine::Fatal:   return 'F';
50
1.18k
  }
51
52
0
  llvm_unreachable("Unknown diagnostic level");
53
0
}
54
55
static IntrusiveRefCntPtr<DiagnosticsEngine>
56
12
createDiagnostics(unsigned int argc, char **argv) {
57
12
  IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(new DiagnosticIDs());
58
59
  // Buffer diagnostics from argument parsing so that we can output them using a
60
  // well formed diagnostic object.
61
12
  TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
62
63
  // Try to build a CompilerInvocation.
64
12
  SmallVector<const char *, 4> Args;
65
12
  Args.push_back("diagtool");
66
12
  Args.append(argv, argv + argc);
67
12
  CreateInvocationOptions CIOpts;
68
12
  CIOpts.Diags =
69
12
      new DiagnosticsEngine(DiagIDs, new DiagnosticOptions(), DiagsBuffer);
70
12
  std::unique_ptr<CompilerInvocation> Invocation =
71
12
      createInvocation(Args, CIOpts);
72
12
  if (!Invocation)
73
0
    return nullptr;
74
75
  // Build the diagnostics parser
76
12
  IntrusiveRefCntPtr<DiagnosticsEngine> FinalDiags =
77
12
    CompilerInstance::createDiagnostics(&Invocation->getDiagnosticOpts());
78
12
  if (!FinalDiags)
79
0
    return nullptr;
80
81
  // Flush any errors created when initializing everything. This could happen
82
  // for invalid command lines, which will probably give non-sensical results.
83
12
  DiagsBuffer->FlushDiagnostics(*FinalDiags);
84
85
12
  return FinalDiags;
86
12
}
87
88
12
int ShowEnabledWarnings::run(unsigned int argc, char **argv, raw_ostream &Out) {
89
  // First check our one flag (--levels).
90
12
  bool ShouldShowLevels = true;
91
12
  if (argc > 0) {
92
12
    StringRef FirstArg(*argv);
93
12
    if (FirstArg.equals("--no-levels")) {
94
7
      ShouldShowLevels = false;
95
7
      --argc;
96
7
      ++argv;
97
7
    } else 
if (5
FirstArg.equals("--levels")5
) {
98
0
      ShouldShowLevels = true;
99
0
      --argc;
100
0
      ++argv;
101
0
    }
102
12
  }
103
104
  // Create the diagnostic engine.
105
12
  IntrusiveRefCntPtr<DiagnosticsEngine> Diags = createDiagnostics(argc, argv);
106
12
  if (!Diags) {
107
0
    printUsage();
108
0
    return EXIT_FAILURE;
109
0
  }
110
111
  // Now we have our diagnostics. Iterate through EVERY diagnostic and see
112
  // which ones are turned on.
113
  // FIXME: It would be very nice to print which flags are turning on which
114
  // diagnostics, but this can be done with a diff.
115
12
  std::vector<PrettyDiag> Active;
116
117
71.1k
  for (const DiagnosticRecord &DR : getBuiltinDiagnosticsByName()) {
118
71.1k
    unsigned DiagID = DR.DiagID;
119
120
71.1k
    if (DiagnosticIDs::isBuiltinNote(DiagID))
121
11.0k
      continue;
122
123
60.1k
    if (!DiagnosticIDs::isBuiltinWarningOrExtension(DiagID))
124
38.4k
      continue;
125
126
21.7k
    DiagnosticsEngine::Level DiagLevel =
127
21.7k
      Diags->getDiagnosticLevel(DiagID, SourceLocation());
128
21.7k
    if (DiagLevel == DiagnosticsEngine::Ignored)
129
13.5k
      continue;
130
131
8.21k
    StringRef WarningOpt = DiagnosticIDs::getWarningOptionForDiag(DiagID);
132
8.21k
    Active.push_back(PrettyDiag(DR.getName(), WarningOpt, DiagLevel));
133
8.21k
  }
134
135
  // Print them all out.
136
8.21k
  for (const PrettyDiag &PD : Active) {
137
8.21k
    if (ShouldShowLevels)
138
1.18k
      Out << getCharForLevel(PD.Level) << "  ";
139
8.21k
    Out << PD.Name;
140
8.21k
    if (!PD.Flag.empty())
141
7.74k
      Out << " [-W" << PD.Flag << "]";
142
8.21k
    Out << '\n';
143
8.21k
  }
144
145
12
  return EXIT_SUCCESS;
146
12
}