cprover
cpp_scope.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: C++ Language Type Checking
4 
5 Author: Daniel Kroening, kroening@cs.cmu.edu
6 
7 \*******************************************************************/
8 
11 
12 #include "cpp_scope.h"
13 
14 #include "cpp_typecheck.h"
15 
16 std::ostream &operator << (std::ostream &out, cpp_scopet::lookup_kindt kind)
17 {
18  switch(kind)
19  {
20  case cpp_scopet::QUALIFIED: return out << "QUALIFIED";
21  case cpp_scopet::SCOPE_ONLY: return out << "SCOPE_ONLY";
22  case cpp_scopet::RECURSIVE: return out << "RECURSIVE";
23  default: UNREACHABLE;
24  }
25 
26  return out;
27 }
28 
30  const irep_idt &base_name_to_lookup,
31  lookup_kindt kind,
32  id_sett &id_set)
33 {
34  cpp_id_mapt::iterator lower_it = sub.lower_bound(base_name_to_lookup);
35 
36  if(lower_it!=sub.end())
37  {
38  cpp_id_mapt::iterator upper_it = sub.upper_bound(base_name_to_lookup);
39 
40  for(cpp_id_mapt::iterator n_it=lower_it;
41  n_it!=upper_it; n_it++)
42  id_set.insert(&n_it->second);
43  }
44 
45  if(base_name == base_name_to_lookup)
46  id_set.insert(this);
47 
48  if(kind==SCOPE_ONLY)
49  return; // done
50 
51  // using scopes
52  for(const auto &s_ptr : using_scopes)
53  {
54  cpp_scopet &other_scope = static_cast<cpp_scopet &>(*s_ptr);
55 
56  // Recursive call.
57  // Note the different kind!
58  other_scope.lookup_rec(base_name_to_lookup, QUALIFIED, id_set);
59  }
60 
61  if(!id_set.empty())
62  return; // done, upwards scopes are hidden
63 
64  // secondary scopes
65  for(const auto &s_ptr : secondary_scopes)
66  {
67  cpp_scopet &other_scope = static_cast<cpp_scopet &>(*s_ptr);
68 
69  // Recursive call.
70  // Note the different kind!
71  other_scope.lookup_rec(base_name_to_lookup, QUALIFIED, id_set);
72  }
73 
74  if(kind==QUALIFIED)
75  return; // done
76 
77  if(!id_set.empty())
78  return; // done
79 
80  // ask parent, recursive call
81  if(!is_root_scope())
82  get_parent().lookup_rec(base_name_to_lookup, kind, id_set);
83 }
84 
86  const irep_idt &base_name_to_lookup,
87  lookup_kindt kind,
88  cpp_idt::id_classt identifier_class,
89  id_sett &id_set)
90 {
91  // we have a hack to do full search in case we
92  // are looking for templates!
93 
94  #if 0
95  std::cout << "B: " << base_name_to_lookup << '\n';
96  std::cout << "K: " << kind << '\n';
97  std::cout << "I: " << identifier_class << '\n';
98  std::cout << "THIS: " << base_name << " " << identifier_class
99  << " " << this->identifier << '\n';
100  #endif
101 
102  cpp_id_mapt::iterator lower_it = sub.lower_bound(base_name_to_lookup);
103 
104  if(lower_it!=sub.end())
105  {
106  cpp_id_mapt::iterator upper_it = sub.upper_bound(base_name_to_lookup);
107 
108  for(cpp_id_mapt::iterator n_it=lower_it;
109  n_it!=upper_it; n_it++)
110  {
111  if(n_it->second.id_class == identifier_class)
112  id_set.insert(&n_it->second);
113  }
114  }
115 
116  if(base_name == base_name_to_lookup && id_class == identifier_class)
117  id_set.insert(this);
118 
119  if(kind==SCOPE_ONLY)
120  return; // done
121 
122  // using scopes
123  for(const auto &s_ptr : using_scopes)
124  {
125  cpp_scopet &other_scope = static_cast<cpp_scopet &>(*s_ptr);
126 
127  // Recursive call.
128  // Note the different kind!
129  other_scope.lookup_rec(
130  base_name_to_lookup, QUALIFIED, identifier_class, id_set);
131  }
132 
133  if(!id_set.empty() && identifier_class != id_classt::TEMPLATE)
134  return; // done, upwards scopes are hidden
135 
136  // secondary scopes
137  for(const auto &s_ptr : secondary_scopes)
138  {
139  cpp_scopet &other_scope = static_cast<cpp_scopet &>(*s_ptr);
140 
141  // Recursive call.
142  // Note the different kind!
143  other_scope.lookup_rec(
144  base_name_to_lookup, QUALIFIED, identifier_class, id_set);
145  }
146 
147  if(kind==QUALIFIED)
148  return; // done
149 
150  if(!id_set.empty() && identifier_class != id_classt::TEMPLATE)
151  return; // done, upwards scopes are hidden
152 
153  // ask parent, recursive call
154  if(!is_root_scope())
156  base_name_to_lookup, kind, identifier_class, id_set);
157 }
158 
160  const irep_idt &id,
161  cpp_idt::id_classt identifier_class)
162 {
163  id_sett id_set;
164 
165  for(cpp_id_mapt::iterator n_it=sub.begin();
166  n_it!=sub.end(); n_it++)
167  {
168  if(
169  n_it->second.identifier == id &&
170  n_it->second.id_class == identifier_class)
171  {
172  id_set.insert(&n_it->second);
173  }
174  }
175 
176  if(identifier == id && id_class == identifier_class)
177  id_set.insert(this);
178 
179  #if 0
180  for(std::size_t i=0; i<parents_size(); i++)
181  {
183  if(parent.identifier == id
184  && parent.id_class == identifier_class)
185  id_set.insert(&parent);
186  }
187  #endif
188 
189  return id_set;
190 }
191 
193 {
194  cpp_idt &id=insert(new_scope_name);
195  id.identifier=prefix+id2string(new_scope_name);
196  id.prefix=prefix+id2string(new_scope_name)+"::";
197  id.this_expr=this_expr;
198  id.class_identifier=class_identifier;
199  id.is_scope=true;
200  return (cpp_scopet &)id;
201 }
202 
203 bool cpp_scopet::contains(const irep_idt &base_name_to_lookup)
204 {
205  return !lookup(base_name_to_lookup, SCOPE_ONLY).empty();
206 }
cpp_scopet::new_scope
class cpp_scopet & new_scope(const irep_idt &new_scope_name)
Definition: cpp_scope.cpp:192
UNREACHABLE
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:504
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:37
cpp_idt::class_identifier
irep_idt class_identifier
Definition: cpp_id.h:81
cpp_scopet::get_parent
cpp_scopet & get_parent() const
Definition: cpp_scope.h:88
cpp_scope.h
C++ Language Type Checking.
cpp_scopet
Definition: cpp_scope.h:21
cpp_scopet::id_sett
std::set< cpp_idt * > id_sett
Definition: cpp_scope.h:28
cpp_idt::id_classt::TEMPLATE
@ TEMPLATE
cpp_idt::this_expr
exprt this_expr
Definition: cpp_id.h:82
cpp_scopet::lookup
id_sett lookup(const irep_idt &base_name_to_lookup, lookup_kindt kind)
Definition: cpp_scope.h:32
cpp_scopet::QUALIFIED
@ QUALIFIED
Definition: cpp_scope.h:30
cpp_scopet::lookup_rec
void lookup_rec(const irep_idt &base_name, lookup_kindt kind, id_sett &)
Definition: cpp_scope.cpp:29
cpp_idt::identifier
irep_idt identifier
Definition: cpp_id.h:78
cpp_scopet::SCOPE_ONLY
@ SCOPE_ONLY
Definition: cpp_scope.h:30
cpp_scopet::lookup_identifier
id_sett lookup_identifier(const irep_idt &id, cpp_idt::id_classt identifier_class)
Definition: cpp_scope.cpp:159
cpp_idt::parent
cpp_idt * parent
Definition: cpp_id.h:115
cpp_scopet::contains
bool contains(const irep_idt &base_name_to_lookup)
Definition: cpp_scope.cpp:203
cpp_idt::sub
cpp_id_mapt sub
Definition: cpp_id.h:110
cpp_idt
Definition: cpp_id.h:29
cpp_idt::id_classt
id_classt
Definition: cpp_id.h:34
cpp_idt::secondary_scopes
scope_listt secondary_scopes
Definition: cpp_id.h:114
id2string
const std::string & id2string(const irep_idt &d)
Definition: irep.h:44
operator<<
std::ostream & operator<<(std::ostream &out, cpp_scopet::lookup_kindt kind)
Definition: cpp_scope.cpp:16
cpp_idt::using_scopes
scope_listt using_scopes
Definition: cpp_id.h:114
cpp_typecheck.h
C++ Language Type Checking.
cpp_scopet::RECURSIVE
@ RECURSIVE
Definition: cpp_scope.h:30
cpp_scopet::is_root_scope
bool is_root_scope() const
Definition: cpp_scope.h:77
cpp_idt::id_class
id_classt id_class
Definition: cpp_id.h:51
cpp_idt::prefix
std::string prefix
Definition: cpp_id.h:85
cpp_scopet::lookup_kindt
lookup_kindt
Definition: cpp_scope.h:30
cpp_idt::base_name
irep_idt base_name
Definition: cpp_id.h:78
cpp_scopet::insert
cpp_idt & insert(const irep_idt &_base_name)
Definition: cpp_scope.h:52