CBMC
string_format_builtin_function.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Built-in function for String.format
4 
5 Author: Romain Brenguier, Joel Allred
6 
7 \*******************************************************************/
8 
11 
12 #include <iterator>
13 #include <string>
14 
15 #include "format_specifier.h"
17 #include "string_refinement_util.h"
18 
19 #include <util/bitvector_expr.h>
20 #include <util/message.h>
21 #include <util/range.h>
22 #include <util/simplify_expr.h>
23 
25  const array_string_exprt &string,
26  const irep_idt &id,
27  array_poolt &array_pool);
28 
30  const exprt &return_code,
31  const std::vector<exprt> &fun_args,
32  array_poolt &array_pool)
33  : string_builtin_functiont(return_code, array_pool)
34 {
35  PRECONDITION(fun_args.size() >= 3);
36  result = array_pool.find(fun_args[1], fun_args[0]);
37  const array_string_exprt format_string_expr =
38  get_string_expr(array_pool, fun_args[2]);
39 
40  // List of arguments after the format string
41  inputs = make_range(fun_args.begin() + 3, fun_args.end())
42  .map([&](const exprt &arg) {
43  INVARIANT(
45  "arguments of format should be strings");
46  return get_string_expr(array_pool, arg);
47  })
48  .collect<std::vector<array_string_exprt>>();
49 
50  // format_string is only initialized if the expression is constant
51  if(
52  array_pool.get_or_create_length(format_string_expr).id() == ID_constant &&
53  format_string_expr.content().id() == ID_array)
54  {
55  const auto length = numeric_cast_v<std::size_t>(
56  to_constant_expr(array_pool.get_or_create_length(format_string_expr)));
58  to_array_expr(format_string_expr.content()), length);
59  }
60 }
61 
62 #if 0
63 // This code is deactivated as it is not used for now, but ultimalety this
64 // should be used to throw an exception when the format string is not correct
69 static bool check_format_string(std::string s)
70 {
71  std::string format_specifier=
72  "%(\\d+\\$)?([-#+ 0,(\\<]*)?(\\d+)?(\\.\\d+)?([tT])?([a-zA-Z%])";
73  std::regex regex(format_specifier);
74  std::smatch match;
75 
76  while(std::regex_search(s, match, regex))
77  {
78  if(match.position()!= 0)
79  for(const auto &c : match.str())
80  if(c=='%')
81  return false;
82  s=match.suffix();
83  }
84 
85  for(const auto &c : s)
86  if(c=='%')
87  return false;
88 
89  return true;
90 }
91 #endif
92 
94 static exprt is_null(const array_string_exprt &string, array_poolt &array_pool)
95 {
96  return and_exprt{
97  equal_exprt{array_pool.get_or_create_length(string),
98  from_integer(4, string.length_type())},
99  and_exprt{equal_exprt{string[0], from_integer('n', string[0].type())},
100  equal_exprt{string[1], from_integer('u', string[0].type())},
101  equal_exprt{string[2], from_integer('l', string[0].type())},
102  equal_exprt{string[3], from_integer('l', string[0].type())}}};
103 }
104 
117 static std::pair<array_string_exprt, string_constraintst>
119  string_constraint_generatort &generator,
120  const format_specifiert &fs,
121  const array_string_exprt &string_arg,
122  const typet &index_type,
123  const typet &char_type,
124  message_handlert &message_handler)
125 {
126  string_constraintst constraints;
127  array_poolt &array_pool = generator.array_pool;
128  const array_string_exprt res = array_pool.fresh_string(index_type, char_type);
129  std::pair<exprt, string_constraintst> return_code;
130  switch(fs.conversion)
131  {
133  return_code = generator.add_axioms_for_string_of_int(
134  res, format_arg_from_string(string_arg, ID_int, array_pool), 0);
135  return {res, std::move(return_code.second)};
137  return_code = generator.add_axioms_for_string_of_int_with_radix(
138  res,
139  format_arg_from_string(string_arg, ID_int, array_pool),
141  16);
142  return {res, std::move(return_code.second)};
144  return_code = generator.add_axioms_from_float_scientific_notation(
145  res, format_arg_from_string(string_arg, ID_float, array_pool));
146  return {res, std::move(return_code.second)};
148  return_code = generator.add_axioms_for_string_of_float(
149  res, format_arg_from_string(string_arg, ID_float, array_pool));
150  return {res, std::move(return_code.second)};
152  {
153  exprt arg_string = format_arg_from_string(string_arg, ID_char, array_pool);
154  array_string_exprt &string_expr = to_array_string_expr(arg_string);
155  // In the case the arg is null, the result will be equal to "null" and
156  // and otherwise we just take the 4th character of the string.
157  const exprt is_null_literal = is_null(string_expr, array_pool);
158  constraints.existential.push_back(
159  equal_exprt{array_pool.get_or_create_length(res),
160  if_exprt{is_null_literal,
162  from_integer(1, index_type)}});
163  constraints.existential.push_back(implies_exprt{
164  is_null_literal,
166  equal_exprt{res[1], from_integer('u', char_type)},
167  equal_exprt{res[2], from_integer('l', char_type)},
168  equal_exprt{res[3], from_integer('l', char_type)}}});
169  constraints.existential.push_back(implies_exprt{
170  not_exprt{is_null_literal},
171  equal_exprt{res[0], typecast_exprt{string_expr[3], char_type}}});
172  return {res, constraints};
173  }
175  return_code = generator.add_axioms_from_bool(
176  res, format_arg_from_string(string_arg, ID_boolean, array_pool));
177  return {res, std::move(return_code.second)};
179  {
180  const exprt arg_string = string_arg;
181  const array_string_exprt string_expr = to_array_string_expr(arg_string);
182  return {std::move(string_expr), {}};
183  }
185  return_code = generator.add_axioms_for_string_of_int(
186  res, format_arg_from_string(string_arg, "hashcode", array_pool), 0);
187  return {res, std::move(return_code.second)};
189  // TODO: the constant should depend on the system: System.lineSeparator()
190  return_code = generator.add_axioms_for_constant(res, "\n");
191  return {res, std::move(return_code.second)};
193  return_code = generator.add_axioms_for_constant(res, "%");
194  return {res, std::move(return_code.second)};
203  {
204  format_specifiert fs_lower = fs;
205  fs_lower.conversion = tolower(fs.conversion);
206  auto format_specifier_result = add_axioms_for_format_specifier(
207  generator, fs_lower, string_arg, index_type, char_type, message_handler);
208 
209  const exprt return_code_upper_case =
210  generator.fresh_symbol("return_code_upper_case", get_return_code_type());
211  const string_to_upper_case_builtin_functiont upper_case_function(
212  return_code_upper_case, res, format_specifier_result.first, array_pool);
213  auto upper_case_constraints =
214  upper_case_function.constraints(generator.fresh_symbol, message_handler);
215  merge(upper_case_constraints, std::move(format_specifier_result.second));
216  return {res, std::move(upper_case_constraints)};
217  }
225  {
227  // For all these unimplemented cases we return a non-deterministic string
228  messaget message{message_handler};
229  message.warning() << "unimplemented format specifier: " << fs.conversion
230  << message.eom;
231  return {array_pool.fresh_string(index_type, char_type), {}};
232  }
233  }
234 
235  INVARIANT(false, "format specifier must belong to [bBhHsScCdoxXeEfgGaAtT%n]");
236 }
237 
243  const array_string_exprt &string,
244  const irep_idt &id,
245  array_poolt &array_pool)
246 {
247  PRECONDITION(
248  to_array_type(string.content().type()).element_type() ==
249  unsignedbv_typet(16));
250 
251  if(id == "string_expr")
252  return string;
253  if(id == ID_int)
254  {
255  // Assume the string has length 4
256  // (int64)string.content[0] << 48 | (int64) string.content[1] << 32 |
257  // (int64)string.content[2] << 16 | (int64) string.content[3]
258  const signedbv_typet type{64};
259  return bitor_exprt{
260  bitor_exprt{shl_exprt{typecast_exprt{string[0], type}, 48},
261  shl_exprt{typecast_exprt{string[1], type}, 32}},
262  bitor_exprt{shl_exprt{typecast_exprt{string[2], type}, 16},
263  typecast_exprt{string[3], type}}};
264  }
265 
266  if(id == ID_char)
267  {
268  // Leave the string unchanged as the "null" string is used to represent null
269  return string;
270  }
271  if(id == ID_boolean)
272  {
273  // We assume the string has length exactly 4, if it is "null" return false
274  // and otherwise ignore the first 3 and return (bool)string.content[3]
275  return if_exprt{is_null(string, array_pool),
276  false_exprt{},
277  typecast_exprt{string[3], bool_typet()}};
278  }
279  if(id == ID_float)
280  {
281  // Deserialize an int and cast to float
282  const exprt as_int = format_arg_from_string(string, ID_int, array_pool);
283  return typecast_exprt{as_int, floatbv_typet{}};
284  }
286 }
287 
296 static std::pair<exprt, string_constraintst> add_axioms_for_format(
297  string_constraint_generatort &generator,
298  const array_string_exprt &res,
299  const std::string &s,
300  const std::vector<array_string_exprt> &args,
301  message_handlert &message_handler)
302 {
303  string_constraintst constraints;
304  array_poolt &array_pool = generator.array_pool;
305  const std::vector<format_elementt> format_strings = parse_format_string(s);
306  std::vector<array_string_exprt> intermediary_strings;
307  std::size_t arg_count = 0;
309  const typet &index_type = res.length_type();
310 
311  array_string_exprt string_arg;
312 
313  for(const format_elementt &fe : format_strings)
314  {
315  if(fe.is_format_specifier())
316  {
317  const format_specifiert &fs = fe.get_format_specifier();
318 
319  if(
322  {
323  if(fs.index == -1)
324  {
325  INVARIANT(
326  arg_count < args.size(), "number of format must match specifiers");
327  string_arg = args[arg_count++];
328  }
329  else
330  {
331  INVARIANT(fs.index > 0, "index in format should be positive");
332  INVARIANT(
333  static_cast<std::size_t>(fs.index) <= args.size(),
334  "number of format must match specifiers");
335 
336  // first argument `args[0]` corresponds to index 1
337  string_arg = args[fs.index - 1];
338  }
339  }
340 
341  auto result = add_axioms_for_format_specifier(
342  generator, fs, string_arg, index_type, char_type, message_handler);
343  merge(constraints, std::move(result.second));
344  intermediary_strings.push_back(result.first);
345  }
346  else
347  {
348  const array_string_exprt str =
349  array_pool.fresh_string(index_type, char_type);
350  auto result = generator.add_axioms_for_constant(
351  str, fe.get_format_text().get_content());
352  merge(constraints, result.second);
353  intermediary_strings.push_back(str);
354  }
355  }
356 
357  exprt return_code = from_integer(0, get_return_code_type());
358 
359  if(intermediary_strings.empty())
360  {
361  constraints.existential.push_back(equal_exprt(
362  array_pool.get_or_create_length(res), from_integer(0, index_type)));
363  return {return_code, constraints};
364  }
365 
366  array_string_exprt str = intermediary_strings[0];
367 
368  if(intermediary_strings.size() == 1)
369  {
370  // Copy the first string
371  auto result = generator.add_axioms_for_substring(
372  res,
373  str,
375  generator.array_pool.get_or_create_length(str));
376  merge(constraints, std::move(result.second));
377  return {result.first, std::move(constraints)};
378  }
379 
380  // start after the first string and stop before the last
381  for(std::size_t i = 1; i < intermediary_strings.size() - 1; ++i)
382  {
383  const array_string_exprt &intermediary = intermediary_strings[i];
384  const array_string_exprt fresh =
385  array_pool.fresh_string(index_type, char_type);
386  auto result = generator.add_axioms_for_concat(fresh, str, intermediary);
387  return_code = maximum(return_code, result.first);
388  merge(constraints, std::move(result.second));
389  str = fresh;
390  }
391 
392  auto result =
393  generator.add_axioms_for_concat(res, str, intermediary_strings.back());
394  merge(constraints, std::move(result.second));
395  return {maximum(result.first, return_code), std::move(constraints)};
396 }
397 
398 static std::vector<mp_integer> deserialize_constant_int_arg(
399  const std::vector<mp_integer> serialized,
400  const unsigned base)
401 {
402  PRECONDITION(serialized.size() == 4);
403 
404  // long value, to be used for other formats?
405  for(std::size_t i = 0; i < 4; i++)
406  {
408  serialized[i] <= 0xFFFF,
409  "Component of serialized value to"
410  "format must be bounded by 0xFFFF");
411  }
412 
413  const int64_t int64_value =
414  (serialized[0] << 48).to_long() | (serialized[1] << 32).to_long() |
415  (serialized[2] << 16).to_long() | serialized[3].to_long();
416  const mp_integer mp_integer_value{int64_value};
417  const std::string long_as_string = integer2string(mp_integer_value, base);
418 
419  return make_range(long_as_string).map([&](char c) { return mp_integer{c}; });
420 }
421 
422 static bool eval_is_null(const std::vector<mp_integer> &string)
423 {
424  return string.size() == 4 && string[0] == 'n' && string[1] == 'u' &&
425  string[2] == 'l' && string[3] == 'l';
426 }
427 
430 static std::vector<mp_integer> eval_format_specifier(
431  const format_specifiert &fs,
432  const std::vector<mp_integer> &arg)
433 {
434  switch(fs.conversion)
435  {
437  {
438  if(eval_is_null(arg))
439  return std::vector<mp_integer>{'n', 'u', 'l', 'l'};
440  return deserialize_constant_int_arg(arg, 10);
441  }
443  {
444  if(eval_is_null(arg))
445  return std::vector<mp_integer>{'n', 'u', 'l', 'l'};
446  auto upper_case_hex = deserialize_constant_int_arg(arg, 16);
447  // convert to lower case
448  return make_range(upper_case_hex).map([](const mp_integer &c) {
449  if('A' <= c && c <= 'Z')
450  return c + 0x20;
451  return c;
452  });
453  }
455  {
456  if(eval_is_null(arg))
457  return std::vector<mp_integer>{'n', 'u', 'l', 'l'};
458  return deserialize_constant_int_arg(arg, 16);
459  }
465  {
466  if(eval_is_null(arg))
467  return std::vector<mp_integer>{'n', 'u', 'l', 'l'};
468  return std::vector<mp_integer>{arg[3]};
469  }
471  {
472  if(arg[3] == 1)
473  return std::vector<mp_integer>{'t', 'r', 'u', 'e'};
474  return std::vector<mp_integer>{'f', 'a', 'l', 's', 'e'};
475  }
477  return arg;
481  // TODO: the constant should depend on the system: System.lineSeparator()
482  return std::vector<mp_integer>{'\n'};
484  return std::vector<mp_integer>{'%'};
493  {
494  format_specifiert fs_lower = fs;
495  fs_lower.conversion = tolower(fs.conversion);
496  auto lower_case = eval_format_specifier(fs_lower, arg);
497  return make_range(lower_case).map([](const mp_integer &c) {
498  // TODO: incomplete
499  if('a' <= c && c <= 'z')
500  return c - 0x20;
501  return c;
502  });
503  }
513  }
514 
515  INVARIANT(false, "format specifier must belong to [bBhHsScCdoxXeEfgGaAtT%n]");
516 }
517 
519  const std::function<exprt(const exprt &)> &get_value) const
520 {
521  if(!format_string.has_value())
522  return {};
523 
524  const std::vector<format_elementt> format_strings =
526  std::vector<mp_integer> result_vector;
527  std::size_t arg_count = 0;
528 
529  for(const format_elementt &fe : format_strings)
530  {
531  if(fe.is_format_specifier())
532  {
533  const format_specifiert &fs = fe.get_format_specifier();
534  if(
537  {
538  std::vector<mp_integer> evaluated_char_vector;
539 
540  if(fs.index == -1)
541  {
542  INVARIANT(
543  arg_count < inputs.size(),
544  "number of format must match specifiers");
545  if(auto arg_value = eval_string(inputs[arg_count++], get_value))
546  evaluated_char_vector = eval_format_specifier(fs, *arg_value);
547  else
548  return {};
549  }
550  else
551  {
552  INVARIANT(fs.index > 0, "index in format should be positive");
553  INVARIANT(
554  static_cast<std::size_t>(fs.index) <= inputs.size(),
555  "number of format must match specifiers");
556 
557  // first argument `args[0]` corresponds to index 1
558  if(auto arg_value = eval_string(inputs[fs.index - 1], get_value))
559  evaluated_char_vector = eval_format_specifier(fs, *arg_value);
560  else
561  return {};
562  }
563  std::move(
564  evaluated_char_vector.begin(),
565  evaluated_char_vector.end(),
566  std::back_inserter(result_vector));
567  }
569  {
570  result_vector.push_back('%');
571  }
572  else
573  {
574  // TODO: the character should depend on the system:
575  // System.lineSeparator()
576  result_vector.push_back('\n');
577  }
578  }
579  else
580  {
581  for(char c : fe.get_format_text().get_content())
582  result_vector.emplace_back(c);
583  }
584  }
585  return make_string(result_vector, to_array_type(result.type()));
586 }
587 
589  string_constraint_generatort &generator,
590  message_handlert &message_handler) const
591 {
592  // When `format_string` was not set, leave the result non-deterministic
593  if(!format_string.has_value())
594  return {};
595 
596  auto result_constraint_pair = add_axioms_for_format(
597  generator, result, format_string.value(), inputs, message_handler);
598  INVARIANT(
599  simplify_expr(result_constraint_pair.first, generator.ns).is_zero(),
600  "add_axioms_for_format should return 0, meaning that formatting was"
601  "successful");
602  result_constraint_pair.second.existential.push_back(
604  return result_constraint_pair.second;
605 }
606 
623  const exprt &pos_integer,
624  int max_length,
625  const typet &length_type,
626  const unsigned long radix)
627 {
628  if(max_length <= 1)
629  return from_integer(1, length_type);
630 
631  // If the current value doesn't fit in a smaller size representation, we have
632  // found the number of digits needed to represent that value.
633  const mp_integer max_value_for_smaller_size =
634  pow((mp_integer)radix, max_length - 1);
635  return if_exprt{
636  less_than(
637  pos_integer,
638  from_integer(max_value_for_smaller_size, pos_integer.type())),
640  pos_integer, max_length - 1, length_type, radix),
641  from_integer(max_length, length_type)};
642 }
643 
651  const exprt &integer,
652  const typet &length_type,
653  const unsigned long radix)
654 {
655  int max_pos_int_length;
656  if(length_type == signedbv_typet(32))
657  {
658  if(radix == 10)
659  max_pos_int_length = 10;
660  else if(radix == 16)
661  max_pos_int_length = 8;
662  else
664  }
665  else
666  {
667  // We only handle 32-bit signed integer type for now.
669  }
670 
671  return if_exprt{
672  greater_or_equal_to(integer, from_integer(0, integer.type())),
674  integer, max_pos_int_length, length_type, radix),
675  plus_exprt{
677  unary_minus_exprt{integer}, max_pos_int_length, length_type, radix),
678  from_integer(1, length_type)}};
679 }
680 
684  const format_specifiert &fs,
685  const array_string_exprt &arg,
686  const typet &index_type,
687  array_poolt &array_pool)
688 {
689  switch(fs.conversion)
690  {
692  {
693  return if_exprt(
694  is_null(arg, array_pool),
697  format_arg_from_string(arg, ID_int, array_pool), index_type, 10));
698  }
701  {
702  return length_of_decimal_int(
703  format_arg_from_string(arg, ID_int, array_pool), index_type, 16);
704  }
711  {
712  const exprt arg_string = format_arg_from_string(arg, ID_char, array_pool);
713  const array_string_exprt &string_expr = to_array_string_expr(arg_string);
714  // In the case the arg is null, the result will be equal to "null" and
715  // and otherwise we just take the 4th character of the string.
716  return if_exprt{is_null(string_expr, array_pool),
719  }
722  {
723  return if_exprt{format_arg_from_string(arg, ID_boolean, array_pool),
726  }
729  {
730  const exprt arg_string =
731  format_arg_from_string(arg, "string_expr", array_pool);
732  const array_string_exprt string_expr = to_array_string_expr(arg_string);
733  return array_pool.get_or_create_length(string_expr);
734  }
738  // TODO: the constant should depend on the system: System.lineSeparator()
739  return from_integer(1, index_type);
741  return from_integer(1, index_type);
747  {
748  return length_for_format_specifier(fs, arg, index_type, array_pool);
749  }
758  // For all these unimplemented cases we return a non-deterministic string
760  }
761 
762  INVARIANT(false, "format specifier must belong to [bBhHsScCdoxXeEfgGaAtT%n]");
763 }
764 
766 {
767  if(!format_string.has_value())
768  return true_exprt{};
769 
771  const std::vector<format_elementt> format_strings =
773  std::vector<exprt> intermediary_string_lengths;
774  std::size_t arg_count = 0;
775  const typet &index_type = result.length_type();
776 
777  for(const format_elementt &fe : format_strings)
778  {
779  if(fe.is_format_specifier())
780  {
781  const format_specifiert &fs = fe.get_format_specifier();
782  array_string_exprt arg;
783  if(
786  {
787  if(fs.index == -1)
788  {
789  INVARIANT(
790  arg_count < inputs.size(),
791  "number of format must match specifiers");
792  arg = inputs[arg_count++];
793  }
794  else
795  {
796  INVARIANT(fs.index > 0, "index in format should be positive");
797  INVARIANT(
798  static_cast<std::size_t>(fs.index) <= inputs.size(),
799  "number of format must match specifiers");
800 
801  // first argument `args[0]` corresponds to index 1
802  arg = inputs[fs.index - 1];
803  }
804  }
805  intermediary_string_lengths.push_back(
807  }
808  else
809  {
810  intermediary_string_lengths.push_back(from_integer(
811  fe.get_format_text().get_content().size(), result.length_type()));
812  }
813  }
814 
815  constraints.push_back(
817 
818  if(intermediary_string_lengths.empty())
819  {
820  constraints.push_back(equal_exprt(
822  return conjunction(constraints);
823  }
824 
825  exprt total_length = intermediary_string_lengths[0];
826  for(std::size_t i = 1; i < intermediary_string_lengths.size(); ++i)
827  {
828  total_length =
829  plus_exprt{std::move(total_length), intermediary_string_lengths[i]};
830  }
832  std::move(total_length)});
833 
834  return conjunction(constraints);
835 }
messaget
Class that provides messages with a built-in verbosity 'level'.
Definition: message.h:154
dstringt
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:36
format_specifiert::LINE_SEPARATOR
static const char LINE_SEPARATOR
Definition: format_specifier.h:47
array_string_exprt::length_type
const typet & length_type() const
Definition: string_expr.h:69
UNIMPLEMENTED
#define UNIMPLEMENTED
Definition: invariant.h:525
mp_integer
BigInt mp_integer
Definition: smt_terms.h:17
conjunction
exprt conjunction(const exprt::operandst &op)
1) generates a conjunction for two or more operands 2) for one operand, returns the operand 3) return...
Definition: std_expr.cpp:62
format_specifiert::BOOLEAN
static const char BOOLEAN
Definition: format_specifier.h:41
string_format_builtin_functiont::constraints
string_constraintst constraints(string_constraint_generatort &generator, message_handlert &message_handler) const override
Add constraints ensuring that the value of result expression of the builtin function corresponds to t...
Definition: string_format_builtin_function.cpp:588
parse_format_string
format_token_listt parse_format_string(const std::string &arg_string)
Definition: format_strings.cpp:186
greater_or_equal_to
binary_relation_exprt greater_or_equal_to(exprt lhs, exprt rhs)
Definition: string_expr.h:19
format_specifiert::DECIMAL_FLOAT
static const char DECIMAL_FLOAT
Definition: format_specifier.h:34
string_constraint_generatort::add_axioms_for_substring
std::pair< exprt, string_constraintst > add_axioms_for_substring(const array_string_exprt &res, const array_string_exprt &str, const exprt &start, const exprt &end)
Add axioms ensuring that res corresponds to the substring of str between indexes ‘start’ = max(start,...
Definition: string_constraint_generator_transformation.cpp:124
to_array_expr
const array_exprt & to_array_expr(const exprt &expr)
Cast an exprt to an array_exprt.
Definition: std_expr.h:1603
format_specifiert::HEXADECIMAL_FLOAT
static const char HEXADECIMAL_FLOAT
Definition: format_specifier.h:35
array_poolt::find
array_string_exprt find(const exprt &pointer, const exprt &length)
Creates a new array if the pointer is not pointing to an array.
Definition: array_pool.cpp:184
format_specifiert::CHARACTER
static const char CHARACTER
Definition: format_specifier.h:37
length_for_format_specifier
exprt length_for_format_specifier(const format_specifiert &fs, const array_string_exprt &arg, const typet &index_type, array_poolt &array_pool)
Return an expression representing the length of the format specifier Does not assume that arg is cons...
Definition: string_format_builtin_function.cpp:683
typet
The type of an expression, extends irept.
Definition: type.h:28
string_to_upper_case_builtin_functiont::constraints
string_constraintst constraints(class symbol_generatort &fresh_symbol, message_handlert &message_handler) const
Set of constraints ensuring result corresponds to input in which lowercase characters of Basic Latin ...
Definition: string_builtin_function.cpp:343
format_specifiert::PERCENT_SIGN
static const char PERCENT_SIGN
Definition: format_specifier.h:48
array_poolt
Correspondance between arrays and pointers string representations.
Definition: array_pool.h:41
string_builtin_functiont::return_code
exprt return_code
Definition: string_builtin_function.h:111
deserialize_constant_int_arg
static std::vector< mp_integer > deserialize_constant_int_arg(const std::vector< mp_integer > serialized, const unsigned base)
Definition: string_format_builtin_function.cpp:398
if_exprt
The trinary if-then-else operator.
Definition: std_expr.h:2322
floatbv_typet
Fixed-width bit-vector with IEEE floating-point interpretation.
Definition: bitvector_types.h:321
format_specifiert::conversion
char conversion
Definition: format_specifier.h:56
string_constraint_generatort::fresh_symbol
symbol_generatort fresh_symbol
Definition: string_constraint_generator.h:61
format_specifiert::DATE_TIME_UPPER
static const char DATE_TIME_UPPER
Definition: format_specifier.h:40
and_exprt
Boolean AND.
Definition: std_expr.h:2070
array_poolt::get_or_create_length
exprt get_or_create_length(const array_string_exprt &s)
Get the length of an array_string_exprt from the array_pool.
Definition: array_pool.cpp:26
get_string_expr
array_string_exprt get_string_expr(array_poolt &array_pool, const exprt &expr)
Fetch the string_exprt corresponding to the given refined_string_exprt.
Definition: array_pool.cpp:199
to_type_with_subtype
const type_with_subtypet & to_type_with_subtype(const typet &type)
Definition: type.h:193
plus_exprt
The plus expression Associativity is not specified.
Definition: std_expr.h:946
format_specifiert::STRING_UPPER
static const char STRING_UPPER
Definition: format_specifier.h:44
exprt
Base class for all expressions.
Definition: expr.h:55
string_format_builtin_functiont::string_format_builtin_functiont
string_format_builtin_functiont(const exprt &return_code, const std::vector< exprt > &fun_args, array_poolt &array_pool)
Constructor from arguments of a function application.
Definition: string_format_builtin_function.cpp:29
format_specifiert::HEXADECIMAL_FLOAT_UPPER
static const char HEXADECIMAL_FLOAT_UPPER
Definition: format_specifier.h:36
string_constraintst
Collection of constraints of different types: existential formulas, universal formulas,...
Definition: string_constraint_generator.h:38
array_string_exprt::content
exprt & content()
Definition: string_expr.h:74
format_specifier.h
bool_typet
The Boolean type.
Definition: std_types.h:35
format_elementt
Definition: format_specifier.h:99
string_constraint_generatort::add_axioms_for_string_of_float
std::pair< exprt, string_constraintst > add_axioms_for_string_of_float(const function_application_exprt &f)
String representation of a float value.
Definition: string_constraint_generator_float.cpp:162
format_specifiert::STRING
static const char STRING
Definition: format_specifier.h:43
index_type
bitvector_typet index_type()
Definition: c_types.cpp:22
equal_exprt
Equality.
Definition: std_expr.h:1305
format_specifiert::HASHCODE_UPPER
static const char HASHCODE_UPPER
Definition: format_specifier.h:46
string_format_builtin_functiont::result
array_string_exprt result
Definition: string_format_builtin_function.h:65
format_specifiert::HEXADECIMAL_INTEGER_UPPER
static const char HEXADECIMAL_INTEGER_UPPER
Definition: format_specifier.h:29
utf16_constant_array_to_java
std::string utf16_constant_array_to_java(const array_exprt &arr, std::size_t length)
Construct a string from a constant array.
Definition: string_refinement_util.cpp:54
UNHANDLED_CASE
#define UNHANDLED_CASE
Definition: invariant.h:526
string_constraint_generatort::array_pool
array_poolt array_pool
Definition: string_constraint_generator.h:63
string_constraint_generatort
Definition: string_constraint_generator.h:47
format_specifiert::HASHCODE
static const char HASHCODE
Definition: format_specifier.h:45
unsignedbv_typet
Fixed-width bit-vector with unsigned binary interpretation.
Definition: bitvector_types.h:158
merge
void merge(string_constraintst &result, string_constraintst other)
Merge two sets of constraints by appending to the first one.
Definition: string_constraint_generator_main.cpp:101
string_builtin_functiont::array_pool
array_poolt & array_pool
Definition: string_builtin_function.h:122
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:84
format_specifiert::index
int index
Definition: format_specifier.h:50
format_specifiert::DATE_TIME
static const char DATE_TIME
Definition: format_specifier.h:39
maximum
exprt maximum(const exprt &a, const exprt &b)
Definition: string_constraint_generator_main.cpp:403
string_to_upper_case_builtin_functiont
Converting each lowercase character of Basic Latin and Latin-1 supplement to the corresponding upperc...
Definition: string_builtin_function.h:286
bitor_exprt
Bit-wise OR.
Definition: bitvector_expr.h:124
string_constraint_generatort::ns
const namespacet ns
Definition: string_constraint_generator.h:65
string_format_builtin_functiont::inputs
std::vector< array_string_exprt > inputs
Definition: string_format_builtin_function.h:69
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
length_of_positive_decimal_int
static exprt length_of_positive_decimal_int(const exprt &pos_integer, int max_length, const typet &length_type, const unsigned long radix)
Return an new expression representing the length of the representation of integer.
Definition: string_format_builtin_function.cpp:622
string_refinement_util.h
PRECONDITION
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
signedbv_typet
Fixed-width bit-vector with two's complement interpretation.
Definition: bitvector_types.h:207
length_of_decimal_int
exprt length_of_decimal_int(const exprt &integer, const typet &length_type, const unsigned long radix)
Compute the length of the decimal representation of an integer.
Definition: string_format_builtin_function.cpp:650
make_string
static array_string_exprt make_string(Iter begin, Iter end, const array_typet &array_type)
Definition: string_builtin_function.cpp:59
simplify_expr
exprt simplify_expr(exprt src, const namespacet &ns)
Definition: simplify_expr.cpp:2931
format_specifiert::GENERAL
static const char GENERAL
Definition: format_specifier.h:32
format_specifiert::DECIMAL_INTEGER
static const char DECIMAL_INTEGER
Definition: format_specifier.h:26
unary_minus_exprt
The unary minus expression.
Definition: std_expr.h:422
irept::id
const irep_idt & id() const
Definition: irep.h:396
message_handlert
Definition: message.h:27
range.h
exprt::operandst
std::vector< exprt > operandst
Definition: expr.h:58
format_specifiert::SCIENTIFIC_UPPER
static const char SCIENTIFIC_UPPER
Definition: format_specifier.h:31
false_exprt
The Boolean constant false.
Definition: std_expr.h:3016
eval_format_specifier
static std::vector< mp_integer > eval_format_specifier(const format_specifiert &fs, const std::vector< mp_integer > &arg)
Return the string to replace the format specifier, as a vector of characters.
Definition: string_format_builtin_function.cpp:430
add_axioms_for_format
static std::pair< exprt, string_constraintst > add_axioms_for_format(string_constraint_generatort &generator, const array_string_exprt &res, const std::string &s, const std::vector< array_string_exprt > &args, message_handlert &message_handler)
Parse s and add axioms ensuring the output corresponds to the output of String.format.
Definition: string_format_builtin_function.cpp:296
to_array_string_expr
array_string_exprt & to_array_string_expr(exprt &expr)
Definition: string_expr.h:95
optionalt
nonstd::optional< T > optionalt
Definition: optional.h:35
get_return_code_type
signedbv_typet get_return_code_type()
Definition: string_constraint_generator_main.cpp:182
string_builtin_functiont
Base class for string functions that are built in the solver.
Definition: string_builtin_function.h:72
string_format_builtin_function.h
char_type
bitvector_typet char_type()
Definition: c_types.cpp:124
simplify_expr.h
format_specifiert::GENERAL_UPPER
static const char GENERAL_UPPER
Definition: format_specifier.h:33
exprt::is_zero
bool is_zero() const
Return whether the expression is a constant representing 0.
Definition: expr.cpp:65
string_constraint_generatort::add_axioms_for_constant
std::pair< exprt, string_constraintst > add_axioms_for_constant(const array_string_exprt &res, irep_idt sval, const exprt &guard=true_exprt())
Add axioms ensuring that the provided string expression and constant are equal.
Definition: string_constraint_generator_constants.cpp:24
format_arg_from_string
static exprt format_arg_from_string(const array_string_exprt &string, const irep_idt &id, array_poolt &array_pool)
Deserialize an argument for format from string.
Definition: string_format_builtin_function.cpp:242
eval_string
optionalt< std::vector< mp_integer > > eval_string(const array_string_exprt &a, const std::function< exprt(const exprt &)> &get_value)
Given a function get_value which gives a valuation to expressions, attempt to find the current value ...
Definition: string_builtin_function.cpp:24
format_specifiert::OCTAL_INTEGER
static const char OCTAL_INTEGER
Definition: format_specifier.h:27
is_null
static exprt is_null(const array_string_exprt &string, array_poolt &array_pool)
Expression which is true when the string is equal to the literal "null".
Definition: string_format_builtin_function.cpp:94
format_specifiert
Field names follow the OpenJDK implementation: http://hg.openjdk.java.net/jdk7/jdk7/jdk/file/9b8c96f9...
Definition: format_specifier.h:22
from_integer
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
Definition: arith_tools.cpp:100
format_specifiert::SCIENTIFIC
static const char SCIENTIFIC
Definition: format_specifier.h:30
to_array_type
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition: std_types.h:844
is_refined_string_type
bool is_refined_string_type(const typet &type)
Definition: refined_string_type.h:52
string_constraint_generatort::add_axioms_from_bool
std::pair< exprt, string_constraintst > add_axioms_from_bool(const function_application_exprt &f)
eval_is_null
static bool eval_is_null(const std::vector< mp_integer > &string)
Definition: string_format_builtin_function.cpp:422
string_constraint_generatort::add_axioms_for_string_of_int
std::pair< exprt, string_constraintst > add_axioms_for_string_of_int(const array_string_exprt &res, const exprt &input_int, size_t max_size)
Add axioms enforcing that the string corresponds to the result of String.valueOf(I) or String....
Definition: string_constraint_generator_valueof.cpp:117
type_with_subtypet::subtype
const typet & subtype() const
Definition: type.h:172
string_constraint_generatort::add_axioms_from_float_scientific_notation
std::pair< exprt, string_constraintst > add_axioms_from_float_scientific_notation(const array_string_exprt &res, const exprt &f)
Add axioms to write the float in scientific notation.
Definition: string_constraint_generator_float.cpp:338
string_constraint_generatort::add_axioms_for_concat
std::pair< exprt, string_constraintst > add_axioms_for_concat(const array_string_exprt &res, const array_string_exprt &s1, const array_string_exprt &s2)
Add axioms enforcing that res is equal to the concatenation of s1 and s2.
Definition: string_concatenation_builtin_function.cpp:160
implies_exprt
Boolean implication.
Definition: std_expr.h:2133
add_axioms_for_format_specifier
static std::pair< array_string_exprt, string_constraintst > add_axioms_for_format_specifier(string_constraint_generatort &generator, const format_specifiert &fs, const array_string_exprt &string_arg, const typet &index_type, const typet &char_type, message_handlert &message_handler)
Parse s and add axioms ensuring the output corresponds to the output of String.format.
Definition: string_format_builtin_function.cpp:118
string_format_builtin_functiont::format_string
optionalt< std::string > format_string
Only set when the format string is a constant.
Definition: string_format_builtin_function.h:68
format_specifiert::CHARACTER_UPPER
static const char CHARACTER_UPPER
Definition: format_specifier.h:38
INVARIANT
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition: invariant.h:423
typecast_exprt
Semantic type conversion.
Definition: std_expr.h:2016
message.h
true_exprt
The Boolean constant true.
Definition: std_expr.h:3007
format_specifiert::BOOLEAN_UPPER
static const char BOOLEAN_UPPER
Definition: format_specifier.h:42
format_specifiert::HEXADECIMAL_INTEGER
static const char HEXADECIMAL_INTEGER
Definition: format_specifier.h:28
string_constraint_generatort::add_axioms_for_string_of_int_with_radix
std::pair< exprt, string_constraintst > add_axioms_for_string_of_int_with_radix(const array_string_exprt &res, const exprt &input_int, const exprt &radix, size_t max_size)
Add axioms enforcing that the string corresponds to the result of String.valueOf(II) or String....
Definition: string_constraint_generator_valueof.cpp:137
string_format_builtin_functiont::eval
optionalt< exprt > eval(const std::function< exprt(const exprt &)> &get_value) const override
Given a function get_value which gives a valuation to expressions, attempt to find the result of the ...
Definition: string_format_builtin_function.cpp:518
less_than
binary_relation_exprt less_than(exprt lhs, exprt rhs)
Definition: string_expr.h:48
make_range
ranget< iteratort > make_range(iteratort begin, iteratort end)
Definition: range.h:524
array_string_exprt
Definition: string_expr.h:66
bitvector_expr.h
string_format_builtin_functiont::length_constraint
exprt length_constraint() const override
Constraint ensuring that the length of the strings are coherent with the function call.
Definition: string_format_builtin_function.cpp:765
validation_modet::INVARIANT
@ INVARIANT
array_poolt::fresh_string
array_string_exprt fresh_string(const typet &index_type, const typet &char_type)
Construct a string expression whose length and content are new variables.
Definition: array_pool.cpp:57
shl_exprt
Left shift.
Definition: bitvector_expr.h:294
string_constraintst::existential
std::vector< exprt > existential
Definition: string_constraint_generator.h:40
not_exprt
Boolean negation.
Definition: std_expr.h:2277
to_constant_expr
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition: std_expr.h:2992
integer2string
const std::string integer2string(const mp_integer &n, unsigned base)
Definition: mp_arith.cpp:103