cprover
cpp_typecheck_bases.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_typecheck.h"
13 
14 #include <set>
15 
17 {
18  std::set<irep_idt> bases;
19  std::set<irep_idt> vbases;
20 
21  irep_idt default_class_access = type.default_access();
22 
23  irept::subt &bases_irep=type.add(ID_bases).get_sub();
24 
25  Forall_irep(base_it, bases_irep)
26  {
27  const cpp_namet &name=
28  to_cpp_name(base_it->find(ID_name));
29 
30  exprt base_symbol_expr=
31  resolve(
32  name,
35 
36  if(base_symbol_expr.id()!=ID_type)
37  {
39  error() << "expected type as struct/class base" << eom;
40  throw 0;
41  }
42 
43  // elaborate any class template instances given as bases
44  elaborate_class_template(base_symbol_expr.type());
45 
46  if(base_symbol_expr.type().id() != ID_struct_tag)
47  {
49  error() << "expected type symbol as struct/class base" << eom;
50  throw 0;
51  }
52 
53  const symbolt &base_symbol =
54  lookup(to_struct_tag_type(base_symbol_expr.type()));
55 
56  if(base_symbol.type.id() != ID_struct)
57  {
59  error() << "expected struct or class as base, but got '"
60  << to_string(base_symbol.type) << "'" << eom;
61  throw 0;
62  }
63 
64  if(to_struct_type(base_symbol.type).is_incomplete())
65  {
67  error() << "base type is incomplete" << eom;
68  throw 0;
69  }
70 
71  bool virtual_base = base_it->get_bool(ID_virtual);
72  irep_idt class_access = base_it->get(ID_protection);
73 
74  if(class_access.empty())
75  class_access = default_class_access;
76 
77  base_symbol_expr.id(ID_base);
78  base_symbol_expr.set(ID_access, class_access);
79 
80  if(virtual_base)
81  base_symbol_expr.set(ID_virtual, true);
82 
83  base_it->swap(base_symbol_expr);
84 
85  // Add base scopes as parents to the current scope
87  static_cast<cpp_scopet &>(*cpp_scopes.id_map[base_symbol.name]));
88 
89  const struct_typet &base_struct_type=
90  to_struct_type(base_symbol.type);
91 
93  base_struct_type,
94  class_access,
95  type,
96  bases,
97  vbases,
98  virtual_base);
99  }
100 
101  if(!vbases.empty())
102  {
103  // add a flag to determine
104  // if this is the most-derived-object
105  struct_typet::componentt most_derived(
106  cpp_scopes.current_scope().prefix + "::" + "@most_derived", bool_typet());
107 
108  most_derived.set_access(ID_public);
109  most_derived.set_base_name("@most_derived");
110  most_derived.set_pretty_name("@most_derived");
111  most_derived.add_source_location()=type.source_location();
112  put_compound_into_scope(most_derived);
113 
114  to_struct_type(type).components().push_back(most_derived);
115  }
116 }
117 
119  const struct_typet &from,
120  const irep_idt &access,
121  struct_typet &to,
122  std::set<irep_idt> &bases,
123  std::set<irep_idt> &vbases,
124  bool is_virtual)
125 {
126  const irep_idt &from_name = from.get(ID_name);
127 
128  if(is_virtual && vbases.find(from_name)!=vbases.end())
129  return;
130 
131  if(bases.find(from_name)!=bases.end())
132  {
134  error() << "error: non-virtual base class " << from_name
135  << " inherited multiple times" << eom;
136  throw 0;
137  }
138 
139  bases.insert(from_name);
140 
141  if(is_virtual)
142  vbases.insert(from_name);
143 
144  // look at the the parents of the base type
145  for(const auto &b : from.bases())
146  {
147  irep_idt sub_access = b.get(ID_access);
148 
149  if(access==ID_private)
150  sub_access=ID_private;
151  else if(access==ID_protected && sub_access!=ID_private)
152  sub_access=ID_protected;
153 
154  const symbolt &symb = lookup(b.type());
155 
156  const bool is_virtual_base = b.get_bool(ID_virtual);
157 
158  // recursive call
160  to_struct_type(symb.type),
161  sub_access,
162  to,
163  bases,
164  vbases,
165  is_virtual_base);
166  }
167 
168  // add the components
170 
171  for(const auto &c : from.components())
172  {
173  if(c.get_bool(ID_from_base))
174  continue;
175 
176  // copy the component
177  dest_c.push_back(c);
178 
179  // now twiddle the copy
180  struct_typet::componentt &component=dest_c.back();
181  component.set(ID_from_base, true);
182 
183  irep_idt comp_access=component.get_access();
184 
185  if(access==ID_public)
186  {
187  if(comp_access==ID_private)
188  component.set_access(ID_noaccess);
189  }
190  else if(access == ID_protected)
191  {
192  if(comp_access==ID_private)
193  component.set_access(ID_noaccess);
194  else
195  component.set_access(ID_private);
196  }
197  else if(access == ID_private)
198  {
199  if(comp_access == ID_noaccess || comp_access == ID_private)
200  component.set_access(ID_noaccess);
201  else
202  component.set_access(ID_private);
203  }
204  else
205  UNREACHABLE;
206 
207  // put into scope
208  }
209 }
UNREACHABLE
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:504
struct_union_typet::components
const componentst & components() const
Definition: std_types.h:142
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:37
cpp_scopet
Definition: cpp_scope.h:21
cpp_typecheckt::elaborate_class_template
void elaborate_class_template(const typet &type)
elaborate class template instances
Definition: cpp_instantiate_template.cpp:224
cpp_typecheckt::add_base_components
void add_base_components(const struct_typet &from, const irep_idt &access, struct_typet &to, std::set< irep_idt > &bases, std::set< irep_idt > &vbases, bool is_virtual)
Definition: cpp_typecheck_bases.cpp:118
cpp_typecheck_fargst
Definition: cpp_typecheck_fargs.h:23
to_struct_type
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition: std_types.h:303
struct_union_typet::componentt::set_access
void set_access(const irep_idt &access)
Definition: std_types.h:99
cpp_scopest::id_map
id_mapt id_map
Definition: cpp_scopes.h:69
cpp_typecheckt::cpp_scopes
cpp_scopest cpp_scopes
Definition: cpp_typecheck.h:109
symbolt::type
typet type
Type of symbol.
Definition: symbol.h:31
irept::add
irept & add(const irep_namet &name)
Definition: irep.cpp:113
cpp_typecheckt::typecheck_compound_bases
void typecheck_compound_bases(struct_typet &type)
Definition: cpp_typecheck_bases.cpp:16
namespacet::lookup
const symbolt & lookup(const irep_idt &name) const
Lookup a symbol in the namespace.
Definition: namespace.h:44
exprt
Base class for all expressions.
Definition: expr.h:53
struct_union_typet::componentst
std::vector< componentt > componentst
Definition: std_types.h:135
component
auto component(T &struct_expr, const irep_idt &name, const namespacet &ns) -> decltype(struct_expr.op0())
Definition: std_expr.cpp:192
bool_typet
The Boolean type.
Definition: std_types.h:37
messaget::eom
static eomt eom
Definition: message.h:297
struct_union_typet::default_access
irep_idt default_access() const
Return the access specification for members where access has not been modified.
Definition: std_types.h:174
Forall_irep
#define Forall_irep(it, irep)
Definition: irep.h:66
cpp_typecheck_resolvet::wantt::TYPE
@ TYPE
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:81
messaget::error
mstreamt & error() const
Definition: message.h:399
cpp_scopet::add_secondary_scope
void add_secondary_scope(cpp_scopet &other)
Definition: cpp_scope.h:103
cpp_scopest::current_scope
cpp_scopet & current_scope()
Definition: cpp_scopes.h:33
messaget::mstreamt::source_location
source_locationt source_location
Definition: message.h:247
typet::source_location
const source_locationt & source_location() const
Definition: type.h:71
struct_union_typet::componentt::set_pretty_name
void set_pretty_name(const irep_idt &name)
Definition: std_types.h:109
struct_union_typet::componentt::set_base_name
void set_base_name(const irep_idt &base_name)
Definition: std_types.h:89
struct_typet::bases
const basest & bases() const
Get the collection of base classes/structs.
Definition: std_types.h:257
cpp_typecheckt::put_compound_into_scope
void put_compound_into_scope(const struct_union_typet::componentt &component)
Definition: cpp_typecheck_compound_type.cpp:782
irept::id
const irep_idt & id() const
Definition: irep.h:418
to_struct_tag_type
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition: std_types.h:515
dstringt::empty
bool empty() const
Definition: dstring.h:88
cpp_typecheck.h
C++ Language Type Checking.
sharing_treet< irept, std::map< irep_namet, irept > >::subt
typename dt::subt subt
Definition: irep.h:182
struct_union_typet::componentt
Definition: std_types.h:64
struct_typet
Structure type, corresponds to C style structs.
Definition: std_types.h:226
cpp_namet::source_location
const source_locationt & source_location() const
Definition: cpp_name.h:73
irept::get
const irep_idt & get(const irep_namet &name) const
Definition: irep.cpp:51
symbolt
Symbol table entry.
Definition: symbol.h:28
irept::set
void set(const irep_namet &name, const irep_idt &value)
Definition: irep.h:442
irept::get_sub
subt & get_sub()
Definition: irep.h:477
cpp_idt::prefix
std::string prefix
Definition: cpp_id.h:85
cpp_typecheckt::to_string
std::string to_string(const typet &) override
Definition: cpp_typecheck.cpp:84
exprt::add_source_location
source_locationt & add_source_location()
Definition: expr.h:259
cpp_typecheckt::resolve
exprt resolve(const cpp_namet &cpp_name, const cpp_typecheck_resolvet::wantt want, const cpp_typecheck_fargst &fargs, bool fail_with_exception=true)
Definition: cpp_typecheck.h:88
cpp_namet
Definition: cpp_name.h:17
struct_union_typet::is_incomplete
bool is_incomplete() const
A struct/union may be incomplete.
Definition: std_types.h:180
symbolt::name
irep_idt name
The unique identifier.
Definition: symbol.h:40
to_cpp_name
cpp_namet & to_cpp_name(irept &cpp_name)
Definition: cpp_name.h:144