summaryrefslogtreecommitdiff
path: root/odb/semantics/elements.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2010-11-28 17:51:23 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2010-11-28 17:51:23 +0200
commit7dff3249f7ef6f8675e0c0fcbe3109d50f4c1b1d (patch)
tree8596735f193cc4a377e97cf63af1a0a6c40d5bbf /odb/semantics/elements.cxx
parentc6a2b0f125c70f521daf820d014ff07b4fe8af3b (diff)
Add support for literal names (template-id, derived type declarator)
Diffstat (limited to 'odb/semantics/elements.cxx')
-rw-r--r--odb/semantics/elements.cxx216
1 files changed, 193 insertions, 23 deletions
diff --git a/odb/semantics/elements.cxx b/odb/semantics/elements.cxx
index 728b1b5..a1a63cd 100644
--- a/odb/semantics/elements.cxx
+++ b/odb/semantics/elements.cxx
@@ -3,8 +3,14 @@
// copyright : Copyright (c) 2009-2010 Code Synthesis Tools CC
// license : GNU GPL v3; see accompanying LICENSE file
+#include <odb/gcc.hxx>
+
#include <cutl/compiler/type-info.hxx>
+
+#include <odb/cxx-lexer.hxx>
+
#include <odb/semantics/elements.hxx>
+#include <odb/semantics/unit.hxx>
namespace semantics
{
@@ -40,25 +46,72 @@ namespace semantics
//
bool nameable::
+ anonymous_ () const
+ {
+ tree n (tree_node ());
+
+ if (TYPE_P (n))
+ {
+ tree name (0);
+
+ if (tree decl = TYPE_NAME (n))
+ name = DECL_NAME (decl);
+
+ return name != 0 && ANON_AGGRNAME_P (name);
+ }
+
+ return true;
+ }
+
+ bool nameable::
fq_anonymous () const
{
// Nameable is fq-anonymous if all the paths to the global scope
// have at least one anonymous link.
//
- if (anonymous ())
- return true;
-
- if (named ().global_scope ())
- return false;
+ if (defined_ != 0 || !named_.empty ())
+ {
+ if (named ().global_scope ())
+ return false;
- if (defined_ != 0 && !defined_->scope ().fq_anonymous ())
- return false;
+ if (defined_ != 0 && !defined_->scope ().fq_anonymous ())
+ return false;
- for (names_list::const_iterator i (named_.begin ()), e (named_.end ());
- i != e; ++i)
+ for (names_list::const_iterator i (named_.begin ()), e (named_.end ());
+ i != e; ++i)
+ {
+ if (!(*i)->scope ().fq_anonymous ())
+ return false;
+ }
+ }
+ else
{
- if (!(*i)->scope ().fq_anonymous ())
- return false;
+ // 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 ());
+
+ if (TYPE_P (type))
+ {
+ tree name (0);
+
+ if (tree decl = TYPE_NAME (type))
+ {
+ name = DECL_NAME (decl);
+ if (name != 0 && ANON_AGGRNAME_P (name))
+ return true;
+
+ tree s (CP_DECL_CONTEXT (decl));
+
+ 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).
+ }
}
return true;
@@ -67,21 +120,115 @@ namespace semantics
bool nameable::
fq_anonymous (names* hint) const
{
- if (hint == 0 && defined_ == 0)
- return true;
+ if (hint != 0 || defined_ != 0)
+ {
+ names& n (hint ? *hint : *defined_);
+
+ if (n.global_scope ())
+ return false;
+
+ return n.scope ().fq_anonymous ();
+ }
+ else
+ return fq_anonymous ();
+ }
+
+ static string
+ qualify_names (string const& n, bool qualify_first)
+ {
+ // @@ Creating a lexer for each call is a bad idea. Need
+ // to cache it somewhere.
+ //
+ cxx_lexer l;
+ l.start (n);
- names& n (hint ? *hint : *defined_);
+ string r, t;
+ bool punc (false);
+ bool scoped (false);
- if (n.global_scope ())
- return false;
+ for (cpp_ttype tt = l.next (t); tt != CPP_EOF; tt = l.next (t))
+ {
+ if (punc && tt > CPP_LAST_PUNCTUATOR)
+ r += ' ';
- return n.scope ().fq_anonymous ();
+ punc = false;
+
+ switch (static_cast<unsigned> (tt))
+ {
+ case CPP_LESS:
+ {
+ r += "< ";
+ break;
+ }
+ case CPP_GREATER:
+ {
+ r += " >";
+ break;
+ }
+ case CPP_COMMA:
+ {
+ r += ", ";
+ break;
+ }
+ case CPP_NAME:
+ {
+ // If the name was not preceeded with '::', qualify it.
+ //
+ if (!scoped)
+ {
+ if (!qualify_first)
+ qualify_first = true;
+ else
+ r += "::";
+ }
+
+ r += t;
+ punc = true;
+ break;
+ }
+ case CPP_KEYWORD:
+ case CPP_NUMBER:
+ {
+ r += t;
+ punc = true;
+ break;
+ }
+ default:
+ {
+ r += t;
+ break;
+ }
+ }
+
+ scoped = (tt == CPP_SCOPE);
+ }
+
+ return r;
+ }
+
+ string nameable::
+ name_ () const
+ {
+ tree n (tree_node ());
+
+ if (!TYPE_P (n))
+ return "<anonymous>";
+
+ // @@ Doing this once and caching the result is probably a
+ // good idea.
+ //
+ return qualify_names (
+ type_as_string (n, TFF_PLAIN_IDENTIFIER | TFF_UNQUALIFIED_NAME), false);
}
string nameable::
fq_name () const
{
- if (named ().global_scope ())
+ // @@ Doing this once and caching the result is probably a
+ // good idea.
+ //
+
+ if (named_p () && named ().global_scope ())
return "";
if (defined_ != 0 && !defined_->scope ().fq_anonymous ())
@@ -94,18 +241,41 @@ namespace semantics
return (*i)->scope ().fq_name () + "::" + name ();
}
- return "<anonymous>";
+ tree n (tree_node ());
+
+ if (!TYPE_P (n))
+ return "<anonymous>";
+
+ return qualify_names (type_as_string (n, TFF_PLAIN_IDENTIFIER), true);
}
string nameable::
fq_name (names* hint) const
{
- names& n (hint ? *hint : *defined_);
+ if (hint != 0 || defined_ != 0)
+ {
+ names& n (hint ? *hint : *defined_);
- if (n.global_scope ())
- return "";
+ if (n.global_scope ())
+ return "";
- return n.scope ().fq_name () + "::" + n.name ();
+ return n.scope ().fq_name () + "::" + n.name ();
+ }
+ else
+ {
+ // Since there was no hint, prefer the literal name over the names
+ // edges.
+ //
+ tree n (tree_node ());
+
+ if (TYPE_P (n))
+ return qualify_names (type_as_string (n, TFF_PLAIN_IDENTIFIER), true);
+
+ // Last resort is to call the other version of fq_name which will
+ // check the names edges.
+ //
+ return fq_name ();
+ }
}
// scope