diff options
Diffstat (limited to 'BuildTools')
-rw-r--r-- | BuildTools/CLang/.gitignore | 4 | ||||
-rw-r--r-- | BuildTools/CLang/CLangDiagnosticsFlagsTool.cpp | 228 | ||||
-rw-r--r-- | BuildTools/CLang/SConscript | 15 | ||||
-rwxr-xr-x | BuildTools/CheckHeaders.py | 21 | ||||
-rw-r--r-- | BuildTools/SCons/SConstruct | 12 |
5 files changed, 279 insertions, 1 deletions
diff --git a/BuildTools/CLang/.gitignore b/BuildTools/CLang/.gitignore new file mode 100644 index 0000000..df682c0 --- /dev/null +++ b/BuildTools/CLang/.gitignore @@ -0,0 +1,4 @@ +CLangDiagnosticsFlags +CLangDiagnosticsFlagsTool.sh +CLangDiagnosticsFlagsTool +clang-diagnostics-overview.* diff --git a/BuildTools/CLang/CLangDiagnosticsFlagsTool.cpp b/BuildTools/CLang/CLangDiagnosticsFlagsTool.cpp new file mode 100644 index 0000000..82cc902 --- /dev/null +++ b/BuildTools/CLang/CLangDiagnosticsFlagsTool.cpp @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include <iostream> +#include <set> +#include <vector> +#include <cassert> +#include <boost/algorithm/string/predicate.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/adjacency_list.hpp> +#include <boost/graph/topological_sort.hpp> +#include <boost/graph/topological_sort.hpp> +#include <boost/graph/graphviz.hpp> + +// ----------------------------------------------------------------------------- +// Include diagnostics data from CLang +// ----------------------------------------------------------------------------- + +#define DIAG(name, a, b, c, d, e, f, g) name, + +namespace diag { + enum LexKinds { +#include <clang/Basic/DiagnosticLexKinds.inc> +#include <clang/Basic/DiagnosticParseKinds.inc> +#include <clang/Basic/DiagnosticCommonKinds.inc> +#include <clang/Basic/DiagnosticDriverKinds.inc> +#include <clang/Basic/DiagnosticFrontendKinds.inc> +#include <clang/Basic/DiagnosticSemaKinds.inc> + }; +} + +#define GET_DIAG_ARRAYS +#include <clang/Basic/DiagnosticGroups.inc> +#undef GET_DIAG_ARRAYS + +struct DiagTableEntry { + const char* name; + const short* array; + const short* group; +}; + +static const DiagTableEntry diagnostics[] = { +#define GET_DIAG_TABLE +#include <clang/Basic/DiagnosticGroups.inc> +#undef GET_DIAG_TABLE +}; +static const size_t diagnostics_count = sizeof(diagnostics) / sizeof(diagnostics[0]); + +// ----------------------------------------------------------------------------- + +using namespace boost; + +struct Properties { + Properties() : missing(false), redundant(false) { + } + + std::string name; + bool have; + bool implicitHave; + bool dontWant; + bool implicitDontWant; + bool ignored; + bool available; + bool missing; + bool redundant; + bool alreadyCovered; +}; + +class GraphVizLabelWriter { + public: + GraphVizLabelWriter(const std::vector<Properties>& properties) : properties(properties) { + } + + template <class VertexOrEdge> + void operator()(std::ostream& out, const VertexOrEdge& v) const { + std::string color; + if (properties[v].missing) { + color = "orange"; + } + else if (properties[v].redundant) { + color = "lightblue"; + } + else if (properties[v].have) { + color = "darkgreen"; + } + else if (properties[v].implicitHave) { + color = "green"; + } + else if (properties[v].dontWant) { + color = "red"; + } + else if (properties[v].implicitDontWant) { + color = "pink"; + } + else if (properties[v].ignored) { + color = "white"; + } + else if (properties[v].available) { + color = "yellow"; + } + else { + assert(false); + } + out << "[label=" << escape_dot_string(properties[v].name) << " fillcolor=\"" << color << "\" style=filled]"; + } + + private: + const std::vector<Properties> properties; +}; + +int main(int argc, char* argv[]) { + // Parse command-line arguments + std::set<std::string> have; + std::set<std::string> dontWant; + std::string outputDir; + for (int i = 1; i < argc; ++i) { + std::string arg(argv[i]); + if (starts_with(arg, "-W")) { + have.insert(arg.substr(2, arg.npos)); + } + else if (starts_with(arg, "-w")) { + dontWant.insert(arg.substr(2, arg.npos)); + } + else if (starts_with(arg, "-O")) { + outputDir = arg.substr(2, arg.npos) + "/"; + } + } + + // Build the graph and initialize properties + typedef adjacency_list<vecS, vecS, bidirectionalS> Graph; + typedef graph_traits<Graph>::vertex_descriptor Vertex; + Graph g(diagnostics_count); + std::vector<Properties> properties(num_vertices(g)); + for (size_t i = 0; i < diagnostics_count; ++i) { + std::string name(diagnostics[i].name); + properties[i].name = name; + properties[i].implicitHave = properties[i].have = have.find(name) != have.end(); + properties[i].implicitDontWant = properties[i].dontWant = dontWant.find(name) != dontWant.end(); + properties[i].ignored = diagnostics[i].group == 0 && diagnostics[i].array == 0; + properties[i].alreadyCovered = false; + properties[i].available = true; + for (const short* j = diagnostics[i].group; j && *j != -1; ++j) { + add_edge(i, *j, g); + } + } + + // Sort the diagnostics + std::list<Vertex> sortedDiagnostics; + boost::topological_sort(g, std::front_inserter(sortedDiagnostics)); + + // Propagate dontWant and have properties down + for(std::list<Vertex>::const_iterator i = sortedDiagnostics.begin(); i != sortedDiagnostics.end(); ++i) { + graph_traits<Graph>::adjacency_iterator adjacentIt, adjacentEnd; + for (tie(adjacentIt, adjacentEnd) = adjacent_vertices(*i, g); adjacentIt != adjacentEnd; ++adjacentIt) { + properties[*adjacentIt].implicitDontWant = properties[*i].implicitDontWant || properties[*adjacentIt].implicitDontWant; + properties[*adjacentIt].implicitHave = properties[*i].implicitHave || properties[*adjacentIt].implicitHave; + } + } + + // Propagate 'available' property upwards + for(std::list<Vertex>::const_reverse_iterator i = sortedDiagnostics.rbegin(); i != sortedDiagnostics.rend(); ++i) { + properties[*i].available = properties[*i].available && !properties[*i].implicitDontWant; + graph_traits<Graph>::in_edge_iterator edgesIt, edgesEnd; + graph_traits<Graph>::edge_descriptor edge; + for (tie(edgesIt, edgesEnd) = in_edges(*i, g); edgesIt != edgesEnd; ++edgesIt) { + properties[source(*edgesIt, g)].available = properties[source(*edgesIt, g)].available && properties[*i].available; + } + } + + // Collect missing & redundant flags + std::set<std::string> missing; + std::set<std::string> redundant; + for(std::list<Vertex>::const_iterator i = sortedDiagnostics.begin(); i != sortedDiagnostics.end(); ++i) { + bool markChildrenCovered = true; + if (properties[*i].alreadyCovered) { + if (properties[*i].have) { + properties[*i].redundant = true; + redundant.insert(properties[*i].name); + } + } + else { + if (properties[*i].available) { + if (!properties[*i].implicitHave && !properties[*i].ignored) { + properties[*i].missing = true; + missing.insert(properties[*i].name); + } + } + else { + markChildrenCovered = false; + } + } + if (markChildrenCovered) { + graph_traits<Graph>::adjacency_iterator adjacentIt, adjacentEnd; + for (tie(adjacentIt, adjacentEnd) = adjacent_vertices(*i, g); adjacentIt != adjacentEnd; ++adjacentIt) { + properties[*adjacentIt].alreadyCovered = true; + } + } + } + + // Write information + if (!missing.empty()) { + std::cout << "Missing diagnostic flags: "; + for(std::set<std::string>::const_iterator i = missing.begin(); i != missing.end(); ++i) { + std::cout << "-W" << *i << " "; + } + std::cout<< std::endl; + } + + if (!redundant.empty()) { + std::cout << "Redundant diagnostic flags: "; + for(std::set<std::string>::const_iterator i = redundant.begin(); i != redundant.end(); ++i) { + std::cout << "-W" << *i << " "; + } + std::cout<< std::endl; + } + + // Write graphviz file + if (!outputDir.empty()) { + std::ofstream f((outputDir + "clang-diagnostics-overview.dot").c_str()); + write_graphviz(f, g, GraphVizLabelWriter(properties)); + f.close(); + } + + return 0; +} diff --git a/BuildTools/CLang/SConscript b/BuildTools/CLang/SConscript new file mode 100644 index 0000000..850c35c --- /dev/null +++ b/BuildTools/CLang/SConscript @@ -0,0 +1,15 @@ +Import("env") + +#myenv = Environment() +#myenv.Append(CPPPATH = ["."]) +#myenv.Program("CLangDiagnosticsFlagsTool", ["CLangDiagnosticsFlagsTool.cpp"]) +# +#disabledDiagnostics = ["-wunreachable-code", "-wunused-macros", "-wmissing-noreturn", "-wlong-long", "-wcast-align", "-wglobal-constructors", "-wmissing-prototypes", "-wpadded", "-wshadow"] +#clangDiagnosticsFlagsToolCommand = "BuildTools/CLang/CLangDiagnosticsFlagsTool -O" + env.Dir(".").abspath + " " + " ".join(disabledDiagnostics) + " " +#clangDiagnosticsFlagsToolCommand += " ".join([flag for flag in env["CXXFLAGS"] if flag.startswith("-W")]) +#clangDiagnosticsFlagsToolCommand += "\n" +#clangDiagnosticsFlagsToolCommand += "dot -Tpng " + env.Dir(".").abspath + "/clang-diagnostics-overview.dot > " + env.Dir(".").abspath + "/clang-diagnostics-overview.png\n" +#v = env.WriteVal("#/BuildTools/CLang/CLangDiagnosticsFlagsTool.sh", env.Value(clangDiagnosticsFlagsToolCommand)) +#env.AddPostAction(v, Chmod(v[0], 0755)) +# +# diff --git a/BuildTools/CheckHeaders.py b/BuildTools/CheckHeaders.py new file mode 100755 index 0000000..73f49db --- /dev/null +++ b/BuildTools/CheckHeaders.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python + +import os, sys + +foundBadHeaders = False + +for (path, dirs, files) in os.walk(".") : + if "3rdParty" in path or ".sconf" in path or ".framework" in path : + continue + if not "Swiften" in path : + continue + + for filename in [os.path.join(path, file) for file in files if file.endswith(".h")] : + file = open(filename, "r") + for line in file.readlines() : + for include in ["iostream", "algorithm", "cassert", "boost/bind.hpp", "boost/filesystem.hpp", "Base/foreach.h", "Base/Log.h", "boost/date_time/date_time.hpp", "boost/filesystem/filesystem.hpp"] : + if "#include" in line and include in line and not "Base/Log" in filename : + print "Found " + include + " include in " + filename + foundBadHeaders = True + +sys.exit(foundBadHeaders) diff --git a/BuildTools/SCons/SConstruct b/BuildTools/SCons/SConstruct index bd40f1f..43b6df0 100644 --- a/BuildTools/SCons/SConstruct +++ b/BuildTools/SCons/SConstruct @@ -178,7 +178,14 @@ else : env.Append(CXXFLAGS = ["-Werror"]) gccVersion = env["CCVERSION"].split(".") if gccVersion >= ["4", "5", "0"] : - env.Append(CCFLAGS = ["-Wlogical-op"]) + env.Append(CXXFLAGS = ["-Wlogical-op"]) + if "clang" in env["CC"] : + env.Append(CXXFLAGS = ["-W#warnings", "-W-Wc++0x-compat", "-Wc++0x-compat", "-Waddress-of-temporary", "-Wambiguous-member-template", "-Warray-bounds", "-Watomic-properties", "-Wbind-to-temporary-copy", "-Wbuiltin-macro-redefined", "-Wc++-compat", "-Wc++0x-extensions", "-Wcomments", "-Wconditional-uninitialized", "-Wconstant-logical-operand", "-Wdeclaration-after-statement", "-Wdeprecated", "-Wdeprecated-implementations", "-Wdeprecated-writable-strings", "-Wduplicate-method-arg", "-Wempty-body", "-Wendif-labels", "-Wenum-compare", "-Wformat=2", "-Wfour-char-constants", "-Wgnu", "-Wincomplete-implementation", "-Winvalid-noreturn", "-Winvalid-offsetof", "-Winvalid-token-paste", "-Wlocal-type-template-args", "-Wmethod-signatures", "-Wmicrosoft", "-Wmissing-declarations", "-Wnon-pod-varargs", "-Wnonfragile-abi2", "-Wnull-dereference", "-Wout-of-line-declaration", "-Woverlength-strings", "-Wpacked", "-Wpointer-arith", "-Wpointer-sign", "-Wprotocol", "-Wreadonly-setter-attrs", "-Wselector", "-Wshift-overflow", "-Wshift-sign-overflow", "-Wstrict-selector-match", "-Wsuper-class-method-mismatch", "-Wtautological-compare", "-Wtypedef-redefinition", "-Wundeclared-selector", "-Wunknown-attributes", "-Wunknown-warning-option", "-Wunnamed-type-template-args", "-Wunused-exception-parameter", "-Wunused-member-function", "-Wused-but-marked-unused", "-Wvariadic-macros"]) +# To enable: +# "-Wheader-hygiene" +# "-Wnon-gcc", +# "-Wweak-vtables", +# "-Wlarge-by-value-copy", if env.get("coverage", 0) : assert(env["PLATFORM"] != "win32") @@ -621,6 +628,9 @@ if env.Dir("#/.git").exists() : # Project files ################################################################################ +# Build tools +env.SConscript(dirs = ["#/BuildTools/CLang"]) + # Modules modules = [] for dir in os.listdir(Dir("#/3rdParty").abspath) : |