Home | History | Annotate | Download | only in diagtool
      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 "clang/Basic/Diagnostic.h"
     17 #include "llvm/Support/Format.h"
     18 #include "llvm/ADT/StringMap.h"
     19 #include "clang/AST/ASTDiagnostic.h"
     20 #include "clang/Basic/AllDiagnostics.h"
     21 
     22 DEF_DIAGTOOL("list-warnings",
     23              "List warnings and their corresponding flags",
     24              ListWarnings)
     25 
     26 using namespace clang;
     27 
     28 namespace {
     29 struct StaticDiagNameIndexRec {
     30   const char *NameStr;
     31   unsigned short DiagID;
     32   uint8_t NameLen;
     33 
     34   StringRef getName() const {
     35     return StringRef(NameStr, NameLen);
     36   }
     37 };
     38 }
     39 
     40 static const StaticDiagNameIndexRec StaticDiagNameIndex[] = {
     41 #define DIAG_NAME_INDEX(ENUM) { #ENUM, diag::ENUM, STR_SIZE(#ENUM, uint8_t) },
     42 #include "clang/Basic/DiagnosticIndexName.inc"
     43 #undef DIAG_NAME_INDEX
     44   { 0, 0, 0 }
     45 };
     46 
     47 static const unsigned StaticDiagNameIndexSize =
     48   sizeof(StaticDiagNameIndex)/sizeof(StaticDiagNameIndex[0])-1;
     49 
     50 namespace {
     51 struct Entry {
     52   llvm::StringRef DiagName;
     53   llvm::StringRef Flag;
     54 
     55   Entry(llvm::StringRef diagN, llvm::StringRef flag)
     56     : DiagName(diagN), Flag(flag) {}
     57 
     58   bool operator<(const Entry &x) const { return DiagName < x.DiagName; }
     59 };
     60 }
     61 
     62 static void printEntries(std::vector<Entry> &entries, llvm::raw_ostream &out) {
     63   for (std::vector<Entry>::iterator it = entries.begin(), ei = entries.end();
     64        it != ei; ++it) {
     65     out << "  " << it->DiagName;
     66     if (!it->Flag.empty())
     67       out << " [-W" << it->Flag << "]";
     68     out << '\n';
     69   }
     70 }
     71 
     72 int ListWarnings::run(unsigned int argc, char **argv, llvm::raw_ostream &out) {
     73   std::vector<Entry> Flagged, Unflagged;
     74   llvm::StringMap<std::vector<unsigned> > flagHistogram;
     75 
     76   for (const StaticDiagNameIndexRec *di = StaticDiagNameIndex, *de = StaticDiagNameIndex + StaticDiagNameIndexSize;
     77        di != de; ++di) {
     78 
     79     unsigned diagID = di->DiagID;
     80 
     81     if (DiagnosticIDs::isBuiltinNote(diagID))
     82       continue;
     83 
     84     if (!DiagnosticIDs::isBuiltinWarningOrExtension(diagID))
     85       continue;
     86 
     87     Entry entry(di->getName(),
     88                 DiagnosticIDs::getWarningOptionForDiag(diagID));
     89 
     90     if (entry.Flag.empty())
     91       Unflagged.push_back(entry);
     92     else {
     93       Flagged.push_back(entry);
     94       flagHistogram.GetOrCreateValue(entry.Flag).getValue().push_back(diagID);
     95     }
     96   }
     97 
     98   std::sort(Flagged.begin(), Flagged.end());
     99   std::sort(Unflagged.begin(), Unflagged.end());
    100 
    101   out << "Warnings with flags (" << Flagged.size() << "):\n";
    102   printEntries(Flagged, out);
    103 
    104   out << "Warnings without flags (" << Unflagged.size() << "):\n";
    105   printEntries(Unflagged, out);
    106 
    107   out << "\nSTATISTICS:\n\n";
    108 
    109   double percentFlagged = ((double) Flagged.size())
    110     / (Flagged.size() + Unflagged.size()) * 100.0;
    111 
    112   out << "  Percentage of warnings with flags: "
    113       << llvm::format("%.4g",percentFlagged) << "%\n";
    114 
    115   out << "  Number of unique flags: "
    116       << flagHistogram.size() << '\n';
    117 
    118   double avgDiagsPerFlag = (double) Flagged.size() / flagHistogram.size();
    119   out << "  Average number of diagnostics per flag: "
    120       << llvm::format("%.4g", avgDiagsPerFlag) << '\n';
    121 
    122   out << '\n';
    123 
    124   return 0;
    125 }
    126 
    127