7272// / family of macros, allowing constructs like
7373// / `INVARIANT(x==y, my_invariantt, (T1)actual1, (T2)actual2, ...)`
7474// /
75- class invariant_failedt : public std ::logic_error
75+ class invariant_failedt
7676{
7777 private:
78- std::string get_invariant_failed_message (
79- const std::string &file,
80- const std::string &function,
81- int line,
82- const std::string &backtrace,
83- const std::string &reason);
78+ std::string get_invariant_failed_message (
79+ const std::string &file,
80+ const std::string &function,
81+ int line,
82+ const std::string &backtrace,
83+ const std::string &reason) const ;
8484
8585 public:
8686 const std::string file;
8787 const std::string function;
8888 const int line;
8989 const std::string backtrace;
9090 const std::string reason;
91+ const std::string condition;
92+
93+ std::string what () const noexcept
94+ {
95+ return get_invariant_failed_message (
96+ file, function, line, backtrace, reason);
97+ };
9198
9299 invariant_failedt (
93100 const std::string &_file,
94101 const std::string &_function,
95102 int _line,
96103 const std::string &_backtrace,
97- const std::string &_reason):
98- logic_error (
99- get_invariant_failed_message (
100- _file,
101- _function,
102- _line,
103- _backtrace,
104- _reason)),
105- file(_file),
106- function(_function),
107- line(_line),
108- backtrace(_backtrace),
109- reason(_reason)
104+ const std::string &_reason,
105+ const std::string &_condition)
106+ : file(_file),
107+ function (_function),
108+ line(_line),
109+ backtrace(_backtrace),
110+ reason(_reason),
111+ condition(_condition)
110112 {
111113 }
112114};
@@ -149,9 +151,10 @@ void report_exception_to_stderr(const invariant_failedt &);
149151// / \param file : C string giving the name of the file.
150152// / \param function : C string giving the name of the function.
151153// / \param line : The line number of the invariant
154+ // / \param condition : the condition this invariant is checking.
152155// / \param params : (variadic) parameters to forward to ET's constructor
153156// / its backtrace member will be set before it is used.
154- template <class ET , typename ...Params>
157+ template <class ET , typename ... Params>
155158#ifdef __GNUC__
156159__attribute__ ((noreturn))
157160#endif
@@ -160,10 +163,17 @@ invariant_violated_structured(
160163 const std::string &file,
161164 const std::string &function,
162165 const int line,
166+ const std::string &condition,
163167 Params &&... params)
164168{
165169 std::string backtrace=get_backtrace ();
166- ET to_throw (file, function, line, backtrace, std::forward<Params>(params)...);
170+ ET to_throw (
171+ file,
172+ function,
173+ line,
174+ backtrace,
175+ std::forward<Params>(params)...,
176+ condition);
167177 // We now have a structured exception ready to use;
168178 // in future this is the place to put a 'throw'.
169179 report_exception_to_stderr (to_throw);
@@ -177,20 +187,20 @@ invariant_violated_structured(
177187// / \param function : C string giving the name of the function.
178188// / \param line : The line number of the invariant
179189// / \param reason : brief description of the invariant violation.
190+ // / \param condition : the condition this invariant is checking.
180191#ifdef __GNUC__
181192__attribute__ ((noreturn))
182193#endif
183- inline void invariant_violated_string (
194+ inline void
195+ invariant_violated_string (
184196 const std::string &file,
185197 const std::string &function,
186198 const int line,
187- const std::string &reason)
199+ const std::string &reason,
200+ const std::string &condition)
188201{
189202 invariant_violated_structured<invariant_failedt>(
190- file,
191- function,
192- line,
193- reason);
203+ file, function, line, condition, reason);
194204}
195205
196206// These require a trailing semicolon by the user, such that INVARIANT
@@ -207,15 +217,23 @@ inline void invariant_violated_string(
207217 { \
208218 if (!(CONDITION)) \
209219 invariant_violated_string ( \
210- __FILE__, __this_function__, __LINE__, (REASON)); /* NOLINT */ \
220+ __FILE__, \
221+ __this_function__, \
222+ __LINE__, \
223+ (REASON), \
224+ #CONDITION); /* NOLINT */ \
211225 } while (false )
212226
213227#define INVARIANT_STRUCTURED (CONDITION, TYPENAME, ...) \
214228 do /* NOLINT */ \
215229 { \
216230 if (!(CONDITION)) \
217231 invariant_violated_structured<TYPENAME>( \
218- __FILE__, __this_function__, __LINE__, __VA_ARGS__); /* NOLINT */ \
232+ __FILE__, \
233+ __this_function__, \
234+ __LINE__, \
235+ __VA_ARGS__, \
236+ #CONDITION); /* NOLINT */ \
219237 } while (false )
220238
221239#endif // End CPROVER_DO_NOT_CHECK / CPROVER_ASSERT / ... if block
0 commit comments