From d9ea777539b166c7347c44a6b7784626405bc029 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Sun, 15 Sep 2013 09:07:05 +0200 Subject: Use base object instead of root for polymorphic id refs In particular, this means that the primary key will point to the base table, not root table and we can figure out the inheritance chain based on tables by traversing their foreign keys. --- odb/processor.cxx | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/odb/processor.cxx b/odb/processor.cxx index 65ee64f..0bb9796 100644 --- a/odb/processor.cxx +++ b/odb/processor.cxx @@ -2126,8 +2126,9 @@ namespace if (poly_root != 0) { using namespace semantics; + using semantics::data_member; - semantics::data_member& idm (*id_member (*poly_root)); + data_member* idm (id_member (*poly_root)); if (poly_root != &c) { @@ -2135,38 +2136,44 @@ namespace // class hierarchy, then add a synthesized virtual pointer // member that points back to the root. // - path const& f (idm.file ()); - size_t l (idm.line ()), col (idm.column ()); + semantics::class_& base (polymorphic_base (c)); + + if (&base != poly_root) + idm = &dynamic_cast (base.names_begin ()->named ()); + + path const& f (idm->file ()); + size_t l (idm->line ()), col (idm->column ()); semantics::data_member& m ( unit.new_node (f, l, col, tree (0))); m.set ("virtual", true); - // Make it the first member in the class. + // Make it the first member in the class. This is important: + // we rely on the corrensponding foreign key to be first. // node_position np (c, c.names_end ()); unit.new_edge ( - np, m, idm.name (), access::public_); + np, m, idm->name (), access::public_); // Use the raw pointer as this member's type. // - if (!poly_root->pointed_p ()) + if (!base.pointed_p ()) { // Create the pointer type in the graph. The pointer node // in GCC seems to always be present, even if not explicitly // used in the translation unit. // - tree t (poly_root->tree_node ()); + tree t (base.tree_node ()); tree ptr (TYPE_POINTER_TO (t)); assert (ptr != 0); ptr = TYPE_MAIN_VARIANT (ptr); pointer& p (unit.new_node (f, l, col, ptr)); unit.insert (ptr, p); - unit.new_edge (p, *poly_root); - assert (poly_root->pointed_p ()); + unit.new_edge (p, base); + assert (base.pointed_p ()); } - unit.new_edge (m, poly_root->pointed ().pointer ()); + unit.new_edge (m, base.pointed ().pointer ()); // Mark it as a special kind of id. // @@ -2193,7 +2200,7 @@ namespace // from reuse-base). // node_position np ( - c, c.find (idm.named ())); + c, c.find (idm->named ())); unit.new_edge ( np, m, "typeid_", access::public_); -- cgit v1.1