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  const cpp_namet cpp_name(identifier, declaration.source_location());
45  cpp_declaratort declarator;
46  declarator.name()=cpp_name;
47 
48  cpp_declarator_convertert cpp_declarator_converter(*this);
49 
50  const symbolt &symbol=
51  cpp_declarator_converter.convert(declaration, declarator);
52 
53  if(!cpp_is_pod(declaration.type()))
54  {
55  error().source_location=follow(declaration.type()).source_location();
56  error() << "anonymous union is not POD" << eom;
57  throw 0;
58  }
59 
60  code_declt decl_statement(cpp_symbol_expr(symbol));
61 
62  new_code.move_to_operands(decl_statement);
63 
64  // do scoping
65  symbolt union_symbol=
66  *symbol_table.get_writeable(follow(symbol.type).get(ID_name));
67 
68  for(const auto &c : to_union_type(union_symbol.type).components())
69  {
70  if(c.type().id() == ID_code)
71  {
72  error().source_location=union_symbol.type.source_location();
73  error() << "anonymous union `" << union_symbol.base_name
74  << "' shall not have function members" << eom;
75  throw 0;
76  }
77 
78  const irep_idt &base_name = c.get_base_name();
79 
80  if(cpp_scopes.current_scope().contains(base_name))
81  {
82  error().source_location=union_symbol.type.source_location();
83  error() << "identifier `" << base_name << "' already in scope"
84  << eom;
85  throw 0;
86  }
87 
88  cpp_idt &id=cpp_scopes.current_scope().insert(base_name);
90  id.identifier = c.get_name();
91  id.class_identifier=union_symbol.name;
92  id.is_member=true;
93  }
94 
95  symbol_table.get_writeable_ref(union_symbol.name)
96  .type.set(ID_C_unnamed_object, symbol.base_name);
97 
98  code.swap(new_code);
99 }
100 
102  cpp_declarationt &declaration)
103 {
104  assert(!declaration.is_template());
105 
106  // we first check if this is a typedef
107  typet &declaration_type=declaration.type();
108  bool is_typedef=declaration.is_typedef();
109 
110  // the name anonymous tag types
111  declaration.name_anon_struct_union();
112 
113  // do the type of the declaration
114  if(declaration.declarators().empty() || !has_auto(declaration_type))
115  typecheck_type(declaration_type);
116 
117  // Elaborate any class template instance _unless_ we do a typedef.
118  // These are only elaborated on usage!
119  if(!is_typedef)
120  elaborate_class_template(declaration_type);
121 
122  // mark as 'already typechecked'
123  if(!declaration.declarators().empty())
124  make_already_typechecked(declaration_type);
125 
126  // Special treatment for anonymous unions
127  if(declaration.declarators().empty() &&
128  follow(declaration.type()).get_bool(ID_C_is_anonymous))
129  {
130  typet final_type=follow(declaration.type());
131 
132  if(final_type.id()!=ID_union)
133  {
134  error().source_location=final_type.source_location();
135  error() << "top-level declaration does not declare anything"
136  << eom;
137  throw 0;
138  }
139 
140  codet dummy;
141  convert_anonymous_union(declaration, dummy);
142  }
143 
144  // do the declarators (optional)
145  for(auto &d : declaration.declarators())
146  {
147  // copy the declarator (we destroy the original)
148  cpp_declaratort declarator=d;
149 
150  cpp_declarator_convertert cpp_declarator_converter(*this);
151 
152  cpp_declarator_converter.is_typedef=is_typedef;
153 
154  symbolt &symbol=cpp_declarator_converter.convert(
155  declaration_type, declaration.storage_spec(),
156  declaration.member_spec(), declarator);
157 
158  // any template instance to remember?
159  if(declaration.find(ID_C_template).is_not_nil())
160  {
161  symbol.type.set(ID_C_template, declaration.find(ID_C_template));
162  symbol.type.set(
163  ID_C_template_arguments,
164  declaration.find(ID_C_template_arguments));
165  }
166 
167  // replace declarator by symbol expression
168  exprt tmp=cpp_symbol_expr(symbol);
169  d.swap(tmp);
170 
171  // is there a constructor to be called for the declarator?
172  if(symbol.is_lvalue &&
173  declarator.init_args().has_operands())
174  {
175  auto constructor = cpp_constructor(
176  symbol.location,
177  cpp_symbol_expr(symbol),
178  declarator.init_args().operands());
179 
180  if(constructor.has_value())
181  symbol.value = constructor.value();
182  else
183  symbol.value = nil_exprt();
184  }
185  }
186 }
bool is_typedef() const
C++ Language Type Checking.
The type of an expression, extends irept.
Definition: type.h:27
irep_idt name
The unique identifier.
Definition: symbol.h:40
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)
optionalt< codet > cpp_constructor(const source_locationt &source_location, const exprt &object, const exprt::operandst &operands)
void name_anon_struct_union()
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.
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)
Move the given argument to the end of exprt's operands.
Definition: expr.cpp:29
exprt value
Initial value of symbol.
Definition: symbol.h:34
const componentst & components() const
Definition: std_types.h:205
typet & type()
Return the type of the expression.
Definition: expr.h:68
Symbol table entry.
Definition: symbol.h:27
const cpp_member_spect & member_spec() const
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:93
const irep_idt & id() const
Definition: irep.h:259
bool contains(const irep_idt &base_name_to_lookup)
Definition: cpp_scope.cpp:203
void elaborate_class_template(const typet &type)
elaborate class template instances
const declaratorst & declarators() const
exprt & init_args()
A codet representing the declaration of a local variable.
Definition: std_code.h:352
The NIL expression.
Definition: std_expr.h:4461
void make_already_typechecked(typet &dest)
source_locationt source_location
Definition: message.h:236
bool cpp_is_pod(const typet &type) const
Definition: cpp_is_pod.cpp:14
void typecheck_type(typet &) override
id_classt id_class
Definition: cpp_id.h:51
const irep_idt & get(const irep_namet &name) const
Definition: irep.cpp:212
mstreamt & error() const
Definition: message.h:386
void convert_template_declaration(cpp_declarationt &declaration)
C++ Language Type Checking.
const typet & follow(const typet &) const
Resolve type symbol to the type it points to.
Definition: namespace.cpp:62
symbol_exprt cpp_symbol_expr(const symbolt &symbol)
Definition: cpp_util.cpp:14
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:35
unsigned anon_counter
bool has_operands() const
Return true if there is at least one operand.
Definition: expr.h:75
const source_locationt & source_location() const
Definition: type.h:62
static eomt eom
Definition: message.h:284
bool is_template() const
typet type
Type of symbol.
Definition: symbol.h:31
source_locationt location
Source code location of definition of symbol.
Definition: symbol.h:37
void convert_anonymous_union(cpp_declarationt &declaration, codet &new_code)
Base class for all expressions.
Definition: expr.h:54
irep_idt base_name
Base (non-scoped) name.
Definition: symbol.h:46
cpp_scopet & current_scope()
Definition: cpp_scopes.h:33
symbolt & convert(const typet &type, const cpp_storage_spect &storage_spec, const cpp_member_spect &member_spec, cpp_declaratort &declarator)
const union_typet & to_union_type(const typet &type)
Cast a typet to a union_typet.
Definition: std_types.h:450
const source_locationt & source_location() const
Definition: expr.h:228
void swap(irept &irep)
Definition: irep.h:303
cpp_namet & name()
Definition: cpp_id.h:28
Data structure for representing an arbitrary statement in a program.
Definition: std_code.h:34
operandst & operands()
Definition: expr.h:78
cpp_idt & insert(const irep_idt &_base_name)
Definition: cpp_scope.h:52
const irept & find(const irep_namet &name) const
Definition: irep.cpp:284
bool is_empty() const
void set(const irep_namet &name, const irep_idt &value)
Definition: irep.h:286
void reserve_operands(operandst::size_type n)
Definition: expr.h:108
bool is_lvalue
Definition: symbol.h:66
cpp_scopest cpp_scopes