From 82208a8315b3d2ec355e3329aa588eea2b064aa6 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 9 Mar 2010 09:59:54 +0200 Subject: Reorganize the directory structure --- odb/plugin.cxx | 311 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 311 insertions(+) create mode 100644 odb/plugin.cxx (limited to 'odb/plugin.cxx') diff --git a/odb/plugin.cxx b/odb/plugin.cxx new file mode 100644 index 0000000..b1faa32 --- /dev/null +++ b/odb/plugin.cxx @@ -0,0 +1,311 @@ +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 +#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. +// +// * How am I going to handle a case where the type of a private +// member is also private (i.e., local class or typedef -- fairly +// common). +// + +enum class_access { ca_public, ca_protected, ca_private }; +const char* class_access_str[] = {"public", "protected", "private"}; + +class traverser +{ +public: + traverser () + : file_ (main_input_filename) + { + } + + void + traverse (tree scope) + { + // First collect all the declarations we are interested in + // in the line-decl map so that they appear in the source + // code order. + // + collect (scope); + emit (); + } + +private: + void + collect (tree ns) + { + cp_binding_level* level = NAMESPACE_LEVEL (ns); + tree decl = level->names; + + // Collect declarations. + // + for (; decl != NULL_TREE; decl = TREE_CHAIN (decl)) + { + switch (TREE_CODE (decl)) + { + case TYPE_DECL: + { + if (DECL_ARTIFICIAL (decl) && + DECL_NAME (decl) != NULL_TREE && + TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE && + DECL_SOURCE_FILE (decl) == file_) + { + decls_[DECL_SOURCE_LINE (decl)] = 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; + } + } + } + + // Traverse namespaces. + // + for(decl = level->namespaces; decl != NULL_TREE; decl = TREE_CHAIN (decl)) + { + if (!DECL_NAMESPACE_STD_P (decl) && + !DECL_IS_BUILTIN (decl) && + DECL_SOURCE_FILE (decl) == file_) + { + tree name = DECL_NAME (decl); + + warning (0, G_ ("namespace declaration %s in %s:%i"), + name ? IDENTIFIER_POINTER (name) : "", + DECL_SOURCE_FILE (decl), + DECL_SOURCE_LINE (decl)); + + collect (decl); + } + } + } + + void + emit () + { + for (decl_map::const_iterator i (decls_.begin ()), e (decls_.end ()); + i != e; ++i) + { + tree decl (i->second); + + switch (TREE_CODE (decl)) + { + case TYPE_DECL: + { + tree type = TREE_TYPE (decl); + tree name = DECL_NAME (decl); + + warning (0, G_ ("class declaration %s in %s:%i"), + IDENTIFIER_POINTER (name), + DECL_SOURCE_FILE (decl), + DECL_SOURCE_LINE (decl)); + + emit_class (type); + break; + } + } + } + } + + void + emit_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: + { + /* + 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: + typedef map decl_map; + + string file_; + decl_map decls_; +}; + +extern "C" void +gate_callback (void* gcc_data, void* user_data) +{ + warning (0, G_ ("main file is %s"), main_input_filename); + + if (!errorcount && !sorrycount) + { + traverser t; + t.traverse (global_namespace); + } + + exit (0); +} + +extern "C" int +plugin_init (struct plugin_name_args *plugin_info, + struct plugin_gcc_version *version) +{ + warning (0, G_ ("starting plugin %s"), plugin_info->base_name); + + // Disable assembly output. + // + asm_file_name = HOST_BIT_BUCKET; + + register_callback (plugin_info->base_name, + PLUGIN_OVERRIDE_GATE, + &gate_callback, + NULL); + + return 0; +} -- cgit v1.1