diff options
Diffstat (limited to 'clang/tools/diagtool')
-rw-r--r-- | clang/tools/diagtool/CMakeLists.txt | 24 | ||||
-rw-r--r-- | clang/tools/diagtool/DiagTool.cpp | 68 | ||||
-rw-r--r-- | clang/tools/diagtool/DiagTool.h | 70 | ||||
-rw-r--r-- | clang/tools/diagtool/ListWarnings.cpp | 126 | ||||
-rw-r--r-- | clang/tools/diagtool/Makefile | 24 | ||||
-rw-r--r-- | clang/tools/diagtool/diagtool_main.cpp | 26 |
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; +} |