cprover
cpp_typecheck_declaration.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 
15 
17 {
18  // see if the declaration is empty
19  if(declaration.is_empty())
20  return;
21 
22  // Record the function bodies so we can check them later.
23  // This function is used recursively, so we save them.
24  method_bodiest old_method_bodies;
25  old_method_bodies.swap(method_bodies);
26 
27  // templates are done in a dedicated function
28  if(declaration.is_template())
29  convert_template_declaration(declaration);
30  else
32 
34  b.swap(method_bodies);
36  method_bodies.swap(old_method_bodies);
37 }
38 
40  cpp_declarationt &declaration,
41  codet &code)
42 {
43  codet new_code(ID_decl_block);
44  new_code.reserve_operands(declaration.declarators().size());
45 
46  // unnamed object
47  std::string identifier="#anon_union"+std::to_string(anon_counter++);
48 
49  irept name(ID_name);
50  name.set(ID_identifier, identifier);
51  name.set(ID_C_source_location, declaration.source_location());
52 
53  cpp_namet cpp_name;
54  cpp_name.move_to_sub(name);
55  cpp_declaratort declarator;
56  declarator.name()=cpp_name;
57 
58  cpp_declarator_convertert cpp_declarator_converter(*this);
59 
60  const symbolt &symbol=
61  cpp_declarator_converter.convert(declaration, declarator);
62 
63  if(!cpp_is_pod(declaration.type()))
64  {
65  error().source_location=follow(declaration.type()).source_location();
66  error() << "anonymous union is not POD" << eom;
67  throw 0;
68  }
69 
70  code_declt decl_statement(cpp_symbol_expr(symbol));
71 
72  new_code.move_to_operands(decl_statement);
73 
74  // do scoping
75  symbolt union_symbol=
76  *symbol_table.get_writeable(follow(symbol.type).get(ID_name));
77  const irept::subt &components=union_symbol.type.add(ID_components).get_sub();
78 
79  forall_irep(it, components)
80  {
81  if(it->find(ID_type).id()==ID_code)
82  {
83  error().source_location=union_symbol.type.source_location();
84  error() << "anonymous union `" << union_symbol.base_name
85  << "' shall not have function members" << eom;
86  throw 0;
87  }
88 
89  const irep_idt &base_name=it->get(ID_base_name);
90 
91  if(cpp_scopes.current_scope().contains(base_name))
92  {
93  error().source_location=union_symbol.type.source_location();
94  error() << "identifier `" << base_name << "' already in scope"
95  << eom;
96  throw 0;
97  }
98 
99  cpp_idt &id=cpp_scopes.current_scope().insert(base_name);
101  id.identifier=it->get(ID_name);
102  id.class_identifier=union_symbol.name;
103  id.is_member=true;
104  }
105 
107  "#unnamed_object", symbol.base_name);
108 
109  code.swap(new_code);
110 }
111 
113  cpp_declarationt &declaration)
114 {
115  assert(!declaration.is_template());
116 
117  // we first check if this is a typedef
118  typet &declaration_type=declaration.type();
119  bool is_typedef=declaration.is_typedef();
120 
121  // the name anonymous tag types
122  declaration.name_anon_struct_union();
123 
124  // do the type of the declaration
125  if(declaration.declarators().empty() || !has_auto(declaration_type))
126  typecheck_type(declaration_type);
127 
128  // Elaborate any class template instance _unless_ we do a typedef.
129  // These are only elaborated on usage!
130  if(!is_typedef)
131  elaborate_class_template(declaration_type);
132 
133  // mark as 'already typechecked'
134  if(!declaration.declarators().empty())
135  make_already_typechecked(declaration_type);
136 
137  // Special treatment for anonymous unions
138  if(declaration.declarators().empty() &&
139  follow(declaration.type()).get_bool(ID_C_is_anonymous))
140  {
141  typet final_type=follow(declaration.type());
142 
143  if(final_type.id()!=ID_union)
144  {
145  error().source_location=final_type.source_location();
146  error() << "top-level declaration does not declare anything"
147  << eom;
148  throw 0;
149  }
150 
151  codet dummy;
152  convert_anonymous_union(declaration, dummy);
153  }
154 
155  // do the declarators (optional)
156  for(auto &d : declaration.declarators())
157  {
158  // copy the declarator (we destroy the original)
159  cpp_declaratort declarator=d;
160 
161  cpp_declarator_convertert cpp_declarator_converter(*this);
162 
163  cpp_declarator_converter.is_typedef=is_typedef;
164 
165  symbolt &symbol=cpp_declarator_converter.convert(
166  declaration_type, declaration.storage_spec(),
167  declaration.member_spec(), declarator);
168 
169  // any template instance to remember?
170  if(declaration.find(ID_C_template).is_not_nil())
171  {
172  symbol.type.set(ID_C_template, declaration.find(ID_C_template));
173  symbol.type.set(
174  ID_C_template_arguments,
175  declaration.find(ID_C_template_arguments));
176  }
177 
178  // replace declarator by symbol expression
179  exprt tmp=cpp_symbol_expr(symbol);
180  d.swap(tmp);
181 
182  // is there a constructor to be called for the declarator?
183  if(symbol.is_lvalue &&
184  declarator.init_args().has_operands())
185  {
186  symbol.value=
188  symbol.location,
189  cpp_symbol_expr(symbol),
190  declarator.init_args().operands());
191  }
192  }
193 }
bool is_typedef() const
C++ Language Type Checking.
The type of an expression.
Definition: type.h:22
irep_idt name
The unique identifier.
Definition: symbol.h:43
void typecheck_type(typet &type)
bool is_not_nil() const
Definition: irep.h:103
const cpp_storage_spect & storage_spec() const
void convert_non_template_declaration(cpp_declarationt &declaration)
static bool has_auto(const typet &type)
std::vector< irept > subt
Definition: irep.h:90
void move_to_sub(irept &irep)
Definition: irep.cpp:204
void name_anon_struct_union()
symbolt & get_writeable_ref(const irep_idt &name)
Find a symbol in the symbol table for read-write access.
void move_to_operands(exprt &expr)
Definition: expr.cpp:22
exprt value
Initial value of symbol.
Definition: symbol.h:37
typet & type()
Definition: expr.h:56
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
const cpp_member_spect & member_spec() const
subt & get_sub()
Definition: irep.h:245
void convert(cpp_linkage_spect &)
symbol_tablet & symbol_table
virtual symbolt * get_writeable(const irep_idt &name) override
Find a symbol in the symbol table for read-write access.
Definition: symbol_table.h:87
const irep_idt & id() const
Definition: irep.h:189
void elaborate_class_template(const typet &type)
elaborate class template instances
const declaratorst & declarators() const
exprt & init_args()
A declaration of a local variable.
Definition: std_code.h:253
void make_already_typechecked(typet &dest)
source_locationt source_location
Definition: message.h:214
bool cpp_is_pod(const typet &type) const
Definition: cpp_is_pod.cpp:14
id_classt id_class
Definition: cpp_id.h:51
const irep_idt & get(const irep_namet &name) const
Definition: irep.cpp:213
mstreamt & error() const
Definition: message.h:302
Base class for tree-like data structures with sharing.
Definition: irep.h:86
void convert_template_declaration(cpp_declarationt &declaration)
C++ Language Type Checking.
const typet & follow(const typet &) const
Definition: namespace.cpp:55
unsigned anon_counter
bool has_operands() const
Definition: expr.h:63
const source_locationt & source_location() const
Definition: type.h:97
void typecheck_method_bodies(method_bodiest &)
bool is_template() const
method_bodiest method_bodies
typet type
Type of symbol.
Definition: symbol.h:34
source_locationt location
Source code location of definition of symbol.
Definition: symbol.h:40
void convert_anonymous_union(cpp_declarationt &declaration, codet &new_code)
Base class for all expressions.
Definition: expr.h:42
bool contains(const irep_idt &base_name)
Definition: cpp_scope.cpp:212
irep_idt base_name
Base (non-scoped) name.
Definition: symbol.h:49
cpp_scopet & current_scope()
Definition: cpp_scopes.h:33
std::string to_string(const string_constraintt &expr)
Used for debug printing.
symbolt & convert(const typet &type, const cpp_storage_spect &storage_spec, const cpp_member_spect &member_spec, cpp_declaratort &declarator)
const source_locationt & source_location() const
Definition: expr.h:125
irept & add(const irep_namet &name)
Definition: irep.cpp:306
void swap(irept &irep)
Definition: irep.h:231
cpp_namet & name()
Definition: cpp_id.h:28
A statement in a programming language.
Definition: std_code.h:21
exprt cpp_symbol_expr(const symbolt &symbol)
Definition: cpp_util.cpp:14
std::list< method_bodyt > method_bodiest
operandst & operands()
Definition: expr.h:66
cpp_idt & insert(const irep_idt &_base_name)
Definition: cpp_scope.h:48
const irept & find(const irep_namet &name) const
Definition: irep.cpp:285
bool is_empty() const
codet cpp_constructor(const source_locationt &source_location, const exprt &object, const exprt::operandst &operands)
void set(const irep_namet &name, const irep_idt &value)
Definition: irep.h:214
void reserve_operands(operandst::size_type n)
Definition: expr.h:96
bool is_lvalue
Definition: symbol.h:68
#define forall_irep(it, irep)
Definition: irep.h:61
cpp_scopest cpp_scopes