CBMC
c_typecheck_initializer.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: ANSI-C Conversion / Type Checking
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
11 
12 #include <util/arith_tools.h>
13 #include <util/byte_operators.h>
14 #include <util/c_types.h>
15 #include <util/config.h>
16 #include <util/cprover_prefix.h>
17 #include <util/expr_initializer.h>
18 #include <util/prefix.h>
19 #include <util/std_types.h>
20 #include <util/string_constant.h>
21 
22 #include "anonymous_member.h"
23 #include "c_typecheck_base.h"
24 #include "type2name.h"
25 
27  exprt &initializer,
28  const typet &type,
29  bool force_constant)
30 {
31  exprt result=do_initializer_rec(initializer, type, force_constant);
32 
33  if(type.id()==ID_array)
34  {
35  const typet &result_type = result.type();
36  DATA_INVARIANT(result_type.id()==ID_array &&
37  to_array_type(result_type).size().is_not_nil(),
38  "any array must have a size");
39 
40  // we don't allow initialisation with symbols of array type
41  if(
42  result.id() != ID_array && result.id() != ID_array_of &&
43  result.id() != ID_compound_literal)
44  {
46  error() << "invalid array initializer " << to_string(result)
47  << eom;
48  throw 0;
49  }
50  }
51 
52  initializer=result;
53 }
54 
57  const exprt &value,
58  const typet &type,
59  bool force_constant)
60 {
61  const typet &full_type=follow(type);
62 
63  if(
64  (full_type.id() == ID_struct || full_type.id() == ID_union) &&
65  to_struct_union_type(full_type).is_incomplete())
66  {
68  error() << "type '" << to_string(type)
69  << "' is still incomplete -- cannot initialize" << eom;
70  throw 0;
71  }
72 
73  if(value.id()==ID_initializer_list)
74  return do_initializer_list(value, type, force_constant);
75 
76  if(
77  value.id() == ID_array && value.get_bool(ID_C_string_constant) &&
78  full_type.id() == ID_array &&
79  (to_array_type(full_type).element_type().id() == ID_signedbv ||
80  to_array_type(full_type).element_type().id() == ID_unsignedbv) &&
81  to_bitvector_type(to_array_type(full_type).element_type()).get_width() ==
83  {
84  exprt tmp=value;
85 
86  // adjust char type
88  to_array_type(full_type).element_type();
89 
90  Forall_operands(it, tmp)
91  it->type() = to_array_type(full_type).element_type();
92 
93  if(full_type.id()==ID_array &&
94  to_array_type(full_type).is_complete())
95  {
96  const auto &array_type = to_array_type(full_type);
97 
98  // check size
99  const auto array_size = numeric_cast<mp_integer>(array_type.size());
100  if(!array_size.has_value())
101  {
103  error() << "array size needs to be constant, got "
104  << to_string(array_type.size()) << eom;
105  throw 0;
106  }
107 
108  if(*array_size < 0)
109  {
111  error() << "array size must not be negative" << eom;
112  throw 0;
113  }
114 
115  if(mp_integer(tmp.operands().size()) > *array_size)
116  {
117  // cut off long strings. gcc does a warning for this
118  tmp.operands().resize(numeric_cast_v<std::size_t>(*array_size));
119  tmp.type()=type;
120  }
121  else if(mp_integer(tmp.operands().size()) < *array_size)
122  {
123  // fill up
124  tmp.type()=type;
125  const auto zero = zero_initializer(
126  array_type.element_type(), value.source_location(), *this);
127  if(!zero.has_value())
128  {
130  error() << "cannot zero-initialize array with subtype '"
131  << to_string(array_type.element_type()) << "'" << eom;
132  throw 0;
133  }
134  tmp.operands().resize(numeric_cast_v<std::size_t>(*array_size), *zero);
135  }
136  }
137 
138  return tmp;
139  }
140 
141  if(
142  value.id() == ID_string_constant && full_type.id() == ID_array &&
143  (to_array_type(full_type).element_type().id() == ID_signedbv ||
144  to_array_type(full_type).element_type().id() == ID_unsignedbv) &&
145  to_bitvector_type(to_array_type(full_type).element_type()).get_width() ==
146  char_type().get_width())
147  {
148  // will go away, to be replaced by the above block
149 
151  // adjust char type
152  to_array_type(tmp1.type()).element_type() =
153  to_array_type(full_type).element_type();
154 
155  exprt tmp2=tmp1.to_array_expr();
156 
157  if(full_type.id()==ID_array &&
158  to_array_type(full_type).is_complete())
159  {
160  // check size
161  const auto array_size =
162  numeric_cast<mp_integer>(to_array_type(full_type).size());
163  if(!array_size.has_value())
164  {
166  error() << "array size needs to be constant, got "
167  << to_string(to_array_type(full_type).size()) << eom;
168  throw 0;
169  }
170 
171  if(*array_size < 0)
172  {
174  error() << "array size must not be negative" << eom;
175  throw 0;
176  }
177 
178  if(mp_integer(tmp2.operands().size()) > *array_size)
179  {
180  // cut off long strings. gcc does a warning for this
181  tmp2.operands().resize(numeric_cast_v<std::size_t>(*array_size));
182  tmp2.type()=type;
183  }
184  else if(mp_integer(tmp2.operands().size()) < *array_size)
185  {
186  // fill up
187  tmp2.type()=type;
188  const auto zero = zero_initializer(
189  to_array_type(full_type).element_type(),
190  value.source_location(),
191  *this);
192  if(!zero.has_value())
193  {
195  error() << "cannot zero-initialize array with subtype '"
196  << to_string(to_array_type(full_type).element_type()) << "'"
197  << eom;
198  throw 0;
199  }
200  tmp2.operands().resize(numeric_cast_v<std::size_t>(*array_size), *zero);
201  }
202  }
203 
204  return tmp2;
205  }
206 
207  if(full_type.id()==ID_array &&
208  to_array_type(full_type).size().is_nil())
209  {
211  error() << "type '" << to_string(full_type)
212  << "' cannot be initialized with '" << to_string(value) << "'"
213  << eom;
214  throw 0;
215  }
216 
217  if(value.id()==ID_designated_initializer)
218  {
220  error() << "type '" << to_string(full_type)
221  << "' cannot be initialized with designated initializer" << eom;
222  throw 0;
223  }
224 
225  exprt result=value;
226  implicit_typecast(result, type);
227  return result;
228 }
229 
231 {
232  // this one doesn't need initialization
233  if(has_prefix(id2string(symbol.name), CPROVER_PREFIX "constant_infinity"))
234  return;
235 
236  if(symbol.is_type)
237  return;
238 
239  if(symbol.value.is_not_nil())
240  {
241  typecheck_expr(symbol.value);
242  do_initializer(symbol.value, symbol.type, true);
243 
244  // A flexible array may have been initialized, which entails a type change.
245  // Note that the type equality test is important: we want to preserve
246  // annotations like typedefs or const-ness when the type is otherwise the
247  // same.
248  if(!symbol.is_macro && symbol.type != symbol.value.type())
249  symbol.type = symbol.value.type();
250  }
251 
252  if(symbol.is_macro)
253  make_constant(symbol.value);
254 }
255 
257  const typet &type,
258  designatort &designator)
259 {
260  designatort::entryt entry(type);
261 
262  const typet &full_type=follow(type);
263 
264  if(full_type.id()==ID_struct)
265  {
266  const struct_typet &struct_type=to_struct_type(full_type);
267 
268  entry.size=struct_type.components().size();
269  entry.subtype.make_nil();
270  // only a top-level struct may end with a variable-length array
271  entry.vla_permitted=designator.empty();
272 
273  for(const auto &c : struct_type.components())
274  {
275  if(c.type().id() != ID_code && !c.get_is_padding())
276  {
277  entry.subtype = c.type();
278  break;
279  }
280 
281  ++entry.index;
282  }
283  }
284  else if(full_type.id()==ID_union)
285  {
286  const union_typet &union_type=to_union_type(full_type);
287 
288  if(union_type.components().empty())
289  {
290  entry.size=0;
291  entry.subtype.make_nil();
292  }
293  else
294  {
295  // The default is to initialize using the first member of the
296  // union.
297  entry.size=1;
298  entry.subtype=union_type.components().front().type();
299  }
300  }
301  else if(full_type.id()==ID_array)
302  {
303  const array_typet &array_type=to_array_type(full_type);
304 
305  if(array_type.size().is_nil())
306  {
307  entry.size=0;
308  entry.subtype = array_type.element_type();
309  }
310  else
311  {
312  const auto array_size = numeric_cast<mp_integer>(array_type.size());
313  if(!array_size.has_value())
314  {
315  error().source_location = array_type.size().source_location();
316  error() << "array has non-constant size '"
317  << to_string(array_type.size()) << "'" << eom;
318  throw 0;
319  }
320 
321  entry.size = numeric_cast_v<std::size_t>(*array_size);
322  entry.subtype = array_type.element_type();
323  }
324  }
325  else if(full_type.id()==ID_vector)
326  {
327  const vector_typet &vector_type=to_vector_type(full_type);
328 
329  const auto vector_size = numeric_cast<mp_integer>(vector_type.size());
330 
331  if(!vector_size.has_value())
332  {
333  error().source_location = vector_type.size().source_location();
334  error() << "vector has non-constant size '"
335  << to_string(vector_type.size()) << "'" << eom;
336  throw 0;
337  }
338 
339  entry.size = numeric_cast_v<std::size_t>(*vector_size);
340  entry.subtype = vector_type.element_type();
341  }
342  else
343  UNREACHABLE;
344 
345  designator.push_entry(entry);
346 }
347 
348 exprt::operandst::const_iterator c_typecheck_baset::do_designated_initializer(
349  exprt &result,
350  designatort &designator,
351  const exprt &initializer_list,
352  exprt::operandst::const_iterator init_it,
353  bool force_constant)
354 {
355  // copy the value, we may need to adjust it
356  exprt value=*init_it;
357 
358  assert(!designator.empty());
359 
360  if(value.id()==ID_designated_initializer)
361  {
362  assert(value.operands().size()==1);
363 
364  designator=
366  designator.front().type,
367  static_cast<const exprt &>(value.find(ID_designator)));
368 
369  assert(!designator.empty());
370 
371  // discard the return value
373  result, designator, value, value.operands().begin(), force_constant);
374  return ++init_it;
375  }
376 
377  exprt *dest=&result;
378 
379  // first phase: follow given designator
380 
381  for(size_t i=0; i<designator.size(); i++)
382  {
383  size_t index=designator[i].index;
384  const typet &type=designator[i].type;
385  const typet &full_type=follow(type);
386 
387  if(full_type.id()==ID_array ||
388  full_type.id()==ID_vector)
389  {
390  // zero_initializer may have built an array_of expression for a large
391  // array; as we have a designated initializer we need to have an array of
392  // individual objects
393  if(dest->id() == ID_array_of)
394  {
395  const array_typet array_type = to_array_type(dest->type());
396  const auto array_size = numeric_cast<mp_integer>(array_type.size());
397  if(!array_size.has_value())
398  {
400  error() << "cannot zero-initialize array with element type '"
401  << to_string(to_type_with_subtype(full_type).subtype()) << "'"
402  << eom;
403  throw 0;
404  }
405  const exprt zero = to_array_of_expr(*dest).what();
406  *dest = array_exprt{{}, array_type};
407  dest->operands().resize(numeric_cast_v<std::size_t>(*array_size), zero);
408  }
409 
410  if(index>=dest->operands().size())
411  {
412  if(full_type.id()==ID_array &&
413  (to_array_type(full_type).size().is_zero() ||
414  to_array_type(full_type).size().is_nil()))
415  {
416  const typet &element_type = to_array_type(full_type).element_type();
417 
418  // we are willing to grow an incomplete or zero-sized array --
419  // do_initializer_list will fix up the resulting type
420  const auto zero =
421  zero_initializer(element_type, value.source_location(), *this);
422  if(!zero.has_value())
423  {
425  error() << "cannot zero-initialize array with element type '"
426  << to_string(element_type) << "'" << eom;
427  throw 0;
428  }
429  dest->operands().resize(
430  numeric_cast_v<std::size_t>(index) + 1, *zero);
431  }
432  else
433  {
435  error() << "array index designator " << index
436  << " out of bounds (" << dest->operands().size()
437  << ")" << eom;
438  throw 0;
439  }
440  }
441 
442  dest = &(dest->operands()[numeric_cast_v<std::size_t>(index)]);
443  }
444  else if(full_type.id()==ID_struct)
445  {
446  const struct_typet::componentst &components=
447  to_struct_type(full_type).components();
448 
449  if(index>=dest->operands().size())
450  {
452  error() << "structure member designator " << index
453  << " out of bounds (" << dest->operands().size()
454  << ")" << eom;
455  throw 0;
456  }
457 
458  DATA_INVARIANT(index<components.size(),
459  "member designator is bounded by components size");
460  DATA_INVARIANT(components[index].type().id()!=ID_code &&
461  !components[index].get_is_padding(),
462  "member designator points at data member");
463 
464  dest=&(dest->operands()[index]);
465  }
466  else if(full_type.id()==ID_union)
467  {
468  const union_typet &union_type=to_union_type(full_type);
469 
470  const union_typet::componentst &components=
471  union_type.components();
472 
473  if(components.empty())
474  {
476  error() << "union member designator found for empty union" << eom;
477  throw 0;
478  }
479  else if(init_it != initializer_list.operands().begin())
480  {
482  {
484  error() << "too many initializers" << eom;
485  throw 0;
486  }
487  else
488  {
490  warning() << "excess elements in union initializer" << eom;
491 
492  return ++init_it;
493  }
494  }
495  else if(index >= components.size())
496  {
498  error() << "union member designator " << index << " out of bounds ("
499  << components.size() << ")" << eom;
500  throw 0;
501  }
502 
503  const union_typet::componentt &component = components[index];
504 
505  if(
506  dest->id() == ID_union &&
507  to_union_expr(*dest).get_component_name() == component.get_name())
508  {
509  // Already right union component. We can initialize multiple submembers,
510  // so do not overwrite this.
511  dest = &(to_union_expr(*dest).op());
512  }
513  else if(dest->id() == ID_union)
514  {
515  // The designated initializer does not initialize the maximum member,
516  // which the (default) zero initializer prepared. Replace this by a
517  // component-specific initializer; other bytes have an unspecified value
518  // (C Standard 6.2.6.1(7)). In practice, objects of static lifetime are
519  // fully zero initialized, so we just byte-update on top of the existing
520  // zero initializer.
521  const auto zero =
522  zero_initializer(component.type(), value.source_location(), *this);
523  if(!zero.has_value())
524  {
526  error() << "cannot zero-initialize union component of type '"
527  << to_string(component.type()) << "'" << eom;
528  throw 0;
529  }
530 
532  {
533  byte_update_exprt byte_update =
534  make_byte_update(*dest, from_integer(0, c_index_type()), *zero);
535  byte_update.add_source_location() = value.source_location();
536  *dest = std::move(byte_update);
537  dest = &(to_byte_update_expr(*dest).op2());
538  }
539  else
540  {
541  union_exprt union_expr(component.get_name(), *zero, type);
542  union_expr.add_source_location() = value.source_location();
543  *dest = std::move(union_expr);
544  dest = &(to_union_expr(*dest).op());
545  }
546  }
547  else if(
548  dest->id() == ID_byte_update_big_endian ||
549  dest->id() == ID_byte_update_little_endian)
550  {
551  // handle the byte update introduced by an earlier initializer (if
552  // current_symbol.is_static_lifetime)
553  byte_update_exprt &byte_update = to_byte_update_expr(*dest);
554  dest = &byte_update.op2();
555  }
556  }
557  else
558  UNREACHABLE;
559  }
560 
561  // second phase: assign value
562  // for this, we may need to go down, adding to the designator
563 
564  while(true)
565  {
566  // see what type we have to initialize
567 
568  const typet &type=designator.back().subtype;
569  const typet &full_type=follow(type);
570 
571  // do we initialize a scalar?
572  if(full_type.id()!=ID_struct &&
573  full_type.id()!=ID_union &&
574  full_type.id()!=ID_array &&
575  full_type.id()!=ID_vector)
576  {
577  // The initializer for a scalar shall be a single expression,
578  // * optionally enclosed in braces. *
579 
580  if(value.id()==ID_initializer_list &&
581  value.operands().size()==1)
582  {
583  *dest =
584  do_initializer_rec(to_unary_expr(value).op(), type, force_constant);
585  }
586  else
587  *dest=do_initializer_rec(value, type, force_constant);
588 
589  assert(full_type==follow(dest->type()));
590 
591  return ++init_it; // done
592  }
593 
594  // union? The component in the zero initializer might
595  // not be the first one.
596  if(full_type.id()==ID_union)
597  {
598  const union_typet &union_type=to_union_type(full_type);
599 
600  const union_typet::componentst &components=
601  union_type.components();
602 
603  if(!components.empty())
604  {
606  union_type.components().front();
607 
608  const auto zero =
609  zero_initializer(component.type(), value.source_location(), *this);
610  if(!zero.has_value())
611  {
613  error() << "cannot zero-initialize union component of type '"
614  << to_string(component.type()) << "'" << eom;
615  throw 0;
616  }
617  union_exprt union_expr(component.get_name(), *zero, type);
618  union_expr.add_source_location()=value.source_location();
619  *dest=union_expr;
620  }
621  }
622 
623  // see what initializer we are given
624  if(value.id()==ID_initializer_list)
625  {
626  *dest=do_initializer_rec(value, type, force_constant);
627  return ++init_it; // done
628  }
629  else if(value.id()==ID_string_constant)
630  {
631  // We stop for initializers that are string-constants,
632  // which are like arrays. We only do so if we are to
633  // initialize an array of scalars.
634  if(
635  full_type.id() == ID_array &&
636  (to_array_type(full_type).element_type().id() == ID_signedbv ||
637  to_array_type(full_type).element_type().id() == ID_unsignedbv))
638  {
639  *dest=do_initializer_rec(value, type, force_constant);
640  return ++init_it; // done
641  }
642  }
643  else if(follow(value.type())==full_type)
644  {
645  // a struct/union/vector can be initialized directly with
646  // an expression of the right type. This doesn't
647  // work with arrays, unfortunately.
648  if(full_type.id()==ID_struct ||
649  full_type.id()==ID_union ||
650  full_type.id()==ID_vector)
651  {
652  *dest=value;
653  return ++init_it; // done
654  }
655  }
656 
657  assert(full_type.id()==ID_struct ||
658  full_type.id()==ID_union ||
659  full_type.id()==ID_array ||
660  full_type.id()==ID_vector);
661 
662  // we are initializing a compound type, and enter it!
663  // this may change the type, full_type might not be valid any more
664  const typet dest_type=full_type;
665  const bool vla_permitted=designator.back().vla_permitted;
666  designator_enter(type, designator);
667 
668  // GCC permits (though issuing a warning with -Wall) composite
669  // types built from flat initializer lists
670  if(dest->operands().empty())
671  {
673  warning() << "initialisation of " << dest_type.id()
674  << " requires initializer list, found " << value.id()
675  << " instead" << eom;
676 
677  // in case of a variable-length array consume all remaining
678  // initializer elements
679  if(vla_permitted &&
680  dest_type.id()==ID_array &&
681  (to_array_type(dest_type).size().is_zero() ||
682  to_array_type(dest_type).size().is_nil()))
683  {
684  value.id(ID_initializer_list);
685  value.operands().clear();
686  for( ; init_it!=initializer_list.operands().end(); ++init_it)
687  value.copy_to_operands(*init_it);
688  *dest=do_initializer_rec(value, dest_type, force_constant);
689 
690  return init_it;
691  }
692  else
693  {
695  error() << "cannot initialize type '" << to_string(dest_type)
696  << "' using value '" << to_string(value) << "'" << eom;
697  throw 0;
698  }
699  }
700 
701  dest = &(to_multi_ary_expr(*dest).op0());
702 
703  // we run into another loop iteration
704  }
705 
706  return ++init_it;
707 }
708 
710 {
711  assert(!designator.empty());
712 
713  while(true)
714  {
715  designatort::entryt &entry=designator[designator.size()-1];
716  const typet &full_type=follow(entry.type);
717 
718  entry.index++;
719 
720  if(full_type.id()==ID_array &&
721  to_array_type(full_type).size().is_nil())
722  return; // we will keep going forever
723 
724  if(full_type.id()==ID_struct &&
725  entry.index<entry.size)
726  {
727  // need to adjust subtype
728  const struct_typet &struct_type=
729  to_struct_type(full_type);
730  const struct_typet::componentst &components=
731  struct_type.components();
732  assert(components.size()==entry.size);
733 
734  // we skip over any padding or code
735  // we also skip over anonymous members
736  while(entry.index < entry.size &&
737  (components[entry.index].get_is_padding() ||
738  (components[entry.index].get_anonymous() &&
739  components[entry.index].type().id() != ID_struct_tag &&
740  components[entry.index].type().id() != ID_union_tag) ||
741  components[entry.index].type().id() == ID_code))
742  {
743  entry.index++;
744  }
745 
746  if(entry.index<entry.size)
747  entry.subtype=components[entry.index].type();
748  }
749 
750  if(entry.index<entry.size)
751  return; // done
752 
753  if(designator.size()==1)
754  return; // done
755 
756  // pop entry
757  designator.pop_entry();
758 
759  assert(!designator.empty());
760  }
761 }
762 
764  const typet &src_type,
765  const exprt &src)
766 {
767  assert(!src.operands().empty());
768 
769  typet type=src_type;
770  designatort designator;
771 
772  forall_operands(it, src)
773  {
774  const exprt &d_op=*it;
775  designatort::entryt entry(type);
776  const typet &full_type=follow(entry.type);
777 
778  if(full_type.id()==ID_array)
779  {
780  if(d_op.id()!=ID_index)
781  {
783  error() << "expected array index designator" << eom;
784  throw 0;
785  }
786 
787  exprt tmp_index = to_unary_expr(d_op).op();
788  make_constant_index(tmp_index);
789 
790  mp_integer index, size;
791 
792  if(to_integer(to_constant_expr(tmp_index), index))
793  {
795  error() << "expected constant array index designator" << eom;
796  throw 0;
797  }
798 
799  if(to_array_type(full_type).size().is_nil())
800  size=0;
801  else if(
802  const auto size_opt =
803  numeric_cast<mp_integer>(to_array_type(full_type).size()))
804  size = *size_opt;
805  else
806  {
808  error() << "expected constant array size" << eom;
809  throw 0;
810  }
811 
812  entry.index = numeric_cast_v<std::size_t>(index);
813  entry.size = numeric_cast_v<std::size_t>(size);
814  entry.subtype = to_array_type(full_type).element_type();
815  }
816  else if(full_type.id()==ID_struct ||
817  full_type.id()==ID_union)
818  {
819  const struct_union_typet &struct_union_type=
820  to_struct_union_type(full_type);
821 
822  if(d_op.id()!=ID_member)
823  {
825  error() << "expected member designator" << eom;
826  throw 0;
827  }
828 
829  const irep_idt &component_name=d_op.get(ID_component_name);
830 
831  if(struct_union_type.has_component(component_name))
832  {
833  // a direct member
834  entry.index=struct_union_type.component_number(component_name);
835  entry.size=struct_union_type.components().size();
836  entry.subtype=struct_union_type.components()[entry.index].type();
837  }
838  else
839  {
840  // We will search for anonymous members,
841  // in a loop. This isn't supported by gcc, but icc does allow it.
842 
843  bool found=false, repeat;
844  typet tmp_type=entry.type;
845 
846  do
847  {
848  repeat=false;
849  std::size_t number = 0;
850  const struct_union_typet::componentst &components=
852 
853  for(const auto &c : components)
854  {
855  if(c.get_name() == component_name)
856  {
857  // done!
858  entry.index=number;
859  entry.size=components.size();
860  entry.subtype = c.type();
861  entry.type=tmp_type;
862  }
863  else if(
864  c.get_anonymous() &&
865  (c.type().id() == ID_struct_tag ||
866  c.type().id() == ID_union_tag) &&
867  has_component_rec(c.type(), component_name, *this))
868  {
869  entry.index=number;
870  entry.size=components.size();
871  entry.subtype = c.type();
872  entry.type=tmp_type;
873  tmp_type=entry.subtype;
874  designator.push_entry(entry);
875  found=repeat=true;
876  break;
877  }
878 
879  ++number;
880  }
881  }
882  while(repeat);
883 
884  if(!found)
885  {
887  error() << "failed to find struct component '" << component_name
888  << "' in initialization of '" << to_string(struct_union_type)
889  << "'" << eom;
890  throw 0;
891  }
892  }
893  }
894  else
895  {
897  error() << "designated initializers cannot initialize '"
898  << to_string(full_type) << "'" << eom;
899  throw 0;
900  }
901 
902  type=entry.subtype;
903  designator.push_entry(entry);
904  }
905 
906  assert(!designator.empty());
907 
908  return designator;
909 }
910 
912  const exprt &value,
913  const typet &type,
914  bool force_constant)
915 {
916  assert(value.id()==ID_initializer_list);
917 
918  const typet &full_type=follow(type);
919 
920  // 6.7.9, 14: An array of character type may be initialized by a character
921  // string literal or UTF-8 string literal, optionally enclosed in braces.
922  if(
923  full_type.id() == ID_array && value.operands().size() >= 1 &&
924  to_multi_ary_expr(value).op0().id() == ID_string_constant &&
925  (to_array_type(full_type).element_type().id() == ID_signedbv ||
926  to_array_type(full_type).element_type().id() == ID_unsignedbv) &&
927  to_bitvector_type(to_array_type(full_type).element_type()).get_width() ==
928  char_type().get_width())
929  {
930  if(value.operands().size() > 1)
931  {
933  warning() << "ignoring excess initializers" << eom;
934  }
935 
936  return do_initializer_rec(
937  to_multi_ary_expr(value).op0(), type, force_constant);
938  }
939 
940  exprt result;
941  if(full_type.id()==ID_struct ||
942  full_type.id()==ID_union ||
943  full_type.id()==ID_vector)
944  {
945  // start with zero everywhere
946  const auto zero = zero_initializer(type, value.source_location(), *this);
947  if(!zero.has_value())
948  {
950  error() << "cannot zero-initialize '" << to_string(full_type) << "'"
951  << eom;
952  throw 0;
953  }
954  result = *zero;
955  }
956  else if(full_type.id()==ID_array)
957  {
958  if(to_array_type(full_type).size().is_nil())
959  {
960  // start with empty array
961  result = array_exprt({}, to_array_type(full_type));
962  result.add_source_location()=value.source_location();
963  }
964  else
965  {
966  // start with zero everywhere
967  const auto zero = zero_initializer(type, value.source_location(), *this);
968  if(!zero.has_value())
969  {
971  error() << "cannot zero-initialize '" << to_string(full_type) << "'"
972  << eom;
973  throw 0;
974  }
975  result = *zero;
976  }
977  }
978  else
979  {
980  // The initializer for a scalar shall be a single expression,
981  // * optionally enclosed in braces. *
982 
983  if(value.operands().size()==1)
984  return do_initializer_rec(
985  to_unary_expr(value).op(), type, force_constant);
986 
988  error() << "cannot initialize '" << to_string(full_type)
989  << "' with an initializer list" << eom;
990  throw 0;
991  }
992 
993  designatort current_designator;
994 
995  designator_enter(type, current_designator);
996 
997  const exprt::operandst &operands=value.operands();
998  for(exprt::operandst::const_iterator it=operands.begin();
999  it!=operands.end(); ) // no ++it
1000  {
1002  result, current_designator, value, it, force_constant);
1003 
1004  // increase designator -- might go up
1005  increment_designator(current_designator);
1006  }
1007 
1008  if(full_type.id()==ID_struct)
1009  {
1010  const struct_typet &full_struct_type = to_struct_type(full_type);
1011  const struct_typet::componentst &components = full_struct_type.components();
1012  // make sure we didn't mess up index computation
1013  CHECK_RETURN(result.operands().size() == components.size());
1014 
1015  if(
1016  !components.empty() &&
1017  components.back().type().get_bool(ID_C_flexible_array_member))
1018  {
1019  const auto array_size = numeric_cast<mp_integer>(
1020  to_array_type(components.back().type()).size());
1021  array_exprt &init_array = to_array_expr(result.operands().back());
1022  if(
1023  !array_size.has_value() ||
1024  (*array_size <= 1 && init_array.operands().size() != *array_size))
1025  {
1026  struct_typet actual_struct_type = full_struct_type;
1027  array_typet &actual_array_type =
1028  to_array_type(actual_struct_type.components().back().type());
1029  actual_array_type.size() = from_integer(
1030  init_array.operands().size(), actual_array_type.index_type());
1031  actual_array_type.set(ID_C_flexible_array_member, true);
1032  init_array.type() = actual_array_type;
1033 
1034  // mimic bits of typecheck_compound_type to produce a new struct tag
1035  actual_struct_type.remove(ID_tag);
1036  type_symbolt compound_symbol{actual_struct_type};
1037  compound_symbol.mode = mode;
1038  compound_symbol.location = value.source_location();
1039  std::string typestr = type2name(compound_symbol.type, *this);
1040  compound_symbol.base_name = "#anon#" + typestr;
1041  compound_symbol.name = "tag-#anon#" + typestr;
1042  irep_idt tag_identifier = compound_symbol.name;
1043 
1044  // We might already have the same anonymous struct, which is fine as it
1045  // will be exactly the same type.
1046  symbol_table.insert(std::move(compound_symbol));
1047 
1048  result.type() = struct_tag_typet{tag_identifier};
1049  }
1050  }
1051  }
1052 
1053  if(full_type.id()==ID_array &&
1054  to_array_type(full_type).size().is_nil())
1055  {
1056  // make complete by setting array size
1057  array_typet &array_type = to_array_type(result.type());
1058  array_type.size() =
1059  from_integer(result.operands().size(), array_type.index_type());
1060  }
1061 
1062  return result;
1063 }
c_typecheck_baset::do_initializer
virtual void do_initializer(exprt &initializer, const typet &type, bool force_constant)
Definition: c_typecheck_initializer.cpp:26
exprt::copy_to_operands
void copy_to_operands(const exprt &expr)
Copy the given argument to the end of exprt's operands.
Definition: expr.h:155
UNREACHABLE
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:503
struct_union_typet::components
const componentst & components() const
Definition: std_types.h:147
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:36
to_union_type
const union_typet & to_union_type(const typet &type)
Cast a typet to a union_typet.
Definition: c_types.h:162
to_unary_expr
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition: std_expr.h:361
c_typecheck_baset::do_designated_initializer
virtual exprt::operandst::const_iterator do_designated_initializer(exprt &result, designatort &designator, const exprt &initializer_list, exprt::operandst::const_iterator init_it, bool force_constant)
Definition: c_typecheck_initializer.cpp:348
mp_integer
BigInt mp_integer
Definition: smt_terms.h:17
byte_update_exprt
Expression corresponding to op() where the bytes starting at position offset (given in number of byte...
Definition: byte_operators.h:77
Forall_operands
#define Forall_operands(it, expr)
Definition: expr.h:27
c_typecheck_baset::current_symbol
symbolt current_symbol
Definition: c_typecheck_base.h:71
arith_tools.h
symbolt::is_macro
bool is_macro
Definition: symbol.h:61
to_array_expr
const array_exprt & to_array_expr(const exprt &expr)
Cast an exprt to an array_exprt.
Definition: std_expr.h:1603
to_struct_type
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition: std_types.h:308
to_struct_union_type
const struct_union_typet & to_struct_union_type(const typet &type)
Cast a typet to a struct_union_typet.
Definition: std_types.h:214
array_of_exprt::what
exprt & what()
Definition: std_expr.h:1515
ternary_exprt::op2
exprt & op2()
Definition: expr.h:131
irept::make_nil
void make_nil()
Definition: irep.h:454
CHECK_RETURN
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:495
typet
The type of an expression, extends irept.
Definition: type.h:28
c_typecheck_base.h
c_typecheck_baset::to_string
virtual std::string to_string(const exprt &expr)
Definition: c_typecheck_base.cpp:24
irept::find
const irept & find(const irep_idt &name) const
Definition: irep.cpp:106
struct_union_typet
Base type for structs and unions.
Definition: std_types.h:61
symbolt::type
typet type
Type of symbol.
Definition: symbol.h:31
vector_typet::size
const constant_exprt & size() const
Definition: std_types.cpp:269
designatort::empty
bool empty() const
Definition: designator.h:36
configt::ansi_ct::flavourt::VISUAL_STUDIO
@ VISUAL_STUDIO
designatort::entryt::vla_permitted
bool vla_permitted
Definition: designator.h:27
type2name.h
prefix.h
union_exprt
Union constructor from single element.
Definition: std_expr.h:1707
to_string_constant
const string_constantt & to_string_constant(const exprt &expr)
Definition: string_constant.h:40
to_array_of_expr
const array_of_exprt & to_array_of_expr(const exprt &expr)
Cast an exprt to an array_of_exprt.
Definition: std_expr.h:1543
to_type_with_subtype
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition: type.h:193
string_constant.h
exprt
Base class for all expressions.
Definition: expr.h:55
struct_union_typet::componentst
std::vector< componentt > componentst
Definition: std_types.h:140
to_union_expr
const union_exprt & to_union_expr(const exprt &expr)
Cast an exprt to a union_exprt.
Definition: std_expr.h:1754
struct_tag_typet
A struct tag type, i.e., struct_typet with an identifier.
Definition: std_types.h:448
designatort::push_entry
void push_entry(const entryt &entry)
Definition: designator.h:45
designatort
Definition: designator.h:20
component
auto component(T &struct_expr, const irep_idt &name, const namespacet &ns) -> decltype(struct_expr.op0())
Definition: std_expr.cpp:76
vector_typet
The vector type.
Definition: std_types.h:1007
to_integer
bool to_integer(const constant_exprt &expr, mp_integer &int_value)
Convert a constant expression expr to an arbitrary-precision integer.
Definition: arith_tools.cpp:20
messaget::eom
static eomt eom
Definition: message.h:297
configt::ansi_c
struct configt::ansi_ct ansi_c
to_bitvector_type
const bitvector_typet & to_bitvector_type(const typet &type)
Cast a typet to a bitvector_typet.
Definition: bitvector_types.h:32
string_constantt
Definition: string_constant.h:14
struct_union_typet::component_number
std::size_t component_number(const irep_idt &component_name) const
Return the sequence number of the component with given name.
Definition: std_types.cpp:46
zero_initializer
optionalt< exprt > zero_initializer(const typet &type, const source_locationt &source_location, const namespacet &ns)
Create the equivalent of zero for type type.
Definition: expr_initializer.cpp:297
irept::get
const irep_idt & get(const irep_idt &name) const
Definition: irep.cpp:45
designatort::entryt
Definition: designator.h:23
c_typecheck_baset::make_constant
virtual void make_constant(exprt &expr)
Definition: c_typecheck_expr.cpp:4394
c_typecheck_baset::do_initializer_list
virtual exprt do_initializer_list(const exprt &value, const typet &type, bool force_constant)
Definition: c_typecheck_initializer.cpp:911
designatort::pop_entry
void pop_entry()
Definition: designator.h:50
array_typet::size
const exprt & size() const
Definition: std_types.h:800
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:84
has_component_rec
bool has_component_rec(const typet &type, const irep_idt &component_name, const namespacet &ns)
Definition: anonymous_member.cpp:74
irept::is_not_nil
bool is_not_nil() const
Definition: irep.h:380
array_exprt::type
const array_typet & type() const
Definition: std_expr.h:1570
byte_operators.h
Expression classes for byte-level operators.
vector_typet::element_type
const typet & element_type() const
The type of the elements of the vector.
Definition: std_types.h:1026
expr_initializer.h
messaget::result
mstreamt & result() const
Definition: message.h:409
messaget::error
mstreamt & error() const
Definition: message.h:399
has_prefix
bool has_prefix(const std::string &s, const std::string &prefix)
Definition: converter.cpp:13
DATA_INVARIANT
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition: invariant.h:510
id2string
const std::string & id2string(const irep_idt &d)
Definition: irep.h:47
messaget::mstreamt::source_location
source_locationt source_location
Definition: message.h:247
forall_operands
#define forall_operands(it, expr)
Definition: expr.h:20
to_byte_update_expr
const byte_update_exprt & to_byte_update_expr(const exprt &expr)
Definition: byte_operators.h:117
type2name
static std::string type2name(const typet &type, const namespacet &ns, symbol_numbert &symbol_number)
Definition: type2name.cpp:81
irept::set
void set(const irep_idt &name, const irep_idt &value)
Definition: irep.h:420
exprt::find_source_location
const source_locationt & find_source_location() const
Get a source_locationt from the expression or from its operands (non-recursively).
Definition: expr.cpp:165
designatort::entryt::size
size_t size
Definition: designator.h:26
std_types.h
symbol_tablet::insert
virtual std::pair< symbolt &, bool > insert(symbolt symbol) override
Author: Diffblue Ltd.
Definition: symbol_table.cpp:17
c_typecheck_baset::symbol_table
symbol_tablet & symbol_table
Definition: c_typecheck_base.h:68
designatort::front
const entryt & front() const
Definition: designator.h:41
struct_union_typet::has_component
bool has_component(const irep_idt &component_name) const
Definition: std_types.h:157
c_typecheck_baset::make_constant_index
virtual void make_constant_index(exprt &expr)
Definition: c_typecheck_expr.cpp:4414
irept::is_nil
bool is_nil() const
Definition: irep.h:376
irept::id
const irep_idt & id() const
Definition: irep.h:396
exprt::operandst
std::vector< exprt > operandst
Definition: expr.h:58
union_typet
The union type.
Definition: c_types.h:124
designatort::back
const entryt & back() const
Definition: designator.h:40
designatort::size
size_t size() const
Definition: designator.h:37
unary_exprt::op
const exprt & op() const
Definition: std_expr.h:326
cprover_prefix.h
designatort::entryt::index
size_t index
Definition: designator.h:25
c_typecheck_baset::designator_enter
void designator_enter(const typet &type, designatort &designator)
Definition: c_typecheck_initializer.cpp:256
c_typecheck_baset::typecheck_expr
virtual void typecheck_expr(exprt &expr)
Definition: c_typecheck_expr.cpp:46
config
configt config
Definition: config.cpp:25
char_type
bitvector_typet char_type()
Definition: c_types.cpp:124
bitvector_typet::get_width
std::size_t get_width() const
Definition: std_types.h:876
union_exprt::get_component_name
irep_idt get_component_name() const
Definition: std_expr.h:1716
struct_union_typet::componentt
Definition: std_types.h:68
configt::ansi_ct::mode
flavourt mode
Definition: config.h:237
symbolt::value
exprt value
Initial value of symbol.
Definition: symbol.h:34
string_constantt::to_array_expr
array_exprt to_array_expr() const
convert string into array constant
Definition: string_constant.cpp:29
struct_typet
Structure type, corresponds to C style structs.
Definition: std_types.h:230
c_typecheck_baset::do_initializer_rec
virtual exprt do_initializer_rec(const exprt &value, const typet &type, bool force_constant)
initialize something of type ‘type’ with given value ‘value’
Definition: c_typecheck_initializer.cpp:56
array_typet
Arrays with given size.
Definition: std_types.h:762
namespace_baset::follow
const typet & follow(const typet &) const
Resolve type symbol to the type it points to.
Definition: namespace.cpp:49
c_typecheck_baset::make_designator
designatort make_designator(const typet &type, const exprt &src)
Definition: c_typecheck_initializer.cpp:763
symbolt
Symbol table entry.
Definition: symbol.h:27
from_integer
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
Definition: arith_tools.cpp:100
symbolt::is_type
bool is_type
Definition: symbol.h:61
CPROVER_PREFIX
#define CPROVER_PREFIX
Definition: cprover_prefix.h:14
to_array_type
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition: std_types.h:844
designatort::entryt::type
typet type
Definition: designator.h:28
symbolt::is_static_lifetime
bool is_static_lifetime
Definition: symbol.h:65
type_symbolt
Symbol table entry describing a data type.
Definition: symbol.h:132
config.h
to_vector_type
const vector_typet & to_vector_type(const typet &type)
Cast a typet to a vector_typet.
Definition: std_types.h:1060
anonymous_member.h
c_typecheck_baset::increment_designator
void increment_designator(designatort &designator)
Definition: c_typecheck_initializer.cpp:709
exprt::operands
operandst & operands()
Definition: expr.h:94
designatort::entryt::subtype
typet subtype
Definition: designator.h:28
irept::remove
void remove(const irep_idt &name)
Definition: irep.cpp:96
exprt::add_source_location
source_locationt & add_source_location()
Definition: expr.h:216
messaget::warning
mstreamt & warning() const
Definition: message.h:404
multi_ary_exprt::op0
exprt & op0()
Definition: std_expr.h:877
c_index_type
bitvector_typet c_index_type()
Definition: c_types.cpp:16
to_multi_ary_expr
const multi_ary_exprt & to_multi_ary_expr(const exprt &expr)
Cast an exprt to a multi_ary_exprt.
Definition: std_expr.h:932
make_byte_update
byte_update_exprt make_byte_update(const exprt &_op, const exprt &_offset, const exprt &_value)
Construct a byte_update_exprt with endianness and byte width matching the current configuration.
Definition: byte_operators.cpp:54
c_typecheck_baset::mode
const irep_idt mode
Definition: c_typecheck_base.h:70
exprt::source_location
const source_locationt & source_location() const
Definition: expr.h:211
array_typet::index_type
typet index_type() const
The type of the index expressions into any instance of this type.
Definition: std_types.cpp:33
array_exprt
Array constructor from list of elements.
Definition: std_expr.h:1562
c_types.h
symbolt::name
irep_idt name
The unique identifier.
Definition: symbol.h:40
irept::get_bool
bool get_bool(const irep_idt &name) const
Definition: irep.cpp:58
c_typecheck_baset::implicit_typecast
virtual void implicit_typecast(exprt &expr, const typet &type)
Definition: c_typecheck_typecast.cpp:13
array_typet::element_type
const typet & element_type() const
The type of the elements of the array.
Definition: std_types.h:785
to_constant_expr
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition: std_expr.h:2992