From e721090795a766341464c4e3f8fbb6fa528a76f6 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 5 Mar 2010 17:28:58 +0200 Subject: Start tracking with git --- makefile | 23 ++++ plugin.cxx | 347 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 370 insertions(+) create mode 100644 makefile create mode 100644 plugin.cxx diff --git a/makefile b/makefile new file mode 100644 index 0000000..0fb0966 --- /dev/null +++ b/makefile @@ -0,0 +1,23 @@ +GXX=g++-4.5 +PLUGIN_INC := $(shell $(GXX) -print-file-name=plugin) + +src := plugin.cxx +obj := $(src:.cxx=.o) + +sunrise.so: $(obj) + $(GXX) -shared -o $@ $(CXXFLAGS) $(LDFLAGS) $^ $(LIBS) + +%.o: %.cxx + $(GXX) -c -o $@ -fPIC $(CPPFLAGS) -I$(PLUGIN_INC)/include $(CXXFLAGS) $< + +# Test. +# +.PHONY: test +test: sunrise.so test.cxx + $(GXX) -x c++ -S -fplugin=./sunrise.so test.cxx + +# Clean. +# +.PHONY: clean +clean: + rm -f *.o sunrise.so diff --git a/plugin.cxx b/plugin.cxx new file mode 100644 index 0000000..8a93a5e --- /dev/null +++ b/plugin.cxx @@ -0,0 +1,347 @@ +extern "C" +{ +#include "gcc-plugin.h" +} + +#include +#include + +extern "C" +{ +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tree.h" +#include "tree-pass.h" +#include "intl.h" + +/* reqs */ +#include "tm.h" + +/* gcc/ headers. */ +#include "diagnostic.h" +#include "c-common.h" +#include "c-pretty-print.h" +#include "tree-iterator.h" +#include "plugin.h" +#include "tree-flow.h" +#include "langhooks.h" +#include "cp/cp-tree.h" +#include "cp/cxx-pretty-print.h" +#include "cp/name-lookup.h" +} + +#include +#include + +using namespace std; + +int plugin_is_GPL_compatible; + +// TODO: +// +// +// * Can plugin define a macro which can then be tested in the code? +// A wrapper that calls g++ with plugin can do that easily. +// +// * Will need to disable as many warnings as possible. +// + +enum class_access { ca_public, ca_protected, ca_private }; +const char* class_access_str[] = {"public", "protected", "private"}; + +class collector +{ +public: + collector () + : file_ (main_input_filename) + { + } + + void + traverse (tree global_scope) + { + traverse_namespace (global_scope); + } + +private: + void + traverse_namespace (tree ns) + { + cp_binding_level* level = NAMESPACE_LEVEL (ns); + tree decl = level->names; + + for (; decl != NULL_TREE; decl = TREE_CHAIN (decl)) + { + switch (TREE_CODE (decl)) + { + /* + case FUNCTION_DECL: + { + if (DECL_ANTICIPATED (decl)) + break; + + warning (0, G_ ("function declaration %s"), + IDENTIFIER_POINTER (DECL_NAME (decl))); + break; + } + */ + + /* + case RECORD_TYPE: + { + warning (0, G_ ("class declaration %s"), + IDENTIFIER_POINTER (DECL_NAME (decl))); + break; + } + */ + + case TYPE_DECL: + { + if (DECL_ARTIFICIAL (decl)) + { + tree type = TREE_TYPE (decl); + tree name = DECL_NAME (decl); + + if (name != NULL_TREE && TREE_CODE (type) == RECORD_TYPE) + { + warning (0, G_ ("class declaration %s in %s:%i"), + IDENTIFIER_POINTER (name), + DECL_SOURCE_FILE (decl), + DECL_SOURCE_LINE (decl)); + + traverse_class (type); + } + } + + break; + } + case NAMESPACE_DECL: + { + tree target = DECL_NAMESPACE_ALIAS (decl); + assert (target != NULL_TREE); + + warning (0, G_ ("namespace alias declaration %s=%s in %s:%i"), + IDENTIFIER_POINTER (DECL_NAME (decl)), + IDENTIFIER_POINTER (DECL_NAME (target)), + DECL_SOURCE_FILE (decl), + DECL_SOURCE_LINE (decl)); + break; + } + default: + { + if (!DECL_IS_BUILTIN (decl)) + { + tree name = DECL_NAME (decl); + + if (name != NULL_TREE) + { + warning (0, G_ ("some declaration %s in %s:%i"), + IDENTIFIER_POINTER (name), + DECL_SOURCE_FILE (decl), + DECL_SOURCE_LINE (decl)); + } + else + { + warning (0, G_ ("some unnamed declaration in %s:%i"), + DECL_SOURCE_FILE (decl), + DECL_SOURCE_LINE (decl)); + } + } + break; + } + } + + //warning (0, G_ ("declaration %u"), (int) (TREE_CODE (decl))); + + + //warning (0, G_ ("declaration %s"), + // IDENTIFIER_POINTER (DECL_NAME (decl))); + } + + for(decl = level->namespaces; decl != NULL_TREE; decl = TREE_CHAIN (decl)) + { + if (DECL_NAMESPACE_STD_P (decl) || DECL_IS_BUILTIN (decl)) + continue; + + tree name = DECL_NAME (decl); + + if (name == NULL_TREE) + { + warning (0, G_ ("anonymous namespace declaration in %s:%i"), + DECL_SOURCE_FILE (decl), + DECL_SOURCE_LINE (decl)); + } + else + { + warning (0, G_ ("namespace declaration %s in %s:%i"), + IDENTIFIER_POINTER (name), + DECL_SOURCE_FILE (decl), + DECL_SOURCE_LINE (decl)); + } + + traverse_namespace (decl); + } + } + + void + traverse_class (tree c) + { + // Traverse base information. + // + tree bis (TYPE_BINFO (c)); + size_t n (bis ? BINFO_N_BASE_BINFOS (bis) : 0); + + for (size_t i (0); i < n; i++) + { + tree bi (BINFO_BASE_BINFO (bis, i)); + + class_access a (ca_public); + + if (BINFO_BASE_ACCESSES (bis)) + { + tree ac (BINFO_BASE_ACCESS (bis, i)); + + if (ac == NULL_TREE || ac == access_public_node) + { + a = ca_public; + } + else if (ac == access_protected_node) + { + a = ca_protected; + } + else + { + assert (ac == access_private_node); + a = ca_private; + } + } + + bool v (BINFO_VIRTUAL_P (bi)); + tree b (BINFO_TYPE (bi)); + tree b_decl (TYPE_NAME (b)); // Typedef decl for this base. + + warning (0, G_ ("\t%s%s base %s"), + class_access_str[a], + (v ? " virtual" : ""), + IDENTIFIER_POINTER (DECL_NAME (b_decl))); + } + + // Traverse data members. + // + for (tree decl (TYPE_FIELDS (c)); + decl != NULL_TREE ; + decl = TREE_CHAIN (decl)) + { + //if (DECL_ARTIFICIAL (field)) + // continue; + + // if (TREE_CODE (field) == TYPE_DECL && TREE_TYPE (field) == c) + // continue; + + switch (TREE_CODE (decl)) + { + case FIELD_DECL: + { + if (!DECL_ARTIFICIAL (decl)) + { + tree name = DECL_NAME (decl); + tree type = TREE_TYPE (decl); + tree type_decl = TYPE_NAME (type); + + warning (0, G_ ("\tdata member declaration %s %s in %s:%i"), + (type_decl ? IDENTIFIER_POINTER (DECL_NAME (type_decl)) : "?"), + IDENTIFIER_POINTER (name), + DECL_SOURCE_FILE (decl), + DECL_SOURCE_LINE (decl)); + break; + } + } + default: + { + //if (!DECL_IS_BUILTIN (decl)) + //{ + tree name = DECL_NAME (decl); + + if (name != NULL_TREE) + { + warning (0, G_ ("\tsome declaration %s in %s:%i"), + IDENTIFIER_POINTER (name), + DECL_SOURCE_FILE (decl), + DECL_SOURCE_LINE (decl)); + } + else + { + warning (0, G_ ("\tsome unnamed declaration in %s:%i"), + DECL_SOURCE_FILE (decl), + DECL_SOURCE_LINE (decl)); + } + //} + break; + } + } + } + } + +private: + string file_; +}; + +extern "C" void +start_unit_callback (void* gcc_data, void* user_data) +{ + warning (0, G_ ("strating unit processing")); +} + +extern "C" void +finish_type_callback (void* gcc_data, void* user_data) +{ + warning (0, G_ ("finished type processing")); +} + +extern "C" void +finish_unit_callback (void* gcc_data, void* user_data) +{ + //traverse_namespace (global_namespace); + //done = true; + warning (0, G_ ("finished unit processing")); +} + +extern "C" void +gate_callback (void* gcc_data, void* user_data) +{ + warning (0, G_ ("main file is %s"), main_input_filename); + + if (!errorcount && !sorrycount) + { + collector c; + c.traverse (global_namespace); + } + + exit (0); + + // Disable every pass. + // + /* + warning (0, G_ ("disabling pass %s"), current_pass->name); + *static_cast (gcc_data) = 0; + */ +} + +extern "C" int +plugin_init (struct plugin_name_args *plugin_info, + struct plugin_gcc_version *version) +{ + warning (0, G_ ("strating plugin %s"), plugin_info->base_name); + + // Disable assembly output. + // + asm_file_name = HOST_BIT_BUCKET; + + //register_callback (plugin_info->base_name, PLUGIN_START_UNIT, &start_unit_callback, NULL); + //register_callback (plugin_info->base_name, PLUGIN_FINISH_TYPE, &finish_type_callback, NULL); + //register_callback (plugin_info->base_name, PLUGIN_FINISH_UNIT, &finish_unit_callback, NULL); + register_callback (plugin_info->base_name, PLUGIN_OVERRIDE_GATE, &gate_callback, NULL); + + return 0; +} -- cgit v1.1