aboutsummaryrefslogtreecommitdiff
path: root/odb
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2015-07-17 12:53:58 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2015-07-17 12:53:58 +0200
commitfa8b674ef4cb32cb92bcc4f3d42bf24b8cf3b7fb (patch)
treefee686936eb4150208e58ee81164931199c79e0e /odb
parent8f6a9c51bc64226d7c296e4b0172f9e56a7eea3b (diff)
Diagnose "composite type used before definition" situations
Diffstat (limited to 'odb')
-rw-r--r--odb/context.cxx23
-rw-r--r--odb/context.hxx6
-rw-r--r--odb/semantics/elements.cxx17
-rw-r--r--odb/semantics/elements.hxx3
-rw-r--r--odb/validator.cxx86
5 files changed, 100 insertions, 35 deletions
diff --git a/odb/context.cxx b/odb/context.cxx
index 59058ba..6dcf987 100644
--- a/odb/context.cxx
+++ b/odb/context.cxx
@@ -1335,18 +1335,17 @@ class_file (semantics::class_& c)
location_t context::
class_location (semantics::class_& c)
{
- if (c.count ("definition"))
- {
- return c.get<location_t> ("definition");
- }
- else if (c.is_a<semantics::class_instantiation> ())
- {
- return c.get<location_t> ("location");
- }
- else
- {
- return real_source_location (TYPE_NAME (c.tree_node ()));
- }
+ return c.count ("definition")
+ ? c.get<location_t> ("definition")
+ : class_real_location (c);
+}
+
+location_t context::
+class_real_location (semantics::class_& c)
+{
+ return c.is_a<semantics::class_instantiation> ()
+ ? c.get<location_t> ("location")
+ : real_source_location (TYPE_NAME (c.tree_node ()));
}
string context::
diff --git a/odb/context.hxx b/odb/context.hxx
index 6398a5f..7032dcf 100644
--- a/odb/context.hxx
+++ b/odb/context.hxx
@@ -1290,6 +1290,12 @@ public:
location_t
class_location (semantics::class_&);
+ // Same as above, but returns "real" location, that is, ignoring
+ // the definition point overrides.
+ //
+ location_t
+ class_real_location (semantics::class_&);
+
// Database names and types.
//
public:
diff --git a/odb/semantics/elements.cxx b/odb/semantics/elements.cxx
index 21e3260..43fb379 100644
--- a/odb/semantics/elements.cxx
+++ b/odb/semantics/elements.cxx
@@ -48,6 +48,23 @@ namespace semantics
//
bool nameable::
+ in_scope (scope_type& s)
+ {
+ for (scope_type* p (&scope ());; p = &p->scope_ ())
+ {
+ //@@ Need to handle namespace extensions.
+ //
+ if (p == &s)
+ return true;
+
+ if (p->global_scope ())
+ break;
+ }
+
+ return false;
+ }
+
+ bool nameable::
anonymous_ () const
{
tree n (tree_node ());
diff --git a/odb/semantics/elements.hxx b/odb/semantics/elements.hxx
index d0156dd..615bb93 100644
--- a/odb/semantics/elements.hxx
+++ b/odb/semantics/elements.hxx
@@ -433,6 +433,9 @@ namespace semantics
return defined_ != 0 ? *defined_ : *named_[0];
}
+ bool
+ in_scope (scope_type&);
+
public:
nameable ()
: defined_ (0)
diff --git a/odb/validator.cxx b/odb/validator.cxx
index c1d82c6..6384d83 100644
--- a/odb/validator.cxx
+++ b/odb/validator.cxx
@@ -1072,13 +1072,66 @@ namespace
{
data_member2 (bool& valid): valid_ (valid) {}
+ // Verify that composite value 'c' that is used by data member
+ // 'm' is defined before (or inside) class 's'.
+ //
+ void
+ verify_composite_location (semantics::class_& c,
+ semantics::class_& s,
+ semantics::data_member& m)
+ {
+ if (c.in_scope (s))
+ return;
+
+ location_t cl;
+ location_t sl;
+
+ // If we are in the same file, then use real locations (as
+ // opposed to definition locations) since that's the order
+ // in which we will be generating the code.
+ //
+ if (class_file (c) == class_file (s))
+ {
+ cl = class_real_location (c);
+ sl = class_real_location (s);
+ }
+ else
+ {
+ cl = class_location (c);
+ sl = class_location (s);
+ }
+
+ if (sl < cl)
+ {
+ const string& cn (class_name (c));
+
+ error (sl)
+ << "composite value type " << class_fq_name (c) << " must "
+ << "be defined before being used in class " << class_fq_name (s)
+ << endl;
+
+ info (m.location ())
+ << "data member " << m.name () << " uses " << cn << endl;
+
+ info (cl) << "class " << cn << " is define here" << endl;
+
+ valid_ = false;
+ }
+ }
+
+
virtual void
traverse (type& m)
{
+ using semantics::class_;
+
+ semantics::type& t (utype (m));
+ class_& s (dynamic_cast<class_&> (m.scope ()));
+
// Validate pointed-to objects.
//
- semantics::class_* c;
- if ((c = object_pointer (utype (m))) || (c = points_to (m)))
+ class_* c;
+ if ((c = object_pointer (t)) || (c = points_to (m)))
{
bool poly (polymorphic (*c));
bool abst (abstract (*c));
@@ -1128,28 +1181,8 @@ namespace
// Make sure composite id is defined before this pointer. Failed
// that we get non-obvious C++ compiler errors in generated code.
//
- using semantics::class_;
-
if (class_* comp = composite_wrapper (idt))
- {
- class_& s (dynamic_cast<class_&> (m.scope ()));
-
- location_t idl (class_location (*comp));
- location_t ml (class_location (s));
-
- if (ml < idl)
- {
- error (m.location ())
- << "composite object id " << class_fq_name (*comp) << " of "
- << "pointed-to class " << class_fq_name (*c) << " must be "
- << "defined before the pointer" << endl;
-
- info (idl)
- << "class " << class_name (*comp) << " is define here" << endl;
-
- valid_ = false;
- }
- }
+ verify_composite_location (*comp, s, m);
}
else if (!view_member (m))
{
@@ -1183,6 +1216,13 @@ namespace
return;
}
}
+
+ // Make sure composite type is defined before (or inside)
+ // this class. Failed that we get non-obvious C++ compiler
+ // errors in generated code.
+ //
+ if (class_* comp = composite_wrapper (t))
+ verify_composite_location (*comp, s, m);
}
bool& valid_;