aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2011-02-01 09:16:39 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2011-02-01 09:16:39 +0200
commitf0cfd3c7942d27e312d27f5a1d94532516f393aa (patch)
treea9fdf2a114d797c1ab765c4b13275700b422d0c3
parent62604d06f0c44cac39e1ce9751e1e11b6568c56f (diff)
Detect and ignore inner names in the fq_*() functions
-rw-r--r--odb/semantics/elements.cxx79
-rw-r--r--odb/semantics/elements.hxx46
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<nameable*> (unit ().find (s)))
- return n->fq_anonymous ();
- }
- else
- return false; // Assume this is a derived type (e.g., pointer).
+ if (nameable* n = dynamic_cast<nameable*> (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 <typename X>
+ // 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_;