From f0cfd3c7942d27e312d27f5a1d94532516f393aa Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Tue, 1 Feb 2011 09:16:39 +0200 Subject: Detect and ignore inner names in the fq_*() functions --- odb/semantics/elements.cxx | 79 +++++++++++++++++++++++++++++----------------- odb/semantics/elements.hxx | 46 +++++++++++++++++++++++++-- 2 files changed, 94 insertions(+), 31 deletions(-) diff --git a/odb/semantics/elements.cxx b/odb/semantics/elements.cxx index ade5975..d6ff1c7 100644 --- a/odb/semantics/elements.cxx +++ b/odb/semantics/elements.cxx @@ -64,8 +64,10 @@ namespace semantics } bool nameable:: - fq_anonymous () const + fq_anonymous_ (scope_entry const* prev) const { + scope_entry scope (this, prev); + // Nameable is fq-anonymous if all the paths to the global scope // have at least one anonymous link. // @@ -74,44 +76,49 @@ namespace semantics if (named ().global_scope ()) return false; - if (defined_ != 0 && !defined_->scope ().fq_anonymous ()) - return false; + if (defined_ != 0) + { + nameable const& s (defined_->scope ()); + + if (!scope.find (&s) && !s.fq_anonymous_ (&scope)) + return false; + } for (names_list::const_iterator i (named_.begin ()), e (named_.end ()); i != e; ++i) { - if (!(*i)->scope ().fq_anonymous ()) + nameable const& s ((*i)->scope ()); + + if (!scope.find (&s) && !s.fq_anonymous_ (&scope)) return false; } } - else + + // If we can get a literal name for this type node, then it is not + // anonymous as long as its scope is not anonymous. + // + tree type (tree_node ()); + + if (TYPE_P (type)) { - // If we can get a literal name for this type, then it is not - // anonymous as long as its scope is not anonymous. - // - tree type (tree_node ()); + tree name (0); - if (TYPE_P (type)) + if (tree decl = TYPE_NAME (type)) { - tree name (0); - - if (tree decl = TYPE_NAME (type)) - { - name = DECL_NAME (decl); - if (name != 0 && ANON_AGGRNAME_P (name)) - return true; + name = DECL_NAME (decl); + if (name != 0 && ANON_AGGRNAME_P (name)) + return true; - tree s (CP_DECL_CONTEXT (decl)); + tree s (CP_DECL_CONTEXT (decl)); - if (TREE_CODE (s) == TYPE_DECL) - s = TREE_TYPE (s); + if (TREE_CODE (s) == TYPE_DECL) + s = TREE_TYPE (s); - if (nameable* n = dynamic_cast (unit ().find (s))) - return n->fq_anonymous (); - } - else - return false; // Assume this is a derived type (e.g., pointer). + if (nameable* n = dynamic_cast (unit ().find (s))) + return scope.find (n) || n->fq_anonymous_ (&scope); } + else + return false; // Assume this is a derived type (e.g., pointer). } return true; @@ -224,21 +231,35 @@ namespace semantics string nameable:: fq_name () const { + return fq_name_ (0); + } + + string nameable:: + fq_name_ (scope_entry const* prev) const + { // @@ Doing this once and caching the result is probably a // good idea. // + scope_entry scope (this, prev); if (named_p () && named ().global_scope ()) return ""; - if (defined_ != 0 && !defined_->scope ().fq_anonymous ()) - return defined_->scope ().fq_name () + "::" + name (); + if (defined_ != 0) + { + nameable const& s (defined_->scope ()); + + if (!scope.find (&s) && !s.fq_anonymous_ (&scope)) + return s.fq_name_ (&scope) + "::" + name (); + } for (names_list::const_iterator i (named_.begin ()), e (named_.end ()); i != e; ++i) { - if (!(*i)->scope ().fq_anonymous ()) - return (*i)->scope ().fq_name () + "::" + name (); + nameable const& s ((*i)->scope ()); + + if (!scope.find (&s) && !s.fq_anonymous_ (&scope)) + return s.fq_name_ (&scope) + "::" + name (); } tree n (tree_node ()); diff --git a/odb/semantics/elements.hxx b/odb/semantics/elements.hxx index bcea379..b11211e 100644 --- a/odb/semantics/elements.hxx +++ b/odb/semantics/elements.hxx @@ -313,7 +313,10 @@ namespace semantics // return true. // bool - fq_anonymous () const; + fq_anonymous () const + { + return fq_anonymous_ (0); + } // As above but use the hint to select the first outer scope. If // hint is 0, use the defines edge. @@ -390,13 +393,52 @@ namespace semantics using node::add_edge_right; - private: + protected: + // We need to keep the scope we have seen in the fq_* function + // family in order to detect names that are inside the node + // and which would otherwise lead to infinite recursion. Here + // is the canonical example: + // + // template + // class c + // { + // typedef c this_type; + // }; + // + struct scope_entry + { + scope_entry (nameable const* e, scope_entry const* p) + : entry_ (e), prev_ (p) + { + } + + bool + find (nameable const* n) const + { + for (scope_entry const* i (this); i != 0; i = i->prev_) + if (i->entry_ == n) + return true; + + return false; + } + + private: + nameable const* entry_; + scope_entry const* prev_; + }; + bool anonymous_ () const; + bool + fq_anonymous_ (scope_entry const*) const; + string name_ () const; + string + fq_name_ (scope_entry const*) const; + private: defines* defined_; names_list named_; -- cgit v1.1