/src/mysql-server/include/my_compiler.h
Line | Count | Source |
1 | | #ifndef MY_COMPILER_INCLUDED |
2 | | #define MY_COMPILER_INCLUDED |
3 | | |
4 | | /* Copyright (c) 2010, 2025, Oracle and/or its affiliates. |
5 | | |
6 | | This program is free software; you can redistribute it and/or modify |
7 | | it under the terms of the GNU General Public License, version 2.0, |
8 | | as published by the Free Software Foundation. |
9 | | |
10 | | This program is designed to work with certain software (including |
11 | | but not limited to OpenSSL) that is licensed under separate terms, |
12 | | as designated in a particular file or component or in included license |
13 | | documentation. The authors of MySQL hereby grant you an additional |
14 | | permission to link the program and your derivative works with the |
15 | | separately licensed software that they have either included with |
16 | | the program or referenced in the documentation. |
17 | | |
18 | | This program is distributed in the hope that it will be useful, |
19 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
20 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
21 | | GNU General Public License, version 2.0, for more details. |
22 | | |
23 | | You should have received a copy of the GNU General Public License |
24 | | along with this program; if not, write to the Free Software |
25 | | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ |
26 | | |
27 | | /** |
28 | | @file include/my_compiler.h |
29 | | Header for compiler-dependent features. |
30 | | |
31 | | Intended to contain a set of reusable wrappers for preprocessor |
32 | | macros, attributes, pragmas, and any other features that are |
33 | | specific to a target compiler. |
34 | | */ |
35 | | |
36 | | #ifndef MYSQL_ABI_CHECK |
37 | | #include <assert.h> |
38 | | #include <stddef.h> /* size_t */ |
39 | | #endif |
40 | | |
41 | | #include "my_config.h" |
42 | | |
43 | | #include "mysql/attribute.h" |
44 | | |
45 | | /* |
46 | | The macros below are borrowed from include/linux/compiler.h in the |
47 | | Linux kernel. Use them to indicate the likelihood of the truthfulness |
48 | | of a condition. This serves two purposes - newer versions of gcc will be |
49 | | able to optimize for branch predication, which could yield significant |
50 | | performance gains in frequently executed sections of the code, and the |
51 | | other reason to use them is for documentation |
52 | | */ |
53 | | #ifdef HAVE_BUILTIN_EXPECT |
54 | | |
55 | | // likely/unlikely are likely to clash with other symbols, do not #define |
56 | | #if defined(__cplusplus) |
57 | 182k | constexpr bool likely(bool expr) { return __builtin_expect(expr, true); } |
58 | 0 | constexpr bool unlikely(bool expr) { return __builtin_expect(expr, false); } |
59 | | #else |
60 | | #define likely(x) __builtin_expect((x), 1) |
61 | | #define unlikely(x) __builtin_expect((x), 0) |
62 | | #endif |
63 | | |
64 | | #else /* HAVE_BUILTIN_EXPECT */ |
65 | | |
66 | | #if defined(__cplusplus) |
67 | | constexpr bool likely(bool expr) { return expr; } |
68 | | constexpr bool unlikely(bool expr) { return expr; } |
69 | | #else |
70 | | #define likely(x) (x) |
71 | | #define unlikely(x) (x) |
72 | | #endif |
73 | | |
74 | | #endif /* HAVE_BUILTIN_EXPECT */ |
75 | | |
76 | | /* Communicate to the compiler the unreachability of the code. */ |
77 | | #ifdef HAVE_BUILTIN_UNREACHABLE |
78 | | #define MY_ASSERT_UNREACHABLE() __builtin_unreachable() |
79 | | #else |
80 | | #define MY_ASSERT_UNREACHABLE() \ |
81 | | do { \ |
82 | | assert(0); \ |
83 | | } while (0) |
84 | | #endif |
85 | | |
86 | | /* Visual Studio requires '__inline' for C code */ |
87 | | #if !defined(__cplusplus) && defined(_MSC_VER) |
88 | | #define inline __inline |
89 | | #endif |
90 | | |
91 | | /* Provide __func__ macro definition for Visual Studio. */ |
92 | | #if defined(_MSC_VER) |
93 | | #define __func__ __FUNCTION__ |
94 | | #endif |
95 | | |
96 | | #if defined(_MSC_VER) |
97 | | #define ALWAYS_INLINE __forceinline |
98 | | #else |
99 | | #define ALWAYS_INLINE __attribute__((always_inline)) inline |
100 | | #endif |
101 | | |
102 | | #if defined(_MSC_VER) |
103 | | #define NO_INLINE __declspec(noinline) |
104 | | #else |
105 | | #define NO_INLINE __attribute__((noinline)) |
106 | | #endif |
107 | | |
108 | | #ifndef __has_attribute |
109 | | #define __has_attribute(x) 0 |
110 | | #endif |
111 | | |
112 | | #ifndef SUPPRESS_UBSAN |
113 | | // clang -fsanitize=undefined |
114 | | #if defined(HAVE_UBSAN) && defined(__clang__) |
115 | | #define SUPPRESS_UBSAN MY_ATTRIBUTE((no_sanitize("undefined"))) |
116 | | // gcc -fsanitize=undefined |
117 | | #elif defined(HAVE_UBSAN) && __has_attribute(no_sanitize_undefined) |
118 | | #define SUPPRESS_UBSAN MY_ATTRIBUTE((no_sanitize_undefined)) |
119 | | #else |
120 | | #define SUPPRESS_UBSAN |
121 | | #endif |
122 | | #endif /* SUPPRESS_UBSAN */ |
123 | | |
124 | | #ifndef SUPPRESS_TSAN |
125 | | #if defined(HAVE_TSAN) && defined(__clang__) |
126 | | #define SUPPRESS_TSAN MY_ATTRIBUTE((no_sanitize("thread"))) |
127 | | #elif defined(HAVE_TSAN) && __has_attribute(no_sanitize_thread) |
128 | | #define SUPPRESS_TSAN MY_ATTRIBUTE((no_sanitize_thread)) |
129 | | #else |
130 | | #define SUPPRESS_TSAN |
131 | | #endif |
132 | | #endif /* SUPPRESS_TSAN */ |
133 | | |
134 | | #ifdef _WIN32 |
135 | | #define STDCALL __stdcall |
136 | | #else |
137 | | #define STDCALL |
138 | | #endif |
139 | | |
140 | | /** |
141 | | * stringify parameters for C99/C++11 _Pragma(). |
142 | | */ |
143 | | #define MY_COMPILER_CPP11_PRAGMA(X) _Pragma(#X) |
144 | | /** |
145 | | * pass parameters to MSVC's __pragma() as is. |
146 | | */ |
147 | | #define MY_COMPILER_MSVC_PRAGMA(X) __pragma(X) |
148 | | |
149 | | // enable compiler specified 'diagnostic' pragmas. |
150 | | // |
151 | | // 1. clang on windows defines both clang and msvc pragmas and generates the |
152 | | // same warnings |
153 | | // 2. clang defines both __clang__ and __GNUC__, but doesn't support all GCC |
154 | | // warnings with the same name |
155 | | // |
156 | | // +---------------------+ |
157 | | // | enabled diagnostics | |
158 | | // +------+-------+------+ |
159 | | // | gcc | clang | msvc | |
160 | | // +-------+------+-------+------+ |
161 | | // | gcc | x | - | - | |
162 | | // | clang | - | x | x | |
163 | | // | msvc | - | - | x | |
164 | | // +-------+------+-------+------+ |
165 | | // ^^^ |
166 | | // +----- current compiler |
167 | | // |
168 | | // suppressions that aren't supported by the compiler are disabled to avoid |
169 | | // "unsupported pragmas" warnings: |
170 | | // |
171 | | // @code |
172 | | // // on GCC, clang-specific diagnostic pragmas are disabled |
173 | | // MY_COMPILER_CLANG_DIAGNOSTIC_IGNORE("-Wdocumentation") |
174 | | // @endcode |
175 | | |
176 | | #if defined(__clang__) |
177 | | #define MY_COMPILER_CLANG_DIAGNOSTIC_PUSH() \ |
178 | | MY_COMPILER_CPP11_PRAGMA(clang diagnostic push) |
179 | | #define MY_COMPILER_CLANG_DIAGNOSTIC_POP() \ |
180 | | MY_COMPILER_CPP11_PRAGMA(clang diagnostic pop) |
181 | | /** |
182 | | * ignore a compiler warning. |
183 | | * |
184 | | * @param X warning option to disable, must be quoted like "-Wdocumentation" |
185 | | */ |
186 | | #define MY_COMPILER_CLANG_DIAGNOSTIC_IGNORE(X) \ |
187 | | MY_COMPILER_CPP11_PRAGMA(clang diagnostic ignored X) |
188 | | /** |
189 | | * turn a compiler warning into an error. |
190 | | * |
191 | | * @param X warning option to turn into an error, must be a quoted string like |
192 | | * "-Wdocumentation" |
193 | | */ |
194 | | #define MY_COMPILER_CLANG_DIAGNOSTIC_ERROR(X) \ |
195 | | MY_COMPILER_CPP11_PRAGMA(clang diagnostic error X) |
196 | | |
197 | | #elif defined(__GNUC__) |
198 | | #define MY_COMPILER_GCC_DIAGNOSTIC_PUSH() \ |
199 | | MY_COMPILER_CPP11_PRAGMA(GCC diagnostic push) |
200 | | #define MY_COMPILER_GCC_DIAGNOSTIC_POP() \ |
201 | | MY_COMPILER_CPP11_PRAGMA(GCC diagnostic pop) |
202 | | /** |
203 | | * ignore a compiler warning. |
204 | | * |
205 | | * @param X warning option to disable, must be quoted like "-Wdocumentation" |
206 | | */ |
207 | | #define MY_COMPILER_GCC_DIAGNOSTIC_IGNORE(X) \ |
208 | | MY_COMPILER_CPP11_PRAGMA(GCC diagnostic ignored X) |
209 | | /** |
210 | | * turn a compiler warning into an error. |
211 | | * |
212 | | * @param X warning option to turn into an error, must be quoted like |
213 | | * "-Wdocumentation" |
214 | | */ |
215 | | #define MY_COMPILER_GCC_DIAGNOSTIC_ERROR(X) \ |
216 | | MY_COMPILER_CPP11_PRAGMA(GCC diagnostic error X) |
217 | | |
218 | | #endif // defined(__GNUC__) |
219 | | |
220 | | #if defined(_MSC_VER) |
221 | | #define MY_COMPILER_MSVC_DIAGNOSTIC_PUSH() \ |
222 | | MY_COMPILER_MSVC_PRAGMA(warning(push)) |
223 | | #define MY_COMPILER_MSVC_DIAGNOSTIC_POP() MY_COMPILER_MSVC_PRAGMA(warning(pop)) |
224 | | /** |
225 | | * ignore a compiler warning. |
226 | | * |
227 | | * @param X warning number to disable |
228 | | */ |
229 | | #define MY_COMPILER_MSVC_DIAGNOSTIC_IGNORE(X) \ |
230 | | MY_COMPILER_MSVC_PRAGMA(warning(disable : X)) |
231 | | #define MY_COMPILER_MSVC_DIAGNOSTIC_ERROR(X) \ |
232 | | MY_COMPILER_MSVC_PRAGMA(warning(error : X)) |
233 | | |
234 | | #endif // defined(_MSC_VER) |
235 | | |
236 | | #if !defined(MY_COMPILER_CLANG_DIAGNOSTIC_ERROR) |
237 | | #define MY_COMPILER_CLANG_DIAGNOSTIC_IGNORE(X) |
238 | | #define MY_COMPILER_CLANG_DIAGNOSTIC_ERROR(X) |
239 | | #endif |
240 | | |
241 | | #if !defined(MY_COMPILER_GCC_DIAGNOSTIC_ERROR) |
242 | | #define MY_COMPILER_GCC_DIAGNOSTIC_IGNORE(X) |
243 | | #define MY_COMPILER_GCC_DIAGNOSTIC_ERROR(X) |
244 | | #endif |
245 | | |
246 | | #if !defined(MY_COMPILER_MSVC_DIAGNOSTIC_ERROR) |
247 | | #define MY_COMPILER_MSVC_DIAGNOSTIC_IGNORE(X) |
248 | | #define MY_COMPILER_MSVC_DIAGNOSTIC_ERROR(X) |
249 | | #endif |
250 | | |
251 | | /** |
252 | | * @def MY_COMPILER_DIAGNOSTIC_PUSH() |
253 | | * |
254 | | * save the compiler's diagnostic (enabled warnings, errors, ...) state |
255 | | * |
256 | | * @see MY_COMPILER_DIAGNOSTIC_POP() |
257 | | */ |
258 | | |
259 | | /** |
260 | | * @def MY_COMPILER_DIAGNOSTIC_POP() |
261 | | * |
262 | | * restore the compiler's diagnostic (enabled warnings, errors, ...) state |
263 | | * |
264 | | * @see MY_COMPILER_DIAGNOSTIC_PUSH() |
265 | | */ |
266 | | |
267 | | #if defined(__clang__) |
268 | | #define MY_COMPILER_DIAGNOSTIC_PUSH() MY_COMPILER_CLANG_DIAGNOSTIC_PUSH() |
269 | | #define MY_COMPILER_DIAGNOSTIC_POP() MY_COMPILER_CLANG_DIAGNOSTIC_POP() |
270 | | #elif defined(__GNUC__) |
271 | | #define MY_COMPILER_DIAGNOSTIC_PUSH() MY_COMPILER_GCC_DIAGNOSTIC_PUSH() |
272 | | #define MY_COMPILER_DIAGNOSTIC_POP() MY_COMPILER_GCC_DIAGNOSTIC_POP() |
273 | | #elif defined(_MSC_VER) |
274 | | #define MY_COMPILER_DIAGNOSTIC_PUSH() MY_COMPILER_MSVC_DIAGNOSTIC_PUSH() |
275 | | #define MY_COMPILER_DIAGNOSTIC_POP() MY_COMPILER_MSVC_DIAGNOSTIC_POP() |
276 | | #else |
277 | | #define MY_COMPILER_DIAGNOSTIC_PUSH() |
278 | | #define MY_COMPILER_DIAGNOSTIC_POP() |
279 | | #endif |
280 | | |
281 | | /** |
282 | | * ignore -Wdocumentation compiler warnings for \@tparam. |
283 | | * |
284 | | * @code |
285 | | * MY_COMPILER_DIAGNOSTIC_PUSH() |
286 | | * MY_COMPILER_CLANG_WORKAROUND_TPARAM_DOCBUG() |
287 | | * ... |
288 | | * MY_COMPILER_DIAGNOSTIC_POP() |
289 | | * @endcode |
290 | | * |
291 | | * @see MY_COMPILER_DIAGNOSTIC_PUSH() |
292 | | * @see MY_COMPILER_DIAGNOSTIC_POP() |
293 | | * |
294 | | * allows to work around false positives -Wdocumentation warnings like: |
295 | | * |
296 | | * - \@tparam and explicitly instantiated templates |
297 | | * https://bugs.llvm.org/show_bug.cgi?id=35144 |
298 | | * |
299 | | */ |
300 | | #define MY_COMPILER_CLANG_WORKAROUND_TPARAM_DOCBUG() \ |
301 | | MY_COMPILER_CLANG_DIAGNOSTIC_IGNORE("-Wdocumentation") |
302 | | |
303 | | /** |
304 | | * ignore -Wdocumentation compiler warnings for \@see \@ref |
305 | | * |
306 | | * @code |
307 | | * MY_COMPILER_DIAGNOSTIC_PUSH() |
308 | | * MY_COMPILER_CLANG_WORKAROUND_REF_DOCBUG() |
309 | | * ... |
310 | | * MY_COMPILER_DIAGNOSTIC_POP() |
311 | | * @endcode |
312 | | * |
313 | | * @see MY_COMPILER_DIAGNOSTIC_PUSH() |
314 | | * @see MY_COMPILER_DIAGNOSTIC_POP() |
315 | | * |
316 | | * allows to work around false positives -Wdocumentation warnings like: |
317 | | * |
318 | | * - \@sa \@ref |
319 | | * - \@see \@ref |
320 | | * - \@return \@ref |
321 | | * https://bugs.llvm.org/show_bug.cgi?id=38905 |
322 | | * |
323 | | */ |
324 | | #define MY_COMPILER_CLANG_WORKAROUND_REF_DOCBUG() \ |
325 | | MY_COMPILER_CLANG_DIAGNOSTIC_IGNORE("-Wdocumentation") |
326 | | |
327 | | /** |
328 | | * ignore -Wunused-variable compiler warnings for \@see \@ref |
329 | | * |
330 | | * @code |
331 | | * MY_COMPILER_DIAGNOSTIC_PUSH() |
332 | | * MY_COMPILER_CLANG_WORKAROUND_FALSE_POSITIVE_UNUSED_VARIABLE_WARNING() |
333 | | * ... |
334 | | * MY_COMPILER_DIAGNOSTIC_POP() |
335 | | * @endcode |
336 | | * |
337 | | * @see MY_COMPILER_DIAGNOSTIC_PUSH() |
338 | | * @see MY_COMPILER_DIAGNOSTIC_POP() |
339 | | * |
340 | | * allows to work around false positives -Wunused-variable warnings like: |
341 | | * |
342 | | * - \@sa \@ref |
343 | | * - \@see \@ref |
344 | | * - \@return \@ref |
345 | | * https://bugs.llvm.org/show_bug.cgi?id=46035 |
346 | | * |
347 | | */ |
348 | | #define MY_COMPILER_CLANG_WORKAROUND_FALSE_POSITIVE_UNUSED_VARIABLE_WARNING() \ |
349 | | MY_COMPILER_CLANG_DIAGNOSTIC_IGNORE("-Wunused-variable") |
350 | | |
351 | | /** |
352 | | * ignore -Wsuggest-attribute=format compiler warnings for \@see \@ref |
353 | | * |
354 | | * @code |
355 | | * MY_COMPILER_DIAGNOSTIC_PUSH() |
356 | | * MY_COMPILER_GCC_WORKAROUND_FALSE_POSITIVE_SUGGEST_ATTRIBUTE_FORMAT() |
357 | | * ... |
358 | | * MY_COMPILER_DIAGNOSTIC_POP() |
359 | | * @endcode |
360 | | * |
361 | | * allows to work around false positives -Wsuggest-attribute=format warnings |
362 | | * like: |
363 | | * |
364 | | * - \@sa \@ref |
365 | | * - \@see \@ref |
366 | | * - \@return \@ref |
367 | | * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116954 |
368 | | * |
369 | | */ |
370 | | #define MY_COMPILER_GCC_WORKAROUND_FALSE_POSITIVE_SUGGEST_ATTRIBUTE_FORMAT() \ |
371 | | MY_COMPILER_GCC_DIAGNOSTIC_IGNORE("-Wsuggest-attribute=format") |
372 | | |
373 | | #endif /* MY_COMPILER_INCLUDED */ |