CBMC
Loading...
Searching...
No Matches
solver_factory.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module: Solver Factory
4
5Author: Daniel Kroening, Peter Schrammel
6
7\*******************************************************************/
8
11
12#include "solver_factory.h"
13
14#include <util/cmdline.h>
16#include <util/exit_codes.h>
17#include <util/message.h>
18#include <util/options.h>
19#include <util/unicode.h>
20#include <util/version.h>
21
24#include <solvers/prop/prop.h>
33
34#include <iostream>
35#include <vector>
36
38 const optionst &_options,
39 const namespacet &_ns,
42 : options(_options),
43 ns(_ns),
44 message_handler(_message_handler),
45 output_xml_in_refinement(_output_xml_in_refinement)
46{
47}
48
49solver_factoryt::solvert::solvert(std::unique_ptr<stack_decision_proceduret> p)
50 : decision_procedure_ptr(std::move(p))
51{
52}
53
55 std::unique_ptr<stack_decision_proceduret> p1,
56 std::unique_ptr<propt> p2)
57 : prop_ptr(std::move(p2)), decision_procedure_ptr(std::move(p1))
58{
59}
60
62 std::unique_ptr<stack_decision_proceduret> p1,
63 std::unique_ptr<std::ofstream> p2)
64 : ofstream_ptr(std::move(p2)), decision_procedure_ptr(std::move(p1))
65{
66}
67
69 std::unique_ptr<boolbvt> p1,
70 std::unique_ptr<propt> p2)
71 : prop_ptr(std::move(p2)), decision_procedure_is_boolbvt_ptr(std::move(p1))
72{
73}
74
76 std::unique_ptr<boolbvt> p1,
77 std::unique_ptr<propt> p2,
78 std::unique_ptr<std::ofstream> p3)
79 : ofstream_ptr(std::move(p3)),
80 prop_ptr(std::move(p2)),
81 decision_procedure_is_boolbvt_ptr(std::move(p1))
82{
83}
84
86{
88 (decision_procedure_ptr != nullptr) !=
89 (decision_procedure_is_boolbvt_ptr != nullptr));
90 if(decision_procedure_ptr)
91 return *decision_procedure_ptr;
92 else
93 return *decision_procedure_is_boolbvt_ptr;
94}
95
97{
98 PRECONDITION(decision_procedure_is_boolbvt_ptr != nullptr);
99 return *decision_procedure_is_boolbvt_ptr;
100}
101
103 solver_resource_limitst &decision_procedure)
104{
105 const int timeout_seconds =
106 options.get_signed_int_option("solver-time-limit");
107
108 if(timeout_seconds > 0)
109 decision_procedure.set_time_limit_seconds(timeout_seconds);
110}
111
112std::unique_ptr<solver_factoryt::solvert> solver_factoryt::get_solver()
113{
114 if(options.get_bool_option("dimacs"))
115 return get_dimacs();
116 if(options.is_set("external-sat-solver"))
117 return get_external_sat();
118 if(
119 options.get_bool_option("refine") &&
120 !options.get_bool_option("refine-strings"))
121 {
122 return get_bv_refinement();
123 }
124 else if(options.get_bool_option("refine-strings"))
125 return get_string_refinement();
126 const auto incremental_smt2_solver =
127 options.get_option("incremental-smt2-solver");
128 if(!incremental_smt2_solver.empty())
130 if(options.get_bool_option("smt2"))
132 return get_default();
133}
134
138{
139 // we shouldn't get here if this option isn't set
140 PRECONDITION(options.get_bool_option("smt2"));
141
143
144 if(options.get_bool_option("bitwuzla"))
146 else if(options.get_bool_option("boolector"))
148 else if(options.get_bool_option("cprover-smt2"))
150 else if(options.get_bool_option("mathsat"))
152 else if(options.get_bool_option("cvc5"))
154 else if(options.get_bool_option("yices"))
156 else if(options.get_bool_option("z3"))
158 else if(options.get_bool_option("generic"))
160
161 return s;
162}
163
167 const std::string &solver)
168{
170 log.warning() << "The specified solver, '" << solver
171 << "', is not available. "
172 << "The default solver will be used instead." << messaget::eom;
173}
174
175template <typename SatcheckT>
176static typename std::enable_if<
177 !std::is_base_of<hardness_collectort, SatcheckT>::value,
178 std::unique_ptr<SatcheckT>>::type
180{
181 auto satcheck = std::make_unique<SatcheckT>(message_handler);
182 if(options.is_set("write-solver-stats-to"))
183 {
185 log.warning()
186 << "Configured solver does not support --write-solver-stats-to. "
187 << "Solver stats will not be written." << messaget::eom;
188 }
189 return satcheck;
190}
191
192template <typename SatcheckT>
193static typename std::enable_if<
194 std::is_base_of<hardness_collectort, SatcheckT>::value,
195 std::unique_ptr<SatcheckT>>::type
197{
198 auto satcheck = std::make_unique<SatcheckT>(message_handler);
199 if(options.is_set("write-solver-stats-to"))
200 {
201 std::unique_ptr<solver_hardnesst> solver_hardness =
202 std::make_unique<solver_hardnesst>();
203 solver_hardness->set_outfile(options.get_option("write-solver-stats-to"));
204 satcheck->solver_hardness = std::move(solver_hardness);
205 }
206 return satcheck;
207}
208
209static std::unique_ptr<propt>
211{
212 const bool no_simplifier = options.get_bool_option("beautify") ||
213 !options.get_bool_option("sat-preprocessor") ||
214 options.get_bool_option("refine-strings");
215
216 if(options.is_set("sat-solver"))
217 {
218 const std::string &solver_option = options.get_option("sat-solver");
219 if(solver_option == "zchaff")
220 {
221#if defined SATCHECK_ZCHAFF
223#else
225#endif
226 }
227 else if(solver_option == "booleforce")
228 {
229#if defined SATCHECK_BOOLERFORCE
231#else
233#endif
234 }
235 else if(solver_option == "minisat1")
236 {
237#if defined SATCHECK_MINISAT1
239#else
241#endif
242 }
243 else if(solver_option == "minisat2")
244 {
245#if defined SATCHECK_MINISAT2
246 if(no_simplifier)
247 {
248 // simplifier won't work with beautification
251 }
252 else // with simplifier
253 {
256 }
257#else
259#endif
260 }
261 else if(solver_option == "ipasir")
262 {
263#if defined SATCHECK_IPASIR
265#else
267#endif
268 }
269 else if(solver_option == "picosat")
270 {
271#if defined SATCHECK_PICOSAT
273#else
275#endif
276 }
277 else if(solver_option == "lingeling")
278 {
279#if defined SATCHECK_LINGELING
281#else
283#endif
284 }
285 else if(solver_option == "glucose")
286 {
287#if defined SATCHECK_GLUCOSE
288 if(no_simplifier)
289 {
290 // simplifier won't work with beautification
293 }
294 else // with simplifier
295 {
298 }
299#else
301#endif
302 }
303 else if(solver_option == "cadical")
304 {
305#if defined SATCHECK_CADICAL
308#else
310#endif
311 }
312 else
313 {
315 log.error() << "unknown solver '" << solver_option << "'"
316 << messaget::eom;
318 }
319 }
320
321 // default solver
322 if(no_simplifier)
323 {
324 // simplifier won't work with beautification
327 }
328 else // with simplifier
329 {
331 }
332}
333
334static std::unique_ptr<std::ofstream> open_outfile_and_check(
335 const std::string &filename,
337 const std::string &arg_name)
338{
339 if(filename.empty())
340 return nullptr;
341
342 auto out = std::make_unique<std::ofstream>(widen_if_needed(filename));
343
344 if(!*out)
345 {
347 "failed to open file: " + filename, arg_name);
348 }
349
351 log.status() << "Outputting formula to file: " << filename << messaget::eom;
352 return out;
353}
354
355std::unique_ptr<solver_factoryt::solvert> solver_factoryt::get_default()
356{
358
359 bool get_array_constraints =
360 options.get_bool_option("show-array-constraints");
361 auto bv_pointers = std::make_unique<bv_pointerst>(
362 ns, *sat_solver, message_handler, get_array_constraints);
363
364 if(options.get_option("arrays-uf") == "never")
366 else if(options.get_option("arrays-uf") == "always")
368
370
371 std::unique_ptr<boolbvt> boolbv = std::move(bv_pointers);
372 return std::make_unique<solvert>(std::move(boolbv), std::move(sat_solver));
373}
374
375std::unique_ptr<solver_factoryt::solvert> solver_factoryt::get_dimacs()
376{
379
380 auto prop = std::make_unique<dimacs_cnft>(message_handler);
381
382 std::string filename = options.get_option("outfile");
383
384 if(filename.empty() || filename == "-")
385 {
386 std::unique_ptr<boolbvt> bv_dimacs =
387 std::make_unique<bv_dimacst>(ns, *prop, message_handler, std::cout);
388
389 return std::make_unique<solvert>(std::move(bv_dimacs), std::move(prop));
390 }
391
392 auto outfile = open_outfile_and_check(filename, message_handler, "--outfile");
393
394 std::unique_ptr<boolbvt> bv_dimacs =
395 std::make_unique<bv_dimacst>(ns, *prop, message_handler, *outfile);
396
397 return std::make_unique<solvert>(
398 std::move(bv_dimacs), std::move(prop), std::move(outfile));
399}
400
401std::unique_ptr<solver_factoryt::solvert> solver_factoryt::get_external_sat()
402{
405
406 std::string external_sat_solver = options.get_option("external-sat-solver");
407 auto prop =
408 std::make_unique<external_satt>(message_handler, external_sat_solver);
409
410 std::unique_ptr<boolbvt> bv_pointers =
411 std::make_unique<bv_pointerst>(ns, *prop, message_handler);
412
413 return std::make_unique<solvert>(std::move(bv_pointers), std::move(prop));
414}
415
416std::unique_ptr<solver_factoryt::solvert> solver_factoryt::get_bv_refinement()
417{
418 std::unique_ptr<propt> prop = get_sat_solver(message_handler, options);
419
421 info.ns = &ns;
422 info.prop = prop.get();
424
425 // we allow setting some parameters
426 if(options.get_bool_option("max-node-refinement"))
427 info.max_node_refinement =
428 options.get_unsigned_int_option("max-node-refinement");
429
430 info.refine_arrays = options.get_bool_option("refine-arrays");
431 info.refine_arithmetic = options.get_bool_option("refine-arithmetic");
433
434 std::unique_ptr<boolbvt> decision_procedure =
435 std::make_unique<bv_refinementt>(info);
436 set_decision_procedure_time_limit(*decision_procedure);
437 return std::make_unique<solvert>(
438 std::move(decision_procedure), std::move(prop));
439}
440
444std::unique_ptr<solver_factoryt::solvert>
446{
448 info.ns = &ns;
450 info.prop = prop.get();
451 info.refinement_bound = DEFAULT_MAX_NB_REFINEMENT;
453 if(options.get_bool_option("max-node-refinement"))
454 info.max_node_refinement =
455 options.get_unsigned_int_option("max-node-refinement");
456 info.refine_arrays = options.get_bool_option("refine-arrays");
457 info.refine_arithmetic = options.get_bool_option("refine-arithmetic");
459
460 std::unique_ptr<boolbvt> decision_procedure =
461 std::make_unique<string_refinementt>(info);
462 set_decision_procedure_time_limit(*decision_procedure);
463 return std::make_unique<solvert>(
464 std::move(decision_procedure), std::move(prop));
465}
466
467std::unique_ptr<solver_factoryt::solvert>
469{
471
472 const std::string outfile_arg = options.get_option("outfile");
473 const std::string dump_smt_formula = options.get_option("dump-smt-formula");
474
475 if(!outfile_arg.empty() && !dump_smt_formula.empty())
476 {
478 "Argument --outfile is incompatible with --dump-smt-formula. ",
479 "--outfile");
480 }
481
482 std::unique_ptr<smt_base_solver_processt> solver_process = nullptr;
483
484 if(!outfile_arg.empty())
485 {
486 bool on_std_out = outfile_arg == "-";
487 std::unique_ptr<std::ostream> outfile =
489 ? nullptr
491 solver_process = std::make_unique<smt_incremental_dry_run_solvert>(
492 message_handler, on_std_out ? std::cout : *outfile, std::move(outfile));
493 }
494 else
495 {
496 const auto out_filename = options.get_option("dump-smt-formula");
497
498 // If no out_filename is provided `open_outfile_and_check` will return
499 // `nullptr`, and the solver will work normally without any logging.
500 solver_process = std::make_unique<smt_piped_solver_processt>(
501 std::move(solver_command),
504 out_filename, message_handler, "--dump-smt-formula"));
505 }
506
507 return std::make_unique<solvert>(
508 std::make_unique<smt2_incremental_decision_proceduret>(
509 ns, std::move(solver_process), message_handler));
510}
511
512std::unique_ptr<solver_factoryt::solvert>
514{
516
517 const std::string &filename = options.get_option("outfile");
518
519 if(filename.empty())
520 {
522 {
524 "required filename not provided",
525 "--outfile",
526 "provide a filename with --outfile");
527 }
528
529 auto smt2_dec = std::make_unique<smt2_dect>(
530 ns,
531 "cbmc",
532 std::string("Generated by CBMC ") + CBMC_VERSION,
533 "QF_AUFBV",
534 solver,
535 options.get_option("external-smt2-solver"),
537
538 if(options.get_bool_option("fpa"))
539 smt2_dec->use_FPA_theory = true;
540
541 return std::make_unique<solvert>(std::move(smt2_dec));
542 }
543 else if(filename == "-")
544 {
545 auto smt2_conv = std::make_unique<smt2_convt>(
546 ns,
547 "cbmc",
548 std::string("Generated by CBMC ") + CBMC_VERSION,
549 "QF_AUFBV",
550 solver,
551 std::cout);
552
553 if(options.get_bool_option("fpa"))
554 smt2_conv->use_FPA_theory = true;
555
556 return std::make_unique<solvert>(std::move(smt2_conv));
557 }
558 else
559 {
560 auto out = open_outfile_and_check(filename, message_handler, "--outfile");
561
562 auto smt2_conv = std::make_unique<smt2_convt>(
563 ns,
564 "cbmc",
565 std::string("Generated by CBMC ") + CBMC_VERSION,
566 "QF_AUFBV",
567 solver,
568 *out);
569
570 if(options.get_bool_option("fpa"))
571 smt2_conv->use_FPA_theory = true;
572
573 return std::make_unique<solvert>(std::move(smt2_conv), std::move(out));
574 }
575}
576
578{
579 if(options.get_bool_option("beautify"))
580 {
582 "the chosen solver does not support beautification", "--beautify");
583 }
584}
585
587{
588 const bool all_properties = options.get_bool_option("all-properties");
589 const bool cover = options.is_set("cover");
590 const bool incremental_loop = options.is_set("incremental-loop");
591
593 {
595 "the chosen solver does not support incremental solving",
596 "--all_properties");
597 }
598 else if(cover)
599 {
601 "the chosen solver does not support incremental solving", "--cover");
602 }
603 else if(incremental_loop)
604 {
606 "the chosen solver does not support incremental solving",
607 "--incremental-loop");
608 }
609}
610
611static void parse_sat_options(const cmdlinet &cmdline, optionst &options)
612{
613 if(cmdline.isset("external-sat-solver"))
614 {
615 options.set_option(
616 "external-sat-solver", cmdline.get_value("external-sat-solver"));
617 }
618
619 options.set_option("sat-preprocessor", !cmdline.isset("no-sat-preprocessor"));
620
621 if(cmdline.isset("dimacs"))
622 options.set_option("dimacs", true);
623
624 if(cmdline.isset("sat-solver"))
625 options.set_option("sat-solver", cmdline.get_value("sat-solver"));
626}
627
628static void parse_smt2_options(const cmdlinet &cmdline, optionst &options)
629{
630 if(cmdline.isset("smt2"))
631 options.set_option("smt2", true);
632
633 if(cmdline.isset("fpa"))
634 options.set_option("fpa", true);
635
636 bool solver_set = false;
637
638 if(cmdline.isset("bitwuzla"))
639 {
640 options.set_option("bitwuzla", true), solver_set = true;
641 options.set_option("smt2", true);
642 }
643
644 if(cmdline.isset("boolector"))
645 {
646 options.set_option("boolector", true), solver_set = true;
647 options.set_option("smt2", true);
648 }
649
650 if(cmdline.isset("cprover-smt2"))
651 {
652 options.set_option("cprover-smt2", true), solver_set = true;
653 options.set_option("smt2", true);
654 }
655
656 if(cmdline.isset("mathsat"))
657 {
658 options.set_option("mathsat", true), solver_set = true;
659 options.set_option("smt2", true);
660 }
661
662 if(cmdline.isset("cvc5"))
663 {
664 options.set_option("cvc5", true), solver_set = true;
665 options.set_option("smt2", true);
666 }
667
668 if(cmdline.isset("incremental-smt2-solver"))
669 {
670 options.set_option(
671 "incremental-smt2-solver", cmdline.get_value("incremental-smt2-solver")),
672 solver_set = true;
673 }
674
675 if(cmdline.isset("yices"))
676 {
677 options.set_option("yices", true), solver_set = true;
678 options.set_option("smt2", true);
679 }
680
681 if(cmdline.isset("z3"))
682 {
683 options.set_option("z3", true), solver_set = true;
684 options.set_option("smt2", true);
685 }
686
687 if(cmdline.isset("external-smt2-solver"))
688 {
689 options.set_option(
690 "external-smt2-solver", cmdline.get_value("external-smt2-solver"));
691 solver_set = true;
692 options.set_option("smt2", true);
693 }
694
695 if(cmdline.isset("smt2") && !solver_set)
696 {
697 if(cmdline.isset("outfile"))
698 {
699 // outfile and no solver should give standard compliant SMT-LIB
700 options.set_option("generic", true);
701 }
702 else
703 {
704 // the default smt2 solver
705 options.set_option("z3", true);
706 }
707 }
708}
709
711{
712 parse_sat_options(cmdline, options);
713 parse_smt2_options(cmdline, options);
714
715 // Detect conflicting solver backend selections. The solver categories
716 // are mutually exclusive: DIMACS output, an external SAT solver, an
717 // SMT2 solver (including --smt2, solver-specific flags like --z3, and
718 // --external-smt2-solver), and the incremental SMT2 solver.
719 std::vector<std::string> solver_flags;
720
721 if(cmdline.isset("dimacs"))
722 solver_flags.push_back("--dimacs");
723
724 if(cmdline.isset("external-sat-solver"))
725 solver_flags.push_back("--external-sat-solver");
726
727 // All SMT2-related flags are in the same category (at most one
728 // reported in the conflict message).
729 for(const char *smt2_flag :
730 {"smt2",
731 "bitwuzla",
732 "boolector",
733 "cprover-smt2",
734 "mathsat",
735 "cvc5",
736 "yices",
737 "z3",
738 "external-smt2-solver"})
739 {
740 if(cmdline.isset(smt2_flag))
741 {
742 solver_flags.push_back(std::string("--") + smt2_flag);
743 break;
744 }
745 }
746
747 if(cmdline.isset("incremental-smt2-solver"))
748 solver_flags.push_back("--incremental-smt2-solver");
749
750 if(solver_flags.size() > 1)
751 {
753 "conflicting solver options: " + solver_flags[0] + " and " +
754 solver_flags[1] + " must not be given together",
755 solver_flags[0] + " " + solver_flags[1]);
756 }
757
758 // --fpa is not supported with the incremental SMT2 solver
759 if(cmdline.isset("incremental-smt2-solver") && cmdline.isset("fpa"))
760 {
762 "--fpa is not supported with --incremental-smt2-solver",
763 "--fpa --incremental-smt2-solver");
764 }
765
766 if(cmdline.isset("outfile"))
767 options.set_option("outfile", cmdline.get_value("outfile"));
768
769 if(cmdline.isset("dump-smt-formula"))
770 options.set_option(
771 "dump-smt-formula", cmdline.get_value("dump-smt-formula"));
772
773 if(cmdline.isset("write-solver-stats-to"))
774 {
775 options.set_option(
776 "write-solver-stats-to", cmdline.get_value("write-solver-stats-to"));
777 }
778
779 if(cmdline.isset("beautify"))
780 options.set_option("beautify", true);
781
782 if(cmdline.isset("refine-arrays"))
783 {
784 options.set_option("refine", true);
785 options.set_option("refine-arrays", true);
786 }
787
788 if(cmdline.isset("refine-arithmetic"))
789 {
790 options.set_option("refine", true);
791 options.set_option("refine-arithmetic", true);
792 }
793
794 if(cmdline.isset("refine"))
795 {
796 options.set_option("refine", true);
797 options.set_option("refine-arrays", true);
798 options.set_option("refine-arithmetic", true);
799 }
800
801 if(cmdline.isset("max-node-refinement"))
802 {
803 options.set_option(
804 "max-node-refinement", cmdline.get_value("max-node-refinement"));
805 }
806}
Writing DIMACS Files.
Abstraction Refinement Loop.
message_handlert & message_handler
Definition ai.h:525
virtual xmlt output_xml(const namespacet &ns, const irep_idt &function_id, const goto_programt &goto_program) const
Output the abstract states for a single function as XML.
Definition ai.cpp:136
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:566
std::string get_value(char option) const
Definition cmdline.cpp:48
virtual bool isset(char option) const
Definition cmdline.cpp:30
Thrown when users pass incorrect command line arguments, for example passing no files to analysis or ...
Class that provides messages with a built-in verbosity 'level'.
Definition message.h:154
static eomt eom
Definition message.h:289
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition namespace.h:91
boolbvt & boolbv_decision_procedure() const
solvert(std::unique_ptr< stack_decision_proceduret > p)
stack_decision_proceduret & decision_procedure() const
message_handlert & message_handler
const optionst & options
const namespacet & ns
std::unique_ptr< solvert > get_external_sat()
std::unique_ptr< solvert > get_default()
solver_factoryt(const optionst &_options, const namespacet &_ns, message_handlert &_message_handler, bool _output_xml_in_refinement)
Note: The solver returned will hold a reference to the namespace ns.
void set_decision_procedure_time_limit(solver_resource_limitst &decision_procedure)
Sets the timeout of decision_procedure if the solver-time-limit option has a positive value (in secon...
std::unique_ptr< solvert > get_dimacs()
std::unique_ptr< solvert > get_string_refinement()
the string refinement adds to the bit vector refinement specifications for functions from the Java st...
std::unique_ptr< solvert > get_smt2(smt2_dect::solvert solver)
const bool output_xml_in_refinement
smt2_dect::solvert get_smt2_solver_type() const
Uses the options to pick an SMT 2.0 solver.
virtual std::unique_ptr< solvert > get_solver()
Returns a solvert object.
std::unique_ptr< solvert > get_incremental_smt2(std::string solver_command)
std::unique_ptr< solvert > get_bv_refinement()
virtual void set_time_limit_seconds(uint32_t)=0
Set the limit for the solver to time out in seconds.
Document and give macros for the exit codes of CPROVER binaries.
#define CPROVER_EXIT_USAGE_ERROR
A usage error is returned when the command line is invalid or conflicting.
Definition exit_codes.h:33
Allows calling an external SAT solver to allow faster integration of newer SAT solvers.
double log(double x)
Definition math.c:2416
STL namespace.
Options.
Decision procedure with incremental SMT2 solving.
void solver(std::vector< framet > &frames, const std::unordered_set< symbol_exprt, irep_hash > &address_taken, const solver_optionst &solver_options, const namespacet &ns, std::vector< propertyt > &properties, std::size_t property_index)
Definition solver.cpp:44
static std::enable_if<!std::is_base_of< hardness_collectort, SatcheckT >::value, std::unique_ptr< SatcheckT > >::type make_satcheck_prop(message_handlert &message_handler, const optionst &options)
static void parse_sat_options(const cmdlinet &cmdline, optionst &options)
static std::unique_ptr< std::ofstream > open_outfile_and_check(const std::string &filename, message_handlert &message_handler, const std::string &arg_name)
static void parse_smt2_options(const cmdlinet &cmdline, optionst &options)
static std::unique_ptr< propt > get_sat_solver(message_handlert &message_handler, const optionst &options)
static void emit_solver_warning(message_handlert &message_handler, const std::string &solver)
Emit a warning for non-existent solver solver via message_handler.
Solver Factory.
void parse_solver_options(const cmdlinet &cmdline, optionst &options)
Parse solver-related command-line parameters in cmdline and set corresponding values in options.
Solver capability to set resource limits.
#define PRECONDITION(CONDITION)
Definition invariant.h:463
void exit(int status)
Definition stdlib.c:102
String support via creating string constraints and progressively instantiating the universal constrai...
#define DEFAULT_MAX_NB_REFINEMENT
string_refinementt constructor arguments
#define widen_if_needed(s)
Definition unicode.h:28
const char * CBMC_VERSION