1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
//===- 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/Analysis/AnalysisDiagnostic.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Lex/LexDiagnostic.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Sema/SemaDiagnostic.h"
#include "clang/Serialization/SerializationDiagnostic.h"
DEF_DIAGTOOL("list-warnings",
"List warnings and their corresponding flags",
ListWarnings)
using namespace clang;
namespace {
template <size_t SizeOfStr, typename FieldType>
class StringSizerHelper {
char FIELD_TOO_SMALL[SizeOfStr <= FieldType(~0U) ? 1 : -1];
public:
enum { Size = SizeOfStr };
};
} // namespace anonymous
#define STR_SIZE(str, fieldTy) StringSizerHelper<sizeof(str)-1, fieldTy>::Size
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;
}
|