summaryrefslogtreecommitdiff
path: root/clang/tools/diagtool
diff options
context:
space:
mode:
authorCarlo Zancanaro <carlo@pc-4w14-0.cs.usyd.edu.au>2012-10-15 17:10:06 +1100
committerCarlo Zancanaro <carlo@pc-4w14-0.cs.usyd.edu.au>2012-10-15 17:10:06 +1100
commitbe1de4be954c80875ad4108e0a33e8e131b2f2c0 (patch)
tree1fbbecf276bf7c7bdcbb4dd446099d6d90eaa516 /clang/tools/diagtool
parentc4626a62754862d20b41e8a46a3574264ea80e6d (diff)
parentf1bd2e48c5324d3f7cda4090c87f8a5b6f463ce2 (diff)
Merge branch 'master' of ssh://bitbucket.org/czan/honours
Diffstat (limited to 'clang/tools/diagtool')
-rw-r--r--clang/tools/diagtool/CMakeLists.txt24
-rw-r--r--clang/tools/diagtool/DiagTool.cpp68
-rw-r--r--clang/tools/diagtool/DiagTool.h70
-rw-r--r--clang/tools/diagtool/ListWarnings.cpp126
-rw-r--r--clang/tools/diagtool/Makefile24
-rw-r--r--clang/tools/diagtool/diagtool_main.cpp26
6 files changed, 338 insertions, 0 deletions
diff --git a/clang/tools/diagtool/CMakeLists.txt b/clang/tools/diagtool/CMakeLists.txt
new file mode 100644
index 0000000..f1fd9de
--- /dev/null
+++ b/clang/tools/diagtool/CMakeLists.txt
@@ -0,0 +1,24 @@
+set( LLVM_LINK_COMPONENTS
+ support
+ )
+
+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)
diff --git a/clang/tools/diagtool/DiagTool.cpp b/clang/tools/diagtool/DiagTool.cpp
new file mode 100644
index 0000000..36e72a2
--- /dev/null
+++ b/clang/tools/diagtool/DiagTool.cpp
@@ -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 {
+ llvm::ManagedStatic<DiagTools> diagTools;
+}
diff --git a/clang/tools/diagtool/DiagTool.h b/clang/tools/diagtool/DiagTool.h
new file mode 100644
index 0000000..dcb6ac7
--- /dev/null
+++ b/clang/tools/diagtool/DiagTool.h
@@ -0,0 +1,70 @@
+//===- 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 "llvm/Support/ManagedStatic.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 llvm::ManagedStatic<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
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;
+}
+
diff --git a/clang/tools/diagtool/Makefile b/clang/tools/diagtool/Makefile
new file mode 100644
index 0000000..6e3bcfc
--- /dev/null
+++ b/clang/tools/diagtool/Makefile
@@ -0,0 +1,24 @@
+##===- 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 = clangBasic.a
+
+include $(CLANG_LEVEL)/Makefile
+
diff --git a/clang/tools/diagtool/diagtool_main.cpp b/clang/tools/diagtool/diagtool_main.cpp
new file mode 100644
index 0000000..e34f0dc
--- /dev/null
+++ b/clang/tools/diagtool/diagtool_main.cpp
@@ -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;
+}