1 2 3 4 5 6 7 8 9 10 11 12
13 14 15
16
17 /*!
18 * ======== Assert ========
19 * Runtime assertion manager
20 *
21 * The `Assert` module provides configurable diagnostics to the program.
22 * Similar to the standard C `assert()` macro, `Assert` methods are
23 * interspersed with other code to add diagnostics to a program. Unlike
24 * the standard C assert support, the `Assert` module provides greater
25 * flexibility in managing the messages displayed, the message string
26 * space overhead, and the runtime handling of failures. In addition,
27 * because the `Assert` methods build atop the Diags module, you can
28 * precisely control which asserts remain in the final application, if any.
29 *
30 * The `Assert` module works in conjunction with the `{@link Diags}` module.
31 * `Assert` statements are added to the code using the
32 * `{@link #isTrue Assert_isTrue()}` function. Execution of assert
33 * statements is controlled by the `{@link Diags#ASSERT}` and
34 * `{@link Diags#INTERNAL}` bits in a module's diagnostics mask. By default,
35 * all module's `Diags_ASSERT` bit is enabled and the `Diags_INTERNAL` bit
36 * is disabled. See `{@link Types#Common$ Types.Common$}` for the
37 * declaration of the bits in the diagnostics mask and
38 * `{@link Defaults#common$ Default.common$}` for the default module settings.
39 *
40 * Two types of asserts are supported: public asserts and internal asserts.
41 *
42 * @p(blist)
43 * - Public asserts have an assert ID and are, by default, controlled
44 * by the `{@link Diags#ASSERT}` bit.
45 * - Internal asserts don't have an assert ID (other than NULL) and
46 * are active only when both the `{@link Diags#ASSERT}` and
47 * `{@link Diags#INTERNAL}` bits of the module's diagnostics mask are set.
48 * @p
49 *
50 * `Assert` IDs are small integer values that index into a table of
51 * assertion descriptors. These descriptors hold an error message
52 * and a diagnostics mask that is used to enable and disable the
53 * assertion at runtime.
54 *
55 * You can remap individual public asserts to different bits in the
56 * diagnostics mask, or can disable the assert altogether. This is
57 * done by setting the mask property of the assert ID. Setting the
58 * mask to 0 disables the assert. In all other cases, the `Diags.ASSERT`
59 * bit is OR'd together with the mask to define the controlling bits.
60 * For example, the module's diagnostics mask must have the `Diags.ASSERT`
61 * bit set and any other bit specified in the mask property of the
62 * assert ID in order to activate the assert.
63 *
64 * @a(Examples)
65 * @p(html)
66 * <hr />
67 * @p
68 * Example 1: The following C code adds an assert to application code
69 * which is not in a module. This assert does not have an assert
70 * identifier (the second argument is NULL); this makes it an internal
71 * assert.
72 *
73 * @p(code)
74 * // file.c
75 * #include <xdc/runtime/Assert.h>
76 *
77 * Assert_isTrue(count > 0, NULL);
78 * @p
79 *
80 * The following XDC configuration statements set both the ASSERT and
81 * INTERNAL bits in the diagnostics mask to enable the internal assert
82 * created in the previous C code. Since the C code is not in a module,
83 * you must set the bits in the diagnostics mask of the
84 * `{@link xdc.runtime.Main xdc.runtime.Main}` module. The Main module
85 * is used to control all `{@link Log}` and `Assert` statements that are
86 * not part of the implementation of a module; for example, top-level
87 * application code or any existing sources that simply call the `Log` or
88 * `Assert` methods.
89 *
90 * @p(code)
91 * // program.cfg
92 * var Assert = xdc.useModule('xdc.runtime.Assert');
93 * var Diags = xdc.useModule('xdc.runtime.Diags');
94 * var Main = xdc.useModule('xdc.runtime.Main');
95 *
96 * Main.common$.diags_ASSERT = Diags.ALWAYS_ON;
97 * Main.common$.diags_INTERNAL = Diags.ALWAYS_ON;
98 * @p
99 *
100 * @p(html)
101 * <hr />
102 * @p
103 * Example 2: The following example shows how to use and configure an
104 * assert ID that is declared by a module. It adds that assert to the
105 * application's C source code, and configures the application to
106 * execute the assert.
107 *
108 * This is part of the XDC file for the module that declares an `Assert` Id:
109 *
110 * @p(code)
111 * // Mod.xdc
112 * import xdc.runtime.Assert;
113 * import xdc.runtime.Diags;
114 *
115 * config Assert.Id A_nonZero = {
116 * msg: "A_nonZero: value must be non-zero"
117 * };
118 * @p
119 *
120 * This is part of the C code for the application:
121 *
122 * @p(code)
123 * // Mod.c
124 * #include <xdc/runtime/Assert.h>
125 *
126 * Assert_isTrue(x != 0, Mod_A_nonZero);
127 * @p
128 *
129 * This is part of the XDC configuration file for the application:
130 *
131 * @p(code)
132 * // program.cfg
133 * var Diags = xdc.useModule('xdc.runtime.Diags');
134 * var Mod = xdc.useModule('my.pkg.Mod');
135 * Mod.common$.diags_ASSERT = Diags.ALWAYS_ON;
136 * @p
137 *
138 * The Assert calls can also be completely removed by defining the symbol
139 * xdc_runtime_Assert_DISABLE_ALL. This can be done on the compile line, e.g.
140 * -Dxdc_runtime_Assert_DISABLE_ALL. This will completely remove the Assert
141 * statements from any code compiled with this flag, regardless of the
142 * application's configuration or your compiler's optimization settings.
143 *
144 * It is also possible to remove all conditions from Assert calls. As explained
145 * above, Assert calls are executed only if certain bits in the module's
146 * Diags mask are set. However, if the symbol
147 * xdc_runtime_Assert_DISABLE_CONDITIONAL_ASSERT is defined, the module's Diags
148 * mask is not queried at all, and all Assert calls are unconditionally
149 * executed.
150 * The symbol xdc_runtime_Assert_DISABLE_ALL has a precedence, and if it's
151 * set, no Assert calls are executed regardless of any definition of
152 * xdc_runtime_Assert_DISABLE_CONDITIONAL_ASSERT.
153 */
154 @DirectCall
155 @CustomHeader
156
157 module Assert {
158
159 /*!
160 * ======== Assert_Desc ========
161 * Assert descriptor
162 *
163 * Each public assert is defined with an assert descriptor. This
164 * structure defines which bits in the module's diagnostics mask
165 * control this assert, and the message raised when the assert fails.
166 * The mask property is optional, it defaults to the
167 * `{@link Diags#ASSERT}` bit.
168 *
169 * @field(mask) Specifies which bits enable the assert.
170 * @field(msg) The message printed when the assert fails.
171 */
172 metaonly struct Desc {
173 Diags.Mask mask;
174 String msg;
175 };
176
177 /*!
178 * ======== Assert_Id ========
179 * Assert identifier
180 *
181 * Each metaonly assert descriptor is encoded into a target accessable
182 * assert Id type which can be passed to the `{@link #isTrue}` function.
183 */
184 @Encoded typedef Desc Id;
185
186 /*!
187 * ======== E_assertFailed ========
188 * The `{@link Error#Id}` raised when an assertion violation is detected
189 *
190 * When an assertion violation is triggered, an error is raised via
191 * `Error_raise()`. `E_assert_Failed` is the `{@link Error#Id}` passed
192 * to `Error_raise()`.
193 *
194 * The first string argument (%s) will be either "", if the assertion Id
195 * is `NULL` (for internal asserts), or ": " (for public asserts).
196 * The second string argument (%s) is the
197 * `Assert.Desc.msg` string associated with the assertion Id; if the
198 * Id is `NULL` (an internal assert) or if text is not loaded
199 * (`!{@link Text#isLoaded}()`), this string is "".
200 *
201 * @see #isTrue
202 * @see Error#Id
203 */
204 readonly config Error.Id E_assertFailed = {msg: "assertion failure%s%s"};
205
206 /*!
207 * ======== Assert_isTrue ========
208 * Test an assertion
209 *
210 * `Assert_isTrue()` statements may be conditionally enabled (disabled)
211 * on a per module basis by setting the calling module's
212 * `{@link IModule#$common $common.diags_ASSERT}` configuration
213 * parameter. If
214 * the `Assert_isTrue()` statement is not in a module, the calling
215 * module is the `{@link Main}` module. You must enable the
216 * `{@link Diags#ASSERT}` bit in the module's diagnostics mask for this
217 * call to be enabled. If a `NULL` assert id is specified, then you
218 * must enable the `{@link Diags#INTERNAL}` in addition to the
219 * `ASSERT` bit.
220 *
221 * If the `Assert_isTrue()` statement is enabled and `expr` evaluates to
222 * false, the assert specified by `id` is raised; i.e., the
223 * `{@link #E_assertFailed}` error is raised with a `NULL`
224 * error block. In other words, the standard `{@link Error#raise}`
225 * handling hooks will be run, `{@link System#abort()}` will be called,
226 * and control does not return to the caller. The `id` may be `null`, in
227 * which case you will get a generic assert message.
228 *
229 * @param(expr) the expression which should evaluate to true
230 * @param(id) identifies the assert being raised
231 *
232 * @a(Examples)
233 * C Code
234 * @p(code)
235 * #include <xdc/runtime/Assert.h>
236 *
237 * Assert_isTrue(count > 0, NULL);
238 * @p
239 */
240 @Macro Void isTrue(Bool expr, Id id);
241
242 internal:
243
244 Void raise(Types.ModuleId mod, CString file, Int line, Id id);
245
246 }
247 248 249
250