1 /* EINA - EFL data type library 2 * Copyright (C) 2008 Gustavo Sverzut Barbieri 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2.1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Lesser General Public License for more details. 13 * 14 * You should have received a copy of the GNU Lesser General Public 15 * License along with this library; 16 * if not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #ifndef EINA_SAFETY_CHECKS_H_ 20 #define EINA_SAFETY_CHECKS_H_ 21 22 /** 23 * @addtogroup Eina_Tools_Group Tools 24 * 25 * @{ 26 */ 27 28 /** 29 * @defgroup Eina_Safety_Checks_Group Safety Checks 30 * 31 * @warning @c eina_safety_checks.h should only be included by source 32 * files after all other includes and before the source file 33 * specific includes. By source file specific includes we 34 * mean those that define the functions that are being 35 * checked. The reason for such complexity is the trick to 36 * avoid compiler optimizations. If compilers are told that 37 * some given function will never receive @c NULL 38 * (EINA_ARG_NONNULL()), then the compiler will emit a warning if 39 * it detects so (good!) and also will remove any checks for that 40 * condition as it believes it will never happen, removing 41 * all safety checks! By including @c eina_safety_checks.h last it 42 * will redefine EINA_ARG_NONNULL() to void and compiler 43 * warning will not be emitted, but checks will be there. The 44 * files already processed with the old macro 45 * EINA_ARG_NONNULL() will still work and emit the warnings. 46 * 47 * 48 * @code 49 * 50 * // all these files will emit warning from EINA_ARG_NONNULL() 51 * #include <Evas.h> // third party headers 52 * #include <Ecore.h> 53 * 54 * #include <eina_safety_checks.h> 55 * // all the files below will NOT emit warning from EINA_ARG_NONNULL(), 56 * // but this is required to have the functions defined there to be checked 57 * // for NULL pointers 58 * #include "my_functions1.h" 59 * #include "my_functions2.h" 60 * 61 * @endcode 62 */ 63 64 /** 65 * @addtogroup Eina_Safety_Checks_Group Safety Checks 66 * 67 * Safety checks are a set of macros to check for parameters or values 68 * that should never happen, it is similar in concept to assert(), but 69 * will log and return instead of abort() your program. 70 * 71 * Since these cases should never happen, one may want to keep safety 72 * checks enabled during tests but disable them during deploy, not 73 * doing any checks at all. This is a common requirement for embedded 74 * systems. When to check or not should be set during compile time 75 * by using @c --disable-safety-checks or @c --enable-safety-checks 76 * options to @c configure script. 77 * 78 * Whenever these macros capture an error, EINA_LOG_ERR() will be 79 * called. 80 * 81 * @see EINA_SAFETY_ON_NULL_RETURN(), EINA_SAFETY_ON_NULL_RETURN_VAL() 82 * and other macros. 83 * 84 * @{ 85 */ 86 87 #include "eina_config.h" 88 #include "eina_error.h" 89 90 EAPI extern Eina_Error EINA_ERROR_SAFETY_FAILED; 91 92 #ifdef EINA_SAFETY_CHECKS 93 94 #include "eina_log.h" 95 96 # ifdef EFL_BETA_API_SUPPORT 97 /** 98 * Log entry-point called every time an eina safety check fails. 99 * 100 * One purpose of this dedicated function is to provide a convenient breakpoint 101 * for GDB debugging. Also, this gives it a dedicated log domain, rather than 102 * using the default one. 103 * 104 * @since 1.17 105 * @internal 106 */ 107 EAPI void _eina_safety_error(const char *file, const char *func, int line, const char *str); 108 # define EINA_SAFETY_ERROR(msg) _eina_safety_error(__FILE__, __func__, __LINE__, msg) 109 # else 110 # define EINA_SAFETY_ERROR(msg) EINA_LOG_ERR("%s", msg) 111 # endif 112 113 #define EINA_SAFETY_ON_NULL_RETURN(exp) \ 114 do \ 115 { \ 116 if (EINA_UNLIKELY((exp) == NULL)) \ 117 { \ 118 EINA_SAFETY_ERROR("safety check failed: " # exp " == NULL"); \ 119 return; \ 120 } \ 121 } \ 122 while (0) 123 124 #define EINA_SAFETY_ON_NULL_RETURN_VAL(exp, val) \ 125 do \ 126 { \ 127 if (EINA_UNLIKELY((exp) == NULL)) \ 128 { \ 129 EINA_SAFETY_ERROR("safety check failed: " # exp " == NULL"); \ 130 return (val); \ 131 } \ 132 } \ 133 while (0) 134 135 #define EINA_SAFETY_ON_NULL_GOTO(exp, label) \ 136 do \ 137 { \ 138 if (EINA_UNLIKELY((exp) == NULL)) \ 139 { \ 140 EINA_SAFETY_ERROR("safety check failed: " # exp " == NULL"); \ 141 goto label; \ 142 } \ 143 } \ 144 while (0) 145 146 #define EINA_SAFETY_ON_TRUE_RETURN(exp) \ 147 do \ 148 { \ 149 if (EINA_UNLIKELY(exp)) \ 150 { \ 151 EINA_SAFETY_ERROR("safety check failed: " # exp " is true"); \ 152 return; \ 153 } \ 154 } \ 155 while (0) 156 157 #define EINA_SAFETY_ON_TRUE_RETURN_VAL(exp, val) \ 158 do \ 159 { \ 160 if (EINA_UNLIKELY(exp)) \ 161 { \ 162 EINA_SAFETY_ERROR("safety check failed: " # exp " is true"); \ 163 return val; \ 164 } \ 165 } \ 166 while (0) 167 168 #define EINA_SAFETY_ON_TRUE_GOTO(exp, label) \ 169 do \ 170 { \ 171 if (EINA_UNLIKELY(exp)) \ 172 { \ 173 EINA_SAFETY_ERROR("safety check failed: " # exp " is true"); \ 174 goto label; \ 175 } \ 176 } \ 177 while (0) 178 179 #define EINA_SAFETY_ON_FALSE_RETURN(exp) \ 180 do \ 181 { \ 182 if (EINA_UNLIKELY(!(exp))) \ 183 { \ 184 EINA_SAFETY_ERROR("safety check failed: " # exp " is false"); \ 185 return; \ 186 } \ 187 } \ 188 while (0) 189 190 #define EINA_SAFETY_ON_FALSE_RETURN_VAL(exp, val) \ 191 do \ 192 { \ 193 if (EINA_UNLIKELY(!(exp))) \ 194 { \ 195 EINA_SAFETY_ERROR("safety check failed: " # exp " is false"); \ 196 return val; \ 197 } \ 198 } \ 199 while (0) 200 201 #define EINA_SAFETY_ON_FALSE_GOTO(exp, label) \ 202 do \ 203 { \ 204 if (EINA_UNLIKELY(!(exp))) \ 205 { \ 206 EINA_SAFETY_ERROR("safety check failed: " # exp " is false"); \ 207 goto label; \ 208 } \ 209 } \ 210 while (0) 211 212 #ifdef EINA_ARG_NONNULL 213 /* make EINA_ARG_NONNULL void so GCC does not optimize safety checks */ 214 #undef EINA_ARG_NONNULL 215 #define EINA_ARG_NONNULL(...) 216 #endif 217 218 #else /* no safety checks */ 219 220 /** 221 * @def EINA_SAFETY_ON_NULL_RETURN 222 * @brief The macro doesn't do anything unless EINA_SAFETY_CHECKS is defined. 223 * @param[in] exp The expression to be evaluated. 224 */ 225 #define EINA_SAFETY_ON_NULL_RETURN(exp) \ 226 do { (void)(!(exp)); } while (0) 227 228 /** 229 * @def EINA_SAFETY_ON_NULL_RETURN_VAL 230 * @brief The macro doesn't do anything unless EINA_SAFETY_CHECKS is defined. 231 * @param[in] exp The expression to be evaluated. 232 * @param[in] val The value to be returned. 233 */ 234 #define EINA_SAFETY_ON_NULL_RETURN_VAL(exp, val) \ 235 do { if (0 && !(exp)) { (void)val; } } while (0) 236 237 /** 238 * @def EINA_SAFETY_ON_NULL_GOTO 239 * @brief The macro doesn't do anything unless EINA_SAFETY_CHECKS is defined. 240 * @param[in] exp The expression to be evaluated. 241 * @param[in] label The label to jump to. 242 */ 243 #define EINA_SAFETY_ON_NULL_GOTO(exp, label) \ 244 do { if (0 && (exp) == NULL) { goto label; } } while (0) 245 246 /** 247 * @def EINA_SAFETY_ON_TRUE_RETURN 248 * @brief The macro doesn't do anything unless EINA_SAFETY_CHECKS is defined. 249 * @param[in] exp The expression to be evaluated. 250 */ 251 #define EINA_SAFETY_ON_TRUE_RETURN(exp) \ 252 do { (void)(exp); } while (0) 253 254 /** 255 * @def EINA_SAFETY_ON_TRUE_RETURN_VAL 256 * @brief The macro doesn't do anything unless EINA_SAFETY_CHECKS is defined. 257 * @param[in] exp The expression to be evaluated. 258 * @param[in] val The value to be returned. 259 */ 260 #define EINA_SAFETY_ON_TRUE_RETURN_VAL(exp, val) \ 261 do { if (0 && (exp)) { (void)val; } } while (0) 262 263 /** 264 * @def EINA_SAFETY_ON_TRUE_GOTO 265 * @brief The macro doesn't do anything unless EINA_SAFETY_CHECKS is defined. 266 * @param[in] exp The expression to be evaluated. 267 * @param[in] label The label to jump to. 268 */ 269 #define EINA_SAFETY_ON_TRUE_GOTO(exp, label) \ 270 do { if (0 && (exp)) { goto label; } } while (0) 271 272 /** 273 * @def EINA_SAFETY_ON_FALSE_RETURN 274 * @brief The macro doesn't do anything unless EINA_SAFETY_CHECKS is defined. 275 * @param[in] exp The expression to be evaluated. 276 */ 277 #define EINA_SAFETY_ON_FALSE_RETURN(exp) \ 278 do { (void)(!(exp)); } while (0) 279 280 /** 281 * @def EINA_SAFETY_ON_FALSE_RETURN_VAL 282 * @brief The macro doesn't do anything unless EINA_SAFETY_CHECKS is defined. 283 * @param[in] exp The expression to be evaluated. 284 * @param[in] val The value to be returned. 285 */ 286 #define EINA_SAFETY_ON_FALSE_RETURN_VAL(exp, val) \ 287 do { if (0 && !(exp)) { (void)val; } } while (0) 288 289 /** 290 * @def EINA_SAFETY_ON_FALSE_GOTO 291 * @brief The macro doesn't do anything unless EINA_SAFETY_CHECKS is defined. 292 * @param[in] exp The expression to be evaluated. 293 * @param[in] label The label to jump to. 294 */ 295 #define EINA_SAFETY_ON_FALSE_GOTO(exp, label) \ 296 do { if (0 && !(exp)) { goto label; } } while (0) 297 298 #endif /* safety checks macros */ 299 #endif /* EINA_SAFETY_CHECKS_H_ */ 300 301 /** 302 * @} 303 */ 304 305 /** 306 * @} 307 */ 308