From fa8b674ef4cb32cb92bcc4f3d42bf24b8cf3b7fb Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 17 Jul 2015 12:53:58 +0200 Subject: Diagnose "composite type used before definition" situations --- odb/context.cxx | 23 ++++++------- odb/context.hxx | 6 ++++ odb/semantics/elements.cxx | 17 +++++++++ odb/semantics/elements.hxx | 3 ++ odb/validator.cxx | 86 +++++++++++++++++++++++++++++++++------------- 5 files changed, 100 insertions(+), 35 deletions(-) (limited to 'odb') 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 ("definition"); - } - else if (c.is_a ()) - { - return c.get ("location"); - } - else - { - return real_source_location (TYPE_NAME (c.tree_node ())); - } + return c.count ("definition") + ? c.get ("definition") + : class_real_location (c); +} + +location_t context:: +class_real_location (semantics::class_& c) +{ + return c.is_a () + ? c.get ("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 (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 (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_; -- cgit v1.1