-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcompile_assert.h
127 lines (106 loc) · 4.16 KB
/
compile_assert.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#ifndef COMPILE_ASSERT_H
#define COMPILE_ASSERT_H
/**
* Copyright 2023 Jonny Grant <jg@jguk.org>
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this list
* of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or other
* materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its contributors may be
* used to endorse or promote products derived from this software without specific
* prior written permission.
*/
/**
* @file compile_assert.h
* @brief Header file providing a macro for compile-time assertions in optimized builds.
*/
// Utilize GCC attribute error as part of an optimized build to stop when conditions
// are not met. This is at build time, by the compiler, when it does redundant code
// removal, aka dead code removal.
//
// Implemented in C, it can be used in C++ projects as well.
//
// compile_assert() is kept as a macro so GCC shows the line it's invoked as in
// any asserts that fire. (If changed to inline, GCC shows the inline function code instead)
//
// Note this relies upon an optimized compiler build, in -O0 builds, it "compiles out"
/**
* @brief Utilize GCC attribute error as part of an optimized build to stop when conditions
* are not met. This is at build time, by the compiler, when it does redundant code
* removal, aka dead code removal.
*
* Implemented in C, it can be used in C++ projects as well.
*
* @note compile_assert() is kept as a macro so GCC shows the line it's invoked as in
* any asserts that fire. (If changed to inline, GCC shows the inline function code instead)
*
* @note This only works in an Optimized build; in -O0 builds, it "compiles out".
*
* @note Future work: The description isn't logged yet - never will be, just note
* to the programmer to refer to when they look up the file and line number of the compiler
* output.
*/
#ifdef __OPTIMIZE__
/**
* @brief Function to stop compilation with an error message if a compile_assert condition is not satisfied.
* There is no implementation as it is only used to stop the compiler.
* @see compile_assert
*/
void _stop_compile() __attribute__ ((error("'compile_assert error detected'")));
void * _stop_compile2() __attribute__ ((error("'compile_assert error detected'")));
int _stop_compile3() __attribute__ ((error("'compile_assert error detected'")));
/**
* @def compile_assert
* @brief Macro for compile-time assertion in optimized builds.
* @param condition The compile-time condition to be checked.
* @param description A description of the assertion (unused).
*/
#define compile_assert(condition, description) \
do { \
if (!(condition)) { \
_stop_compile(); \
} \
} while (0)
#else
#define compile_assert(condition, description)
#endif
#ifdef __OPTIMIZE__
/**
* @def compile_assert_never_null
* @brief Macro to ensure a pointer is never NULL in optimized builds.
* @param ptr The pointer to be checked for NULL.
* @return The pointer ptr if not NULL.
*/
#define compile_assert_never_null(ptr) ((ptr) ? (ptr) : _stop_compile2())
#else
#define compile_assert_never_null(ptr) ptr
#endif
#ifdef __OPTIMIZE__
/**
* @def compile_assert_ptr
* @brief Macro to check a condition and show the pointer, or stop the
* compiler by calling the error function in optimized builds.
* @param condition
* @param ptr The pointer.
* @return The pointer.
*/
#define compile_assert_ptr(condition, ptr) ((condition) ? (ptr) : _stop_compile2())
#else
#define compile_assert_ptr(condition, ptr) ptr
#endif
#ifdef __OPTIMIZE__
/**
* @def compile_assert_scalar
* @brief Macro to check a condition and substitute with the scalar in an optimized build.
* @param condition
* @param scalar The value.
* @return The scalar value.
*/
#define compile_assert_scalar(condition, scalar) ((condition) ? (scalar) : _stop_compile3())
#else
#define compile_assert_scalar(condition, scalar) scalar
#endif
#endif