1 /*
2 * Copyright (c) 2015 Dmitry V. Levin <ldv@strace.io>
3 * Copyright (c) 2015-2022 The strace developers.
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: LGPL-2.1-or-later
7 */
8
9 #ifndef STRACE_GCC_COMPAT_H
10 # define STRACE_GCC_COMPAT_H
11
12 # if defined __GNUC__ && defined __GNUC_MINOR__
13 # define GNUC_PREREQ(maj, min) \
14 ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
15 # else
16 # define GNUC_PREREQ(maj, min) 0
17 # endif
18
19 # if defined __clang__ && defined __clang_major__ && defined __clang_minor__
20 # define CLANG_PREREQ(maj, min) \
21 ((__clang_major__ << 16) + __clang_minor__ >= ((maj) << 16) + (min))
22 # else
23 # define CLANG_PREREQ(maj, min) 0
24 # endif
25
26 # ifdef __GLIBC__
27 # ifdef __GLIBC_MINOR__
28 # define GLIBC_PREREQ_GE(maj, min) \
29 ((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min))
30 # define GLIBC_PREREQ_LT(maj, min) \
31 ((__GLIBC__ << 16) + __GLIBC_MINOR__ < ((maj) << 16) + (min))
32 # else /* !__GLIBC_MINOR__ */
33 # define GLIBC_PREREQ_GE(maj, min) 0
34 # define GLIBC_PREREQ_LT(maj, min) 1
35 # endif
36 # else /* !__GLIBC__ */
37 # define GLIBC_PREREQ_GE(maj, min) 0
38 # define GLIBC_PREREQ_LT(maj, min) 0
39 # endif
40
41 # if !(GNUC_PREREQ(2, 0) || CLANG_PREREQ(1, 0))
42 # define __attribute__(x) /* empty */
43 # endif
44
45 # if GNUC_PREREQ(2, 5)
46 # define ATTRIBUTE_NORETURN __attribute__((__noreturn__))
47 # else
48 # define ATTRIBUTE_NORETURN /* empty */
49 # endif
50
51 # if GNUC_PREREQ(2, 7)
52 # define ATTRIBUTE_FORMAT(args) __attribute__((__format__ args))
53 # define ATTRIBUTE_ALIGNED(arg) __attribute__((__aligned__(arg)))
54 # define ATTRIBUTE_PACKED __attribute__((__packed__))
55 # else
56 # define ATTRIBUTE_FORMAT(args) /* empty */
57 # define ATTRIBUTE_ALIGNED(arg) /* empty */
58 # define ATTRIBUTE_PACKED /* empty */
59 # endif
60
61 /*
62 * Evaluates to:
63 * 1, if the given two types are known to be the same;
64 * 0, otherwise.
65 */
66 # if GNUC_PREREQ(3, 0)
67 # define IS_SAME_TYPE(x_, y_) \
68 __builtin_types_compatible_p(__typeof__(x_), __typeof__(y_))
69 # else
70 /* Cannot tell whether these types are the same. */
71 # define IS_SAME_TYPE(x_, y_) 0
72 # endif
73
74 # if GNUC_PREREQ(3, 0)
75 # define ATTRIBUTE_MALLOC __attribute__((__malloc__))
76 # else
77 # define ATTRIBUTE_MALLOC /* empty */
78 # endif
79
80 # if GNUC_PREREQ(3, 1)
81 # define ATTRIBUTE_NOINLINE __attribute__((__noinline__))
82 # else
83 # define ATTRIBUTE_NOINLINE /* empty */
84 # endif
85
86 # if GNUC_PREREQ(4, 0)
87 # define ATTRIBUTE_SENTINEL __attribute__((__sentinel__))
88 # else
89 # define ATTRIBUTE_SENTINEL /* empty */
90 # endif
91
92 # if GNUC_PREREQ(4, 1)
93 # define ALIGNOF(t_) __alignof__(t_)
94 # else
95 # define ALIGNOF(t_) (sizeof(struct { char x_; t_ y_; }) - sizeof(t_))
96 # endif
97
98 # if GNUC_PREREQ(4, 3)
99 # define ATTRIBUTE_ALLOC_SIZE(args) __attribute__((__alloc_size__ args))
100 # else
101 # define ATTRIBUTE_ALLOC_SIZE(args) /* empty */
102 # endif
103
104 # if GNUC_PREREQ(7, 0)
105 # define ATTRIBUTE_FALLTHROUGH __attribute__((__fallthrough__))
106 # else
107 # define ATTRIBUTE_FALLTHROUGH ((void) 0)
108 # endif
109
110 # if CLANG_PREREQ(2, 8)
111 # define DIAG_PUSH_IGNORE_OVERRIDE_INIT \
112 _Pragma("clang diagnostic push"); \
113 _Pragma("clang diagnostic ignored \"-Winitializer-overrides\"");
114 # define DIAG_POP_IGNORE_OVERRIDE_INIT \
115 _Pragma("clang diagnostic pop");
116 # elif GNUC_PREREQ(4, 6) /* 4.2 for -Woverride-init, 4.6 for diagnostic push */
117 # define DIAG_PUSH_IGNORE_OVERRIDE_INIT \
118 _Pragma("GCC diagnostic push"); \
119 _Pragma("GCC diagnostic ignored \"-Woverride-init\"");
120 # define DIAG_POP_IGNORE_OVERRIDE_INIT \
121 _Pragma("GCC diagnostic pop");
122 # else
123 # define DIAG_PUSH_IGNORE_OVERRIDE_INIT /* empty */
124 # define DIAG_POP_IGNORE_OVERRIDE_INIT /* empty */
125 # endif
126
127 # if CLANG_PREREQ(1, 0)
128 # define DIAG_PUSH_IGNORE_NONNULL \
129 _Pragma("clang diagnostic push"); \
130 _Pragma("clang diagnostic ignored \"-Wnonnull\"");
131 # define DIAG_POP_IGNORE_NONNULL \
132 _Pragma("clang diagnostic pop");
133 # elif GNUC_PREREQ(4, 6) /* 3.3 for -Wnonnull, 4.6 for diagnostic push/pop */
134 # define DIAG_PUSH_IGNORE_NONNULL \
135 _Pragma("GCC diagnostic push"); \
136 _Pragma("GCC diagnostic ignored \"-Wnonnull\"");
137 # define DIAG_POP_IGNORE_NONNULL \
138 _Pragma("GCC diagnostic pop");
139 # else
140 # define DIAG_PUSH_IGNORE_NONNULL /* empty */
141 # define DIAG_POP_IGNORE_NONNULL /* empty */
142 # endif
143
144 # if GNUC_PREREQ(6, 0)
145 # define DIAG_PUSH_IGNORE_TAUTOLOGICAL_COMPARE \
146 _Pragma("GCC diagnostic push"); \
147 _Pragma("GCC diagnostic ignored \"-Wtautological-compare\"");
148 # define DIAG_POP_IGNORE_TAUTOLOGICAL_COMPARE \
149 _Pragma("GCC diagnostic pop");
150 # else
151 # define DIAG_PUSH_IGNORE_TAUTOLOGICAL_COMPARE /* empty */
152 # define DIAG_POP_IGNORE_TAUTOLOGICAL_COMPARE /* empty */
153 # endif
154
155 # if CLANG_PREREQ(6, 0)
156 # define DIAG_PUSH_IGNORE_TAUTOLOGICAL_CONSTANT_COMPARE \
157 _Pragma("clang diagnostic push"); \
158 _Pragma("clang diagnostic ignored \"-Wtautological-constant-compare\"");
159 # define DIAG_POP_IGNORE_TAUTOLOGICAL_CONSTANT_COMPARE \
160 _Pragma("clang diagnostic pop");
161 # else
162 # define DIAG_PUSH_IGNORE_TAUTOLOGICAL_CONSTANT_COMPARE /* empty */
163 # define DIAG_POP_IGNORE_TAUTOLOGICAL_CONSTANT_COMPARE /* empty */
164 # endif
165
166 #endif /* !STRACE_GCC_COMPAT_H */