aboutsummaryrefslogtreecommitdiff
path: root/odb/type-processor.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2010-11-15 17:46:28 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2010-11-15 17:46:28 +0200
commit89a3b6133ade1ccb3a8e9ab9c86eac6aaef5db69 (patch)
tree394eb90c5acc9b55460bc7e4961cf791a60e397d /odb/type-processor.cxx
parent61acf05c698a8b611c5ccf6aed8d3e654d5acf8e (diff)
Add support for custom object pointers
New option: --default-pointer. New object pragma specifier: pointer.
Diffstat (limited to 'odb/type-processor.cxx')
-rw-r--r--odb/type-processor.cxx143
1 files changed, 142 insertions, 1 deletions
diff --git a/odb/type-processor.cxx b/odb/type-processor.cxx
index 5834e1f..b99cfb9 100644
--- a/odb/type-processor.cxx
+++ b/odb/type-processor.cxx
@@ -389,10 +389,151 @@ namespace
virtual void
traverse (type& c)
{
- if (!(c.count ("object") || comp_value (c)))
+ bool obj (c.count ("object"));
+
+ if (!(obj || comp_value (c)))
return;
names (c);
+
+ // Assign object pointer.
+ //
+ if (obj)
+ {
+ string ptr;
+ string const& name (c.fq_name ());
+
+ if (c.count ("pointer"))
+ {
+ string const& p (c.get<string> ("pointer"));
+
+ if (p == "*")
+ ptr = name + "*";
+ else if (p[p.size () - 1] == '*')
+ ptr = p;
+ else if (p.find ('<') != string::npos)
+ ptr = p;
+ else
+ {
+ // This is not a template-id. Resolve it and see if it is a
+ // template or a type.
+ //
+ try
+ {
+ tree t (resolve_type (p, c.scope ()));
+ int tc (TREE_CODE (t));
+
+ if (tc == TYPE_DECL)
+ ptr = p;
+ else if (tc == TEMPLATE_DECL && DECL_CLASS_TEMPLATE_P (t))
+ ptr = p + "< " + name + " >";
+ else
+ {
+ cerr << c.file () << ":" << c.line () << ":" << c.column ()
+ << ": error: name '" << p << "' specified with "
+ << "'#pragma object pointer' does not name a type "
+ << "or a template" << endl;
+
+ throw generation_failed ();
+ }
+ }
+ catch (invalid_name const&)
+ {
+ cerr << c.file () << ":" << c.line () << ":" << c.column ()
+ << ": error: type name '" << p << "' specified with "
+ << "'#pragma object pointer' is invalid" << endl;
+
+ throw generation_failed ();
+ }
+ catch (unable_to_resolve const&)
+ {
+ cerr << c.file () << ":" << c.line () << ":" << c.column ()
+ << ": error: unable to resolve type name '" << p
+ << "' specified with '#pragma object pointer'" << endl;
+
+ throw generation_failed ();
+ }
+ }
+ }
+ else
+ {
+ // Use the default pointer.
+ //
+ string const& p (options.default_pointer ());
+
+ if (p == "*")
+ ptr = name + "*";
+ else
+ ptr = p + "< " + name + " >";
+ }
+
+ c.set ("object-pointer", ptr);
+ }
+ }
+
+ private:
+ struct invalid_name {};
+ struct unable_to_resolve {};
+
+ tree
+ resolve_type (string const& qn, semantics::scope& ss)
+ {
+ tree scope (ss.tree_node ());
+
+ for (size_t b (0), e (qn.find (':')), size (qn.size ());;
+ e = qn.find (':', b))
+ {
+ bool last (e == string::npos);
+ string n (qn, b, last ? string::npos : e - b);
+
+ if (n.empty ())
+ {
+ if (b == 0)
+ scope = global_namespace;
+ else
+ throw invalid_name ();
+ }
+ else
+ {
+ tree nid (get_identifier (n.c_str ()));
+ scope = lookup_qualified_name (scope, nid, last, false);
+
+ // If this is the first component in the name, then also
+ // search the outer scopes.
+ //
+ if (scope == error_mark_node && b == 0 && !ss.global_scope ())
+ {
+ semantics::scope* s (&ss);
+ do
+ {
+ s = &s->scope_ ();
+ scope = lookup_qualified_name (
+ s->tree_node (), nid, last, false);
+ } while (scope == error_mark_node && !s->global_scope ());
+ }
+
+ if (scope == error_mark_node)
+ throw unable_to_resolve ();
+
+ if (!last && TREE_CODE (scope) == TYPE_DECL)
+ scope = TREE_TYPE (scope);
+ }
+
+ if (e == string::npos)
+ break;
+
+ if (qn[++e] != ':')
+ throw invalid_name ();
+
+ ++e; // Second ':'.
+
+ if (e == size)
+ break;
+
+ b = e;
+ }
+
+ return scope;
}
private: