aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2013-10-15 07:01:17 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2013-10-15 07:01:17 +0200
commita482f1c4dd4efab83d3b19309900f1cbf54383a5 (patch)
tree3c1ab27e420cbf760a54a1c4be61bbd0448a4873
parent400d258aab3722be3a4b8548870afad1574f3ad8 (diff)
Automatically map C++11 enum classes (strong enums)
-rw-r--r--NEWS4
-rw-r--r--doc/manual.xhtml138
-rw-r--r--odb/context.cxx15
-rw-r--r--odb/parser.cxx39
-rw-r--r--odb/relational/mssql/context.cxx9
-rw-r--r--odb/relational/mysql/context.cxx59
-rw-r--r--odb/relational/oracle/context.cxx9
-rw-r--r--odb/relational/pgsql/context.cxx9
-rw-r--r--odb/relational/sqlite/context.cxx9
-rw-r--r--odb/semantics/elements.hxx7
-rw-r--r--odb/semantics/enum.cxx21
-rw-r--r--odb/semantics/enum.hxx90
-rw-r--r--odb/semantics/fundamental.cxx68
-rw-r--r--odb/semantics/fundamental.hxx61
-rw-r--r--odb/traversal/enum.cxx21
-rw-r--r--odb/traversal/enum.hxx23
16 files changed, 439 insertions, 143 deletions
diff --git a/NEWS b/NEWS
index eb0a28f..0deac8f 100644
--- a/NEWS
+++ b/NEWS
@@ -10,6 +10,10 @@ Version 2.3.0
to Chapter 9, "Sections" in the ODB manual as well as the 'section'
example in the odb-examples package.
+ * Support for automatic mapping of C++11 enum classes in addition to the
+ "old" enums. For more information, refer to the ODB manual "Type Mapping"
+ sections for each database system.
+
* Support for pattern matching (SQL LIKE operator) in the C++-integrated
queries. For more information, refer to Section 4.1, "ODB Query Language"
in the ODB manual.
diff --git a/doc/manual.xhtml b/doc/manual.xhtml
index 79722db..9537121 100644
--- a/doc/manual.xhtml
+++ b/doc/manual.xhtml
@@ -15809,10 +15809,11 @@ class person
<p>Default values specified as enumerators are only supported for
members that are mapped to an <code>ENUM</code> or an integer
type in the database, which is the case for the automatic
- mapping of C++ enums to suitable database types as performed
- by the ODB compiler. If you have mapped a C++ enum to another
- database type, then you should use a literal corresponding
- to that type to specify the default value. For example:</p>
+ mapping of C++ enums and enum classes to suitable database
+ types as performed by the ODB compiler. If you have mapped
+ a C++ enum or enum class to another database type, then you
+ should use a literal corresponding to that type to specify
+ the default value. For example:</p>
<pre class="cxx">
enum gender {male, female, undisclosed};
@@ -18670,16 +18671,18 @@ person.hxx
to the <code>VARCHAR(255)</code> MySQL type. Otherwise,
it is mapped to <code>TEXT</code>.</p>
- <p>Additionally, by default, C++ enumerations are automatically
- mapped to a suitable MySQL type. Contiguous enumerations with
- the zero first enumerator are mapped to the MySQL <code>ENUM</code>
- type. All other enumerations are mapped to <code>INT</code> or
- <code>INT UNSIGNED</code>. In both cases the default <code>NULL</code>
- semantics is <code>NOT NULL</code>. For example:</p>
+ <p>Additionally, by default, C++ enums and C++11 enum classes are
+ automatically mapped to suitable MySQL types. Contiguous
+ enumerations with the zero first enumerator are mapped to
+ the MySQL <code>ENUM</code> type. All other enumerations
+ are mapped to the MySQL types corresponding to their
+ underlying integral types (see table above). In both
+ cases the default <code>NULL</code> semantics is
+ <code>NOT NULL</code>. For example:</p>
<pre class="cxx">
enum color {red, green, blue};
-enum taste
+enum class taste: unsigned char
{
bitter = 1, // Non-zero first enumerator.
sweet,
@@ -18693,7 +18696,7 @@ class object
...
color color_; // Mapped to ENUM ('red', 'green', 'blue') NOT NULL.
- taste taste_; // Mapped to INT UNSIGNED NOT NULL.
+ taste taste_; // Mapped to TINYNT UNSIGNED NOT NULL.
};
</pre>
@@ -19433,9 +19436,30 @@ class object
<code>db&nbsp;not_null</code> pragma (<a href="#14.4.6">Section
14.4.6, "<code>null/not_null</code>"</a>).</p>
- <p>Additionally, by default, C++ enumerations are automatically mapped to
- the SQLite <code>INTEGER</code> type with the default <code>NULL</code>
- semantics being <code>NOT NULL</code>.</p>
+ <p>Additionally, by default, C++ enums and C++11 enum classes are
+ automatically mapped to the SQLite <code>INTEGER</code> type with
+ the default <code>NULL</code> semantics being <code>NOT NULL</code>.
+ For example:</p>
+
+ <pre class="cxx">
+enum color {red, green, blue};
+enum class taste: unsigned char
+{
+ bitter = 1,
+ sweet,
+ sour = 4,
+ salty
+};
+
+#pragma db object
+class object
+{
+ ...
+
+ color color_; // Automatically mapped to INTEGER.
+ taste taste_; // Automatically mapped to INTEGER.
+};
+ </pre>
<p>Note also that SQLite only operates with signed integers and the largest
value that an SQLite database can store is a signed 64-bit integer. As
@@ -20406,9 +20430,31 @@ class object
<code>db&nbsp;type</code> pragma (<a href="#14.4.3">Section 14.4.3,
"<code>type</code>"</a>).</p>
- <p>Additionally, by default, C++ enumerations are automatically
- mapped to <code>INTEGER</code> with the default <code>NULL</code>
- semantics being <code>NOT NULL</code>.</p>
+ <p>Additionally, by default, C++ enums and C++11 enum classes are
+ automatically mapped to the PostgreSQL types corresponding to their
+ underlying integral types (see table above). The default
+ <code>NULL</code> semantics is <code>NOT NULL</code>. For
+ example:</p>
+
+ <pre class="cxx">
+enum color {red, green, blue};
+enum class taste: unsigned char
+{
+ bitter = 1,
+ sweet,
+ sour = 4,
+ salty
+};
+
+#pragma db object
+class object
+{
+ ...
+
+ color color_; // Automatically mapped to INTEGER.
+ taste taste_; // Automatically mapped to SMALLINT.
+};
+ </pre>
<p>Note also that because PostgreSQL does not support unsigned integers,
the <code>unsigned&nbsp;short</code>, <code>unsigned&nbsp;int</code>, and
@@ -21174,9 +21220,31 @@ class object
object ids that are mapped to these Oracle types, an empty string is
an invalid value.</p>
- <p>Additionally, by default, C++ enumerations are automatically
- mapped to <code>NUMBER(10)</code> with the default <code>NULL</code>
- semantics being <code>NOT NULL</code>.</p>
+ <p>Additionally, by default, C++ enums and C++11 enum classes are
+ automatically mapped to the Oracle types corresponding to their
+ underlying integral types (see table above). The default
+ <code>NULL</code> semantics is <code>NOT NULL</code>. For
+ example:</p>
+
+ <pre class="cxx">
+enum color {red, green, blue};
+enum class taste: unsigned char
+{
+ bitter = 1,
+ sweet,
+ sour = 4,
+ salty
+};
+
+#pragma db object
+class object
+{
+ ...
+
+ color color_; // Automatically mapped to NUMBER(10).
+ taste taste_; // Automatically mapped to NUMBER(3).
+};
+ </pre>
<p>It is also possible to add support for additional Oracle types,
such as <code>XML</code>, geospatial types, user-defined types,
@@ -22114,9 +22182,31 @@ class object
always change this mapping using the <code>db&nbsp;type</code> pragma
(<a href="#14.4.3">Section 14.4.3, "<code>type</code>"</a>).</p>
- <p>Additionally, by default, C++ enumerations are automatically
- mapped to <code>INT</code> with the default <code>NULL</code>
- semantics being <code>NOT NULL</code>.</p>
+ <p>Additionally, by default, C++ enums and C++11 enum classes are
+ automatically mapped to the SQL Server types corresponding to their
+ underlying integral types (see table above). The default
+ <code>NULL</code> semantics is <code>NOT NULL</code>. For
+ example:</p>
+
+ <pre class="cxx">
+enum color {red, green, blue};
+enum class taste: unsigned char
+{
+ bitter = 1,
+ sweet,
+ sour = 4,
+ salty
+};
+
+#pragma db object
+class object
+{
+ ...
+
+ color color_; // Automatically mapped to INT.
+ taste taste_; // Automatically mapped to TINYINT.
+};
+ </pre>
<p>Note also that because SQL Server does not support unsigned integers,
the <code>unsigned&nbsp;short</code>, <code>unsigned&nbsp;int</code>, and
diff --git a/odb/context.cxx b/odb/context.cxx
index 4db15a0..352cb51 100644
--- a/odb/context.cxx
+++ b/odb/context.cxx
@@ -1926,16 +1926,25 @@ database_type_impl (semantics::type& t,
bool id,
bool* null)
{
- type_map_type::const_iterator i (data_->type_map_.find (t, hint));
+ using semantics::enum_;
+
+ // By default map an enum as its underlying type.
+ //
+ if (enum_* e = dynamic_cast<enum_*> (&t))
+ return database_type_impl (
+ e->underlying_type (), e->underlying_type_hint (), id, null);
+ // Built-in type mapping.
+ //
+ type_map_type::const_iterator i (data_->type_map_.find (t, hint));
if (i != data_->type_map_.end ())
{
if (null != 0)
*null = i->second.null;
return id ? i->second.id_type : i->second.type;
}
- else
- return string ();
+
+ return string ();
}
static string
diff --git a/odb/parser.cxx b/odb/parser.cxx
index 14dd81a..140e09e 100644
--- a/odb/parser.cxx
+++ b/odb/parser.cxx
@@ -746,7 +746,7 @@ parse (tree global_scope, path const& main_file)
define_fund<fund_char> (char_type_node);
define_fund<fund_wchar> (wchar_type_node);
- if (ops_.std () == cxx_version::cxx11)
+ if (ops_.std () >= cxx_version::cxx11)
{
define_fund<fund_char16> (char16_type_node);
define_fund<fund_char32> (char32_type_node);
@@ -1422,8 +1422,29 @@ emit_enum (tree e,
e_node = &dynamic_cast<enum_&> (*n);
else
{
- e_node = &unit_->new_node<enum_> (
- file, line, clmn, e, TYPE_UNSIGNED (e) != 0);
+ e_node = &unit_->new_node<enum_> (file, line, clmn, e);
+
+ // Set the underlying type even for incomplete (forward-declared) enums.
+ //
+ tree ut (ENUM_UNDERLYING_TYPE (e));
+ names* hint (unit_->find_hint (ut));
+ integral_type* un = dynamic_cast<integral_type*> (
+ unit_->find (TYPE_MAIN_VARIANT (ut)));
+
+ // For "old" enums GCC creates a distinct type node and the only way to
+ // get to one of the known integrals is via its name.
+ //
+ if (un == 0)
+ {
+ ut = TREE_TYPE (TYPE_NAME (ut));
+ un = dynamic_cast<integral_type*> (unit_->find (TYPE_MAIN_VARIANT (ut)));
+ }
+
+ underlies& edge (unit_->new_edge<underlies> (*un, *e_node));
+
+ if (hint != 0)
+ edge.hint (*hint);
+
unit_->insert (e, *e_node);
}
@@ -1459,9 +1480,17 @@ emit_enum (tree e,
unit_->new_edge<enumerates> (*e_node, er_node);
unit_->insert (decl, er_node);
- // Inject enumerators into the outer scope.
+ // In C++11 the enumerators are always available in the enum's
+ // scope, even for old enums.
+ //
+ if (ops_.std () >= cxx_version::cxx11)
+ unit_->new_edge<names> (*e_node, er_node, name, access::public_);
+
+ // Inject enumerators into the outer scope unless this is an
+ // enum class.
//
- unit_->new_edge<names> (*scope_, er_node, name, access);
+ if (UNSCOPED_ENUM_P (e))
+ unit_->new_edge<names> (*scope_, er_node, name, access);
if (trace)
ts << "\tenumerator " << name << " at " << file << ":" << line << endl;
diff --git a/odb/relational/mssql/context.cxx b/odb/relational/mssql/context.cxx
index 1df235d..a0037eb 100644
--- a/odb/relational/mssql/context.cxx
+++ b/odb/relational/mssql/context.cxx
@@ -156,18 +156,11 @@ namespace relational
if (!r.empty ())
return r;
- using semantics::enum_;
using semantics::array;
- // Enum mapping.
- //
- if (t.is_a<semantics::enum_> ())
- {
- r = "INT";
- }
// char[N] mapping.
//
- else if (array* a = dynamic_cast<array*> (&t))
+ if (array* a = dynamic_cast<array*> (&t))
{
semantics::type& bt (a->base_type ());
bool c (bt.is_a<semantics::fund_char> ());
diff --git a/odb/relational/mysql/context.cxx b/odb/relational/mysql/context.cxx
index 75b71e9..55dd4f7 100644
--- a/odb/relational/mysql/context.cxx
+++ b/odb/relational/mysql/context.cxx
@@ -286,15 +286,12 @@ namespace relational
bool id,
bool* null)
{
- string r (base_context::database_type_impl (t, hint, id, null));
-
- if (!r.empty ())
- return r;
-
using semantics::enum_;
using semantics::enumerator;
using semantics::array;
+ string r;
+
// Enum mapping.
//
if (enum_* e = dynamic_cast<enum_*> (&t))
@@ -302,43 +299,41 @@ namespace relational
// We can only map to ENUM if the C++ enumeration is contiguous
// and starts with 0.
//
- if (e->unsigned_ ())
+ enum_::enumerates_iterator i (e->enumerates_begin ()),
+ end (e->enumerates_end ());
+
+ if (i != end)
{
- enum_::enumerates_iterator i (e->enumerates_begin ()),
- end (e->enumerates_end ());
+ r += "ENUM(";
- if (i != end)
+ for (unsigned long long j (0); i != end; ++i, ++j)
{
- r += "ENUM(";
-
- for (unsigned long long j (0); i != end; ++i, ++j)
- {
- enumerator const& er (i->enumerator ());
+ enumerator const& er (i->enumerator ());
- if (er.value () != j)
- break;
-
- if (j != 0)
- r += ", ";
+ if (er.value () != j)
+ break;
- r += quote_string (er.name ());
- }
+ if (j != 0)
+ r += ", ";
- if (i == end)
- r += ")";
- else
- r.clear ();
+ r += quote_string (er.name ());
}
- }
-
- if (r.empty ())
- {
- r = "INT";
- if (e->unsigned_ ())
- r += " UNSIGNED";
+ if (i == end)
+ r += ")";
+ else
+ r.clear ();
}
+
+ if (!r.empty ())
+ return r;
}
+
+ r = base_context::database_type_impl (t, hint, id, null);
+
+ if (!r.empty ())
+ return r;
+
// char[N] mapping.
//
else if (array* a = dynamic_cast<array*> (&t))
diff --git a/odb/relational/oracle/context.cxx b/odb/relational/oracle/context.cxx
index f885564..98cda52 100644
--- a/odb/relational/oracle/context.cxx
+++ b/odb/relational/oracle/context.cxx
@@ -152,18 +152,11 @@ namespace relational
if (!r.empty ())
return r;
- using semantics::enum_;
using semantics::array;
- // Enum mapping.
- //
- if (t.is_a<semantics::enum_> ())
- {
- r = "NUMBER(10)";
- }
// char[N] mapping.
//
- else if (array* a = dynamic_cast<array*> (&t))
+ if (array* a = dynamic_cast<array*> (&t))
{
semantics::type& bt (a->base_type ());
if (bt.is_a<semantics::fund_char> ())
diff --git a/odb/relational/pgsql/context.cxx b/odb/relational/pgsql/context.cxx
index 947c6bd..d09fa2c 100644
--- a/odb/relational/pgsql/context.cxx
+++ b/odb/relational/pgsql/context.cxx
@@ -252,18 +252,11 @@ namespace relational
if (!r.empty ())
return r;
- using semantics::enum_;
using semantics::array;
- // Enum mapping.
- //
- if (t.is_a<semantics::enum_> ())
- {
- r = "INTEGER";
- }
// char[N] mapping.
//
- else if (array* a = dynamic_cast<array*> (&t))
+ if (array* a = dynamic_cast<array*> (&t))
{
semantics::type& bt (a->base_type ());
if (bt.is_a<semantics::fund_char> ())
diff --git a/odb/relational/sqlite/context.cxx b/odb/relational/sqlite/context.cxx
index 664af35..f347d30 100644
--- a/odb/relational/sqlite/context.cxx
+++ b/odb/relational/sqlite/context.cxx
@@ -242,18 +242,11 @@ namespace relational
if (!r.empty ())
return r;
- using semantics::enum_;
using semantics::array;
- // Enum mapping.
- //
- if (t.is_a<semantics::enum_> ())
- {
- r = "INTEGER";
- }
// char[N] mapping.
//
- else if (array* a = dynamic_cast<array*> (&t))
+ if (array* a = dynamic_cast<array*> (&t))
{
semantics::type& bt (a->base_type ());
if (bt.is_a<semantics::fund_char> () ||
diff --git a/odb/semantics/elements.hxx b/odb/semantics/elements.hxx
index 1199c0c..059b639 100644
--- a/odb/semantics/elements.hxx
+++ b/odb/semantics/elements.hxx
@@ -178,9 +178,10 @@ namespace semantics
// edges.
//
void
- add_edge_right (edge&)
- {
- }
+ add_edge_left (edge&) {}
+
+ void
+ add_edge_right (edge&) {}
protected:
// For virtual inheritance. Should never be actually called.
diff --git a/odb/semantics/enum.cxx b/odb/semantics/enum.cxx
index 7cffe30..dd8b905 100644
--- a/odb/semantics/enum.cxx
+++ b/odb/semantics/enum.cxx
@@ -22,13 +22,18 @@ namespace semantics
{
}
+ underlies::
+ underlies ()
+ : type_ (0), enum__ (0), hint_ (0)
+ {
+ }
+
enum_::
enum_ (path const& file,
size_t line,
size_t column,
- tree tn,
- bool unsigned_)
- : node (file, line, column, tn), unsigned__ (unsigned_)
+ tree tn)
+ : node (file, line, column, tn)
{
}
@@ -54,15 +59,25 @@ namespace semantics
//
{
type_info ti (typeid (enumerator));
+ ti.add_base (typeid (nameable));
ti.add_base (typeid (instance));
insert (ti);
}
+ // underlies
+ //
+ {
+ type_info ti (typeid (underlies));
+ ti.add_base (typeid (edge));
+ insert (ti);
+ }
+
// enum_
//
{
type_info ti (typeid (enum_));
ti.add_base (typeid (type));
+ ti.add_base (typeid (scope));
insert (ti);
}
}
diff --git a/odb/semantics/enum.hxx b/odb/semantics/enum.hxx
index de07885..02f2b27 100644
--- a/odb/semantics/enum.hxx
+++ b/odb/semantics/enum.hxx
@@ -7,6 +7,7 @@
#include <vector>
#include <odb/semantics/elements.hxx>
+#include <odb/semantics/fundamental.hxx>
namespace semantics
{
@@ -101,7 +102,62 @@ namespace semantics
//
//
- class enum_: public type
+ class underlies: public edge
+ {
+ public:
+ typedef semantics::enum_ enum_type;
+
+ integral_type&
+ type () const
+ {
+ return *type_;
+ }
+
+ enum_type&
+ enum_ () const
+ {
+ return *enum__;
+ }
+
+ // Names edge in terms of which this edge was defined. Can be NULL.
+ //
+ public:
+ void
+ hint (names& hint)
+ {
+ hint_ = &hint;
+ }
+
+ names*
+ hint () const
+ {
+ return hint_;
+ }
+
+ public:
+ underlies ();
+
+ void
+ set_left_node (integral_type& n)
+ {
+ type_ = &n;
+ }
+
+ void
+ set_right_node (enum_type& n)
+ {
+ enum__ = &n;
+ }
+
+ protected:
+ integral_type* type_;
+ enum_type* enum__;
+ names* hint_;
+ };
+
+ //
+ //
+ class enum_: public type, public scope
{
private:
typedef std::vector<enumerates*> enumerates_list;
@@ -123,14 +179,38 @@ namespace semantics
return enumerates_.end ();
}
+ underlies&
+ underlied () const
+ {
+ return *underlied_;
+ }
+
+ integral_type&
+ underlying_type () const
+ {
+ return underlied_->type ();
+ }
+
+ names*
+ underlying_type_hint () const
+ {
+ return underlied_->hint ();
+ }
+
bool
unsigned_ () const
{
- return unsigned__;
+ return underlying_type ().unsigned_ ();
}
public:
- enum_ (path const&, size_t line, size_t column, tree, bool unsigned_);
+ enum_ (path const&, size_t line, size_t column, tree);
+
+ void
+ add_edge_right (underlies& e)
+ {
+ underlied_ = &e;
+ }
void
add_edge_left (enumerates& e)
@@ -138,9 +218,11 @@ namespace semantics
enumerates_.push_back (&e);
}
+ using scope::add_edge_left;
+
private:
- bool unsigned__;
enumerates_list enumerates_;
+ underlies* underlied_;
};
}
diff --git a/odb/semantics/fundamental.cxx b/odb/semantics/fundamental.cxx
index 537a5cf..4a3bd69 100644
--- a/odb/semantics/fundamental.cxx
+++ b/odb/semantics/fundamental.cxx
@@ -2,6 +2,8 @@
// copyright : Copyright (c) 2009-2013 Code Synthesis Tools CC
// license : GNU GPL v3; see accompanying LICENSE file
+#include <odb/gcc.hxx>
+
#include <cutl/compiler/type-info.hxx>
#include <odb/semantics/fundamental.hxx>
@@ -22,6 +24,22 @@ namespace semantics
return type::fq_name (hint);
}
+ // char
+ //
+ bool fund_char::
+ unsigned_ () const
+ {
+ return TYPE_UNSIGNED (tree_node ()) != 0;
+ }
+
+ // wchar_t
+ //
+ bool fund_wchar::
+ unsigned_ () const
+ {
+ return TYPE_UNSIGNED (tree_node ()) != 0;
+ }
+
// type info
//
namespace
@@ -48,11 +66,19 @@ namespace semantics
insert (ti);
}
+ // integral_type
+ //
+ {
+ type_info ti (typeid (integral_type));
+ ti.add_base (typeid (fund_type));
+ insert (ti);
+ }
+
// fund_bool
//
{
type_info ti (typeid (fund_bool));
- ti.add_base (typeid (fund_type));
+ ti.add_base (typeid (integral_type));
insert (ti);
}
@@ -60,7 +86,7 @@ namespace semantics
//
{
type_info ti (typeid (fund_char));
- ti.add_base (typeid (fund_type));
+ ti.add_base (typeid (integral_type));
insert (ti);
}
@@ -68,7 +94,23 @@ namespace semantics
//
{
type_info ti (typeid (fund_wchar));
- ti.add_base (typeid (fund_type));
+ ti.add_base (typeid (integral_type));
+ insert (ti);
+ }
+
+ // fund_char16
+ //
+ {
+ type_info ti (typeid (fund_char16));
+ ti.add_base (typeid (integral_type));
+ insert (ti);
+ }
+
+ // fund_char32
+ //
+ {
+ type_info ti (typeid (fund_char32));
+ ti.add_base (typeid (integral_type));
insert (ti);
}
@@ -76,7 +118,7 @@ namespace semantics
//
{
type_info ti (typeid (fund_signed_char));
- ti.add_base (typeid (fund_type));
+ ti.add_base (typeid (integral_type));
insert (ti);
}
@@ -84,7 +126,7 @@ namespace semantics
//
{
type_info ti (typeid (fund_unsigned_char));
- ti.add_base (typeid (fund_type));
+ ti.add_base (typeid (integral_type));
insert (ti);
}
@@ -92,7 +134,7 @@ namespace semantics
//
{
type_info ti (typeid (fund_short));
- ti.add_base (typeid (fund_type));
+ ti.add_base (typeid (integral_type));
insert (ti);
}
@@ -100,7 +142,7 @@ namespace semantics
//
{
type_info ti (typeid (fund_unsigned_short));
- ti.add_base (typeid (fund_type));
+ ti.add_base (typeid (integral_type));
insert (ti);
}
@@ -108,7 +150,7 @@ namespace semantics
//
{
type_info ti (typeid (fund_int));
- ti.add_base (typeid (fund_type));
+ ti.add_base (typeid (integral_type));
insert (ti);
}
@@ -116,7 +158,7 @@ namespace semantics
//
{
type_info ti (typeid (fund_unsigned_int));
- ti.add_base (typeid (fund_type));
+ ti.add_base (typeid (integral_type));
insert (ti);
}
@@ -124,7 +166,7 @@ namespace semantics
//
{
type_info ti (typeid (fund_long));
- ti.add_base (typeid (fund_type));
+ ti.add_base (typeid (integral_type));
insert (ti);
}
@@ -132,7 +174,7 @@ namespace semantics
//
{
type_info ti (typeid (fund_unsigned_long));
- ti.add_base (typeid (fund_type));
+ ti.add_base (typeid (integral_type));
insert (ti);
}
@@ -140,7 +182,7 @@ namespace semantics
//
{
type_info ti (typeid (fund_long_long));
- ti.add_base (typeid (fund_type));
+ ti.add_base (typeid (integral_type));
insert (ti);
}
@@ -148,7 +190,7 @@ namespace semantics
//
{
type_info ti (typeid (fund_unsigned_long_long));
- ti.add_base (typeid (fund_type));
+ ti.add_base (typeid (integral_type));
insert (ti);
}
diff --git a/odb/semantics/fundamental.hxx b/odb/semantics/fundamental.hxx
index 55ce322..75cbbf5 100644
--- a/odb/semantics/fundamental.hxx
+++ b/odb/semantics/fundamental.hxx
@@ -13,7 +13,7 @@ namespace semantics
// Fundamental C++ types.
//
- struct fund_type: public type
+ struct fund_type: type
{
virtual string
fq_name () const;
@@ -27,84 +27,105 @@ namespace semantics
fund_void (tree tn): node (path ("<fundamental>"), 0, 0, tn) {}
};
- struct fund_bool: fund_type
- {
- fund_bool (tree tn): node (path ("<fundamental>"), 0, 0, tn) {}
- };
-
//
// Integral.
//
- struct fund_char: fund_type
+ struct integral_type: fund_type
+ {
+ virtual bool
+ unsigned_ () const = 0;
+ };
+
+ struct fund_bool: integral_type
+ {
+ fund_bool (tree tn): node (path ("<fundamental>"), 0, 0, tn) {}
+ virtual bool unsigned_ () const {return true;}
+ };
+
+ struct fund_char: integral_type
{
fund_char (tree tn): node (path ("<fundamental>"), 0, 0, tn) {}
+ virtual bool unsigned_ () const;
};
- struct fund_wchar: fund_type
+ struct fund_wchar: integral_type
{
fund_wchar (tree tn): node (path ("<fundamental>"), 0, 0, tn) {}
+ virtual bool unsigned_ () const;
};
- struct fund_char16: fund_type
+ struct fund_char16: integral_type
{
fund_char16 (tree tn): node (path ("<fundamental>"), 0, 0, tn) {}
+ virtual bool unsigned_ () const {return true;}
};
- struct fund_char32: fund_type
+ struct fund_char32: integral_type
{
fund_char32 (tree tn): node (path ("<fundamental>"), 0, 0, tn) {}
+ virtual bool unsigned_ () const {return true;}
};
- struct fund_signed_char: fund_type
+ struct fund_signed_char: integral_type
{
fund_signed_char (tree tn): node (path ("<fundamental>"), 0, 0, tn) {}
+ virtual bool unsigned_ () const {return false;}
};
- struct fund_unsigned_char: fund_type
+ struct fund_unsigned_char: integral_type
{
fund_unsigned_char (tree tn): node (path ("<fundamental>"), 0, 0, tn) {}
+ virtual bool unsigned_ () const {return true;}
};
- struct fund_short: fund_type
+ struct fund_short: integral_type
{
fund_short (tree tn): node (path ("<fundamental>"), 0, 0, tn) {}
+ virtual bool unsigned_ () const {return false;}
};
- struct fund_unsigned_short: fund_type
+ struct fund_unsigned_short: integral_type
{
fund_unsigned_short (tree tn): node (path ("<fundamental>"), 0, 0, tn) {}
+ virtual bool unsigned_ () const {return true;}
};
- struct fund_int: fund_type
+ struct fund_int: integral_type
{
fund_int (tree tn): node (path ("<fundamental>"), 0, 0, tn) {}
+ virtual bool unsigned_ () const {return false;}
};
- struct fund_unsigned_int: fund_type
+ struct fund_unsigned_int: integral_type
{
fund_unsigned_int (tree tn): node (path ("<fundamental>"), 0, 0, tn) {}
+ virtual bool unsigned_ () const {return true;}
};
- struct fund_long: fund_type
+ struct fund_long: integral_type
{
fund_long (tree tn): node (path ("<fundamental>"), 0, 0, tn) {}
+ virtual bool unsigned_ () const {return false;}
};
- struct fund_unsigned_long: fund_type
+ struct fund_unsigned_long: integral_type
{
fund_unsigned_long (tree tn): node (path ("<fundamental>"), 0, 0, tn) {}
+ virtual bool unsigned_ () const {return true;}
};
- struct fund_long_long: fund_type
+ struct fund_long_long: integral_type
{
fund_long_long (tree tn): node (path ("<fundamental>"), 0, 0, tn) {}
+ virtual bool unsigned_ () const {return false;}
};
- struct fund_unsigned_long_long: fund_type
+ struct fund_unsigned_long_long: integral_type
{
fund_unsigned_long_long (tree tn)
: node (path ("<fundamental>"), 0, 0, tn) {}
+ virtual bool unsigned_ () const {return true;}
};
//
diff --git a/odb/traversal/enum.cxx b/odb/traversal/enum.cxx
index 149f962..fd4ff89 100644
--- a/odb/traversal/enum.cxx
+++ b/odb/traversal/enum.cxx
@@ -14,13 +14,34 @@ namespace traversal
//
//
+ void underlies::
+ traverse (type& u)
+ {
+ dispatch (u.type ());
+ }
+
+ //
+ //
void enum_::
traverse (type& e)
{
+ underlied (e);
enumerates (e);
}
void enum_::
+ underlied (type& e)
+ {
+ underlied (e, *this);
+ }
+
+ void enum_::
+ underlied (type& e, edge_dispatcher& d)
+ {
+ d.dispatch (e.underlied ());
+ }
+
+ void enum_::
enumerates (type& e)
{
enumerates (e, *this);
diff --git a/odb/traversal/enum.hxx b/odb/traversal/enum.hxx
index 1efccaa..c949934 100644
--- a/odb/traversal/enum.hxx
+++ b/odb/traversal/enum.hxx
@@ -12,10 +12,7 @@ namespace traversal
{
struct enumerates: edge<semantics::enumerates>
{
- enumerates ()
- {
- }
-
+ enumerates () {}
enumerates (node_dispatcher& n)
{
node_traverser (n);
@@ -27,12 +24,30 @@ namespace traversal
struct enumerator: node<semantics::enumerator> {};
+ struct underlies: edge<semantics::underlies>
+ {
+ underlies () {}
+ underlies (node_dispatcher& n)
+ {
+ node_traverser (n);
+ }
+
+ virtual void
+ traverse (type&);
+ };
+
struct enum_: node<semantics::enum_>
{
virtual void
traverse (type&);
virtual void
+ underlied (type&);
+
+ virtual void
+ underlied (type&, edge_dispatcher&);
+
+ virtual void
enumerates (type&);
virtual void