diff options
author | Ted Kremenek <kremenek@apple.com> | 2011-08-09 03:39:19 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2011-08-09 03:39:19 +0000 |
commit | f88d335ca7af009377d8effa7d674d43ada8e5e3 (patch) | |
tree | 16ebd00e5a4f1b7b400986a26c63e305071d6924 /clang/tools | |
parent | 309e288e01ef364ca3327d81f84510b2e289e8df (diff) | |
download | bcm5719-llvm-f88d335ca7af009377d8effa7d674d43ada8e5e3.tar.gz bcm5719-llvm-f88d335ca7af009377d8effa7d674d43ada8e5e3.zip |
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
llvm-svn: 137109
Diffstat (limited to 'clang/tools')
-rw-r--r-- | clang/tools/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang/tools/Makefile | 2 | ||||
-rw-r--r-- | clang/tools/diagtool/CMakeLists.txt | 20 | ||||
-rw-r--r-- | clang/tools/diagtool/DiagTool.cpp | 68 | ||||
-rw-r--r-- | clang/tools/diagtool/DiagTool.h | 69 | ||||
-rw-r--r-- | clang/tools/diagtool/ListWarnings.cpp | 106 | ||||
-rw-r--r-- | clang/tools/diagtool/Makefile | 25 | ||||
-rw-r--r-- | clang/tools/diagtool/diagtool_main.cpp | 26 |
8 files changed, 316 insertions, 1 deletions
diff --git a/clang/tools/CMakeLists.txt b/clang/tools/CMakeLists.txt index 1b5252e0507..1bca496eaac 100644 --- a/clang/tools/CMakeLists.txt +++ b/clang/tools/CMakeLists.txt @@ -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) diff --git a/clang/tools/Makefile b/clang/tools/Makefile index bfd2a641ec1..4ea2cdd32d2 100644 --- a/clang/tools/Makefile +++ b/clang/tools/Makefile @@ -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 diff --git a/clang/tools/diagtool/CMakeLists.txt b/clang/tools/diagtool/CMakeLists.txt new file mode 100644 index 00000000000..e69c8e99947 --- /dev/null +++ b/clang/tools/diagtool/CMakeLists.txt @@ -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) diff --git a/clang/tools/diagtool/DiagTool.cpp b/clang/tools/diagtool/DiagTool.cpp new file mode 100644 index 00000000000..1e3f4ef6374 --- /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 { + DiagTools diagTools; +} diff --git a/clang/tools/diagtool/DiagTool.h b/clang/tools/diagtool/DiagTool.h new file mode 100644 index 00000000000..5e5e11f2e28 --- /dev/null +++ b/clang/tools/diagtool/DiagTool.h @@ -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 diff --git a/clang/tools/diagtool/ListWarnings.cpp b/clang/tools/diagtool/ListWarnings.cpp new file mode 100644 index 00000000000..70be1c4531e --- /dev/null +++ b/clang/tools/diagtool/ListWarnings.cpp @@ -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; +} + diff --git a/clang/tools/diagtool/Makefile b/clang/tools/diagtool/Makefile new file mode 100644 index 00000000000..22d74110e44 --- /dev/null +++ b/clang/tools/diagtool/Makefile @@ -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 + diff --git a/clang/tools/diagtool/diagtool_main.cpp b/clang/tools/diagtool/diagtool_main.cpp new file mode 100644 index 00000000000..66a73e947a1 --- /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; +} |