diff options
Diffstat (limited to 'clang/tools/diagtool/ListWarnings.cpp')
-rw-r--r-- | clang/tools/diagtool/ListWarnings.cpp | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/clang/tools/diagtool/ListWarnings.cpp b/clang/tools/diagtool/ListWarnings.cpp new file mode 100644 index 0000000..2bbeca8 --- /dev/null +++ b/clang/tools/diagtool/ListWarnings.cpp @@ -0,0 +1,126 @@ +//===- ListWarnings.h - diagtool tool for printing warning flags ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides a diagtool tool that displays warning flags for +// diagnostics. +// +//===----------------------------------------------------------------------===// + +#include "DiagTool.h" +#include "clang/Basic/Diagnostic.h" +#include "llvm/Support/Format.h" +#include "llvm/ADT/StringMap.h" +#include "clang/AST/ASTDiagnostic.h" +#include "clang/Basic/AllDiagnostics.h" + +DEF_DIAGTOOL("list-warnings", + "List warnings and their corresponding flags", + ListWarnings) + +using namespace clang; + +namespace { +struct StaticDiagNameIndexRec { + const char *NameStr; + unsigned short DiagID; + uint8_t NameLen; + + StringRef getName() const { + return StringRef(NameStr, NameLen); + } +}; +} + +static const StaticDiagNameIndexRec StaticDiagNameIndex[] = { +#define DIAG_NAME_INDEX(ENUM) { #ENUM, diag::ENUM, STR_SIZE(#ENUM, uint8_t) }, +#include "clang/Basic/DiagnosticIndexName.inc" +#undef DIAG_NAME_INDEX + { 0, 0, 0 } +}; + +static const unsigned StaticDiagNameIndexSize = + sizeof(StaticDiagNameIndex)/sizeof(StaticDiagNameIndex[0])-1; + +namespace { +struct Entry { + llvm::StringRef DiagName; + llvm::StringRef Flag; + + Entry(llvm::StringRef diagN, llvm::StringRef flag) + : DiagName(diagN), Flag(flag) {} + + bool operator<(const Entry &x) const { return DiagName < x.DiagName; } +}; +} + +static void printEntries(std::vector<Entry> &entries, llvm::raw_ostream &out) { + for (std::vector<Entry>::iterator it = entries.begin(), ei = entries.end(); + it != ei; ++it) { + out << " " << it->DiagName; + if (!it->Flag.empty()) + out << " [-W" << it->Flag << "]"; + out << '\n'; + } +} + +int ListWarnings::run(unsigned int argc, char **argv, llvm::raw_ostream &out) { + std::vector<Entry> Flagged, Unflagged; + llvm::StringMap<std::vector<unsigned> > flagHistogram; + + for (const StaticDiagNameIndexRec *di = StaticDiagNameIndex, *de = StaticDiagNameIndex + StaticDiagNameIndexSize; + di != de; ++di) { + + unsigned diagID = di->DiagID; + + if (DiagnosticIDs::isBuiltinNote(diagID)) + continue; + + if (!DiagnosticIDs::isBuiltinWarningOrExtension(diagID)) + continue; + + Entry entry(di->getName(), + DiagnosticIDs::getWarningOptionForDiag(diagID)); + + if (entry.Flag.empty()) + Unflagged.push_back(entry); + else { + Flagged.push_back(entry); + flagHistogram.GetOrCreateValue(entry.Flag).getValue().push_back(diagID); + } + } + + std::sort(Flagged.begin(), Flagged.end()); + std::sort(Unflagged.begin(), Unflagged.end()); + + out << "Warnings with flags (" << Flagged.size() << "):\n"; + printEntries(Flagged, out); + + out << "Warnings without flags (" << Unflagged.size() << "):\n"; + printEntries(Unflagged, out); + + out << "\nSTATISTICS:\n\n"; + + double percentFlagged = ((double) Flagged.size()) + / (Flagged.size() + Unflagged.size()) * 100.0; + + out << " Percentage of warnings with flags: " + << llvm::format("%.4g",percentFlagged) << "%\n"; + + out << " Number of unique flags: " + << flagHistogram.size() << '\n'; + + double avgDiagsPerFlag = (double) Flagged.size() / flagHistogram.size(); + out << " Average number of diagnostics per flag: " + << llvm::format("%.4g", avgDiagsPerFlag) << '\n'; + + out << '\n'; + + return 0; +} + |