зеркало из https://github.com/microsoft/clang.git
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:
Родитель
6948bc4bcb
Коммит
2dc651dfd4
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
Загрузка…
Ссылка в новой задаче