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 
9 
12 
13 #include "cpp_typecheck.h"
14 
16 
18 {
19  // see if the declaration is empty
20  if(declaration.is_empty())
21  return;
22 
23  // The function bodies must not be checked here,
24  // but only at the very end when all declarations have been
25  // processed (or considering forward declarations at least)
26 
27  // templates are done in a dedicated function
28  if(declaration.is_template())
29  convert_template_declaration(declaration);
30  else
32 }
33 
35  cpp_declarationt &declaration,
36  codet &code)
37 {
38  codet new_code(ID_decl_block);
39  new_code.reserve_operands(declaration.declarators().size());
40 
41  // unnamed object
42  std::string identifier="#anon_union"+std::to_string(anon_counter++);
43 
44  irept name(ID_name);
45  name.set(ID_identifier, identifier);
46  name.set(ID_C_source_location, declaration.source_location());
47 
48  cpp_namet cpp_name;
49  cpp_name.move_to_sub(name);
50  cpp_declaratort declarator;
51  declarator.name()=cpp_name;
52 
53  cpp_declarator_convertert cpp_declarator_converter(*this);
54 
55  const symbolt &symbol=
56  cpp_declarator_converter.convert(declaration, declarator);
57 
58  if(!cpp_is_pod(declaration.type()))
59  {
60  error().source_location=follow(declaration.type()).source_location();
61  error() << "anonymous union is not POD" << eom;
62  throw 0;
63  }
64 
65  code_declt decl_statement(cpp_symbol_expr(symbol));
66 
67  new_code.move_to_operands(decl_statement);
68 
69  // do scoping
70  symbolt union_symbol=
71  *symbol_table.get_writeable(follow(symbol.type).get(ID_name));
72  const irept::subt &components=union_symbol.type.add(ID_components).get_sub();
73 
74  forall_irep(it, components)
75  {
76  if(it->find(ID_type).id()==ID_code)
77  {
78  error().source_location=union_symbol.type.source_location();
79  error() << "anonymous union `" << union_symbol.base_name
80  << "' shall not have function members" << eom;
81  throw 0;
82  }
83 
84  const irep_idt &base_name=it->get(ID_base_name);
85 
86  if(cpp_scopes.current_scope().contains(base_name))
87  {
88  error().source_location=union_symbol.type.source_location();
89  error() << "identifier `" << base_name << "' already in scope"
90  << eom;
91  throw 0;
92  }
93 
94  cpp_idt &id=cpp_scopes.current_scope().insert(base_name);
96  id.identifier=it->get(ID_name);
97  id.class_identifier=union_symbol.name;
98  id.is_member=true;
99  }
100 
101  symbol_table.get_writeable_ref(union_symbol.name)
102  .type.set(ID_C_unnamed_object, symbol.base_name);
103 
104  code.swap(new_code);
105 }
106 
108  cpp_declarationt &declaration)
109 {
110  assert(!declaration.is_template());
111 
112  // we first check if this is a typedef
113  typet &declaration_type=declaration.type();
114  bool is_typedef=declaration.is_typedef();
115 
116  // the name anonymous tag types
117  declaration.name_anon_struct_union();
118 
119  // do the type of the declaration
120  if(declaration.declarators().empty() || !has_auto(declaration_type))
121  typecheck_type(declaration_type);
122 
123  // Elaborate any class template instance _unless_ we do a typedef.
124  // These are only elaborated on usage!
125  if(!is_typedef)
126  elaborate_class_template(declaration_type);
127 
128  // mark as 'already typechecked'
129  if(!declaration.declarators().empty())
130  make_already_typechecked(declaration_type);
131 
132  // Special treatment for anonymous unions
133  if(declaration.declarators().empty() &&
134  follow(declaration.type()).get_bool(ID_C_is_anonymous))
135  {
136  typet final_type=follow(declaration.type());
137 
138  if(final_type.id()!=ID_union)
139  {
140  error().source_location=final_type.source_location();
141  error() << "top-level declaration does not declare anything"
142  << eom;
143  throw 0;
144  }
145 
146  codet dummy;
147  convert_anonymous_union(declaration, dummy);
148  }
149 
150  // do the declarators (optional)
151  for(auto &d : declaration.declarators())
152  {
153  // copy the declarator (we destroy the original)
154  cpp_declaratort declarator=d;
155 
156  cpp_declarator_convertert cpp_declarator_converter(*this);
157 
158  cpp_declarator_converter.is_typedef=is_typedef;
159 
160  symbolt &symbol=cpp_declarator_converter.convert(
161  declaration_type, declaration.storage_spec(),
162  declaration.member_spec(), declarator);
163 
164  // any template instance to remember?
165  if(declaration.find(ID_C_template).is_not_nil())
166  {
167  symbol.type.set(ID_C_template, declaration.find(ID_C_template));
168  symbol.type.set(
169  ID_C_template_arguments,
170  declaration.find(ID_C_template_arguments));
171  }
172 
173  // replace declarator by symbol expression
174  exprt tmp=cpp_symbol_expr(symbol);
175  d.swap(tmp);
176 
177  // is there a constructor to be called for the declarator?
178  if(symbol.is_lvalue &&
179  declarator.init_args().has_operands())
180  {
181  symbol.value=
183  symbol.location,
184  cpp_symbol_expr(symbol),
185  declarator.init_args().operands());
186  }
187  }
188 }
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:173
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:160
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:317
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:259
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:254
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:156
void convert_template_declaration(cpp_declarationt &declaration)
C++ Language Type Checking.
const typet & follow(const typet &) const
Definition: namespace.cpp:55
dstringt has one field, an unsigned integer no which is an index into a static table of strings...
Definition: dstring.h:33
unsigned anon_counter
bool has_operands() const
Definition: expr.h:63
const source_locationt & source_location() const
Definition: type.h:97
bool is_template() const
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:303
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
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:286
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:62
cpp_scopest cpp_scopes