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=
22  type.get_bool(ID_C_class)?ID_private:ID_public;
23 
24  irept::subt &bases_irep=type.add(ID_bases).get_sub();
25 
26  Forall_irep(base_it, bases_irep)
27  {
28  const cpp_namet &name=
29  to_cpp_name(base_it->find(ID_name));
30 
31  exprt base_symbol_expr=
32  resolve(
33  name,
36 
37  if(base_symbol_expr.id()!=ID_type)
38  {
40  error() << "expected type as struct/class base" << eom;
41  throw 0;
42  }
43 
44  // elaborate any class template instances given as bases
45  elaborate_class_template(base_symbol_expr.type());
46 
47  if(base_symbol_expr.type().id()!=ID_symbol)
48  {
50  error() << "expected type symbol as struct/class base" << eom;
51  throw 0;
52  }
53 
54  const symbolt &base_symbol =
55  lookup(to_symbol_type(base_symbol_expr.type()));
56 
57  if(base_symbol.type.id()==ID_incomplete_struct)
58  {
60  error() << "base type is incomplete" << eom;
61  throw 0;
62  }
63  else if(base_symbol.type.id()!=ID_struct)
64  {
66  error() << "expected struct or class as base, but got `"
67  << to_string(base_symbol.type) << "'" << 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 
107  most_derived.type()=bool_typet();
108  most_derived.set_access(ID_public);
109  most_derived.set(ID_base_name, "@most_derived");
110  most_derived.set_name(
111  cpp_scopes.current_scope().prefix+"::"+"@most_derived");
112  most_derived.set(ID_pretty_name, "@most_derived");
113  most_derived.add_source_location()=type.source_location();
114  put_compound_into_scope(most_derived);
115 
116  to_struct_type(type).components().push_back(most_derived);
117  }
118 }
119 
121  const struct_typet &from,
122  const irep_idt &access,
123  struct_typet &to,
124  std::set<irep_idt> &bases,
125  std::set<irep_idt> &vbases,
126  bool is_virtual)
127 {
128  const irep_idt &from_name = from.get(ID_name);
129 
130  if(is_virtual && vbases.find(from_name)!=vbases.end())
131  return;
132 
133  if(bases.find(from_name)!=bases.end())
134  {
136  error() << "error: non-virtual base class " << from_name
137  << " inherited multiple times" << eom;
138  throw 0;
139  }
140 
141  bases.insert(from_name);
142 
143  if(is_virtual)
144  vbases.insert(from_name);
145 
146  // look at the the parents of the base type
147  forall_irep(it, from.find(ID_bases).get_sub())
148  {
149  irep_idt sub_access=it->get(ID_access);
150 
151  if(access==ID_private)
152  sub_access=ID_private;
153  else if(access==ID_protected && sub_access!=ID_private)
154  sub_access=ID_protected;
155 
156  const symbolt &symb=
157  lookup(it->find(ID_type).get(ID_identifier));
158 
159  bool is_virtual=it->get_bool(ID_virtual);
160 
161  // recursive call
163  to_struct_type(symb.type),
164  sub_access,
165  to,
166  bases,
167  vbases,
168  is_virtual);
169  }
170 
171  // add the components
172  const struct_typet::componentst &src_c=from.components();
174 
175  for(struct_typet::componentst::const_iterator
176  it=src_c.begin();
177  it!=src_c.end();
178  it++)
179  {
180  if(it->get_bool(ID_from_base))
181  continue;
182 
183  // copy the component
184  dest_c.push_back(*it);
185 
186  // now twiddle the copy
187  struct_typet::componentt &component=dest_c.back();
188  component.set(ID_from_base, true);
189 
190  irep_idt comp_access=component.get_access();
191 
192  if(access==ID_public)
193  {
194  if(comp_access==ID_private)
195  component.set_access("noaccess");
196  }
197  else if(access == ID_protected)
198  {
199  if(comp_access==ID_private)
200  component.set_access("noaccess");
201  else
202  component.set_access(ID_private);
203  }
204  else if(access == ID_private)
205  {
206  if(comp_access == "noaccess" || comp_access == ID_private)
207  component.set_access("noaccess");
208  else
209  component.set_access(ID_private);
210  }
211  else
212  UNREACHABLE;
213 
214  // put into scope
215  }
216 }
irep_idt name
The unique identifier.
Definition: symbol.h:43
std::vector< irept > subt
Definition: irep.h:90
void set_name(const irep_idt &name)
Definition: std_types.h:187
cpp_namet & to_cpp_name(irept &cpp_name)
Definition: cpp_name.h:144
std::vector< componentt > componentst
Definition: std_types.h:243
const symbol_typet & to_symbol_type(const typet &type)
Cast a generic typet to a symbol_typet.
Definition: std_types.h:139
const componentst & components() const
Definition: std_types.h:245
typet & type()
Definition: expr.h:56
The proper Booleans.
Definition: std_types.h:34
Symbol table entry.This is a symbol in the symbol table, stored in an object of type symbol_tablet...
Definition: symbol.h:30
static mstreamt & eom(mstreamt &m)
Definition: message.h:272
Structure type.
Definition: std_types.h:297
bool get_bool(const irep_namet &name) const
Definition: irep.cpp:240
void add_secondary_scope(cpp_scopet &other)
Definition: cpp_scope.h:104
subt & get_sub()
Definition: irep.h:245
std::string prefix
Definition: cpp_id.h:80
const irep_idt & id() const
Definition: irep.h:189
const source_locationt & source_location() const
Definition: cpp_name.h:73
void elaborate_class_template(const typet &type)
elaborate class template instances
source_locationt source_location
Definition: message.h:214
void set_access(const irep_idt &access)
Definition: std_types.h:207
const irep_idt & get(const irep_namet &name) const
Definition: irep.cpp:213
mstreamt & error() const
Definition: message.h:302
C++ Language Type Checking.
#define Forall_irep(it, irep)
Definition: irep.h:65
const struct_typet & to_struct_type(const typet &type)
Cast a generic typet to a struct_typet.
Definition: std_types.h:318
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:87
id_mapt id_map
Definition: cpp_scopes.h:69
const source_locationt & source_location() const
Definition: type.h:97
typet type
Type of symbol.
Definition: symbol.h:34
void swap(dstringt &b)
Definition: dstring.h:118
const irep_idt & get_access() const
Definition: std_types.h:202
void typecheck_compound_bases(struct_typet &type)
Base class for all expressions.
Definition: expr.h:42
cpp_scopet & current_scope()
Definition: cpp_scopes.h:33
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)
#define UNREACHABLE
Definition: invariant.h:250
irept & add(const irep_namet &name)
Definition: irep.cpp:306
virtual std::string to_string(const typet &type)
source_locationt & add_source_location()
Definition: expr.h:130
void put_compound_into_scope(const struct_union_typet::componentt &component)
bool empty() const
Definition: dstring.h:61
const irept & find(const irep_namet &name) const
Definition: irep.cpp:285
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See namespace_baset::lookup().
Definition: namespace.cpp:130
void set(const irep_namet &name, const irep_idt &value)
Definition: irep.h:214
#define forall_irep(it, irep)
Definition: irep.h:61
cpp_scopest cpp_scopes