1 //===- ListWarnings.h - diagtool tool for printing warning flags ----------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file provides a diagtool tool that displays warning flags for 11 // diagnostics. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #include "DiagTool.h" 16 #include "DiagnosticNames.h" 17 #include "clang/AST/ASTDiagnostic.h" 18 #include "clang/Basic/AllDiagnostics.h" 19 #include "clang/Basic/Diagnostic.h" 20 #include "llvm/ADT/StringMap.h" 21 #include "llvm/Support/Format.h" 22 23 DEF_DIAGTOOL("list-warnings", 24 "List warnings and their corresponding flags", 25 ListWarnings) 26 27 using namespace clang; 28 using namespace diagtool; 29 30 namespace { 31 struct Entry { 32 llvm::StringRef DiagName; 33 llvm::StringRef Flag; 34 35 Entry(llvm::StringRef diagN, llvm::StringRef flag) 36 : DiagName(diagN), Flag(flag) {} 37 38 bool operator<(const Entry &x) const { return DiagName < x.DiagName; } 39 }; 40 } 41 42 static void printEntries(std::vector<Entry> &entries, llvm::raw_ostream &out) { 43 for (std::vector<Entry>::iterator it = entries.begin(), ei = entries.end(); 44 it != ei; ++it) { 45 out << " " << it->DiagName; 46 if (!it->Flag.empty()) 47 out << " [-W" << it->Flag << "]"; 48 out << '\n'; 49 } 50 } 51 52 int ListWarnings::run(unsigned int argc, char **argv, llvm::raw_ostream &out) { 53 std::vector<Entry> Flagged, Unflagged; 54 llvm::StringMap<std::vector<unsigned> > flagHistogram; 55 56 ArrayRef<DiagnosticRecord> AllDiagnostics = getBuiltinDiagnosticsByName(); 57 58 for (ArrayRef<DiagnosticRecord>::iterator di = AllDiagnostics.begin(), 59 de = AllDiagnostics.end(); 60 di != de; ++di) { 61 unsigned diagID = di->DiagID; 62 63 if (DiagnosticIDs::isBuiltinNote(diagID)) 64 continue; 65 66 if (!DiagnosticIDs::isBuiltinWarningOrExtension(diagID)) 67 continue; 68 69 Entry entry(di->getName(), 70 DiagnosticIDs::getWarningOptionForDiag(diagID)); 71 72 if (entry.Flag.empty()) 73 Unflagged.push_back(entry); 74 else { 75 Flagged.push_back(entry); 76 flagHistogram.GetOrCreateValue(entry.Flag).getValue().push_back(diagID); 77 } 78 } 79 80 out << "Warnings with flags (" << Flagged.size() << "):\n"; 81 printEntries(Flagged, out); 82 83 out << "Warnings without flags (" << Unflagged.size() << "):\n"; 84 printEntries(Unflagged, out); 85 86 out << "\nSTATISTICS:\n\n"; 87 88 double percentFlagged = ((double) Flagged.size()) 89 / (Flagged.size() + Unflagged.size()) * 100.0; 90 91 out << " Percentage of warnings with flags: " 92 << llvm::format("%.4g",percentFlagged) << "%\n"; 93 94 out << " Number of unique flags: " 95 << flagHistogram.size() << '\n'; 96 97 double avgDiagsPerFlag = (double) Flagged.size() / flagHistogram.size(); 98 out << " Average number of diagnostics per flag: " 99 << llvm::format("%.4g", avgDiagsPerFlag) << '\n'; 100 101 out << " Number in -Wpedantic (not covered by other -W flags): " 102 << flagHistogram.GetOrCreateValue("pedantic").getValue().size() 103 << '\n'; 104 105 out << '\n'; 106 107 return 0; 108 } 109 110