From d1ad30f7a517e69bc87d1347224f1c9ab38493b3 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Thu, 25 Oct 2012 10:35:36 +0200 Subject: Static multi-database support Add new options (--multi-database, --default-database). Generate common code to -odb.?xx files and database-specific to -odb-.?xx. --- odb/relational/processor.cxx | 1102 +----------------------------------------- 1 file changed, 9 insertions(+), 1093 deletions(-) (limited to 'odb/relational/processor.cxx') diff --git a/odb/relational/processor.cxx b/odb/relational/processor.cxx index f000858..5100739 100644 --- a/odb/relational/processor.cxx +++ b/odb/relational/processor.cxx @@ -305,497 +305,14 @@ namespace relational throw operation_failed (); } - process_access (m, "get"); - process_access (m, "set"); - process_index (m); - } - - // - // Process member access expressions. - // - - enum found_type - { - found_none, - found_some, // Found something but keep looking for a better one. - found_best - }; - - // Check if a function is a suitable accessor for this member. - // - found_type - check_accessor (semantics::data_member& m, - tree f, - string const& n, - member_access& ma, - bool strict) - { - // Must be const. - // - if (!DECL_CONST_MEMFUNC_P (f)) - return found_none; - - // Accessor is a function with no arguments (other than 'this'). - // - if (DECL_CHAIN (DECL_ARGUMENTS (f)) != NULL_TREE) - return found_none; - - // Note that to get the return type we have to use - // TREE_TYPE(TREE_TYPE()) and not DECL_RESULT, as - // suggested in the documentation. - // - tree r (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (f)))); - int tc (TREE_CODE (r)); - - // In the strict mode make sure the function returns for non-array - // types a value or a (const) reference to the member type and for - // array types a (const) pointer to element type. In the lax mode - // we just check that the return value is not void. - // - if (strict) - { - semantics::type& t (utype (m)); - semantics::array* ar (dynamic_cast (&t)); - - if (ar != 0 && tc != POINTER_TYPE) - return found_none; - - tree bt (ar != 0 || tc == REFERENCE_TYPE ? TREE_TYPE (r) : r); - tree bt_mv (TYPE_MAIN_VARIANT (bt)); - - if ((ar != 0 ? ar->base_type () : t).tree_node () != bt_mv) - return found_none; - } - else if (r == void_type_node) - return found_none; - - cxx_tokens& e (ma.expr); - e.push_back (cxx_token (0, CPP_KEYWORD, "this")); - e.push_back (cxx_token (0, CPP_DOT)); - e.push_back (cxx_token (0, CPP_NAME, n)); - e.push_back (cxx_token (0, CPP_OPEN_PAREN, n)); - e.push_back (cxx_token (0, CPP_CLOSE_PAREN, n)); - - // See if it returns by value. - // - ma.by_value = (tc != REFERENCE_TYPE && tc != POINTER_TYPE); - - return found_best; - } - - // Check if a function is a suitable modifier for this member. - // - found_type - check_modifier (semantics::data_member& m, - tree f, - string const& n, - member_access& ma, - bool strict) - { - tree a (DECL_ARGUMENTS (f)); - a = DECL_CHAIN (a); // Skip this. - - // For a modifier, it can either be a function that returns a non- - // const reference (or non-const pointer, in case the member is an - // array) or a by-value modifier that sets a new value. If both are - // available, we prefer the former for efficiency. - // - cxx_tokens& e (ma.expr); - semantics::type& t (utype (m)); - semantics::array* ar (dynamic_cast (&t)); - - if (a == NULL_TREE) + if (m.count ("polymorphic-ref")) { - // Note that to get the return type we have to use - // TREE_TYPE(TREE_TYPE()) and not DECL_RESULT, as - // suggested in the documentation. - // - tree r (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (f)))); - int tc (TREE_CODE (r)); - - // By-reference modifier. Should return a reference or a pointer. - // - if (tc != (ar != 0 ? POINTER_TYPE : REFERENCE_TYPE)) - return found_none; - - // The base type should not be const and, in strict mode, should - // match the member type. - // - tree bt (TREE_TYPE (r)); - - if (CP_TYPE_CONST_P (bt)) - return found_none; - - tree bt_mv (TYPE_MAIN_VARIANT (bt)); - - if (strict && (ar != 0 ? ar->base_type () : t).tree_node () != bt_mv) - return found_none; - - e.clear (); // Could contain by value modifier. - e.push_back (cxx_token (0, CPP_KEYWORD, "this")); - e.push_back (cxx_token (0, CPP_DOT)); - e.push_back (cxx_token (0, CPP_NAME, n)); - e.push_back (cxx_token (0, CPP_OPEN_PAREN, n)); - e.push_back (cxx_token (0, CPP_CLOSE_PAREN, n)); - - return found_best; + m.set ("not-null", true); + m.set ("deferred", false); + m.set ("on-delete", sema_rel::foreign_key::cascade); } - // Otherwise look for a by value modifier, which is a function - // with a single argument. - // - else if (DECL_CHAIN (a) == NULL_TREE) - { - // In the lax mode any function with a single argument works - // for us. And we don't care what it returns. - // - if (strict) - { - // In the strict mode make sure the argument matches the - // member. This is exactly the same logic as in accessor - // with regards to arrays, references, etc. - // - tree at (TREE_TYPE (a)); - int tc (TREE_CODE (at)); - - if (ar != 0 && tc != POINTER_TYPE) - return found_none; - - tree bt (ar != 0 || tc == REFERENCE_TYPE ? TREE_TYPE (at) : at); - tree bt_mv (TYPE_MAIN_VARIANT (bt)); - - if ((ar != 0 ? ar->base_type () : t).tree_node () != bt_mv) - return found_none; - } - - if (e.empty ()) - { - e.push_back (cxx_token (0, CPP_KEYWORD, "this")); - e.push_back (cxx_token (0, CPP_DOT)); - e.push_back (cxx_token (0, CPP_NAME, n)); - e.push_back (cxx_token (0, CPP_OPEN_PAREN, n)); - e.push_back (cxx_token (0, CPP_QUERY)); - e.push_back (cxx_token (0, CPP_CLOSE_PAREN, n)); - - // Continue searching in case there is version that returns a - // non-const reference which we prefer for efficiency. - // - return found_some; - } - else - return found_none; // We didn't find anything better. - } - - return found_none; - } - - void - process_access (semantics::data_member& m, std::string const& k) - { - bool virt (m.count ("virtual")); - - // Ignore certain special virtual members. - // - if (virt && (m.count ("polymorphic-ref") || m.count ("discriminator"))) - return; - - char const* kind (k == "get" ? "accessor" : "modifier"); - semantics::class_& c (dynamic_cast (m.scope ())); - - // If we don't have an access expression, try to come up with - // one. - // - if (!m.count (k)) - { - found_type found (found_none); - semantics::access const& a (m.named ().access ()); - member_access& ma (m.set (k, member_access (m.location (), true))); - - // If this member is not virtual and is either public or if we - // are a friend of this class, then go for the member directly. - // - if (!virt && (a == semantics::access::public_ || - c.get ("friend"))) - { - ma.expr.push_back (cxx_token (0, CPP_KEYWORD, "this")); - ma.expr.push_back (cxx_token (0, CPP_DOT)); - ma.expr.push_back (cxx_token (0, CPP_NAME, m.name ())); - found = found_best; - } - - // Otherwise, try to find a suitable accessor/modifier. - // - - // First try the original name. If that doesn't produce anything, - // then try the public name. - // - bool t (k == "get" - ? options.accessor_regex_trace () - : options.modifier_regex_trace ()); - regex_mapping const& re ( - k == "get" ? accessor_regex : modifier_regex); - - for (unsigned short j (0); found != found_best && j != 2; ++j) - { - string b (j == 0 ? m.name () : public_name (m, false)); - - // Skip the second pass if original and public names are the same. - // - if (j == 1 && b == m.name ()) - continue; - - if (t) - cerr << kind << (j == 0 ? " original" : " public") - << " name '" << b << "'" << endl; - - for (regex_mapping::const_iterator i (re.begin ()); - found != found_best && i != re.end (); - ++i) - { - if (t) - cerr << "try: '" << i->regex () << "' : "; - - if (!i->match (b)) - { - if (t) - cerr << '-' << endl; - continue; - } - - string n (i->replace (b)); - - if (t) - cerr << "'" << n << "' : "; - - tree decl ( - lookup_qualified_name ( - c.tree_node (), get_identifier (n.c_str ()), false, false)); - - if (decl == error_mark_node || TREE_CODE (decl) != BASELINK) - { - if (t) - cerr << '-' << endl; - continue; - } - - // OVL_* macros work for both FUNCTION_DECL and OVERLOAD. - // - for (tree o (BASELINK_FUNCTIONS (decl)); - o != 0; - o = OVL_NEXT (o)) - { - tree f (OVL_CURRENT (o)); - - // We are only interested in public non-static member - // functions. Note that TREE_PUBLIC() returns something - // other than what we need. - // - if (!DECL_NONSTATIC_MEMBER_FUNCTION_P (f) || - TREE_PRIVATE (f) || TREE_PROTECTED (f)) - continue; - - found_type r (k == "get" - ? check_accessor (m, f, n, ma, true) - : check_modifier (m, f, n, ma, true)); - - if (r != found_none) - { - // Update the location of the access expression to point - // to this function. - // - ma.loc = location (DECL_SOURCE_LOCATION (f)); - found = r; - } - } - - if (t) - cerr << (found != found_none ? '+' : '-') << endl; - } - } - - // If that didn't work then the generated code won't be able - // to access this member. - // - if (found == found_none) - { - location const& l (m.location ()); - - if (virt) - { - error (l) << "no suitable " << kind << " function could be " - << "automatically found for virtual data member '" - << m.name () << "'" << endl; - - info (l) << "use '#pragma db " << k << "' to explicitly " - << "specify the " << kind << " function or " - << "expression" << endl; - } - else - { - error (l) << "data member '" << m.name () << "' is " - << a.string () << " and no suitable " << kind - << " function could be automatically found" << endl; - info (l) << "consider making class 'odb::access' a friend of " - << "class '" << class_name (c) << "'" << endl; - - info (l) << "or use '#pragma db " << k << "' to explicitly " - << "specify the " << kind << " function or " - << "expression" << endl; - } - - throw operation_failed (); - } - } - - member_access& ma (m.get (k)); - cxx_tokens& e (ma.expr); - - // If it is just a name, resolve it and convert to an appropriate - // expression. - // - if (e.size () == 1 && e.back ().type == CPP_NAME) - { - string n (e.back ().literal); - e.clear (); - - tree decl ( - lookup_qualified_name ( - c.tree_node (), get_identifier (n.c_str ()), false, false)); - - if (decl == error_mark_node) - { - error (ma.loc) << "unable to resolve data member or function " - << "name '" << n << "'" << endl; - throw operation_failed (); - } - - switch (TREE_CODE (decl)) - { - case FIELD_DECL: - { - e.push_back (cxx_token (0, CPP_KEYWORD, "this")); - e.push_back (cxx_token (0, CPP_DOT)); - e.push_back (cxx_token (0, CPP_NAME, n)); - break; - } - case BASELINK: - { - // OVL_* macros work for both FUNCTION_DECL and OVERLOAD. - // - for (tree o (BASELINK_FUNCTIONS (decl)); - o != 0; - o = OVL_NEXT (o)) - { - tree f (OVL_CURRENT (o)); - - // We are only interested in non-static member functions. - // - if (!DECL_NONSTATIC_MEMBER_FUNCTION_P (f)) - continue; - - if ((k == "get" - ? check_accessor (m, f, n, ma, false) - : check_modifier (m, f, n, ma, false)) == found_best) - break; - } - - if (e.empty ()) - { - error (ma.loc) << "unable to find suitable " << kind - << " function '" << n << "'" << endl; - throw operation_failed (); - } - break; - } - default: - { - error (ma.loc) << "name '" << n << "' does not refer to a data " - << "member or function" << endl; - throw operation_failed (); - } - } - } - - // If there is no 'this' keyword, then add it as a prefix. - // - { - bool t (false); - for (cxx_tokens::iterator i (e.begin ()); i != e.end (); ++i) - { - if (i->type == CPP_KEYWORD && i->literal == "this") - { - t = true; - break; - } - } - - if (!t) - { - e.insert (e.begin (), cxx_token (0, CPP_DOT)); - e.insert (e.begin (), cxx_token (0, CPP_KEYWORD, "this")); - } - } - - // Check that there is no placeholder in the accessor expression. - // - if (k == "get" && ma.placeholder ()) - { - error (ma.loc) << "(?) placeholder in the accessor expression" - << endl; - throw operation_failed (); - } - - // Check that the member type is default-constructible if we - // have a by value modifier. - // - if (k == "set" && ma.placeholder ()) - { - semantics::class_* c (dynamic_cast (&utype (m))); - - // Assume all other types are default-constructible. - // - if (c != 0) - { - // If this type is a class template instantiation, then make - // sure it is instantiated. While types used in real members - // will be instantiated, this is not necessarily the case for - // virtual members. Without the instantiation we won't be able - // to detect whether the type has the default ctor. - // - // It would have been cleaner to do it in post_process_pragmas() - // but there we don't yet know whether we need the default ctor. - // And it is a good idea not to require instantiability unless - // we really need it. - // - tree type (c->tree_node ()); - - if (!COMPLETE_TYPE_P (type) && - CLASSTYPE_TEMPLATE_INSTANTIATION (type)) - { - // Reset input location so that we get nice diagnostics in - // case of an error. Use the location of the virtual pragma. - // - location_t loc (m.get ("virtual-location")); - input_location = loc; - - if (instantiate_class_template (type) == error_mark_node || - errorcount != 0 || - !COMPLETE_TYPE_P (type)) - { - error (loc) << "unable to instantiate virtual data member " << - "type" << endl; - throw operation_failed (); - } - } - - if (!c->default_ctor ()) - { - error (ma.loc) << "modifier expression requires member type " << - "to be default-constructible" << endl; - throw operation_failed (); - } - } - } + process_index (m); } // Convert index/unique specifiers to the index entry in the object. @@ -2351,44 +1868,7 @@ namespace relational struct class_: traversal::class_, context { class_ () - : std_string_ (0), std_string_hint_ (0), access_ (0) { - // Resolve the std::string type node. - // - using semantics::scope; - - for (scope::names_iterator_pair ip (unit.find ("std")); - ip.first != ip.second; ++ip.first) - { - if (scope* ns = dynamic_cast (&ip.first->named ())) - { - scope::names_iterator_pair jp (ns->find ("string")); - - if (jp.first != jp.second) - { - std_string_ = dynamic_cast ( - &jp.first->named ()); - std_string_hint_ = &*jp.first; - break; - } - } - } - - assert (std_string_ != 0); // No std::string? - - // Resolve odb::access, if any. - // - tree odb = lookup_qualified_name ( - global_namespace, get_identifier ("odb"), false, false); - - if (odb != error_mark_node) - { - access_ = lookup_qualified_name ( - odb, get_identifier ("access"), true, false); - - access_ = (access_ != error_mark_node ? TREE_TYPE (access_) : 0); - } - *this >> member_names_ >> member_; } @@ -2400,28 +1880,12 @@ namespace relational if (k == class_other) return; - // Check if odb::access is a friend of this class. - // - c.set ("friend", access_ != 0 && is_friend (c.tree_node (), access_)); - - // Assign pointer. - // - if (k == class_object || k == class_view) - assign_pointer (c); - - // Do some additional pre-processing. - // - if (k == class_object) - traverse_object_pre (c); - names (c); - // Do some additional post-processing. - // if (k == class_object) - traverse_object_post (c); + traverse_object (c); else if (k == class_view) - traverse_view_post (c); + traverse_view (c); } // @@ -2429,149 +1893,7 @@ namespace relational // virtual void - traverse_object_pre (type& c) - { - semantics::class_* poly_root (polymorphic (c)); - - // Determine whether it is a session object. - // - if (!c.count ("session")) - { - // If this is a derived class in a polymorphic hierarchy, - // then it should have the same session value as the root. - // - if (poly_root != 0 && poly_root != &c) - c.set ("session", session (*poly_root)); - else - { - // See if any of the namespaces containing this class specify - // the session value. - // - bool found (false); - for (semantics::scope* s (&c.scope ());; s = &s->scope_ ()) - { - using semantics::namespace_; - - namespace_* ns (dynamic_cast (s)); - - if (ns == 0) - continue; // Some other scope. - - if (ns->extension ()) - ns = &ns->original (); - - if (ns->count ("session")) - { - c.set ("session", ns->get ("session")); - found = true; - break; - } - - if (ns->global_scope ()) - break; - } - - // If still not found, then use the default value. - // - if (!found) - c.set ("session", options.generate_session ()); - } - } - - if (session (c)) - features.session_object = true; - - if (poly_root != 0) - { - using namespace semantics; - - semantics::data_member& idm (*id_member (*poly_root)); - - if (poly_root != &c) - { - // If we are a derived class in the polymorphic persistent - // 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::data_member& m ( - unit.new_node (f, l, col, tree (0))); - m.set ("virtual", true); - - // Make it the first member in the class. - // - node_position np (c, c.names_end ()); - unit.new_edge ( - np, m, idm.name (), access::public_); - - // Use the raw pointer as this member's type. - // - if (!poly_root->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 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 (m, poly_root->pointed ().pointer ()); - - m.set ("not-null", true); - m.set ("deferred", false); - m.set ("on-delete", sema_rel::foreign_key::cascade); - - // Mark it as a special kind of id. - // - m.set ("id", true); - m.set ("polymorphic-ref", true); - } - else - { - // If we are a root of the polymorphic persistent class hierarchy, - // then add a synthesized virtual member for the discriminator. - // Use the location of the polymorphic pragma as the location of - // this member. - // - location_t loc (c.get ("polymorphic-location")); - semantics::data_member& m ( - unit.new_node ( - path (LOCATION_FILE (loc)), - LOCATION_LINE (loc), - LOCATION_COLUMN (loc), - tree (0))); - m.set ("virtual", true); - - // Insert it after the id member (or first if this id comes - // from reuse-base). - // - node_position np ( - c, c.find (idm.named ())); - unit.new_edge ( - np, m, "typeid_", access::public_); - - belongs& edge (unit.new_edge (m, *std_string_)); - edge.hint (*std_string_hint_); - - m.set ("readonly", true); - m.set ("discriminator", true); - - c.set ("discriminator", &m); - } - } - } - - virtual void - traverse_object_post (type& c) + traverse_object (type& c) { // Process indexes. Here we need to do two things: resolve member // names to member paths and assign names to unnamed indexes. We @@ -2767,7 +2089,7 @@ namespace relational typedef vector relationships; virtual void - traverse_view_post (type& c) + traverse_view (type& c) { bool has_q (c.count ("query")); bool has_o (c.count ("objects")); @@ -3154,417 +2476,11 @@ namespace relational view_object& pointee_; }; - void - assign_pointer (type& c) - { - location_t loc (0); // Pragma location, or 0 if not used. - - try - { - string ptr; - string const& type (class_fq_name (c)); - - tree decl (0); // Resolved template node. - string decl_name; // User-provided template name. - tree resolve_scope (0); // Scope in which we resolve names. - - class_pointer const* cp (0); - bool cp_template (false); - - if (c.count ("pointer")) - { - cp = &c.get ("pointer"); - } - // If we are a derived type in polymorphic hierarchy, then use - // our root's pointer type by default. - // - else if (semantics::class_* r = polymorphic (c)) - { - if (&c != r && r->count ("pointer-template")) - cp = r->get ("pointer-template"); - } - - if (cp != 0) - { - string const& p (cp->name); - - if (p == "*") - { - ptr = type + "*"; - cp_template = true; - } - else if (p[p.size () - 1] == '*') - ptr = p; - else if (p.find ('<') != string::npos) - { - // Template-id. - // - ptr = p; - decl_name.assign (p, 0, p.find ('<')); - } - else - { - // This is not a template-id. Resolve it and see if it is a - // template or a type. - // - decl = resolve_name (p, cp->scope, true); - int tc (TREE_CODE (decl)); - - if (tc == TYPE_DECL) - { - ptr = p; - - // This can be a typedef'ed alias for a TR1 template-id. - // - if (tree ti = TYPE_TEMPLATE_INFO (TREE_TYPE (decl))) - { - decl = TI_TEMPLATE (ti); // DECL_TEMPLATE - - // Get to the most general template declaration. - // - while (DECL_TEMPLATE_INFO (decl)) - decl = DECL_TI_TEMPLATE (decl); - } - else - decl = 0; // Not a template. - } - else if (tc == TEMPLATE_DECL && DECL_CLASS_TEMPLATE_P (decl)) - { - ptr = p + "< " + type + " >"; - decl_name = p; - cp_template = true; - } - else - { - error (cp->loc) - << "name '" << p << "' specified with db pragma pointer " - << "does not name a type or a template" << endl; - - throw operation_failed (); - } - } - - // Resolve scope is the scope of the pragma. - // - resolve_scope = cp->scope; - loc = cp->loc; - } - else - { - // See if any of the namespaces containing this class specify - // a pointer. - // - for (semantics::scope* s (&c.scope ());; s = &s->scope_ ()) - { - using semantics::namespace_; - - namespace_* ns (dynamic_cast (s)); - - if (ns == 0) - continue; // Some other scope. - - if (ns->extension ()) - ns = &ns->original (); - - if (!ns->count ("pointer")) - { - if (ns->global_scope ()) - break; - else - continue; - } - - cp = &ns->get ("pointer"); - string const& p (cp->name); - - // Namespace-specified pointer can only be '*' or are template. - // - if (p == "*") - ptr = type + "*"; - else if (p[p.size () - 1] == '*') - { - error (cp->loc) - << "name '" << p << "' specified with db pragma pointer " - << "at namespace level cannot be a raw pointer" << endl; - } - else if (p.find ('<') != string::npos) - { - error (cp->loc) - << "name '" << p << "' specified with db pragma pointer " - << "at namespace level cannot be a template-id" << endl; - } - else - { - // Resolve this name and make sure it is a template. - // - decl = resolve_name (p, cp->scope, true); - int tc (TREE_CODE (decl)); - - if (tc == TEMPLATE_DECL && DECL_CLASS_TEMPLATE_P (decl)) - { - ptr = p + "< " + type + " >"; - decl_name = p; - } - else - { - error (cp->loc) - << "name '" << p << "' specified with db pragma pointer " - << "does not name a template" << endl; - } - } - - if (ptr.empty ()) - throw operation_failed (); - - cp_template = true; - - // Resolve scope is the scope of the pragma. - // - resolve_scope = cp->scope; - loc = cp->loc; - break; - } - - // Use the default pointer. - // - if (ptr.empty ()) - { - string const& p (options.default_pointer ()); - - if (p == "*") - ptr = type + "*"; - else - { - ptr = p + "< " + type + " >"; - decl_name = p; - } - - // Resolve scope is the scope of the class. - // - resolve_scope = c.scope ().tree_node (); - } - } - - // If this class is a root of a polymorphic hierarchy, then cache - // the pointer template so that we can use it for derived classes. - // - if (cp != 0 && cp_template && polymorphic (c) == &c) - c.set ("pointer-template", cp); - - // Check if we are using TR1. - // - if (decl != 0 || !decl_name.empty ()) - { - bool& tr1 (features.tr1_pointer); - bool& boost (features.boost_pointer); - - // First check the user-supplied name. - // - tr1 = tr1 - || decl_name.compare (0, 8, "std::tr1") == 0 - || decl_name.compare (0, 10, "::std::tr1") == 0; - - // If there was no match, also resolve the name since it can be - // a using-declaration for a TR1 template. - // - if (!tr1) - { - if (decl == 0) - decl = resolve_name (decl_name, resolve_scope, false); - - if (TREE_CODE (decl) != TEMPLATE_DECL || ! - DECL_CLASS_TEMPLATE_P (decl)) - { - // This is only checked for the --default-pointer option. - // - error (c.file (), c.line (), c.column ()) - << "name '" << decl_name << "' specified with the " - << "--default-pointer option does not name a class " - << "template" << endl; - - throw operation_failed (); - } - - string n (decl_as_string (decl, TFF_PLAIN_IDENTIFIER)); - - // In case of a boost TR1 implementation, we cannot distinguish - // between the boost:: and std::tr1:: usage since the latter is - // just a using-declaration for the former. - // - tr1 = tr1 - || n.compare (0, 8, "std::tr1") == 0 - || n.compare (0, 10, "::std::tr1") == 0; - - boost = boost - || n.compare (0, 17, "boost::shared_ptr") == 0 - || n.compare (0, 19, "::boost::shared_ptr") == 0; - } - } - - // Fully-qualify all the unqualified components of the name. - // - try - { - lex_.start (ptr); - ptr.clear (); - - string t; - bool punc (false); - bool scoped (false); - - for (cpp_ttype tt (lex_.next (t)); - tt != CPP_EOF; - tt = lex_.next (t)) - { - if (punc && tt > CPP_LAST_PUNCTUATOR) - ptr += ' '; - - punc = false; - - switch (static_cast (tt)) - { - case CPP_LESS: - { - ptr += "< "; - break; - } - case CPP_GREATER: - { - ptr += " >"; - break; - } - case CPP_COMMA: - { - ptr += ", "; - break; - } - case CPP_NAME: - { - // If the name was not preceeded with '::', look it - // up in the pragmas's scope and add the qualifer. - // - if (!scoped) - { - tree decl (resolve_name (t, resolve_scope, false)); - tree scope (CP_DECL_CONTEXT (decl)); - - if (scope != global_namespace) - { - ptr += "::"; - ptr += decl_as_string (scope, TFF_PLAIN_IDENTIFIER); - } - - ptr += "::"; - } - - ptr += t; - punc = true; - break; - } - case CPP_KEYWORD: - case CPP_NUMBER: - { - ptr += t; - punc = true; - break; - } - default: - { - ptr += t; - break; - } - } - - scoped = (tt == CPP_SCOPE); - } - } - catch (cxx_lexer::invalid_input const&) - { - throw operation_failed (); - } - - c.set ("object-pointer", ptr); - } - catch (invalid_name const& ex) - { - if (loc != 0) - error (loc) - << "name '" << ex.name () << "' specified with db pragma " - << "pointer is invalid" << endl; - else - error (c.file (), c.line (), c.column ()) - << "name '" << ex.name () << "' specified with the " - << "--default-pointer option is invalid" << endl; - - - throw operation_failed (); - } - catch (unable_to_resolve const& ex) - { - if (loc != 0) - error (loc) - << "unable to resolve name '" << ex.name () << "' specified " - << "with db pragma pointer" << endl; - else - error (c.file (), c.line (), c.column ()) - << "unable to resolve name '" << ex.name () << "' specified " - << "with the --default-pointer option" << endl; - - throw operation_failed (); - } - } - - private: - struct invalid_name - { - invalid_name (string const& n): name_ (n) {} - - string const& - name () const {return name_;} - - private: - string name_; - }; - - typedef lookup::unable_to_resolve unable_to_resolve; - - tree - resolve_name (string const& qn, tree scope, bool is_type) - { - try - { - string tl; - tree tn; - cpp_ttype tt, ptt; - - nlex_.start (qn); - tt = nlex_.next (tl, &tn); - - string name; - return lookup::resolve_scoped_name ( - nlex_, tt, tl, tn, ptt, scope, name, is_type); - } - catch (cxx_lexer::invalid_input const&) - { - throw invalid_name (qn); - } - catch (lookup::invalid_name const&) - { - throw invalid_name (qn); - } - } - private: cxx_string_lexer lex_; - cxx_string_lexer nlex_; // Nested lexer. data_member member_; traversal::names member_names_; - - semantics::type* std_string_; - semantics::names* std_string_hint_; - - tree access_; // odb::access node. }; } -- cgit v1.1