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  for(auto &base : bases_irep)
26  {
27  const cpp_namet &name = to_cpp_name(base.find(ID_name));
28 
29  exprt base_symbol_expr=
30  resolve(
31  name,
34 
35  if(base_symbol_expr.id()!=ID_type)
36  {
38  error() << "expected type as struct/class base" << eom;
39  throw 0;
40  }
41 
42  // elaborate any class template instances given as bases
43  elaborate_class_template(base_symbol_expr.type());
44 
45  if(base_symbol_expr.type().id() != ID_struct_tag)
46  {
48  error() << "expected type symbol as struct/class base" << eom;
49  throw 0;
50  }
51 
52  const symbolt &base_symbol =
53  lookup(to_struct_tag_type(base_symbol_expr.type()));
54 
55  if(base_symbol.type.id() != ID_struct)
56  {
58  error() << "expected struct or class as base, but got '"
59  << to_string(base_symbol.type) << "'" << eom;
60  throw 0;
61  }
62 
63  if(to_struct_type(base_symbol.type).is_incomplete())
64  {
66  error() << "base type is incomplete" << eom;
67  throw 0;
68  }
69 
70  bool virtual_base = base.get_bool(ID_virtual);
71  irep_idt class_access = base.get(ID_protection);
72 
73  if(class_access.empty())
74  class_access = default_class_access;
75 
76  base_symbol_expr.id(ID_base);
77  base_symbol_expr.set(ID_access, class_access);
78 
79  if(virtual_base)
80  base_symbol_expr.set(ID_virtual, true);
81 
82  base.swap(base_symbol_expr);
83 
84  // Add base scopes as parents to the current scope
86  static_cast<cpp_scopet &>(*cpp_scopes.id_map[base_symbol.name]));
87 
88  const struct_typet &base_struct_type=
89  to_struct_type(base_symbol.type);
90 
92  base_struct_type,
93  class_access,
94  type,
95  bases,
96  vbases,
97  virtual_base);
98  }
99 
100  if(!vbases.empty())
101  {
102  // add a flag to determine
103  // if this is the most-derived-object
104  struct_typet::componentt most_derived(
105  cpp_scopes.current_scope().prefix + "::" + "@most_derived", bool_typet());
106 
107  most_derived.set_access(ID_public);
108  most_derived.set_base_name("@most_derived");
109  most_derived.set_pretty_name("@most_derived");
110  most_derived.add_source_location()=type.source_location();
111  put_compound_into_scope(most_derived);
112 
113  to_struct_type(type).components().push_back(most_derived);
114  }
115 }
116 
118  const struct_typet &from,
119  const irep_idt &access,
120  struct_typet &to,
121  std::set<irep_idt> &bases,
122  std::set<irep_idt> &vbases,
123  bool is_virtual)
124 {
125  const irep_idt &from_name = from.get(ID_name);
126 
127  if(is_virtual && vbases.find(from_name)!=vbases.end())
128  return;
129 
130  if(bases.find(from_name)!=bases.end())
131  {
133  error() << "error: non-virtual base class " << from_name
134  << " inherited multiple times" << eom;
135  throw 0;
136  }
137 
138  bases.insert(from_name);
139 
140  if(is_virtual)
141  vbases.insert(from_name);
142 
143  // look at the the parents of the base type
144  for(const auto &b : from.bases())
145  {
146  irep_idt sub_access = b.get(ID_access);
147 
148  if(access==ID_private)
149  sub_access=ID_private;
150  else if(access==ID_protected && sub_access!=ID_private)
151  sub_access=ID_protected;
152 
153  const symbolt &symb = lookup(b.type());
154 
155  const bool is_virtual_base = b.get_bool(ID_virtual);
156 
157  // recursive call
159  to_struct_type(symb.type),
160  sub_access,
161  to,
162  bases,
163  vbases,
164  is_virtual_base);
165  }
166 
167  // add the components
169 
170  for(const auto &c : from.components())
171  {
172  if(c.get_bool(ID_from_base))
173  continue;
174 
175  // copy the component
176  dest_c.push_back(c);
177 
178  // now twiddle the copy
179  struct_typet::componentt &component=dest_c.back();
180  component.set(ID_from_base, true);
181 
182  irep_idt comp_access=component.get_access();
183 
184  if(access==ID_public)
185  {
186  if(comp_access==ID_private)
187  component.set_access(ID_noaccess);
188  }
189  else if(access == ID_protected)
190  {
191  if(comp_access==ID_private)
192  component.set_access(ID_noaccess);
193  else
194  component.set_access(ID_private);
195  }
196  else if(access == ID_private)
197  {
198  if(comp_access == ID_noaccess || comp_access == ID_private)
199  component.set_access(ID_noaccess);
200  else
201  component.set_access(ID_private);
202  }
203  else
204  UNREACHABLE;
205 
206  // put into scope
207  }
208 }
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:141
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:117
cpp_typecheck_fargst
Definition: cpp_typecheck_fargs.h:21
to_struct_type
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition: std_types.h:302
struct_union_typet::componentt::set_access
void set_access(const irep_idt &access)
Definition: std_types.h:98
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:122
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:54
struct_union_typet::componentst
std::vector< componentt > componentst
Definition: std_types.h:134
component
auto component(T &struct_expr, const irep_idt &name, const namespacet &ns) -> decltype(struct_expr.op0())
Definition: std_expr.cpp:55
bool_typet
The Boolean type.
Definition: std_types.h:36
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:173
cpp_typecheck_resolvet::wantt::TYPE
@ TYPE
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:82
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:108
struct_union_typet::componentt::set_base_name
void set_base_name(const irep_idt &base_name)
Definition: std_types.h:88
struct_typet::bases
const basest & bases() const
Get the collection of base classes/structs.
Definition: std_types.h:256
cpp_typecheckt::put_compound_into_scope
void put_compound_into_scope(const struct_union_typet::componentt &component)
Definition: cpp_typecheck_compound_type.cpp:802
irept::id
const irep_idt & id() const
Definition: irep.h:407
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:468
dstringt::empty
bool empty() const
Definition: dstring.h:88
cpp_typecheck.h
C++ Language Type Checking.
sharing_treet< irept, forward_list_as_mapt< irep_namet, irept > >::subt
typename dt::subt subt
Definition: irep.h:171
struct_union_typet::componentt
Definition: std_types.h:63
struct_typet
Structure type, corresponds to C style structs.
Definition: std_types.h:225
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:431
irept::get_sub
subt & get_sub()
Definition: irep.h:467
cpp_idt::prefix
std::string prefix
Definition: cpp_id.h:84
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:243
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:179
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:148