Add 'diagtool' to the 'tools/' directory. diagtool is a new tool (WIP) for analyzing and working with clang diagnostics.

Some interesting stats from 'diagtool list-warnings' on the current version of clang:

  Percentage of warnings with flags: 48.79%
  Number of unique flags: 148
  Average number of diagnostics per flag: 2.041

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@137109 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Ted Kremenek 2011-08-09 03:39:19 +00:00
Родитель 6948bc4bcb
Коммит 2dc651dfd4
8 изменённых файлов: 316 добавлений и 1 удалений

Просмотреть файл

@ -1,5 +1,6 @@
add_subdirectory(arcmt-test)
add_subdirectory(c-arcmt-test)
add_subdirectory(c-index-test)
add_subdirectory(diagtool)
add_subdirectory(driver)
add_subdirectory(libclang)

Просмотреть файл

@ -8,7 +8,7 @@
##===----------------------------------------------------------------------===##
CLANG_LEVEL := ..
DIRS := driver libclang c-index-test arcmt-test c-arcmt-test
DIRS := driver libclang c-index-test arcmt-test c-arcmt-test diagtool
include $(CLANG_LEVEL)/../../Makefile.config

Просмотреть файл

@ -0,0 +1,20 @@
set( LLVM_USED_LIBS
clangBasic
clangLex
clangSema
)
add_clang_executable(diagtool
diagtool_main.cpp
DiagTool.cpp
ListWarnings.cpp
)
if(UNIX)
set(CLANGXX_LINK_OR_COPY create_symlink)
else()
set(CLANGXX_LINK_OR_COPY copy)
endif()
install(TARGETS diagtool
RUNTIME DESTINATION bin)

Просмотреть файл

@ -0,0 +1,68 @@
//===- DiagTool.cpp - Classes for defining diagtool tools -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the boilerplate for defining diagtool tools.
//
//===----------------------------------------------------------------------===//
#include "DiagTool.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/SmallString.h"
#include <vector>
using namespace diagtool;
DiagTool::DiagTool(llvm::StringRef toolCmd,
llvm::StringRef toolDesc)
: cmd(toolCmd), description(toolDesc) {}
DiagTool::~DiagTool() {}
typedef llvm::StringMap<DiagTool *> ToolMap;
static inline ToolMap *getTools(void *v) { return static_cast<ToolMap*>(v); }
DiagTools::DiagTools() : tools(new ToolMap()) {}
DiagTools::~DiagTools() { delete getTools(tools); }
DiagTool *DiagTools::getTool(llvm::StringRef toolCmd) {
ToolMap::iterator it = getTools(tools)->find(toolCmd);
return (it == getTools(tools)->end()) ? 0 : it->getValue();
}
void DiagTools::registerTool(DiagTool *tool) {
getTools(tools)->GetOrCreateValue(tool->getName(), tool);
}
void DiagTools::printCommands(llvm::raw_ostream &out) {
std::vector<llvm::StringRef> toolNames;
unsigned maxName = 0;
for (ToolMap::iterator it = getTools(tools)->begin(),
ei = getTools(tools)->end(); it != ei; ++it) {
toolNames.push_back(it->getKey());
unsigned len = it->getKey().size();
if (len > maxName)
maxName = len;
}
std::sort(toolNames.begin(), toolNames.end());
for (std::vector<llvm::StringRef>::iterator it = toolNames.begin(),
ei = toolNames.end(); it != ei; ++it) {
out << " " << (*it);
unsigned spaces = (maxName + 3) - (it->size());
for (unsigned i = 0; i < spaces; ++i)
out << ' ';
out << getTool(*it)->getDescription() << '\n';
}
}
namespace diagtool {
DiagTools diagTools;
}

69
tools/diagtool/DiagTool.h Normal file
Просмотреть файл

@ -0,0 +1,69 @@
//===- DiagTool.h - Classes for defining diagtool tools -------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the boilerplate for defining diagtool tools.
//
//===----------------------------------------------------------------------===//
#ifndef DIAGTOOL_DIAGTOOL_H
#define DIAGTOOL_DIAGTOOL_H
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
#include <string>
namespace diagtool {
class DiagTool {
const std::string cmd;
const std::string description;
public:
DiagTool(llvm::StringRef toolCmd, llvm::StringRef toolDesc);
virtual ~DiagTool();
llvm::StringRef getName() const { return cmd; }
llvm::StringRef getDescription() const { return description; }
virtual int run(unsigned argc, char *argv[], llvm::raw_ostream &out) = 0;
};
class DiagTools {
void *tools;
public:
DiagTools();
~DiagTools();
DiagTool *getTool(llvm::StringRef toolCmd);
void registerTool(DiagTool *tool);
void printCommands(llvm::raw_ostream &out);
};
extern DiagTools diagTools;
template <typename DIAGTOOL>
class RegisterDiagTool {
public:
RegisterDiagTool() { diagTools.registerTool(new DIAGTOOL()); }
};
} // end diagtool namespace
#define DEF_DIAGTOOL(NAME, DESC, CLSNAME)\
namespace {\
class CLSNAME : public diagtool::DiagTool {\
public:\
CLSNAME() : DiagTool(NAME, DESC) {}\
virtual ~CLSNAME() {}\
virtual int run(unsigned argc, char *argv[], llvm::raw_ostream &out);\
};\
diagtool::RegisterDiagTool<CLSNAME> Register##CLSNAME;\
}
#endif

Просмотреть файл

@ -0,0 +1,106 @@
//===- 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"
DEF_DIAGTOOL("list-warnings",
"List warnings and their corresponding flags",
ListWarnings)
using namespace clang;
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) {
llvm::IntrusiveRefCntPtr<DiagnosticIDs> Diags(new DiagnosticIDs);
Diagnostic D(Diags);
std::vector<Entry> Flagged, Unflagged;;
llvm::StringMap<std::vector<unsigned> > flagHistogram;
for (DiagnosticIDs::diag_iterator di = DiagnosticIDs::diags_begin(),
de = DiagnosticIDs::diags_end(); di != de; ++di) {
unsigned diagID = di.getDiagID();
if (DiagnosticIDs::isBuiltinNote(diagID))
continue;
if (!DiagnosticIDs::isBuiltinWarningOrExtension(diagID))
continue;
Entry entry(di.getDiagName(),
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;
}

25
tools/diagtool/Makefile Normal file
Просмотреть файл

@ -0,0 +1,25 @@
##===- tools/driver/Makefile -------------------------------*- Makefile -*-===##
#
# The LLVM Compiler Infrastructure
#
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
#
##===----------------------------------------------------------------------===##
CLANG_LEVEL := ../..
TOOLNAME = diagtool
# No plugins, optimize startup time.
TOOL_NO_EXPORTS := 1
# Don't install this.
NO_INSTALL = 1
LINK_COMPONENTS := support
USEDLIBS = clangCodeGen.a clangParse.a clangSema.a \
clangAST.a clangLex.a clangBasic.a
include $(CLANG_LEVEL)/Makefile

Просмотреть файл

@ -0,0 +1,26 @@
//===- diagtool_main.h - Entry point for invoking all diagnostic tools ----===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the main function for diagtool.
//
//===----------------------------------------------------------------------===//
#include "DiagTool.h"
using namespace diagtool;
int main(int argc, char *argv[]) {
if (argc > 1)
if (DiagTool *tool = diagTools.getTool(argv[1]))
return tool->run(argc - 1, &argv[2], llvm::errs());
llvm::errs() << "usage: diagtool <command> [<args>]\n\n";
diagTools.printCommands(llvm::errs());
return 1;
}