xref: /openbsd-src/gnu/llvm/clang/tools/diagtool/ListWarnings.cpp (revision e5dd70708596ae51455a0ffa086a00c5b29f8583)
1*e5dd7070Spatrick //===- ListWarnings.h - diagtool tool for printing warning flags ----------===//
2*e5dd7070Spatrick //
3*e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5*e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*e5dd7070Spatrick //
7*e5dd7070Spatrick //===----------------------------------------------------------------------===//
8*e5dd7070Spatrick //
9*e5dd7070Spatrick // This file provides a diagtool tool that displays warning flags for
10*e5dd7070Spatrick // diagnostics.
11*e5dd7070Spatrick //
12*e5dd7070Spatrick //===----------------------------------------------------------------------===//
13*e5dd7070Spatrick 
14*e5dd7070Spatrick #include "DiagTool.h"
15*e5dd7070Spatrick #include "DiagnosticNames.h"
16*e5dd7070Spatrick #include "clang/Basic/AllDiagnostics.h"
17*e5dd7070Spatrick #include "clang/Basic/Diagnostic.h"
18*e5dd7070Spatrick #include "llvm/ADT/StringMap.h"
19*e5dd7070Spatrick #include "llvm/Support/Format.h"
20*e5dd7070Spatrick 
21*e5dd7070Spatrick DEF_DIAGTOOL("list-warnings",
22*e5dd7070Spatrick              "List warnings and their corresponding flags",
23*e5dd7070Spatrick              ListWarnings)
24*e5dd7070Spatrick 
25*e5dd7070Spatrick using namespace clang;
26*e5dd7070Spatrick using namespace diagtool;
27*e5dd7070Spatrick 
28*e5dd7070Spatrick namespace {
29*e5dd7070Spatrick struct Entry {
30*e5dd7070Spatrick   llvm::StringRef DiagName;
31*e5dd7070Spatrick   llvm::StringRef Flag;
32*e5dd7070Spatrick 
Entry__anon3391f4920111::Entry33*e5dd7070Spatrick   Entry(llvm::StringRef diagN, llvm::StringRef flag)
34*e5dd7070Spatrick     : DiagName(diagN), Flag(flag) {}
35*e5dd7070Spatrick 
operator <__anon3391f4920111::Entry36*e5dd7070Spatrick   bool operator<(const Entry &x) const { return DiagName < x.DiagName; }
37*e5dd7070Spatrick };
38*e5dd7070Spatrick }
39*e5dd7070Spatrick 
printEntries(std::vector<Entry> & entries,llvm::raw_ostream & out)40*e5dd7070Spatrick static void printEntries(std::vector<Entry> &entries, llvm::raw_ostream &out) {
41*e5dd7070Spatrick   for (const Entry &E : entries) {
42*e5dd7070Spatrick     out << "  " << E.DiagName;
43*e5dd7070Spatrick     if (!E.Flag.empty())
44*e5dd7070Spatrick       out << " [-W" << E.Flag << "]";
45*e5dd7070Spatrick     out << '\n';
46*e5dd7070Spatrick   }
47*e5dd7070Spatrick }
48*e5dd7070Spatrick 
run(unsigned int argc,char ** argv,llvm::raw_ostream & out)49*e5dd7070Spatrick int ListWarnings::run(unsigned int argc, char **argv, llvm::raw_ostream &out) {
50*e5dd7070Spatrick   std::vector<Entry> Flagged, Unflagged;
51*e5dd7070Spatrick   llvm::StringMap<std::vector<unsigned> > flagHistogram;
52*e5dd7070Spatrick 
53*e5dd7070Spatrick   for (const DiagnosticRecord &DR : getBuiltinDiagnosticsByName()) {
54*e5dd7070Spatrick     const unsigned diagID = DR.DiagID;
55*e5dd7070Spatrick 
56*e5dd7070Spatrick     if (DiagnosticIDs::isBuiltinNote(diagID))
57*e5dd7070Spatrick       continue;
58*e5dd7070Spatrick 
59*e5dd7070Spatrick     if (!DiagnosticIDs::isBuiltinWarningOrExtension(diagID))
60*e5dd7070Spatrick       continue;
61*e5dd7070Spatrick 
62*e5dd7070Spatrick     Entry entry(DR.getName(), DiagnosticIDs::getWarningOptionForDiag(diagID));
63*e5dd7070Spatrick 
64*e5dd7070Spatrick     if (entry.Flag.empty())
65*e5dd7070Spatrick       Unflagged.push_back(entry);
66*e5dd7070Spatrick     else {
67*e5dd7070Spatrick       Flagged.push_back(entry);
68*e5dd7070Spatrick       flagHistogram[entry.Flag].push_back(diagID);
69*e5dd7070Spatrick     }
70*e5dd7070Spatrick   }
71*e5dd7070Spatrick 
72*e5dd7070Spatrick   out << "Warnings with flags (" << Flagged.size() << "):\n";
73*e5dd7070Spatrick   printEntries(Flagged, out);
74*e5dd7070Spatrick 
75*e5dd7070Spatrick   out << "Warnings without flags (" << Unflagged.size() << "):\n";
76*e5dd7070Spatrick   printEntries(Unflagged, out);
77*e5dd7070Spatrick 
78*e5dd7070Spatrick   out << "\nSTATISTICS:\n\n";
79*e5dd7070Spatrick 
80*e5dd7070Spatrick   double percentFlagged =
81*e5dd7070Spatrick       ((double)Flagged.size()) / (Flagged.size() + Unflagged.size()) * 100.0;
82*e5dd7070Spatrick 
83*e5dd7070Spatrick   out << "  Percentage of warnings with flags: "
84*e5dd7070Spatrick       << llvm::format("%.4g", percentFlagged) << "%\n";
85*e5dd7070Spatrick 
86*e5dd7070Spatrick   out << "  Number of unique flags: "
87*e5dd7070Spatrick       << flagHistogram.size() << '\n';
88*e5dd7070Spatrick 
89*e5dd7070Spatrick   double avgDiagsPerFlag = (double) Flagged.size() / flagHistogram.size();
90*e5dd7070Spatrick   out << "  Average number of diagnostics per flag: "
91*e5dd7070Spatrick       << llvm::format("%.4g", avgDiagsPerFlag) << '\n';
92*e5dd7070Spatrick 
93*e5dd7070Spatrick   out << "  Number in -Wpedantic (not covered by other -W flags): "
94*e5dd7070Spatrick       << flagHistogram["pedantic"].size() << '\n';
95*e5dd7070Spatrick 
96*e5dd7070Spatrick   out << '\n';
97*e5dd7070Spatrick 
98*e5dd7070Spatrick   return 0;
99*e5dd7070Spatrick }
100*e5dd7070Spatrick 
101