ABC: A System for Sequential Synthesis and Verification
 
Loading...
Searching...
No Matches
contract.hpp
Go to the documentation of this file.
1#ifndef _contract_hpp_INCLUDED
2#define _contract_hpp_INCLUDED
3
4#include "global.h"
5
7
8/*------------------------------------------------------------------------*/
9#ifndef CADICAL_NCONTRACTS
10/*------------------------------------------------------------------------*/
11
12// If the user violates API contracts while calling functions declared in
13// 'cadical.hpp' and implemented in 'solver.cpp' then an error is reported.
14// Currently we also force aborting the program. In the future it might be
15// better to allow the user to provide a call back function, which then can
16// for instance throw a C++ exception or execute a 'longjmp' in 'C' etc.
17
18#define CONTRACT_VIOLATED(...) \
19 do { \
20 fatal_message_start (); \
21 fprintf (stderr, \
22 "invalid API usage of '%s' in '%s': ", __PRETTY_FUNCTION__, \
23 __FILE__); \
24 fprintf (stderr, __VA_ARGS__); \
25 fputc ('\n', stderr); \
26 fflush (stderr); \
27 abort (); \
28 } while (0)
29
30/*------------------------------------------------------------------------*/
31
32namespace CaDiCaL {
33
34// It would be much easier to just write 'REQUIRE (this, "not initialized")'
35// which however produces warnings due to the '-Wnonnull' check. Note, that
36// 'this' is always assumed to be non zero in modern C++. Much worse, if we
37// use instead 'this != 0' or something similar like 'this != nullptr' then
38// optimization silently removes this check ('gcc-7.4.0' at least) even
39// though of course a zero pointer might be used as 'this' if the user did
40// not initialize it. The only solution I found is to disable optimization
41// for this check. It does not seem to be necessary for 'clang++' though
42// ('clang++-6.0.0' at least). The alternative is to not check that the
43// user forgot to initialize the solver pointer, but as long this works we
44// keep this ugly hack. It also forces the function not to be inlined.
45// The actual code I is in 'contract.cpp'.
46//
47void require_solver_pointer_to_be_non_zero (const void *ptr,
48 const char *function_name,
49 const char *file_name);
50#define REQUIRE_NON_ZERO_THIS() \
51 do { \
52 require_solver_pointer_to_be_non_zero (this, __PRETTY_FUNCTION__, \
53 __FILE__); \
54 } while (0)
55
56} // namespace CaDiCaL
57
58/*------------------------------------------------------------------------*/
59
60// These are common shortcuts for 'Solver' API contracts (requirements).
61
62#define REQUIRE(COND, ...) \
63 do { \
64 if ((COND)) \
65 break; \
66 CONTRACT_VIOLATED (__VA_ARGS__); \
67 } while (0)
68
69#define REQUIRE_INITIALIZED() \
70 do { \
71 REQUIRE_NON_ZERO_THIS (); \
72 REQUIRE (external, "external solver not initialized"); \
73 REQUIRE (internal, "internal solver not initialized"); \
74 } while (0)
75
76#define REQUIRE_VALID_STATE() \
77 do { \
78 REQUIRE_INITIALIZED (); \
79 REQUIRE (this->state () & VALID, "solver in invalid state"); \
80 } while (0)
81
82#define REQUIRE_READY_STATE() \
83 do { \
84 REQUIRE_VALID_STATE (); \
85 REQUIRE (state () != ADDING, \
86 "clause incomplete (terminating zero not added)"); \
87 } while (0)
88
89#define REQUIRE_VALID_OR_SOLVING_STATE() \
90 do { \
91 REQUIRE_INITIALIZED (); \
92 REQUIRE (this->state () & (VALID | SOLVING), \
93 "solver neither in valid nor solving state"); \
94 } while (0)
95
96#define REQUIRE_VALID_LIT(LIT) \
97 do { \
98 REQUIRE ((int) (LIT) && ((int) (LIT)) != INT_MIN, \
99 "invalid literal '%d'", (int) (LIT)); \
100 REQUIRE (external->is_valid_input ((int) (LIT)), \
101 "extension variable %d defined by the solver", (int) (LIT)); \
102 } while (0)
103
104#define REQUIRE_STEADY_STATE() \
105 do { \
106 REQUIRE_INITIALIZED (); \
107 REQUIRE (this->state () & STEADY, "solver is not in steady state"); \
108 } while (0)
109
110/*------------------------------------------------------------------------*/
111#else // CADICAL_NCONTRACTS
112/*------------------------------------------------------------------------*/
113
114#define REQUIRE(...) \
115 do { \
116 } while (0)
117#define REQUIRE_INITIALIZED() \
118 do { \
119 } while (0)
120#define REQUIRE_VALID_STATE() \
121 do { \
122 } while (0)
123#define REQUIRE_READY_STATE() \
124 do { \
125 } while (0)
126#define REQUIRE_VALID_OR_SOLVING_STATE() \
127 do { \
128 } while (0)
129#define REQUIRE_VALID_LIT(...) \
130 do { \
131 } while (0)
132#define REQUIRE_STEADY_STATE() \
133 do { \
134 } while (0)
135
136/*------------------------------------------------------------------------*/
137#endif
138/*------------------------------------------------------------------------*/
139
141
142#endif
#define ABC_NAMESPACE_CXX_HEADER_START
#define ABC_NAMESPACE_CXX_HEADER_END