From bba30281f89fbd30e898071a103643be924f001d Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 19 Sep 2014 14:27:33 +0200 Subject: Avoid clashes between nested composites in query columns --- odb/common-query.cxx | 49 +++++++++++++++++++++++++++++++++++++++++++------ odb/common-query.hxx | 4 ++++ 2 files changed, 47 insertions(+), 6 deletions(-) diff --git a/odb/common-query.cxx b/odb/common-query.cxx index 281e324..fea8e67 100644 --- a/odb/common-query.cxx +++ b/odb/common-query.cxx @@ -2,6 +2,8 @@ // copyright : Copyright (c) 2009-2013 Code Synthesis Tools CC // license : GNU GPL v3; see accompanying LICENSE file +#include + #include using namespace std; @@ -13,7 +15,7 @@ using namespace std; // struct query_nested_types: object_columns_base, virtual context { - query_nested_types (bool ptr): ptr_ (ptr), in_ptr_ (false) {} + query_nested_types (bool ptr): ptr_ (ptr), in_ptr_ (false), depth_ (0) {} virtual void traverse_object (semantics::class_& c) @@ -30,12 +32,15 @@ struct query_nested_types: object_columns_base, virtual context { string name (prefix_ + public_name (*m)); name += in_ptr_ ? "_column_class_" : "_class_"; + name += query_columns::depth_suffix (depth_); types.push_back (name); + depth_++; string p (prefix_); prefix_ = name + "::"; object_columns_base::traverse_composite (m, c); prefix_ = p; + depth_--; } else object_columns_base::traverse_composite (m, c); // Base @@ -69,6 +74,7 @@ protected: bool ptr_; bool in_ptr_; // True while we are "inside" an object pointer. string prefix_; + size_t depth_; }; void query_utils:: @@ -463,8 +469,22 @@ query_columns:: query_columns (bool decl, bool ptr, semantics::class_& c) : decl_ (decl), ptr_ (ptr), in_ptr_ (false), fq_name_ (class_fq_name (c)), - resue_abstract_ (abstract (c) && !polymorphic (c)) + resue_abstract_ (abstract (c) && !polymorphic (c)), + depth_ (0) +{ +} + +string query_columns:: +depth_suffix (size_t d) { + if (d != 0) + { + ostringstream os; + os << d; + return os.str () + '_'; + } + + return string (); } void query_columns:: @@ -492,6 +512,17 @@ traverse_composite (semantics::data_member* m, semantics::class_& c) string name (public_name (*m)); string suffix (in_ptr_ ? "_column_class_" : "_class_"); + // Add depth to the nested composite to avoid potential name conflicts + // in situations like these: + // + // struct inner { ... }; + // struct outer { inner value; }; + // struct object { outer value; } + // + suffix += depth_suffix (depth_); + + depth_++; + if (decl_) { os << "// " << name << endl @@ -528,7 +559,7 @@ traverse_composite (semantics::data_member* m, semantics::class_& c) os << "};"; if (!in_ptr_) - os << "static " << const_ << name << "_class_ " << name << ";" + os << "static " << const_ << name << suffix << " " << name << ";" << endl; } else @@ -542,17 +573,22 @@ traverse_composite (semantics::data_member* m, semantics::class_& c) scope_ = old_scope; - // Composite member. Note that here we don't use suffix. + // Composite member. Note that here we don't use suffix for the in- + // pointer case because the actual pointer column type derives from + // the composite column type (dual interface; see traverse_pointer() + // below). // string tmpl (ptr_ ? "pointer_query_columns" : "query_columns"); tmpl += "< " + fq_name_ + ", id_" + db.string () + ", A >" + scope_; os << "template " << endl << const_ << "typename " << tmpl << "::" << name << - (in_ptr_ ? "_type_" : "_class_") << endl + (in_ptr_ ? string ("_type_") : suffix) << endl << tmpl << "::" << name << ";" << endl; } + + depth_--; } void query_columns:: @@ -671,7 +707,8 @@ traverse_pointer (semantics::data_member& m, semantics::class_& c) << endl; os << "struct " << name << "_type_: " << - name << "_pointer_type_, " << name << "_column_class_" + name << "_pointer_type_, " << + name << "_column_class_" << depth_suffix (depth_) << "{"; if (!const_.empty ()) diff --git a/odb/common-query.hxx b/odb/common-query.hxx index 066e88d..e0bad6e 100644 --- a/odb/common-query.hxx +++ b/odb/common-query.hxx @@ -143,6 +143,9 @@ struct query_columns: object_columns_base, virtual context virtual void traverse_pointer (semantics::data_member&, semantics::class_&); + static string + depth_suffix (size_t); + protected: bool decl_; bool ptr_; @@ -151,6 +154,7 @@ protected: string fq_name_; bool resue_abstract_; // Object is reuse-abstract. string scope_; + size_t depth_; }; // Generate the list of base classes for the query_columns or -- cgit v1.1