From 1f87ed70f983bc0fb920a0e1360de0977fe10c9f Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Wed, 28 Dec 2016 11:01:06 +0200 Subject: Fix GCC 6 issue with PRAGMA_DB macro In GCC 6 we use the position of the macro expansion, not the position inside the macro itself. This means that multiple pragmas inside PRAGMA_DB will all have the same position which we were not handling properly. --- odb/parser.cxx | 8 ++++---- odb/pragma.cxx | 8 ++++---- odb/pragma.hxx | 52 ++++++++++++++++++++++++++++++++-------------------- 3 files changed, 40 insertions(+), 28 deletions(-) diff --git a/odb/parser.cxx b/odb/parser.cxx index 6dfff6f..079f6f3 100644 --- a/odb/parser.cxx +++ b/odb/parser.cxx @@ -852,12 +852,12 @@ parse (tree global_scope, path const& main_file) } pragma_set& s (decl_pragmas_[ns]); - pragma_set::iterator it (s.find (p)); + pragma_set::iterator it (s.find (p.context_name)); // Make sure we override only if this pragma came after the one // already in the set. // - if (it == s.end () || it->loc < p.loc) + if (it == s.end () || it->second.loc <= p.loc) s.insert (p); } @@ -2179,7 +2179,7 @@ process_pragmas (declaration const& decl, // Finally, copy the resulting pragma set to context. // for (pragma_set::iterator i (prags.begin ()); i != prags.end (); ++i) - add_pragma (node, *i); + add_pragma (node, i->second); } void parser::impl:: @@ -2195,7 +2195,7 @@ process_named_pragmas (declaration const& decl, node& node) // Copy the resulting pragma set to context. // for (pragma_set::iterator i (prags.begin ()); i != prags.end (); ++i) - add_pragma (node, *i); + add_pragma (node, i->second); } void parser::impl:: diff --git a/odb/pragma.cxx b/odb/pragma.cxx index 0c925ca..62d97b4 100644 --- a/odb/pragma.cxx +++ b/odb/pragma.cxx @@ -4391,23 +4391,23 @@ post_process_pragmas () for (pragma_set::iterator j (i->second.begin ()), e (i->second.end ()); j != e; ++j) { - string const& name (j->context_name); + string const& name (j->second.context_name); if (name == "object") { - p = &*j; + p = &j->second; diag_name = "persistent object"; break; } else if (name == "view") { - p = &*j; + p = &j->second; diag_name = "view"; break; } else if (name == "value") { - p = &*j; + p = &j->second; diag_name = "composite value"; break; } diff --git a/odb/pragma.hxx b/odb/pragma.hxx index d6b0f42..f13c6e0 100644 --- a/odb/pragma.hxx +++ b/odb/pragma.hxx @@ -181,16 +181,6 @@ struct pragma { } - bool - operator< (pragma const& y) const - { - if (add == 0) - return context_name < y.context_name; - else - return context_name < y.context_name || - (context_name == y.context_name && loc < y.loc); - } - std::string pragma_name; // Actual pragma name for diagnostics. std::string context_name; // Context entry name. cutl::container::any value; @@ -204,29 +194,51 @@ typedef std::vector pragma_list; // A set of pragmas. Insertion of a pragma with the same name and no // custom add function overrides the old value. // -struct pragma_set: std::set +struct pragma_set: std::multimap { - typedef std::set base; + typedef std::multimap base; pragma& insert (pragma const& p) { - std::pair r (base::insert (p)); + std::string const& n (p.context_name); + std::pair r (equal_range (n)); + + iterator i (end ()); - pragma& x (const_cast (*r.first)); + if (p.add == 0) + { + if (r.first != r.second) + { + i = r.first; + assert (++r.first == r.second); - if (!r.second) - x = p; + i->second = p; + } + } + else if (r.first != r.second) + assert ((--r.second)->second.loc <= p.loc); - return x; + if (i == end ()) + i = base::insert (base::value_type (n, p)); + + return i->second; } - template void - insert (I begin, I end) + insert (const_iterator begin, const_iterator end) { for (; begin != end; ++begin) - insert (*begin); + insert (begin->second); + } + + // Return the last pragma in the equal range which (by construction) has the + // location greater or equal to all the other pragmas in this range. + // + iterator + find (std::string const& n) + { + return equal_range (n).second; } }; -- cgit v1.1