Clang Project

clang_source_code/tools/diagtool/ListWarnings.cpp
1//===- ListWarnings.h - 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// This file provides a diagtool tool that displays warning flags for
10// diagnostics.
11//
12//===----------------------------------------------------------------------===//
13
14#include "DiagTool.h"
15#include "DiagnosticNames.h"
16#include "clang/Basic/AllDiagnostics.h"
17#include "clang/Basic/Diagnostic.h"
18#include "llvm/ADT/StringMap.h"
19#include "llvm/Support/Format.h"
20
21 RegisterListWarnings;}" file_link="DiagTool.h.html#58" macro="true">DEF_DIAGTOOL("list-warnings",
22 RegisterListWarnings;}" file_link="DiagTool.h.html#58" macro="true">             "List warnings and their corresponding flags",
23 RegisterListWarnings;}" file_link="DiagTool.h.html#58" macro="true">             ListWarnings)
24
25using namespace clang;
26using namespace diagtool;
27
28namespace {
29struct Entry {
30  llvm::StringRef DiagName;
31  llvm::StringRef Flag;
32
33  Entry(llvm::StringRef diagNllvm::StringRef flag)
34    : DiagName(diagN), Flag(flag) {}
35
36  bool operator<(const Entry &xconst { return DiagName < x.DiagName; }
37};
38}
39
40static void printEntries(std::vector<Entry> &entriesllvm::raw_ostream &out) {
41  for (const Entry &E : entries) {
42    out << "  " << E.DiagName;
43    if (!E.Flag.empty())
44      out << " [-W" << E.Flag << "]";
45    out << '\n';
46  }
47}
48
49int ListWarnings::run(unsigned int argcchar **argvllvm::raw_ostream &out) {
50  std::vector<EntryFlaggedUnflagged;
51  llvm::StringMap<std::vector<unsigned> > flagHistogram;
52
53  for (const DiagnosticRecord &DR : getBuiltinDiagnosticsByName()) {
54    const unsigned diagID = DR.DiagID;
55
56    if (DiagnosticIDs::isBuiltinNote(diagID))
57      continue;
58
59    if (!DiagnosticIDs::isBuiltinWarningOrExtension(diagID))
60      continue;
61
62    Entry entry(DR.getName(), DiagnosticIDs::getWarningOptionForDiag(diagID));
63
64    if (entry.Flag.empty())
65      Unflagged.push_back(entry);
66    else {
67      Flagged.push_back(entry);
68      flagHistogram[entry.Flag].push_back(diagID);
69    }
70  }
71
72  out << "Warnings with flags (" << Flagged.size() << "):\n";
73  printEntries(Flaggedout);
74
75  out << "Warnings without flags (" << Unflagged.size() << "):\n";
76  printEntries(Unflaggedout);
77
78  out << "\nSTATISTICS:\n\n";
79
80  double percentFlagged =
81      ((double)Flagged.size()) / (Flagged.size() + Unflagged.size()) * 100.0;
82
83  out << "  Percentage of warnings with flags: "
84      << llvm::format("%.4g", percentFlagged) << "%\n";
85
86  out << "  Number of unique flags: "
87      << flagHistogram.size() << '\n';
88
89  double avgDiagsPerFlag = (double) Flagged.size() / flagHistogram.size();
90  out << "  Average number of diagnostics per flag: "
91      << llvm::format("%.4g", avgDiagsPerFlag) << '\n';
92
93  out << "  Number in -Wpedantic (not covered by other -W flags): "
94      << flagHistogram["pedantic"].size() << '\n';
95
96  out << '\n';
97
98  return 0;
99}
100
101