9 #ifndef CPROVER_UTIL_INVARIANT_H
10 #define CPROVER_UTIL_INVARIANT_H
15 #include <type_traits>
112 const std::string
file;
113 const std::string
function;
122 virtual std::string
what() const noexcept;
125 const std::
string &_file,
126 const std::
string &_function,
128 const std::
string &_backtrace,
129 const std::
string &_condition,
130 const std::
string &_reason)
149 virtual std::string
what() const noexcept;
152 const std::
string &_file,
153 const std::
string &_function,
155 const std::
string &_backtrace,
156 const std::
string &_condition,
157 const std::
string &_reason,
158 const std::
string &_diagnostics)
172 #define CBMC_NORETURN __attribute((noreturn))
173 #elif defined(_MSC_VER)
174 #define CBMC_NORETURN __declspec(noreturn)
175 #elif __cplusplus >= 201703L
176 #define CBMC_NORETURN [[noreturn]]
178 #define CBMC_NORETURN
181 #if defined(CPROVER_INVARIANT_CPROVER_ASSERT)
183 #define INVARIANT(CONDITION, REASON) \
184 __CPROVER_assert((CONDITION), "Invariant : " REASON)
185 #define INVARIANT_WITH_DIAGNOSTICS(CONDITION, REASON, ...) \
186 __CPROVER_assert((CONDITION), "Invariant : " REASON)
188 #define INVARIANT_STRUCTURED(CONDITION, TYPENAME, ...) \
189 INVARIANT(CONDITION, "")
191 #elif defined(CPROVER_INVARIANT_DO_NOT_CHECK)
196 #define INVARIANT(CONDITION, REASON) \
200 #define INVARIANT_WITH_DIAGNOSTICS(CONDITION, REASON, ...) \
204 #define INVARIANT_STRUCTURED(CONDITION, TYPENAME, ...) do {} while(false)
206 #elif defined(CPROVER_INVARIANT_ASSERT)
210 #define INVARIANT(CONDITION, REASON) assert((CONDITION) && ((REASON), true))
211 #define INVARIANT_WITH_DIAGNOSTICS(CONDITION, REASON, ...) \
212 assert((CONDITION) && ((REASON), true))
214 #define INVARIANT_STRUCTURED(CONDITION, TYPENAME, ...) assert((CONDITION))
236 template <
class ET,
typename... Params>
238 typename std::enable_if<std::is_base_of<invariant_failedt, ET>::value>::type
240 const std::string &file,
241 const std::string &
function,
243 const std::string &condition,
253 std::forward<Params>(params)...);
276 const std::string &file,
277 const std::string &
function,
279 const std::string &condition,
280 const std::string &reason)
282 invariant_violated_structured<invariant_failedt>(
283 file,
function, line, condition, reason);
288 template <
typename T>
297 template <
typename T>
303 "to avoid unintended strangeness, diagnostics_helpert needs to be "
304 "specialised for each diagnostic type");
311 template <std::
size_t N>
347 template <
typename T>
351 typename std::remove_cv<typename std::remove_reference<T>::type>::type>::
352 diagnostics_as_string(std::forward<T>(val));
359 template <
typename T,
typename... Ts>
366 template <
typename... Diagnostics>
369 std::ostringstream out;
370 out <<
"\n<< EXTRA DIAGNOSTICS >>";
372 out <<
"\n<< END EXTRA DIAGNOSTICS >>";
378 template <
typename... Diagnostics>
380 const std::string &file,
381 const std::string &
function,
384 std::string condition,
385 Diagnostics &&... diagnostics)
387 invariant_violated_structured<invariant_with_diagnostics_failedt>(
396 #define EXPAND_MACRO(x) x
402 #define CURRENT_FUNCTION_NAME __FUNCTION__
404 #define CURRENT_FUNCTION_NAME __func__
407 #define INVARIANT_STRUCTURED(CONDITION, TYPENAME, ...) \
411 invariant_violated_structured<TYPENAME>( \
413 CURRENT_FUNCTION_NAME, \
423 #define INVARIANT(CONDITION, REASON) \
428 invariant_violated_string( \
429 __FILE__, CURRENT_FUNCTION_NAME, __LINE__, #CONDITION, REASON); \
437 #define INVARIANT_WITH_DIAGNOSTICS(CONDITION, REASON, ...) \
442 report_invariant_failure( \
444 CURRENT_FUNCTION_NAME, \
463 #define PRECONDITION(CONDITION) INVARIANT(CONDITION, "Precondition")
464 #define PRECONDITION_WITH_DIAGNOSTICS(CONDITION, ...) \
465 INVARIANT_WITH_DIAGNOSTICS(CONDITION, "Precondition", __VA_ARGS__)
467 #define PRECONDITION_STRUCTURED(CONDITION, TYPENAME, ...) \
468 EXPAND_MACRO(INVARIANT_STRUCTURED(CONDITION, TYPENAME, __VA_ARGS__))
479 #define POSTCONDITION(CONDITION) INVARIANT(CONDITION, "Postcondition")
480 #define POSTCONDITION_WITH_DIAGNOSTICS(CONDITION, ...) \
481 INVARIANT_WITH_DIAGNOSTICS(CONDITION, "Postcondition", __VA_ARGS__)
483 #define POSTCONDITION_STRUCTURED(CONDITION, TYPENAME, ...) \
484 EXPAND_MACRO(INVARIANT_STRUCTURED(CONDITION, TYPENAME, __VA_ARGS__))
495 #define CHECK_RETURN(CONDITION) INVARIANT(CONDITION, "Check return value")
496 #define CHECK_RETURN_WITH_DIAGNOSTICS(CONDITION, ...) \
497 INVARIANT_WITH_DIAGNOSTICS(CONDITION, "Check return value", __VA_ARGS__)
499 #define CHECK_RETURN_STRUCTURED(CONDITION, TYPENAME, ...) \
500 EXPAND_MACRO(INVARIANT_STRUCTURED(CONDITION, TYPENAME, __VA_ARGS__))
506 # define UNREACHABLE \
509 INVARIANT(false, "Unreachable"); \
510 __builtin_unreachable(); \
512 # define UNREACHABLE_BECAUSE(REASON) \
515 INVARIANT(false, REASON); \
516 __builtin_unreachable(); \
518 # define UNREACHABLE_STRUCTURED(TYPENAME, ...) \
521 EXPAND_MACRO(INVARIANT_STRUCTURED(false, TYPENAME, __VA_ARGS__)); \
522 __builtin_unreachable(); \
525 # define UNREACHABLE INVARIANT(false, "Unreachable")
526 # define UNREACHABLE_BECAUSE(REASON) INVARIANT(false, REASON)
527 # define UNREACHABLE_STRUCTURED(TYPENAME, ...) \
528 EXPAND_MACRO(INVARIANT_STRUCTURED(false, TYPENAME, __VA_ARGS__))
534 #define DATA_INVARIANT(CONDITION, REASON) INVARIANT(CONDITION, REASON)
535 #define DATA_INVARIANT_WITH_DIAGNOSTICS(CONDITION, REASON, ...) \
536 INVARIANT_WITH_DIAGNOSTICS(CONDITION, REASON, __VA_ARGS__)
538 #define DATA_INVARIANT_STRUCTURED(CONDITION, TYPENAME, ...) \
539 EXPAND_MACRO(INVARIANT_STRUCTURED(CONDITION, TYPENAME, __VA_ARGS__))
542 # define UNIMPLEMENTED_FEATURE(FEATURE) \
545 INVARIANT(false, std::string{"Reached unimplemented "} + (FEATURE)); \
546 __builtin_unreachable(); \
549 # define UNIMPLEMENTED_FEATURE(FEATURE) \
550 INVARIANT(false, std::string{"Reached unimplemented "} + (FEATURE))
557 #define TODO INVARIANT(false, "Todo")
558 #define UNIMPLEMENTED INVARIANT(false, "Unimplemented")
559 #define UNHANDLED_CASE INVARIANT(false, "Unhandled case")
A logic error, augmented with a distinguished field to hold a backtrace.
const std::string backtrace
const std::string condition
virtual ~invariant_failedt()=default
const std::string function
virtual std::string what() const noexcept
A class that includes diagnostic information related to an invariant violation.
virtual std::string what() const noexcept
const std::string diagnostics
void write_rest_diagnostics(std::ostream &)
std::string diagnostic_as_string(T &&val)
std::string assemble_diagnostics()
void report_exception_to_stderr(const invariant_failedt &)
Dump exception report to stderr.
std::string get_backtrace()
Returns a backtrace.
void report_invariant_failure(const std::string &file, const std::string &function, int line, std::string reason, std::string condition, Diagnostics &&... diagnostics)
This is a wrapper function, used by the macro 'INVARIANT_WITH_DIAGNOSTICS'.
void invariant_violated_string(const std::string &file, const std::string &function, const int line, const std::string &condition, const std::string &reason)
This is a wrapper function used by the macro 'INVARIANT(CONDITION, REASON)'.
std::enable_if< std::is_base_of< invariant_failedt, ET >::value >::type invariant_violated_structured(const std::string &file, const std::string &function, const int line, const std::string &condition, Params &&... params)
This function is the backbone of all the invariant types.
void print_backtrace(std::ostream &out)
Prints a back trace to 'out'.
bool cbmc_invariants_should_throw
Set this to true to cause invariants to throw a C++ exception rather than abort the program.
Helper to enable invariant throwing as above bounded to an object lifetime:
~cbmc_invariants_should_throwt()
cbmc_invariants_should_throwt()
static std::string diagnostics_as_string(const char *string)
static std::string diagnostics_as_string(const char(&string)[N])
static std::string diagnostics_as_string(std::string string)
Helper to give us some diagnostic in a usable form on assertion failure.
static std::string diagnostics_as_string(const T &)