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 DEF_DIAGTOOL("list-warnings", 22 "List warnings and their corresponding flags", 23 ListWarnings) 24 25 using namespace clang; 26 using namespace diagtool; 27 28 namespace { 29 struct Entry { 30 llvm::StringRef DiagName; 31 llvm::StringRef Flag; 32 33 Entry(llvm::StringRef diagN, llvm::StringRef flag) 34 : DiagName(diagN), Flag(flag) {} 35 36 bool operator<(const Entry &x) const { return DiagName < x.DiagName; } 37 }; 38 } 39 40 static void printEntries(std::vector<Entry> &entries, llvm::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 49 int ListWarnings::run(unsigned int argc, char **argv, llvm::raw_ostream &out) { 50 std::vector<Entry> Flagged, Unflagged; 51 llvm::StringMap<std::vector<unsigned> > flagHistogram; 52 53 for (const DiagnosticRecord &DR : getBuiltinDiagnosticsByName()) { 54 const unsigned diagID = DR.DiagID; 55 56 if (DiagnosticIDs{}.isNote(diagID)) 57 continue; 58 59 if (!DiagnosticIDs{}.isWarningOrExtension(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(Flagged, out); 74 75 out << "Warnings without flags (" << Unflagged.size() << "):\n"; 76 printEntries(Unflagged, out); 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