Branch data Line data Source code
1 : : /***************************************************************************
2 : : *
3 : : * The IPPL Framework
4 : : *
5 : : ***************************************************************************/
6 : :
7 : : #ifndef PASSERT_H
8 : : #define PASSERT_H
9 : : #include <exception>
10 : : #include <stdexcept>
11 : : #include <string>
12 : :
13 : : #include "Utility/IpplInfo.h"
14 : : //////////////////////////////////////////////////////////////////////
15 : : //
16 : : // This is a compile time assert.
17 : : // That is, if you say:
18 : : // CTAssert<true>::test();
19 : : // it compiles just fine and inserts no code.
20 : : // If you say:
21 : : // CTAssert<false>::test();
22 : : // you get a compile error that it can't find CTAssert<false>::test().
23 : : //
24 : : // The template argument can of course be a calculation of const bools
25 : : // that are known at compile time.
26 : : //
27 : : //////////////////////////////////////////////////////////////////////
28 : :
29 : : template <bool B>
30 : : struct IpplCTAssert {};
31 : :
32 : : template <>
33 : : struct IpplCTAssert<true> {
34 : : static void test() {}
35 : : };
36 : :
37 : : #if defined(NOCTAssert)
38 : : #define CTAssert(c)
39 : : #else
40 : : #define CTAssert(c) IpplCTAssert<(c)>::test()
41 : : #endif
42 : :
43 : : //===========================================================================//
44 : : // class assertion - exception notification class for assertions
45 : :
46 : : // This class should really be derived from std::runtime_error, but
47 : : // unfortunately we don't have good implementation of the library standard
48 : : // yet, on compilers other than KCC. So, this class will keep with the
49 : : // "what" method evidenced in the standard, but dispense with inheriting from
50 : : // classes for which we don't have implementations...
51 : : //===========================================================================//
52 : :
53 : : class assertion : public std::runtime_error {
54 : : char* msg;
55 : :
56 : : public:
57 : : assertion(const char* cond, const char* file, int line);
58 : :
59 : : assertion(const char* m);
60 : :
61 : : assertion(const assertion& a);
62 : :
63 [ # # ]: 0 : ~assertion() throw() { delete[] msg; }
64 : :
65 : : assertion& operator=(const assertion& a);
66 : :
67 : : using std::runtime_error::what;
68 : :
69 : 0 : virtual const char* what() { return msg; };
70 : : };
71 : :
72 : : //---------------------------------------------------------------------------//
73 : : // Now we define a run time assertion mechanism. We will call it "PAssert",
74 : : // to reflect the idea that this is for use in IPPL per se, recognizing that
75 : : // there are numerous other assertion facilities in use in client codes.
76 : : //---------------------------------------------------------------------------//
77 : :
78 : : // These are the functions that will be called in the assert macros.
79 : : void toss_cookies(const char* cond, const char* file, int line);
80 : : template <class S, class T>
81 : 0 : void toss_cookies(const char* cond, const char* astr, const char* bstr, S a, T b, const char* file,
82 : : int line) {
83 [ # # # # : 0 : std::string what = "Assertion '" + std::string(cond) + "' failed. \n";
# # ]
84 [ # # # # : 0 : what += std::string(astr) + " = " + std::to_string(a) + ", ";
# # # # #
# # # ][ #
# # # # #
# # # # ]
85 [ # # # # : 0 : what += std::string(bstr) + " = " + std::to_string(b) + "\n";
# # # # #
# ][ # # #
# # # # #
# # # # ]
86 [ # # ]: 0 : what += "in \n";
87 [ # # # # : 0 : what += std::string(file) + ", line " + std::to_string(line);
# # # # ]
88 : :
89 [ # # ]: 0 : throw std::runtime_error(what);
90 : 0 : }
91 : : void insist(const char* cond, const char* msg, const char* file, int line);
92 : :
93 : : //---------------------------------------------------------------------------//
94 : : // The PAssert macro is intended to be used for validating preconditions
95 : : // which must be true in order for following code to be correct, etc. For
96 : : // example, PAssert( x > 0. ); y = sqrt(x); If the assertion fails, the code
97 : : // should just bomb. Philosophically, it should be used to feret out bugs in
98 : : // preceding code, making sure that prior results are within reasonable
99 : : // bounds before proceeding to use those results in further computation, etc.
100 : : //---------------------------------------------------------------------------//
101 : :
102 : : #ifdef NOPAssert
103 : : #define PAssert(c)
104 : : #define PAssert_EQ(a, b)
105 : : #define PAssert_NE(a, b)
106 : : #define PAssert_LT(a, b)
107 : : #define PAssert_LE(a, b)
108 : : #define PAssert_GT(a, b)
109 : : #define PAssert_GE(a, b)
110 : : #else
111 : : #ifdef __HIP_PLATFORM_AMD__ // toss_cookies are not supported so just do a no-operation
112 : : #define PAssert(c)
113 : : #define PAssert_CMP(cmp, a, b)
114 : : #else
115 : : #define PAssert(c) \
116 : : if (!(c)) \
117 : : toss_cookies(#c, __FILE__, __LINE__);
118 : : #define PAssert_CMP(cmp, a, b) \
119 : : if (!(cmp)) \
120 : : toss_cookies(#cmp, #a, #b, a, b, __FILE__, __LINE__);
121 : : #endif
122 : : #define PAssert_EQ(a, b) PAssert_CMP(a == b, a, b)
123 : : #define PAssert_NE(a, b) PAssert_CMP(a != b, a, b)
124 : : #define PAssert_LT(a, b) PAssert_CMP(a < b, a, b)
125 : : #define PAssert_LE(a, b) PAssert_CMP(a <= b, a, b)
126 : : #define PAssert_GT(a, b) PAssert_CMP(a > b, a, b)
127 : : #define PAssert_GE(a, b) PAssert_CMP(a >= b, a, b)
128 : : #endif
129 : :
130 : : //---------------------------------------------------------------------------//
131 : : // The PInsist macro is akin to the PAssert macro, but it provides the
132 : : // opportunity to specify an instructive message. The idea here is that you
133 : : // should use Insist for checking things which are more or less under user
134 : : // control. If the user makes a poor choice, we "insist" that it be
135 : : // corrected, providing a corrective hint.
136 : : //---------------------------------------------------------------------------//
137 : :
138 : : #define PInsist(c, m) \
139 : : if (!(c)) \
140 : : insist(#c, m, __FILE__, __LINE__);
141 : :
142 : : //---------------------------------------------------------------------------//
143 : : // NOTE: We provide a way to eliminate assertions, but not insistings. The
144 : : // idea is that PAssert is used to perform sanity checks during program
145 : : // development, which you might want to eliminate during production runs for
146 : : // performance sake. PInsist is used for things which really really must be
147 : : // true, such as "the file must've been opened", etc. So, use PAssert for
148 : : // things which you want taken out of production codes (like, the check might
149 : : // inhibit inlining or something like that), but use PInsist for those things
150 : : // you want checked even in a production code.
151 : : //---------------------------------------------------------------------------//
152 : :
153 : : #endif // PASSERT_H
154 : :
155 : : // vi: set et ts=4 sw=4 sts=4:
156 : : // Local Variables:
157 : : // mode:c
158 : : // c-basic-offset: 4
159 : : // indent-tabs-mode: nil
160 : : // require-final-newline: nil
161 : : // End:
|