aboutsummaryrefslogtreecommitdiff
path: root/odb/lookup.cxx
blob: cc02c66c0af1894f4f492687c4908284259f0de3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// file      : odb/lookup.cxx
// author    : Boris Kolpackov <boris@codesynthesis.com>
// copyright : Copyright (c) 2009-2011 Code Synthesis Tools CC
// license   : GNU GPL v3; see accompanying LICENSE file

#include <odb/lookup.hxx>

using namespace std;

namespace lookup
{
  std::string
  parse_scoped_name (std::string& t, cpp_ttype& tt, cxx_lexer& lex)
  {
    string name;

    if (tt == CPP_SCOPE)
    {
      name += "::";
      tt = lex.next (t);
    }

    while (true)
    {
      // @@ We still need to handle fundamental types, e.g., unsigned int.
      //
      if (tt != CPP_NAME && tt != CPP_KEYWORD)
        throw invalid_name ();

      name += t;
      tt = lex.next (t);

      if (tt != CPP_SCOPE)
        break;

      name += "::";
      tt = lex.next (t);
    }

    return name;
  }

  tree
  resolve_scoped_name (string& t,
                       cpp_ttype& tt,
                       cpp_ttype& ptt,
                       cxx_lexer& lex,
                       tree scope,
                       string& name,
                       bool is_type,
                       tree* end_scope)
  {
    tree id;
    bool first (true);

    if (tt == CPP_SCOPE)
    {
      name += "::";
      scope = global_namespace;
      first = false;

      ptt = tt;
      tt = lex.next (t);
    }

    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)
        throw invalid_name ();

      name += t;
      id = get_identifier (t.c_str ());
      ptt = tt;
      tt = lex.next (t);

      bool last (tt != CPP_SCOPE);
      tree decl = lookup_qualified_name (scope, id, last && is_type, false);

      // If this is the first component in the name, then also search the
      // outer scopes.
      //
      if (decl == error_mark_node && first && scope != global_namespace)
      {
        do
        {
          scope = TYPE_P (scope)
            ? CP_TYPE_CONTEXT (scope)
            : CP_DECL_CONTEXT (scope);
          decl = lookup_qualified_name (scope, id, last && is_type, false);
        } while (decl == error_mark_node && scope != global_namespace);
      }

      if (decl == error_mark_node)
        throw unable_to_resolve (name, last);

      scope = decl;

      if (last)
        break;

      first = false;

      if (TREE_CODE (scope) == TYPE_DECL)
        scope = TREE_TYPE (scope);

      name += "::";

      ptt = tt;
      tt = lex.next (t);
    }

    return scope;
  }
}