Coverage Report

Created: 2020-02-25 14:32

/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
7.26k
    : 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.04k
static char getCharForLevel(DiagnosticsEngine::Level Level) {
43
1.04k
  switch (Level) {
44
0
  case DiagnosticsEngine::Ignored: return ' ';
45
0
  case DiagnosticsEngine::Note:    return '-';
46
0
  case DiagnosticsEngine::Remark:  return 'R';
47
1.00k
  case DiagnosticsEngine::Warning: return 'W';
48
40
  case DiagnosticsEngine::Error:   return 'E';
49
1
  case DiagnosticsEngine::Fatal:   return 'F';
50
0
  }
51
0
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
12
59
12
  // Buffer diagnostics from argument parsing so that we can output them using a
60
12
  // well formed diagnostic object.
61
12
  TextDiagnosticBuffer *DiagsBuffer = new TextDiagnosticBuffer;
62
12
  IntrusiveRefCntPtr<DiagnosticsEngine> InterimDiags(
63
12
    new DiagnosticsEngine(DiagIDs, new DiagnosticOptions(), DiagsBuffer));
64
12
65
12
  // Try to build a CompilerInvocation.
66
12
  SmallVector<const char *, 4> Args;
67
12
  Args.push_back("diagtool");
68
12
  Args.append(argv, argv + argc);
69
12
  std::unique_ptr<CompilerInvocation> Invocation =
70
12
      createInvocationFromCommandLine(Args, InterimDiags);
71
12
  if (!Invocation)
72
0
    return nullptr;
73
12
74
12
  // Build the diagnostics parser
75
12
  IntrusiveRefCntPtr<DiagnosticsEngine> FinalDiags =
76
12
    CompilerInstance::createDiagnostics(&Invocation->getDiagnosticOpts());
77
12
  if (!FinalDiags)
78
0
    return nullptr;
79
12
80
12
  // Flush any errors created when initializing everything. This could happen
81
12
  // for invalid command lines, which will probably give non-sensical results.
82
12
  DiagsBuffer->FlushDiagnostics(*FinalDiags);
83
12
84
12
  return FinalDiags;
85
12
}
86
87
12
int ShowEnabledWarnings::run(unsigned int argc, char **argv, raw_ostream &Out) {
88
12
  // First check our one flag (--levels).
89
12
  bool ShouldShowLevels = true;
90
12
  if (argc > 0) {
91
12
    StringRef FirstArg(*argv);
92
12
    if (FirstArg.equals("--no-levels")) {
93
7
      ShouldShowLevels = false;
94
7
      --argc;
95
7
      ++argv;
96
7
    } else 
if (5
FirstArg.equals("--levels")5
) {
97
0
      ShouldShowLevels = true;
98
0
      --argc;
99
0
      ++argv;
100
0
    }
101
12
  }
102
12
103
12
  // Create the diagnostic engine.
104
12
  IntrusiveRefCntPtr<DiagnosticsEngine> Diags = createDiagnostics(argc, argv);
105
12
  if (!Diags) {
106
0
    printUsage();
107
0
    return EXIT_FAILURE;
108
0
  }
109
12
110
12
  // Now we have our diagnostics. Iterate through EVERY diagnostic and see
111
12
  // which ones are turned on.
112
12
  // FIXME: It would be very nice to print which flags are turning on which
113
12
  // diagnostics, but this can be done with a diff.
114
12
  std::vector<PrettyDiag> Active;
115
12
116
64.4k
  for (const DiagnosticRecord &DR : getBuiltinDiagnosticsByName()) {
117
64.4k
    unsigned DiagID = DR.DiagID;
118
64.4k
119
64.4k
    if (DiagnosticIDs::isBuiltinNote(DiagID))
120
10.2k
      continue;
121
54.1k
122
54.1k
    if (!DiagnosticIDs::isBuiltinWarningOrExtension(DiagID))
123
34.7k
      continue;
124
19.4k
125
19.4k
    DiagnosticsEngine::Level DiagLevel =
126
19.4k
      Diags->getDiagnosticLevel(DiagID, SourceLocation());
127
19.4k
    if (DiagLevel == DiagnosticsEngine::Ignored)
128
12.1k
      continue;
129
7.26k
130
7.26k
    StringRef WarningOpt = DiagnosticIDs::getWarningOptionForDiag(DiagID);
131
7.26k
    Active.push_back(PrettyDiag(DR.getName(), WarningOpt, DiagLevel));
132
7.26k
  }
133
12
134
12
  // Print them all out.
135
7.26k
  for (const PrettyDiag &PD : Active) {
136
7.26k
    if (ShouldShowLevels)
137
1.04k
      Out << getCharForLevel(PD.Level) << "  ";
138
7.26k
    Out << PD.Name;
139
7.26k
    if (!PD.Flag.empty())
140
6.74k
      Out << " [-W" << PD.Flag << "]";
141
7.26k
    Out << '\n';
142
7.26k
  }
143
12
144
12
  return EXIT_SUCCESS;
145
12
}