From c0957cfe1c73ecb6c96314e45e7d29b4199b20d6 Mon Sep 17 00:00:00 2001 From: Boris Kolpackov Date: Fri, 31 Aug 2012 10:03:45 +0200 Subject: Add support for virtual data members New test: common/virtual. --- odb/lookup.cxx | 249 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 242 insertions(+), 7 deletions(-) (limited to 'odb/lookup.cxx') diff --git a/odb/lookup.cxx b/odb/lookup.cxx index b3e0551..2190301 100644 --- a/odb/lookup.cxx +++ b/odb/lookup.cxx @@ -3,12 +3,120 @@ // license : GNU GPL v3; see accompanying LICENSE file #include +#include using namespace std; namespace lookup { - std::string + // Return canonical fundamental type name ( , e.g., + // short unsigned int) or empty string if it is not a fundamental type. + // Note that the type can still be invalid (e.g., unsigned float) so it + // needs to be resolved. + // + static string + parse_fundamental (cxx_lexer& l, + cpp_ttype& tt, + string& tl, + tree& tn, + cpp_ttype& ptt, + string& name) + { + bool + si (false), // signed + un (false), // unsigned + sh (false), // short + lo (false), // long + ll (false); // long long + + string type; + + for (; tt == CPP_KEYWORD; ptt = tt, tt = l.next (tl, &tn)) + { + if (!name.empty ()) + name += ' '; + name += tl; + + if (tl == "signed") + { + if (si || un) + throw invalid_name (); + + si = true; + } + else if (tl == "unsigned") + { + if (si || un) + throw invalid_name (); + + un = true; + } + else if (tl == "short") + { + if (sh || lo || ll) + throw invalid_name (); + + sh = true; + } + else if (tl == "long") + { + if (sh || ll) + throw invalid_name (); + + if (lo) + { + lo = false; + ll = true; + } + else + lo = true; + } + else if (tl == "bool" || + tl == "char" || + tl == "wchar_t" || + tl == "char16_t" || // C++11 + tl == "char32_t" || // C++11 + tl == "int" || + tl == "float" || + tl == "double") + { + if (!type.empty ()) + throw invalid_name (); + + type = tl; + } + else + break; + } + + if (type.empty () && (si || un || sh || lo || ll)) + type = "int"; // If type not specified, it defaults to int. + + if (type.empty ()) + return type; + + string r; + + if (sh) + r += "short "; + + if (lo) + r += "long "; + + if (ll) + r += "long long "; + + if (si && type == "char") + r += "signed "; + + if (un) + r += "unsigned "; + + r += type; + return r; + } + + string parse_scoped_name (cxx_lexer& l, cpp_ttype& tt, string& tl, tree& tn) { string name; @@ -18,12 +126,18 @@ namespace lookup name += "::"; tt = l.next (tl, &tn); } + else if (tt == CPP_KEYWORD) + { + cpp_ttype ptt; // Not used. + string t (parse_fundamental (l, tt, tl, tn, ptt, name)); + + if (!t.empty ()) + return name; + } while (true) { - // @@ We still need to handle fundamental types, e.g., unsigned int. - // - if (tt != CPP_NAME && tt != CPP_KEYWORD) + if (tt != CPP_NAME) throw invalid_name (); name += tl; @@ -63,15 +177,32 @@ namespace lookup ptt = tt; tt = l.next (tl, &tn); } + else if (tt == CPP_KEYWORD) + { + string t (parse_fundamental (l, tt, tl, tn, ptt, name)); + + if (!t.empty ()) + { + tree decl ( + lookup_qualified_name ( + global_namespace, get_identifier (t.c_str ()), true, false)); + + if (decl == error_mark_node) + throw unable_to_resolve (name, true); + + if (end_scope != 0) + *end_scope = global_namespace; + + return decl; + } + } while (true) { if (end_scope != 0) *end_scope = scope; - // @@ We still need to handle fundamental types, e.g., unsigned int. - // - if (tt != CPP_NAME && tt != CPP_KEYWORD) + if (tt != CPP_NAME) throw invalid_name (); name += tl; @@ -137,4 +268,108 @@ namespace lookup return scope; } + + semantics::node& + resolve_scoped_name (cxx_lexer& l, + cpp_ttype& tt, + string& tl, + tree& tn, + cpp_ttype& ptt, + semantics::scope& start_scope, + string& name, + semantics::type_id const& tid, + bool trailing_scope, + semantics::scope** end_scope) + { + bool first (true); + semantics::scope* scope (&start_scope); + + if (tt == CPP_SCOPE) + { + name += "::"; + for (; !scope->global_scope (); scope = &scope->scope_ ()) ; + first = false; + + ptt = tt; + tt = l.next (tl, &tn); + } + else if (tt == CPP_KEYWORD) + { + string t (parse_fundamental (l, tt, tl, tn, ptt, name)); + + if (!t.empty ()) + { + for (; !scope->global_scope (); scope = &scope->scope_ ()) ; + + if (end_scope != 0) + *end_scope = scope; + + return scope->lookup (t); + } + } + + semantics::names* r; + + for (;;) + { + if (end_scope != 0) + *end_scope = scope; + + if (tt != CPP_NAME) + throw invalid_name (); + + name += tl; + string n (tl); + ptt = tt; + tt = l.next (tl, &tn); + + bool last (true); + if (tt == CPP_SCOPE) + { + // If trailing scope names are allowed, then we also need to + // check what's after the scope. + // + if (trailing_scope) + { + ptt = tt; + tt = l.next (tl, &tn); + + if (tt == CPP_NAME) + last = false; + } + else + last = false; + } + + // If this is the first component in the name, then also search the + // outer scopes. + // + bool hidden (false); + r = scope->lookup ( + n, + (last ? tid : typeid (semantics::scope)), + (first ? 0 : semantics::scope::exclude_outer) | + (last ? semantics::scope::include_hidden : 0), + (last ? &hidden : 0)); + + if (r == 0) + throw semantics::unresolved (name, hidden); + + if (last) + break; + + scope = &dynamic_cast (r->named ()); + first = false; + + name += "::"; + + if (!trailing_scope) + { + ptt = tt; + tt = l.next (tl, &tn); + } + } + + return r->named (); + } } -- cgit v1.1