diff options
-rw-r--r-- | odb/gcc.hxx | 35 | ||||
-rw-r--r-- | odb/makefile | 9 | ||||
-rw-r--r-- | odb/odb.cxx | 2 | ||||
-rw-r--r-- | odb/plugin.cxx | 963 | ||||
-rw-r--r-- | odb/semantics.hxx | 16 | ||||
-rw-r--r-- | odb/semantics/class.cxx | 49 | ||||
-rw-r--r-- | odb/semantics/class.hxx | 135 | ||||
-rw-r--r-- | odb/semantics/derived.cxx | 96 | ||||
-rw-r--r-- | odb/semantics/derived.hxx | 376 | ||||
-rw-r--r-- | odb/semantics/elements.cxx | 155 | ||||
-rw-r--r-- | odb/semantics/elements.hxx | 550 | ||||
-rw-r--r-- | odb/semantics/elements.ixx | 15 | ||||
-rw-r--r-- | odb/semantics/fundamental.cxx | 168 | ||||
-rw-r--r-- | odb/semantics/fundamental.hxx | 113 | ||||
-rw-r--r-- | odb/semantics/namespace.cxx | 28 | ||||
-rw-r--r-- | odb/semantics/namespace.hxx | 31 | ||||
-rw-r--r-- | odb/semantics/unit.cxx | 32 | ||||
-rw-r--r-- | odb/semantics/unit.hxx | 142 |
18 files changed, 2811 insertions, 104 deletions
diff --git a/odb/gcc.hxx b/odb/gcc.hxx new file mode 100644 index 0000000..ab54707 --- /dev/null +++ b/odb/gcc.hxx @@ -0,0 +1,35 @@ +// file : odb/gcc.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_GCC_TREE_HXX +#define ODB_GCC_TREE_HXX + +// GCC header includes to get the parse tree declarations. The order +// is important and doesn't follow any kind of logic. +// + +#include <stdlib.h> +#include <gmp.h> + +#include <cstdlib> // Include before GCC poisons some declarations. + +extern "C" +{ +#include "gcc-plugin.h" + +#include "config.h" +#include "system.h" +#include "coretypes.h" +#include "tree.h" +#include "intl.h" + +#include "tm.h" + +#include "diagnostic.h" +#include "c-common.h" +#include "cp/cp-tree.h" +} + +#endif // ODB_GCC_TREE_HXX diff --git a/odb/makefile b/odb/makefile index 031df62..825cd7b 100644 --- a/odb/makefile +++ b/odb/makefile @@ -8,7 +8,14 @@ include $(dir $(lastword $(MAKEFILE_LIST)))../build/bootstrap.make # Plugin units. # cxx_ptun := plugin.cxx -cxx_ptun += + +cxx_ptun += \ +semantics/class.cxx \ +semantics/derived.cxx \ +semantics/elements.cxx \ +semantics/fundamental.cxx \ +semantics/namespace.cxx \ +semantics/unit.cxx # Driver units # diff --git a/odb/odb.cxx b/odb/odb.cxx index fe6a0e4..1f8d516 100644 --- a/odb/odb.cxx +++ b/odb/odb.cxx @@ -253,7 +253,7 @@ plugin_path (string const& drv) for (size_t b (0), e (paths.find (':')); b != string::npos;) { - string p (paths, b, e - b); + string p (paths, b, e != string::npos ? e - b : e); // Empty path (i.e., a double colon or a colon at the beginning // or end of PATH) means search in the current dirrectory. diff --git a/odb/plugin.cxx b/odb/plugin.cxx index a8b8ddf..5af4230 100644 --- a/odb/plugin.cxx +++ b/odb/plugin.cxx @@ -1,73 +1,102 @@ -extern "C" -{ -#include "gcc-plugin.h" -} - -#include <stdlib.h> -#include <gmp.h> +// file : odb/plugin.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file -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 <gcc.hxx> // Keep it first. +#include <set> #include <map> #include <string> +#include <memory> // std::auto_ptr #include <cassert> +#include <sstream> -using namespace std; +#include <semantics.hxx> -int plugin_is_GPL_compatible; +#ifndef LOCATION_COLUMN +#define LOCATION_COLUMN(LOC) (expand_location (LOC).column) +#endif -// TODO: -// -// * 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). -// +#ifndef DECL_SOURCE_COLUMN +#define DECL_SOURCE_COLUMN(NODE) LOCATION_COLUMN (DECL_SOURCE_LOCATION (NODE)) +#endif -enum class_access { ca_public, ca_protected, ca_private }; -const char* class_access_str[] = {"public", "protected", "private"}; +using namespace std; +using namespace semantics; -class traverser +int plugin_is_GPL_compatible; + +class parser { public: - traverser () - : file_ (main_input_filename) + typedef semantics::access access; + + parser () { } - void - traverse (tree scope) + auto_ptr<semantics::unit> + parse (tree global_scope, path const& main_file) { + /* + for (size_t i (0); i < line_table->used; ++i) + { + const line_map* m (line_table->maps + i); + warning (0, G_ ("line map to %s reason %d"), m->to_file, m->reason); + } + + for (size_t i (0); i < line_table->used; ++i) + { + const line_map* m (line_table->maps + i); + + if (MAIN_FILE_P (m) || m->reason != LC_ENTER) + continue; + + const line_map* i (INCLUDED_FROM (line_table, m)); + + if (!MAIN_FILE_P (i)) + continue; + + warning (0, G_ ("#includ %s at %s:%d"), + m->to_file, + i->to_file, + LAST_SOURCE_LINE (i)); + } + */ + + auto_ptr<unit> u (new unit (main_file)); + unit_ = u.get (); + scope_ = unit_; + + // Define fundamental types. + // + define_fund<fund_void> (void_type_node); + define_fund<fund_bool> (boolean_type_node); + define_fund<fund_char> (char_type_node); + define_fund<fund_wchar> (wchar_type_node); + define_fund<fund_signed_char> (signed_char_type_node); + define_fund<fund_unsigned_char> (unsigned_char_type_node); + define_fund<fund_short> (short_integer_type_node); + define_fund<fund_unsigned_short> (short_unsigned_type_node); + define_fund<fund_int> (integer_type_node); + define_fund<fund_unsigned_int> (unsigned_type_node); + define_fund<fund_long> (long_integer_type_node); + define_fund<fund_unsigned_long> (long_unsigned_type_node); + define_fund<fund_long_long> (long_long_integer_type_node); + define_fund<fund_unsigned_long_long> (long_long_unsigned_type_node); + define_fund<fund_float> (float_type_node); + define_fund<fund_double> (double_type_node); + define_fund<fund_long_double> (long_double_type_node); + // 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); + collect (global_scope); emit (); + + return u; } private: @@ -81,17 +110,69 @@ private: // for (; decl != NULL_TREE; decl = TREE_CHAIN (decl)) { + if (DECL_IS_BUILTIN (decl)) + continue; + 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_) + /* + location_t l (DECL_SOURCE_LOCATION (decl)); + + if (l > BUILTINS_LOCATION) { - decls_[DECL_SOURCE_LINE (decl)] = decl; + warning (0, G_ ("decl in %s"), DECL_SOURCE_FILE (decl)); + + const line_map* map = linemap_lookup (line_table, l); + + if (map != 0 && !MAIN_FILE_P (map)) + { + map = INCLUDED_FROM (line_table, map); + warning (0, G_ ("included from %s:%d"), + map->to_file, + LAST_SOURCE_LINE (map)); + } } + */ + + if (DECL_NAME (decl) != NULL_TREE) + decls_.insert (decl); + + /* + tree type (TREE_TYPE (decl)); + + if (TREE_CODE (type) == RECORD_TYPE) + { + tree name (DECL_NAME (decl)); + + if (name != NULL_TREE) + { + if (DECL_ARTIFICIAL (decl)) + { + // If we have an anonymous class typedef, use the user- + // supplied name instead of the synthesized one. ARM + // says that in typedef struct {} S; S becomes struct's + // name. + // + if (ANON_AGGRNAME_P (name)) + { + tree d (TYPE_NAME (type)); + + if (d != NULL_TREE && + !DECL_ARTIFICIAL (d) && + DECL_NAME (d) != NULL_TREE && + !ANON_AGGRNAME_P (DECL_NAME (d))) + { + decls_.insert (d); + } + } + else + decls_.insert (decl); + } + } + } + */ break; } @@ -126,9 +207,9 @@ private: // 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_) + // !DECL_NAMESPACE_STD_P (decl) + + if (!DECL_IS_BUILTIN (decl)) { tree name = DECL_NAME (decl); @@ -145,33 +226,185 @@ private: void emit () { - for (decl_map::const_iterator i (decls_.begin ()), e (decls_.end ()); + for (decl_set::const_iterator i (decls_.begin ()), e (decls_.end ()); i != e; ++i) { - tree decl (i->second); + tree decl (*i); - switch (TREE_CODE (decl)) + // Get this declaration's namespace and unwind our scope until + // we find a common prefix of namespaces. + // + string pfx; + string ns (fq_scope (decl)); + + for (pfx = scope_->fq_name (); !pfx.empty (); pfx = scope_->fq_name ()) { - case TYPE_DECL: + if (ns.compare (0, pfx.size (), pfx) == 0) + break; + + scope_ = &scope_->scope_ (); + } + + // Build the rest of the namespace hierarchy for this declaration. + // + if (ns != pfx) + { + path f (DECL_SOURCE_FILE (decl)); + size_t l (DECL_SOURCE_LINE (decl)); + size_t c (DECL_SOURCE_COLUMN (decl)); + + for (size_t b (pfx.size () + 2), e (ns.find ("::", b)); + b != string::npos;) { - tree type = TREE_TYPE (decl); - tree name = DECL_NAME (decl); + string n (ns, b, e == string::npos ? e : e - b); - warning (0, G_ ("class declaration %s in %s:%i"), - IDENTIFIER_POINTER (name), + warning (0, G_ ("creating namespace %s for %s:%d"), + n.c_str (), DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl)); - emit_class (type); + // Use the declarations's file, line, and column as an + // approximation for this namespace origin. + // + namespace_& node (unit_->new_node<namespace_> (f, l, c)); + unit_->new_edge<defines> (*scope_, node, n); + scope_ = &node; + + if (e == string::npos) + b = e; + else + { + b = e + 2; + e = ns.find ("::", b); + } + } + } + + switch (TREE_CODE (decl)) + { + case TYPE_DECL: + { + tree t (TREE_TYPE (decl)); + tree decl_name (DECL_NAME (decl)); + char const* name (IDENTIFIER_POINTER (decl_name)); + + if (DECL_ARTIFICIAL (decl) && TREE_CODE (t) == RECORD_TYPE) + { + // If we have an anonymous class typedef, use the user- + // supplied name instead of the synthesized one. ARM + // says that in typedef struct {} S; S becomes struct's + // name. + // + if (ANON_AGGRNAME_P (decl_name)) + { + tree d (TYPE_NAME (t)); + + if (d != NULL_TREE && + !DECL_ARTIFICIAL (d) && + DECL_NAME (d) != NULL_TREE && + !ANON_AGGRNAME_P (DECL_NAME (d))) + { + decl = d; + decl_name = DECL_NAME (decl); + name = IDENTIFIER_POINTER (decl_name); + } + else + { + // This type has only the synthesized name which means that + // it is either typedef'ed as a derived type or it is used + // to declare a varibale or similar. The first case will be + // covered by the typedef handling code below. The second + // case we don't care about. + // + break; + } + } + + path file (DECL_SOURCE_FILE (decl)); + size_t line (DECL_SOURCE_LINE (decl)); + size_t clmn (DECL_SOURCE_COLUMN (decl)); + + warning (0, G_ ("start class declaration %s in %s:%d"), + name, + DECL_SOURCE_FILE (decl), + DECL_SOURCE_LINE (decl)); + + class_& node (emit_class (t, file, line, clmn)); + + if (COMPLETE_TYPE_P (t)) + unit_->new_edge<defines> (*scope_, node, name); + else + unit_->new_edge<declares> (*scope_, node, name); + + warning (0, G_ ("end class declaration %s (%p) in %s:%d"), + name, + &node, + DECL_SOURCE_FILE (decl), + DECL_SOURCE_LINE (decl)); + } + else + { + // Normal typedef. We need to detect and ignore the anonymous + // class typedef case described above since we already used + // this name to define the class. + // + if (TREE_CODE (t) == RECORD_TYPE && + TYPE_NAME (TYPE_MAIN_VARIANT (t)) == decl) + break; + + path f (DECL_SOURCE_FILE (decl)); + size_t l (DECL_SOURCE_LINE (decl)); + size_t c (DECL_SOURCE_COLUMN (decl)); + + type& node (emit_type (t, f, l, c)); + unit_->new_edge<typedefs> (*scope_, node, name); + + string s (emit_type_name (t, false)); + + warning (0, G_ ("typedef declaration %s (%p) -> %s in %s:%i"), + s.c_str (), + &node, + name, + DECL_SOURCE_FILE (decl), + DECL_SOURCE_LINE (decl)); + } + + break; + } + case TEMPLATE_DECL: + { break; } } } } - void - emit_class (tree c) + class_& + emit_class (tree c, + path const& file, + size_t line, + size_t clmn, + bool stub = false) { + c = TYPE_MAIN_VARIANT (c); + + // See if there is a stub already for this type. + // + class_* class_node (0); + + if (node* n = unit_->find (c)) + { + class_node = &dynamic_cast<class_&> (*n); + } + else + { + class_node = &unit_->new_node<class_> (file, line, clmn); + unit_->insert (c, *class_node); + } + + if (stub || !COMPLETE_TYPE_P (c)) + return *class_node; + // Traverse base information. // tree bis (TYPE_BINFO (c)); @@ -180,8 +413,7 @@ private: for (size_t i (0); i < n; i++) { tree bi (BINFO_BASE_BINFO (bis, i)); - - class_access a (ca_public); + access a (access::public_); if (BINFO_BASE_ACCESSES (bis)) { @@ -189,34 +421,39 @@ private: if (ac == NULL_TREE || ac == access_public_node) { - a = ca_public; + a = access::public_; } else if (ac == access_protected_node) { - a = ca_protected; + a = access::protected_; } else { assert (ac == access_private_node); - a = ca_private; + a = access::private_; } } - bool v (BINFO_VIRTUAL_P (bi)); - tree b (BINFO_TYPE (bi)); - tree b_decl (TYPE_NAME (b)); // Typedef decl for this base. + bool virt (BINFO_VIRTUAL_P (bi)); + tree base (BINFO_TYPE (bi)); + tree base_decl (TYPE_NAME (base)); // 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))); + a.string (), + (virt ? " virtual" : ""), + IDENTIFIER_POINTER (DECL_NAME (base_decl))); + + // Find the corresponding graph node. + // + node* base_node (unit_->find (base)); + assert (base_node != 0); + unit_->new_edge<inherits> ( + *class_node, dynamic_cast<class_&> (*base_node), a, virt); } // Traverse data members. // - for (tree decl (TYPE_FIELDS (c)); - decl != NULL_TREE ; - decl = TREE_CHAIN (decl)) + for (tree d (TYPE_FIELDS (c)); d != NULL_TREE ; d = TREE_CHAIN (d)) { //if (DECL_ARTIFICIAL (field)) // continue; @@ -224,54 +461,576 @@ private: // if (TREE_CODE (field) == TYPE_DECL && TREE_TYPE (field) == c) // continue; - switch (TREE_CODE (decl)) + switch (TREE_CODE (d)) { case FIELD_DECL: { - if (!DECL_ARTIFICIAL (decl)) + if (!DECL_ARTIFICIAL (d)) { - tree name = DECL_NAME (decl); - tree type = TREE_TYPE (decl); - tree type_decl = TYPE_NAME (type); + tree t (TREE_TYPE (d)); + char const* name (IDENTIFIER_POINTER (DECL_NAME (d))); + + path file (DECL_SOURCE_FILE (d)); + size_t line (DECL_SOURCE_LINE (d)); + size_t clmn (DECL_SOURCE_COLUMN (d)); + + string type_name (emit_type_name (t)); + + access a (decl_access (d)); + + type& type_node (emit_type (t, file, line, clmn)); + data_member& member_node ( + unit_->new_node<data_member> (file, line, clmn)); + + unit_->new_edge<belongs> (member_node, type_node); + unit_->new_edge<names> (*class_node, member_node, name, a); + + warning (0, G_ ("\t%s data member %s (%p) %s in %s:%i"), + a.string (), + type_name.c_str (), + &type_node, + name, + file.string ().c_str (), + line); - 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); + tree name = DECL_NAME (d); if (name != NULL_TREE) { warning (0, G_ ("\tsome declaration %s in %s:%i"), IDENTIFIER_POINTER (name), - DECL_SOURCE_FILE (decl), - DECL_SOURCE_LINE (decl)); + DECL_SOURCE_FILE (d), + DECL_SOURCE_LINE (d)); } else { warning (0, G_ ("\tsome unnamed declaration in %s:%i"), - DECL_SOURCE_FILE (decl), - DECL_SOURCE_LINE (decl)); + DECL_SOURCE_FILE (d), + DECL_SOURCE_LINE (d)); } */ break; } } } + + return *class_node; + } + + // Create new or find existing semantic graph type. + // + type& + emit_type (tree t, + path const& file, + size_t line, + size_t clmn) + { + node* n (unit_->find (TYPE_MAIN_VARIANT (t))); + + type& r (n != 0 + ? dynamic_cast<type&> (*n) + : create_type (t, file, line, clmn)); + + if (n != 0) + warning (0, G_ ("emit_type: found node %p for type %p"), + &r, + TYPE_MAIN_VARIANT (t)); + + if (cp_type_quals (t) == TYPE_UNQUALIFIED) + return r; + + // See if this type already has this variant. + // + bool qc (CP_TYPE_CONST_P (t)); + bool qv (CP_TYPE_VOLATILE_P (t)); + bool qr (CP_TYPE_RESTRICT_P (t)); + + for (type::qualified_iterator i (r.qualified_begin ()); + i != r.qualified_end (); ++i) + { + qualifier& q (i->qualifier ()); + + if (q.const_ () == qc && q.volatile_ () == qv && q.restrict_ () == qr) + { + warning (0, G_ ("emit_type: found qualifier variant %p"), &q); + return q; + } + } + + // No such variant yet. Create a new one. + // + qualifier& q (unit_->new_node<qualifier> (file, line, clmn, qc, qv, qr)); + unit_->new_edge<qualifies> (q, r); + return q; + } + + + type& + create_type (tree t, + path const& file, + size_t line, + size_t clmn) + { + type* r (0); + + switch (TREE_CODE (t)) + { + // + // User-defined types. + // + case RECORD_TYPE: + { + tree ti (TYPE_TEMPLATE_INFO (t)); + + if (ti == NULL_TREE) + { + // Ordinary class. There are two situations which can lead + // here. First is when we have an anonymous class that is + // part of the declaration, for example: + // + // typedef const struct {...} s; + // + // The second situation is a named class definition which + // we haven't parsed yet. In this case we are going to + // create a "stub" class node which will be processed and + // filled in later. + // + + t = TYPE_MAIN_VARIANT (t); + tree d (TYPE_NAME (t)); + + warning (0, G_ ("start anon/stub class declaration in %s:%d"), + file.string ().c_str (), + line); + + if (d == NULL_TREE || ANON_AGGRNAME_P (DECL_NAME (d))) + { + r = &emit_class (t, file, line, clmn); + } + else + { + // Use the "defining" declaration's file, line, and column + // information to create the stub. + // + r = &emit_class (t, + path (DECL_SOURCE_FILE (d)), + DECL_SOURCE_LINE (d), + DECL_SOURCE_COLUMN (d), + true); + } + + warning (0, G_ ("end anon/stub class declaration (%p) in %s:%d"), + r, + file.string ().c_str (), + line); + } + else + { + // Template instantiation. + // + /* + tree decl (TI_TEMPLATE (ti)); // DECL_TEMPLATE + string id (IDENTIFIER_POINTER (DECL_NAME (decl))); + + id += '<'; + + tree args (INNERMOST_TEMPLATE_ARGS (TI_ARGS (ti))); + + int n (TREE_VEC_LENGTH (args)); + + for (size_t i (0), n (TREE_VEC_LENGTH (args)); i < n ; ++i) + { + tree a (TREE_VEC_ELT (args, i)); + + if (i != 0) + id += ", "; + + // Assume type-only arguments. + // + id += emit_type (a); + } + + id += '>'; + + r = id + r; + */ + } + + break; + } + + /* + + case UNION_TYPE: + { + break; + } + case ENUMERAL_TYPE: + { + break; + } + + */ + + // + // Derived types. + // + + case ARRAY_TYPE: + { + unsigned long long size (0); + + if (tree index = TYPE_DOMAIN (t)) + { + tree max (TYPE_MAX_VALUE (index)); + + if (TREE_CODE (max) == INTEGER_CST) + { + HOST_WIDE_INT hwl (TREE_INT_CST_LOW (max)); + HOST_WIDE_INT hwh (TREE_INT_CST_HIGH (max)); + + // The docs say that TYPE_DOMAIN will be NULL if the + // array doesn't specify bounds. In reality, both + // low and high parts are set to HOST_WIDE_INT_MAX. + // + if (hwl != ~HOST_WIDE_INT (0) && hwh != ~HOST_WIDE_INT (0)) + { + unsigned long long l (hwl); + unsigned long long h (hwh); + unsigned short width (HOST_BITS_PER_WIDE_INT); + + size = (h << width) + l + 1; + } + } + else + { + error (G_ ("%s:%d: non-integer array index %s"), + file.string ().c_str (), + line, + tree_code_name[TREE_CODE (max)]); + } + } + + type& bt (emit_type (TREE_TYPE (t), file, line, clmn)); + array& a (unit_->new_node<array> (file, line, clmn, size)); + unit_->new_edge<contains> (a, bt); + unit_->insert (TYPE_MAIN_VARIANT (t), a); + r = &a; + break; + } + case REFERENCE_TYPE: + { + type& bt (emit_type (TREE_TYPE (t), file, line, clmn)); + reference& ref (unit_->new_node<reference> (file, line, clmn)); + unit_->new_edge<references> (ref, bt); + unit_->insert (TYPE_MAIN_VARIANT (t), ref); + r = &ref; + break; + } + case POINTER_TYPE: + { + if (!TYPE_PTRMEM_P (t)) + { + type& bt (emit_type (TREE_TYPE (t), file, line, clmn)); + pointer& p (unit_->new_node<pointer> (file, line, clmn)); + unit_->new_edge<points> (p, bt); + unit_->insert (TYPE_MAIN_VARIANT (t), p); + r = &p; + } + + break; + } + default: + { + error (G_ ("%s:%d: unexpected type %s"), + file.string ().c_str (), + line, + tree_code_name[TREE_CODE (t)]); + break; + } + } + + return *r; + } + + string + emit_type_name (tree type, bool direct = true) + { + { + warning (0, G_ ("type object %p; main %p"), + type, + TYPE_MAIN_VARIANT (type)); + + for (tree v (TYPE_MAIN_VARIANT (type)); v != 0; v = TYPE_NEXT_VARIANT (v)) + warning (0, G_ ("\t variant %p"), v); + } + + // First see if there is a "direct" name for this type. + // + if (direct) + { + if (tree decl = TYPE_NAME (type)) + { + tree t (TREE_TYPE (decl)); + + if (same_type_p (type, t)) + return IDENTIFIER_POINTER (DECL_NAME (decl)); + } + } + + string r; + + if (CP_TYPE_CONST_P (type)) + r += " const"; + + if (CP_TYPE_VOLATILE_P (type)) + r += " volatile"; + + if (CP_TYPE_RESTRICT_P (type)) + r += " __restrict"; + + switch (TREE_CODE (type)) + { + // + // User-defined types. + // + + case RECORD_TYPE: + { + tree ti (TYPE_TEMPLATE_INFO (type)); + + if (ti == NULL_TREE) + { + type = TYPE_MAIN_VARIANT (type); + + // Ordinary class. + // + tree decl (TYPE_NAME (type)); + r = IDENTIFIER_POINTER (DECL_NAME (decl)) + r; + } + else + { + // Template instantiation. + // + tree decl (TI_TEMPLATE (ti)); // DECL_TEMPLATE + string id (IDENTIFIER_POINTER (DECL_NAME (decl))); + + id += '<'; + + tree args (INNERMOST_TEMPLATE_ARGS (TI_ARGS (ti))); + + int n (TREE_VEC_LENGTH (args)); + + for (size_t i (0), n (TREE_VEC_LENGTH (args)); i < n ; ++i) + { + tree a (TREE_VEC_ELT (args, i)); + + if (i != 0) + id += ", "; + + // Assume type-only arguments. + // + id += emit_type_name (a); + } + + id += '>'; + + r = id + r; + } + + break; + } + + /* + case UNION_TYPE: + { + break; + } + case ENUMERAL_TYPE: + { + break; + } + */ + + // + // Derived types. + // + + case ARRAY_TYPE: + { + unsigned long long size (0); + + if (tree index = TYPE_DOMAIN (type)) + { + tree max (TYPE_MAX_VALUE (index)); + + if (TREE_CODE (max) == INTEGER_CST) + { + HOST_WIDE_INT hwl (TREE_INT_CST_LOW (max)); + HOST_WIDE_INT hwh (TREE_INT_CST_HIGH (max)); + + if (hwl != ~HOST_WIDE_INT (0) && hwh != ~HOST_WIDE_INT (0)) + { + unsigned long long l (hwl); + unsigned long long h (hwh); + unsigned short width (HOST_BITS_PER_WIDE_INT); + + size = (h << width) + l + 1; + } + } + else + { + error (G_ ("non-integer array index %s"), + tree_code_name[TREE_CODE (type)]); + } + } + + tree t (TREE_TYPE (type)); + + if (size != 0) + { + ostringstream ostr; + ostr << size; + r = emit_type_name (t) + "[" + ostr.str () + "]" + r; + } + else + r = emit_type_name (t) + "[]" + r; + + break; + } + case REFERENCE_TYPE: + { + tree t (TREE_TYPE (type)); + r = emit_type_name (t) + "&" + r; + break; + } + case POINTER_TYPE: + { + if (!TYPE_PTRMEM_P (type)) + { + tree t (TREE_TYPE (type)); + r = emit_type_name (t) + "*" + r; + } + + break; + } + + // + // Fundamental types. + // + + case VOID_TYPE: + case REAL_TYPE: + case BOOLEAN_TYPE: + case INTEGER_TYPE: + { + type = TYPE_MAIN_VARIANT (type); + tree decl (TYPE_NAME (type)); + r = IDENTIFIER_POINTER (DECL_NAME (decl)) + r; + break; + } + default: + { + r = "<unsupported>"; + break; + } + } + + return r; + } + + + // Return declaration's fully-qualified scope name (e.g., ::foo::bar). + // + string + fq_scope (tree decl) + { + string s, tmp; + + for (tree scope (CP_DECL_CONTEXT (decl)); + scope != global_namespace; + scope = CP_DECL_CONTEXT (scope)) + { + tree n = DECL_NAME (scope); + + tmp = "::"; + tmp += (n != NULL_TREE ? IDENTIFIER_POINTER (n) : ""); + tmp += s; + s.swap (tmp); + } + + return s; + } + + // Return access for decl. + // + access + decl_access (tree decl) + { + if (TREE_PRIVATE (decl)) + return access::private_; + + if (TREE_PROTECTED (decl)) + return access::protected_; + + return access::public_; + } + + // + // + template <typename T> + void + define_fund (tree t) + { + t = TYPE_MAIN_VARIANT (t); + char const* name (IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (t)))); + + T& node (unit_->new_fund_node<T> ()); + unit_->new_edge<defines> (*scope_, node, name); + unit_->insert (t, node); } private: - typedef map<size_t, tree> decl_map; + unit* unit_; + scope* scope_; + + struct location_comparator + { + bool operator() (tree x, tree y) const + { + location_t xloc (DECL_SOURCE_LOCATION (x)); + location_t yloc (DECL_SOURCE_LOCATION (y)); + + if (xloc != yloc) + return xloc < yloc; + + size_t xl (LOCATION_LINE (xloc)); + size_t yl (LOCATION_LINE (yloc)); + + if (xl != yl) + return xl < yl; + + size_t xc (LOCATION_COLUMN (xloc)); + size_t yc (LOCATION_COLUMN (yloc)); + + if (xc != yc) + return xc < yc; + + return false; + } + }; + + typedef std::multiset<tree, location_comparator> decl_set; + decl_set decls_; - string file_; - decl_map decls_; + typedef std::map<string, fund_type*> fund_type_map; + fund_type_map fund_types_; }; extern "C" void @@ -281,8 +1040,8 @@ gate_callback (void* gcc_data, void* user_data) if (!errorcount && !sorrycount) { - traverser t; - t.traverse (global_namespace); + parser p; + auto_ptr<unit> u (p.parse (global_namespace, path (main_input_filename))); } exit (0); diff --git a/odb/semantics.hxx b/odb/semantics.hxx new file mode 100644 index 0000000..46350be --- /dev/null +++ b/odb/semantics.hxx @@ -0,0 +1,16 @@ +// file : odb/semantics.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_SEMANTICS_HXX +#define ODB_SEMANTICS_HXX + +#include <semantics/class.hxx> +#include <semantics/derived.hxx> +#include <semantics/elements.hxx> +#include <semantics/fundamental.hxx> +#include <semantics/namespace.hxx> +#include <semantics/unit.hxx> + +#endif // ODB_SEMANTICS_HXX diff --git a/odb/semantics/class.cxx b/odb/semantics/class.cxx new file mode 100644 index 0000000..5575745 --- /dev/null +++ b/odb/semantics/class.cxx @@ -0,0 +1,49 @@ +// file : odb/semantics/class.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include <cutl/compiler/type-info.hxx> + +#include <semantics/class.hxx> + +namespace semantics +{ + // type info + // + namespace + { + struct init + { + init () + { + using compiler::type_info; + + // data_member + // + { + type_info ti (typeid (data_member)); + ti.add_base (typeid (nameable)); + ti.add_base (typeid (instance)); + insert (ti); + } + + // inherits + // + { + type_info ti (typeid (inherits)); + ti.add_base (typeid (edge)); + insert (ti); + } + + // class_ + // + { + type_info ti (typeid (class_)); + ti.add_base (typeid (scope)); + insert (ti); + } + } + } init_; + } +} diff --git a/odb/semantics/class.hxx b/odb/semantics/class.hxx new file mode 100644 index 0000000..d4a0900 --- /dev/null +++ b/odb/semantics/class.hxx @@ -0,0 +1,135 @@ +// file : odb/semantics/class.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_SEMANTICS_CLASS_HXX +#define ODB_SEMANTICS_CLASS_HXX + +#include <vector> +#include <semantics/elements.hxx> + +namespace semantics +{ + class class_; + + // + // + class data_member: public nameable, public instance + { + public: + data_member (path const& file, size_t line, size_t column) + : node (file, line, column) + { + } + }; + + // + // + class inherits: public edge + { + public: + typedef semantics::access access_type; + + class_& + base () const + { + return *base_; + } + + class_& + derived () const + { + return *derived_; + } + + bool + virtual_ () const + { + return virt_; + } + + access_type + access () const + { + return access_; + } + + public: + inherits (access_type access, bool virt) + : virt_ (virt), access_ (access) + { + } + + void + set_left_node (class_& n) + { + derived_ = &n; + } + + void + set_right_node (class_& n) + { + base_ = &n; + } + + protected: + bool virt_; + access_type access_; + + class_* base_; + class_* derived_; + }; + + // + // + class class_: public type, public scope + { + private: + typedef std::vector<inherits*> inherits_list; + + public: + typedef inherits_list::const_iterator inherits_iterator; + + inherits_iterator + inherits_begin () const + { + return inherits_.begin (); + } + + inherits_iterator + inherits_end () const + { + return inherits_.end (); + } + + public: + class_ (path const& file, size_t line, size_t column) + : node (file, line, column) + { + } + + void + add_edge_left (inherits& e) + { + inherits_.push_back (&e); + } + + void + add_edge_right (inherits&) + { + } + + using scope::add_edge_left; + using scope::add_edge_right; + + // Resolve conflict between scope::scope and nameable::scope. + // + using nameable::scope; + + private: + inherits_list inherits_; + }; +} + +#endif // ODB_SEMANTICS_CLASS_HXX diff --git a/odb/semantics/derived.cxx b/odb/semantics/derived.cxx new file mode 100644 index 0000000..490dac4 --- /dev/null +++ b/odb/semantics/derived.cxx @@ -0,0 +1,96 @@ +// file : odb/semantics/derived.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include <cutl/compiler/type-info.hxx> + +#include <semantics/derived.hxx> + +namespace semantics +{ + // type info + // + namespace + { + struct init + { + init () + { + using compiler::type_info; + + // derived_type + // + { + type_info ti (typeid (derived_type)); + ti.add_base (typeid (type)); + insert (ti); + } + + // qualifies + // + { + type_info ti (typeid (qualifies)); + ti.add_base (typeid (edge)); + insert (ti); + } + + // qualifier + // + { + type_info ti (typeid (qualifier)); + ti.add_base (typeid (derived_type)); + insert (ti); + } + + // points + // + { + type_info ti (typeid (points)); + ti.add_base (typeid (edge)); + insert (ti); + } + + // pointer + // + { + type_info ti (typeid (pointer)); + ti.add_base (typeid (derived_type)); + insert (ti); + } + + // references + // + { + type_info ti (typeid (references)); + ti.add_base (typeid (edge)); + insert (ti); + } + + // reference + // + { + type_info ti (typeid (reference)); + ti.add_base (typeid (derived_type)); + insert (ti); + } + + // contains + // + { + type_info ti (typeid (contains)); + ti.add_base (typeid (edge)); + insert (ti); + } + + // array + // + { + type_info ti (typeid (array)); + ti.add_base (typeid (derived_type)); + insert (ti); + } + } + } init_; + } +} diff --git a/odb/semantics/derived.hxx b/odb/semantics/derived.hxx new file mode 100644 index 0000000..5e20de8 --- /dev/null +++ b/odb/semantics/derived.hxx @@ -0,0 +1,376 @@ +// file : odb/semantics/derived.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_SEMANTICS_DERIVED_HXX +#define ODB_SEMANTICS_DERIVED_HXX + +#include <semantics/elements.hxx> + +namespace semantics +{ + // + // Derived types (cvr-qualifiers, pointer, reference, and array). + // + + class derived_type: public type + { + public: + virtual type& + base_type () const = 0; + }; + + // + // + class qualifier; + + class qualifies: public edge + { + public: + typedef semantics::type type_type; + typedef semantics::qualifier qualifier_type; + + type_type& + type () const + { + return *type_; + } + + qualifier_type& + qualifier () const + { + return *qualifier_; + } + + public: + qualifies () + { + } + + void + set_left_node (qualifier_type& n) + { + qualifier_ = &n; + } + + void + set_right_node (type_type& n) + { + type_ = &n; + } + + protected: + type_type* type_; + qualifier_type* qualifier_; + }; + + class qualifier: public derived_type + { + public: + typedef semantics::qualifies qualifies_type; + + bool + const_ () const + { + return c_; + } + + bool + volatile_ () const + { + return v_; + } + + bool + restrict_ () const + { + return r_; + } + + virtual type& + base_type () const + { + return qualifies_->type (); + } + + qualifies_type& + qualifies () const + { + return *qualifies_; + } + + public: + qualifier (path const& file, + size_t line, + size_t column, + bool c, + bool v, + bool r) + : node (file, line, column), c_ (c), v_ (v), r_ (r), qualifies_ (0) + { + } + + void + add_edge_left (qualifies_type& e) + { + assert (qualifies_ == 0); + qualifies_ = &e; + } + + private: + bool c_, v_, r_; + qualifies_type* qualifies_; + }; + + // + // + class pointer; + + class points: public edge + { + public: + typedef semantics::type type_type; + typedef semantics::pointer pointer_type; + + type_type& + type () const + { + return *type_; + } + + pointer_type& + pointer () const + { + return *pointer_; + } + + public: + points () + { + } + + void + set_left_node (pointer_type& n) + { + pointer_ = &n; + } + + void + set_right_node (type_type& n) + { + type_ = &n; + } + + protected: + type_type* type_; + pointer_type* pointer_; + }; + + class pointer: public type + { + public: + typedef semantics::points points_type; + + virtual type& + base_type () const + { + return points_->type (); + } + + points_type& + points () const + { + return *points_; + } + + public: + pointer (path const& file, size_t line, size_t column) + : node (file, line, column), points_ (0) + { + } + + void + add_edge_left (points_type& e) + { + assert (points_ == 0); + points_ = &e; + } + + private: + points_type* points_; + }; + + + // + // + class reference; + + class references: public edge + { + public: + typedef semantics::type type_type; + typedef semantics::reference reference_type; + + type_type& + type () const + { + return *type_; + } + + reference_type& + reference () const + { + return *reference_; + } + + public: + references () + { + } + + void + set_left_node (reference_type& n) + { + reference_ = &n; + } + + void + set_right_node (type_type& n) + { + type_ = &n; + } + + protected: + type_type* type_; + reference_type* reference_; + }; + + class reference: public type + { + public: + typedef semantics::references references_type; + + virtual type& + base_type () const + { + return references_->type (); + } + + references_type& + references () const + { + return *references_; + } + + public: + reference (path const& file, size_t line, size_t column) + : node (file, line, column), references_ (0) + { + } + + void + add_edge_left (references_type& e) + { + assert (references_ == 0); + references_ = &e; + } + + private: + references_type* references_; + }; + + + // + // + class array; + + class contains: public edge + { + public: + typedef semantics::type type_type; + typedef semantics::array array_type; + + type_type& + type () const + { + return *type_; + } + + array_type& + array () const + { + return *array_; + } + + public: + contains () + { + } + + void + set_left_node (array_type& n) + { + array_ = &n; + } + + void + set_right_node (type_type& n) + { + type_ = &n; + } + + protected: + type_type* type_; + array_type* array_; + }; + + class array: public type + { + public: + typedef semantics::contains contains_type; + + // Return the number of elements in the array or 0 if it is not + // specified (e.g., int[]). + // + unsigned long long + size () const + { + return size_; + } + + virtual type& + base_type () const + { + return contains_->type (); + } + + contains_type& + contains () const + { + return *contains_; + } + + public: + array (path const& file, + size_t line, + size_t column, + unsigned long long size) + : node (file, line, column), contains_ (0), size_ (size) + { + } + + void + add_edge_left (contains_type& e) + { + assert (contains_ == 0); + contains_ = &e; + } + + private: + contains_type* contains_; + unsigned long long size_; + }; +} + +#endif // ODB_SEMANTICS_DERIVED_HXX diff --git a/odb/semantics/elements.cxx b/odb/semantics/elements.cxx new file mode 100644 index 0000000..d14835c --- /dev/null +++ b/odb/semantics/elements.cxx @@ -0,0 +1,155 @@ +// file : odb/semantics/elements.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include <cutl/compiler/type-info.hxx> + +#include <semantics/elements.hxx> + +namespace semantics +{ + // access + // + static char const* access_str[] = {"public", "protected", "private"}; + + char const* access:: + string () const + { + return access_str[value_]; + } + + // nameable + // + + string nameable:: + fq_name () const + { + if (named ().global_scope ()) + return ""; + else + return scope ().fq_name () + "::" + name (); + } + + // scope + // + + scope::names_iterator_pair scope:: + find (string const& name) const + { + names_map::const_iterator i (names_map_.find (name)); + + if (i == names_map_.end ()) + return names_iterator_pair (names_.end (), names_.end ()); + else + return names_iterator_pair (i->second.begin (), i->second.end ()); + } + + scope::names_iterator scope:: + find (names& e) + { + list_iterator_map::iterator i (iterator_map_.find (&e)); + return i != iterator_map_.end () ? i->second : names_.end (); + } + + void scope:: + add_edge_left (names& e) + { + names_list::iterator it (names_.insert (names_.end (), &e)); + iterator_map_[&e] = it; + names_map_[e.name ()].push_back (&e); + } + + // type info + // + namespace + { + struct init + { + init () + { + using compiler::type_info; + + // node + // + insert (type_info (typeid (node))); + + // edge + // + insert (type_info (typeid (edge))); + + // names + // + { + type_info ti (typeid (names)); + ti.add_base (typeid (edge)); + insert (ti); + } + + // declares + // + { + type_info ti (typeid (declares)); + ti.add_base (typeid (names)); + insert (ti); + } + + // defines + // + { + type_info ti (typeid (defines)); + ti.add_base (typeid (declares)); + insert (ti); + } + + // typedefs + // + { + type_info ti (typeid (typedefs)); + ti.add_base (typeid (declares)); + insert (ti); + } + + // nameable + // + { + type_info ti (typeid (nameable)); + ti.add_base (typeid (node)); + insert (ti); + } + + // scope + // + { + type_info ti (typeid (scope)); + ti.add_base (typeid (nameable)); + insert (ti); + } + + // type + // + { + type_info ti (typeid (type)); + ti.add_base (typeid (nameable)); + insert (ti); + } + + // belongs + // + { + type_info ti (typeid (belongs)); + ti.add_base (typeid (edge)); + insert (ti); + } + + // instance + // + { + type_info ti (typeid (instance)); + ti.add_base (typeid (node)); + insert (ti); + } + } + } init_; + } +} diff --git a/odb/semantics/elements.hxx b/odb/semantics/elements.hxx new file mode 100644 index 0000000..0b89831 --- /dev/null +++ b/odb/semantics/elements.hxx @@ -0,0 +1,550 @@ +// file : odb/semantics/elements.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_SEMANTICS_ELEMENTS_HXX +#define ODB_SEMANTICS_ELEMENTS_HXX + +#include <gcc.hxx> // Keep it first. + +#include <map> +#include <list> +#include <vector> +#include <string> +#include <cstdlib> // std::abort +#include <cstddef> // std::size_t +#include <utility> // std::pair +#include <cassert> + +#include <cutl/fs/path.hxx> + +#include <cutl/container/graph.hxx> +#include <cutl/container/pointer-iterator.hxx> + +#include <cutl/compiler/context.hxx> + +namespace semantics +{ + using namespace cutl; + + using std::size_t; + using std::string; + + using container::graph; + using container::pointer_iterator; + + using compiler::context; + + // GCC parse tree node. + // + typedef ::tree gcc_tree; + + // + // + using fs::path; + using fs::invalid_path; + + // + // + class access + { + public: + enum value { public_, protected_, private_ }; + + access (value v) + : value_ (v) + { + } + + operator value () const + { + return value_; + } + + char const* string () const; + + private: + value value_; + }; + + // + // + class node; + class edge; + + // + // + class edge: public context + { + public: + virtual + ~edge () {} + + public: + template <typename X> + bool + is_a () const + { + return dynamic_cast<X const*> (this) != 0; + } + }; + + // + // + class node: public context + { + public: + virtual + ~node () {} + + public: + path const& + file () const + { + return file_; + } + + size_t + line () const + { + return line_; + } + + size_t + column () const + { + return column_; + } + + public: + template <typename X> + bool + is_a () const + { + return dynamic_cast<X const*> (this) != 0; + } + + public: + node (path const& file, size_t line, size_t column) + : file_ (file), line_ (line), column_ (column) + { + } + + // Sink functions that allow extensions in the form of one-way + // edges. + // + void + add_edge_right (edge&) + { + } + + protected: + // For virtual inheritance. Should never be actually called. + // + node () + : file_ ("") + { + // GCC plugin machinery #define's abort as a macro. + // + //std::abort (); + abort (); + } + + private: + path file_; + size_t line_; + size_t column_; + }; + + // + // + class scope; + class nameable; + + + // + // + class names: public edge + { + public: + typedef semantics::scope scope_type; + typedef semantics::access access_type; + + string const& + name () const + { + return name_; + } + + scope_type& + scope () const + { + return *scope_; + } + + // Return true if the entity that this edge names is a global scope. + // In this case calling scope() is undefined behavior. + // + bool + global_scope () const + { + return scope_ == 0; + } + + nameable& + named () const + { + return *named_; + } + + access_type + access () const + { + return access_; + } + + public: + names (string const& name, access_type access = access_type::public_) + : name_ (name), access_ (access) + { + } + + void + set_left_node (scope_type& n) + { + scope_ = &n; + } + + void + set_right_node (nameable& n) + { + named_ = &n; + } + + protected: + scope_type* scope_; + nameable* named_; + string name_; + access_type access_; + }; + + // + // Declarations and definitions. + // + + class declares: public names + { + public: + declares (string const& name, access_type access = access_type::public_) + : names (name, access) + { + } + }; + + class defines: public declares + { + public: + defines (string const& name, access_type access = access_type::public_) + : declares (name, access) + { + } + }; + + class type; + class typedefs: public declares + { + public: + typedef semantics::type type_type; + + type_type& + type () const; + + public: + typedefs (string const& name, access_type access = access_type::public_) + : declares (name, access) + { + } + }; + + // + // + class nameable: public virtual node + { + typedef std::vector<names*> names_list; + + public: + typedef semantics::scope scope_type; + + bool + anonymous () const + { + return defined_ == 0 && named_.empty (); + } + + string + name () const + { + return named ().name (); + } + + string + fq_name () const; + + scope_type& + scope () const + { + return named ().scope (); + } + + names& + named () const + { + return defined_ != 0 ? *defined_ : *named_[0]; + } + + public: + nameable () + : defined_ (0) + { + } + + void + add_edge_right (defines& e) + { + assert (defined_ == 0); + defined_ = &e; + } + + void + add_edge_right (names& e) + { + named_.push_back (&e); + } + + using node::add_edge_right; + + private: + defines* defined_; + names_list named_; + }; + + + // + // + class scope: public virtual nameable + { + protected: + typedef std::list<names*> names_list; + typedef std::map<names*, names_list::iterator> list_iterator_map; + typedef std::map<string, names_list> names_map; + + public: + typedef pointer_iterator<names_list::iterator> names_iterator; + typedef pointer_iterator<names_list::const_iterator> names_const_iterator; + + typedef + std::pair<names_const_iterator, names_const_iterator> + names_iterator_pair; + + public: + bool + global_scope () const + { + return named ().global_scope (); + } + + scope& + scope_ () const + { + return nameable::scope (); + } + + names_iterator + names_begin () + { + return names_.begin (); + } + + names_iterator + names_end () + { + return names_.end (); + } + + names_const_iterator + names_begin () const + { + return names_.begin (); + } + + names_const_iterator + names_end () const + { + return names_.end (); + } + + virtual names_iterator_pair + find (string const& name) const; + + names_iterator + find (names&); + + public: + scope (path const& file, size_t line, size_t column) + : node (file, line, column) + { + } + + void + add_edge_left (names&); + + using nameable::add_edge_right; + + protected: + scope () + { + } + + private: + names_list names_; + list_iterator_map iterator_map_; + names_map names_map_; + }; + + // + // + class belongs; + class qualifies; + + class type: public virtual nameable + { + typedef std::vector<qualifies*> qualified; + + public: + typedef pointer_iterator<qualified::const_iterator> qualified_iterator; + + qualified_iterator + qualified_begin () const + { + return qualified_.begin (); + } + + qualified_iterator + qualified_end () const + { + return qualified_.end (); + } + + public: + type (path const& file, size_t line, size_t column) + : node (file, line, column) + { + } + + void + add_edge_right (belongs&) + { + } + + void + add_edge_right (qualifies& e) + { + qualified_.push_back (&e); + } + + using nameable::add_edge_right; + + protected: + type () + { + } + + private: + qualified qualified_; + }; + + // + // + class instance; + + class belongs: public edge + { + public: + typedef semantics::type type_type; + typedef semantics::instance instance_type; + + type_type& + type () const + { + return *type_; + } + + instance_type& + instance () const + { + return *instance_; + } + + public: + belongs () + { + } + + void + set_left_node (instance_type& n) + { + instance_ = &n; + } + + void + set_right_node (type_type& n) + { + type_ = &n; + } + + private: + type_type* type_; + instance_type* instance_; + }; + + // + // + class instance: public virtual node + { + public: + typedef semantics::type type_type; + typedef semantics::belongs belongs_type; + + type_type& + type () const + { + return belongs_->type (); + } + + belongs_type& + belongs () const + { + return *belongs_; + } + + public: + void + add_edge_left (belongs_type& e) + { + belongs_ = &e; + } + + protected: + instance () + { + } + + private: + belongs_type* belongs_; + }; +} + +#include <semantics/elements.ixx> + +#endif // ODB_SEMANTICS_ELEMENTS_HXX diff --git a/odb/semantics/elements.ixx b/odb/semantics/elements.ixx new file mode 100644 index 0000000..7d92cdd --- /dev/null +++ b/odb/semantics/elements.ixx @@ -0,0 +1,15 @@ +// file : odb/semantics/elements.ixx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +namespace semantics +{ + // typedefs + // + inline typedefs::type_type& typedefs:: + type () const + { + return dynamic_cast<type_type&> (named ()); + } +} diff --git a/odb/semantics/fundamental.cxx b/odb/semantics/fundamental.cxx new file mode 100644 index 0000000..0edca0c --- /dev/null +++ b/odb/semantics/fundamental.cxx @@ -0,0 +1,168 @@ +// file : odb/semantics/fundamental.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include <cutl/compiler/type-info.hxx> + +#include <semantics/fundamental.hxx> + +namespace semantics +{ + // type info + // + namespace + { + struct init + { + init () + { + using compiler::type_info; + + // fund_type + // + { + type_info ti (typeid (fund_type)); + ti.add_base (typeid (type)); + insert (ti); + } + + // fund_void + // + { + type_info ti (typeid (fund_void)); + ti.add_base (typeid (fund_type)); + insert (ti); + } + + // fund_bool + // + { + type_info ti (typeid (fund_bool)); + ti.add_base (typeid (fund_type)); + insert (ti); + } + + // fund_char + // + { + type_info ti (typeid (fund_char)); + ti.add_base (typeid (fund_type)); + insert (ti); + } + + // fund_wchar + // + { + type_info ti (typeid (fund_wchar)); + ti.add_base (typeid (fund_type)); + insert (ti); + } + + // fund_signed_char + // + { + type_info ti (typeid (fund_signed_char)); + ti.add_base (typeid (fund_type)); + insert (ti); + } + + // fund_unsigned_char + // + { + type_info ti (typeid (fund_unsigned_char)); + ti.add_base (typeid (fund_type)); + insert (ti); + } + + // fund_short + // + { + type_info ti (typeid (fund_short)); + ti.add_base (typeid (fund_type)); + insert (ti); + } + + // fund_unsigned_short + // + { + type_info ti (typeid (fund_unsigned_short)); + ti.add_base (typeid (fund_type)); + insert (ti); + } + + // fund_int + // + { + type_info ti (typeid (fund_int)); + ti.add_base (typeid (fund_type)); + insert (ti); + } + + // fund_unsigned_int + // + { + type_info ti (typeid (fund_unsigned_int)); + ti.add_base (typeid (fund_type)); + insert (ti); + } + + // fund_long + // + { + type_info ti (typeid (fund_long)); + ti.add_base (typeid (fund_type)); + insert (ti); + } + + // fund_unsigned_long + // + { + type_info ti (typeid (fund_unsigned_long)); + ti.add_base (typeid (fund_type)); + insert (ti); + } + + // fund_long_long + // + { + type_info ti (typeid (fund_long_long)); + ti.add_base (typeid (fund_type)); + insert (ti); + } + + // fund_unsigned_long_long + // + { + type_info ti (typeid (fund_unsigned_long_long)); + ti.add_base (typeid (fund_type)); + insert (ti); + } + + // fund_float + // + { + type_info ti (typeid (fund_float)); + ti.add_base (typeid (fund_type)); + insert (ti); + } + + // fund_double + // + { + type_info ti (typeid (fund_double)); + ti.add_base (typeid (fund_type)); + insert (ti); + } + + // fund_long_double + // + { + type_info ti (typeid (fund_long_double)); + ti.add_base (typeid (fund_type)); + insert (ti); + } + } + } init_; + } +} diff --git a/odb/semantics/fundamental.hxx b/odb/semantics/fundamental.hxx new file mode 100644 index 0000000..aa8225a --- /dev/null +++ b/odb/semantics/fundamental.hxx @@ -0,0 +1,113 @@ +// file : odb/semantics/fundamental.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_SEMANTICS_FUNDAMENTAL_HXX +#define ODB_SEMANTICS_FUNDAMENTAL_HXX + +#include <semantics/elements.hxx> + +namespace semantics +{ + // + // Fundamental C++ types. + // + + class fund_type: public type {}; + + struct fund_void: fund_type + { + fund_void (): node (path ("<fundamental>"), 0, 0) {} + }; + + struct fund_bool: fund_type + { + fund_bool (): node (path ("<fundamental>"), 0, 0) {} + }; + + // + // Integral. + // + + struct fund_char: fund_type + { + fund_char (): node (path ("<fundamental>"), 0, 0) {} + }; + + struct fund_wchar: fund_type + { + fund_wchar (): node (path ("<fundamental>"), 0, 0) {} + }; + + struct fund_signed_char: fund_type + { + fund_signed_char (): node (path ("<fundamental>"), 0, 0) {} + }; + + struct fund_unsigned_char: fund_type + { + fund_unsigned_char (): node (path ("<fundamental>"), 0, 0) {} + }; + + struct fund_short: fund_type + { + fund_short (): node (path ("<fundamental>"), 0, 0) {} + }; + + struct fund_unsigned_short: fund_type + { + fund_unsigned_short (): node (path ("<fundamental>"), 0, 0) {} + }; + + struct fund_int: fund_type + { + fund_int (): node (path ("<fundamental>"), 0, 0) {} + }; + + struct fund_unsigned_int: fund_type + { + fund_unsigned_int (): node (path ("<fundamental>"), 0, 0) {} + }; + + struct fund_long: fund_type + { + fund_long (): node (path ("<fundamental>"), 0, 0) {} + }; + + struct fund_unsigned_long: fund_type + { + fund_unsigned_long (): node (path ("<fundamental>"), 0, 0) {} + }; + + struct fund_long_long: fund_type + { + fund_long_long (): node (path ("<fundamental>"), 0, 0) {} + }; + + struct fund_unsigned_long_long: fund_type + { + fund_unsigned_long_long (): node (path ("<fundamental>"), 0, 0) {} + }; + + // + // Real. + // + + struct fund_float: fund_type + { + fund_float (): node (path ("<fundamental>"), 0, 0) {} + }; + + struct fund_double: fund_type + { + fund_double (): node (path ("<fundamental>"), 0, 0) {} + }; + + struct fund_long_double: fund_type + { + fund_long_double (): node (path ("<fundamental>"), 0, 0) {} + }; +} + +#endif // ODB_SEMANTICS_FUNDAMENTAL_HXX diff --git a/odb/semantics/namespace.cxx b/odb/semantics/namespace.cxx new file mode 100644 index 0000000..72e977f --- /dev/null +++ b/odb/semantics/namespace.cxx @@ -0,0 +1,28 @@ +// file : odb/semantics/namespace.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include <cutl/compiler/type-info.hxx> + +#include <semantics/namespace.hxx> + +namespace semantics +{ + // type info + // + namespace + { + struct init + { + init () + { + using compiler::type_info; + + type_info ti (typeid (namespace_)); + ti.add_base (typeid (scope)); + insert (ti); + } + } init_; + } +} diff --git a/odb/semantics/namespace.hxx b/odb/semantics/namespace.hxx new file mode 100644 index 0000000..b6a673c --- /dev/null +++ b/odb/semantics/namespace.hxx @@ -0,0 +1,31 @@ +// file : odb/semantics/namespace.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_SEMANTICS_NAMESPACE_HXX +#define ODB_SEMANTICS_NAMESPACE_HXX + +#include <semantics/elements.hxx> + +namespace semantics +{ + class namespace_: public scope + { + public: + namespace_ (path const& file, size_t line, size_t column) + : node (file, line, column) + { + } + + namespace_ () + { + } + + // Resolve conflict between scope::scope and nameable::scope. + // + using nameable::scope; + }; +} + +#endif // ODB_SEMANTICS_NAMESPACE_HXX diff --git a/odb/semantics/unit.cxx b/odb/semantics/unit.cxx new file mode 100644 index 0000000..073b7fd --- /dev/null +++ b/odb/semantics/unit.cxx @@ -0,0 +1,32 @@ +// file : odb/semantics/unit.cxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#include <cutl/compiler/type-info.hxx> + +#include <semantics/unit.hxx> + +namespace semantics +{ + // type info + // + namespace + { + struct init + { + init () + { + using compiler::type_info; + + // unit + // + { + type_info ti (typeid (unit)); + ti.add_base (typeid (namespace_)); + insert (ti); + } + } + } init_; + } +} diff --git a/odb/semantics/unit.hxx b/odb/semantics/unit.hxx new file mode 100644 index 0000000..c208876 --- /dev/null +++ b/odb/semantics/unit.hxx @@ -0,0 +1,142 @@ +// file : odb/semantics/unit.hxx +// author : Boris Kolpackov <boris@codesynthesis.com> +// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_SEMANTICS_UNIT_HXX +#define ODB_SEMANTICS_UNIT_HXX + +#include <map> + +#include <semantics/elements.hxx> +#include <semantics/namespace.hxx> + +namespace semantics +{ + class unit: public graph<node, edge>, public namespace_ + { + public: + unit (path const& file) + : node (file, 1, 1), graph_ (*this) + { + // Use a special edge to get this->name() return the global + // namespace name (""). + // + new_edge<global_names> (*this, *this); + } + + // Mapping from GCC tree node to semantic graph node. + // + public: + node* + find (gcc_tree key) const + { + gcc_tree_node_map::const_iterator i (gcc_tree_node_map_.find (key)); + return i != gcc_tree_node_map_.end () ? i->second : 0; + } + + void + insert (gcc_tree key, node& value) + { + gcc_tree_node_map_[key] = &value; + } + + public: + template <typename T> + T& + new_node (path const& file, size_t line, size_t column) + { + return graph_.new_node<T> (file, line, column); + } + + template <typename T, typename A0> + T& + new_node (path const& file, size_t line, size_t column, A0 const& a0) + { + return graph_.new_node<T> (file, line, column, a0); + } + + template <typename T, typename A0, typename A1> + T& + new_node (path const& file, size_t line, size_t column, + A0 const& a0, A1 const& a1) + { + return graph_.new_node<T> (file, line, column, a0, a1); + } + + template <typename T, typename A0, typename A1, typename A2> + T& + new_node (path const& file, size_t line, size_t column, + A0 const& a0, A1 const& a1, A2 const& a2) + { + return graph_.new_node<T> (file, line, column, a0, a1, a2); + } + + template <typename T, typename A0, typename A1, typename A2, typename A3> + T& + new_node (path const& file, size_t line, size_t column, + A0 const& a0, A1 const& a1, A2 const& a2, A3 const& a3) + { + return graph_.new_node<T> (file, line, column, a0, a1, a2, a3); + } + + // For fundamental types. + // + template <typename T> + T& + new_fund_node () + { + return graph_.new_node<T> (); + } + + protected: + // Special names edge for the global namespace. + // + class global_names: public names + { + public: + global_names () + : names ("") + { + scope_ = 0; + } + + void + set_left_node (unit&) + { + } + + void + set_right_node (nameable& n) + { + named_ = &n; + } + + void + clear_left_node (unit&) + { + } + + void + clear_right_node (nameable& n) + { + assert (named_ == &n); + named_ = 0; + } + }; + + public: + void + add_edge_left (global_names&) + { + } + + private: + graph<node, edge>& graph_; + + typedef std::map<gcc_tree, node*> gcc_tree_node_map; + gcc_tree_node_map gcc_tree_node_map_; + }; +} + +#endif // ODB_SEMANTICS_UNIT_HXX |