1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #pragma once
18 
19 /* These definitions are in a separate file so that they
20  * may be included from C- as well as C++-based projects. */
21 
22 #include <folly/portability/Config.h>
23 
24 /**
25  * Portable version check.
26  */
27 #ifndef __GNUC_PREREQ
28 #if defined __GNUC__ && defined __GNUC_MINOR__
29 /* nolint */
30 #define __GNUC_PREREQ(maj, min) \
31   ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
32 #else
33 /* nolint */
34 #define __GNUC_PREREQ(maj, min) 0
35 #endif
36 #endif
37 
38 // portable version check for clang
39 #ifndef __CLANG_PREREQ
40 #if defined __clang__ && defined __clang_major__ && defined __clang_minor__
41 /* nolint */
42 #define __CLANG_PREREQ(maj, min) \
43   ((__clang_major__ << 16) + __clang_minor__ >= ((maj) << 16) + (min))
44 #else
45 /* nolint */
46 #define __CLANG_PREREQ(maj, min) 0
47 #endif
48 #endif
49 
50 #if defined(__has_builtin)
51 #define FOLLY_HAS_BUILTIN(...) __has_builtin(__VA_ARGS__)
52 #else
53 #define FOLLY_HAS_BUILTIN(...) 0
54 #endif
55 
56 #if defined(__has_feature)
57 #define FOLLY_HAS_FEATURE(...) __has_feature(__VA_ARGS__)
58 #else
59 #define FOLLY_HAS_FEATURE(...) 0
60 #endif
61 
62 /* FOLLY_SANITIZE_ADDRESS is defined to 1 if the current compilation unit
63  * is being compiled with ASAN enabled.
64  *
65  * Beware when using this macro in a header file: this macro may change values
66  * across compilation units if some libraries are built with ASAN enabled
67  * and some built with ASAN disabled.  For instance, this may occur, if folly
68  * itself was compiled without ASAN but a downstream project that uses folly is
69  * compiling with ASAN enabled.
70  *
71  * Use FOLLY_LIBRARY_SANITIZE_ADDRESS (defined in folly-config.h) to check if
72  * folly itself was compiled with ASAN enabled.
73  */
74 #ifndef FOLLY_SANITIZE_ADDRESS
75 #if FOLLY_HAS_FEATURE(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
76 #define FOLLY_SANITIZE_ADDRESS 1
77 #endif
78 #endif
79 
80 /* Define attribute wrapper for function attribute used to disable
81  * address sanitizer instrumentation. Unfortunately, this attribute
82  * has issues when inlining is used, so disable that as well. */
83 #ifdef FOLLY_SANITIZE_ADDRESS
84 #if defined(__clang__)
85 #if __has_attribute(__no_sanitize__)
86 #define FOLLY_DISABLE_ADDRESS_SANITIZER \
87   __attribute__((__no_sanitize__("address"), __noinline__))
88 #elif __has_attribute(__no_address_safety_analysis__)
89 #define FOLLY_DISABLE_ADDRESS_SANITIZER \
90   __attribute__((__no_address_safety_analysis__, __noinline__))
91 #elif __has_attribute(__no_sanitize_address__)
92 #define FOLLY_DISABLE_ADDRESS_SANITIZER \
93   __attribute__((__no_sanitize_address__, __noinline__))
94 #endif
95 #elif defined(__GNUC__)
96 #define FOLLY_DISABLE_ADDRESS_SANITIZER \
97   __attribute__((__no_address_safety_analysis__, __noinline__))
98 #endif
99 #endif
100 #ifndef FOLLY_DISABLE_ADDRESS_SANITIZER
101 #define FOLLY_DISABLE_ADDRESS_SANITIZER
102 #endif
103 
104 /* Define a convenience macro to test when thread sanitizer is being used
105  * across the different compilers (e.g. clang, gcc) */
106 #ifndef FOLLY_SANITIZE_THREAD
107 #if FOLLY_HAS_FEATURE(thread_sanitizer) || defined(__SANITIZE_THREAD__)
108 #define FOLLY_SANITIZE_THREAD 1
109 #endif
110 #endif
111 
112 #ifdef FOLLY_SANITIZE_THREAD
113 #define FOLLY_DISABLE_THREAD_SANITIZER \
114   __attribute__((no_sanitize_thread, noinline))
115 #else
116 #define FOLLY_DISABLE_THREAD_SANITIZER
117 #endif
118 
119 /**
120  * Define a convenience macro to test when memory sanitizer is being used
121  * across the different compilers (e.g. clang, gcc)
122  */
123 #ifndef FOLLY_SANITIZE_MEMORY
124 #if FOLLY_HAS_FEATURE(memory_sanitizer) || defined(__SANITIZE_MEMORY__)
125 #define FOLLY_SANITIZE_MEMORY 1
126 #endif
127 #endif
128 
129 #ifdef FOLLY_SANITIZE_MEMORY
130 #define FOLLY_DISABLE_MEMORY_SANITIZER \
131   __attribute__((no_sanitize_memory, noinline))
132 #else
133 #define FOLLY_DISABLE_MEMORY_SANITIZER
134 #endif
135 
136 /**
137  * Define a convenience macro to test when ASAN, UBSAN, TSAN or MSAN sanitizer
138  * are being used
139  */
140 #ifndef FOLLY_SANITIZE
141 #if defined(FOLLY_SANITIZE_ADDRESS) || defined(FOLLY_SANITIZE_THREAD) || \
142     defined(FOLLY_SANITIZE_MEMORY)
143 #define FOLLY_SANITIZE 1
144 #endif
145 #endif
146 
147 #ifdef FOLLY_SANITIZE
148 #define FOLLY_DISABLE_UNDEFINED_BEHAVIOR_SANITIZER(...) \
149   __attribute__((no_sanitize(__VA_ARGS__)))
150 #else
151 #define FOLLY_DISABLE_UNDEFINED_BEHAVIOR_SANITIZER(...)
152 #endif // FOLLY_SANITIZE
153 
154 #define FOLLY_DISABLE_SANITIZERS  \
155   FOLLY_DISABLE_ADDRESS_SANITIZER \
156   FOLLY_DISABLE_THREAD_SANITIZER  \
157   FOLLY_DISABLE_MEMORY_SANITIZER  \
158   FOLLY_DISABLE_UNDEFINED_BEHAVIOR_SANITIZER("undefined")
159 
160 /**
161  * Macro for marking functions as having public visibility.
162  */
163 #if defined(__GNUC__)
164 #define FOLLY_EXPORT __attribute__((__visibility__("default")))
165 #else
166 #define FOLLY_EXPORT
167 #endif
168 
169 // noinline
170 #ifdef _MSC_VER
171 #define FOLLY_NOINLINE __declspec(noinline)
172 #elif defined(__GNUC__)
173 #define FOLLY_NOINLINE __attribute__((__noinline__))
174 #else
175 #define FOLLY_NOINLINE
176 #endif
177 
178 // always inline
179 #ifdef _MSC_VER
180 #define FOLLY_ALWAYS_INLINE __forceinline
181 #elif defined(__GNUC__)
182 #define FOLLY_ALWAYS_INLINE inline __attribute__((__always_inline__))
183 #else
184 #define FOLLY_ALWAYS_INLINE inline
185 #endif
186 
187 // attribute hidden
188 #if defined(_MSC_VER)
189 #define FOLLY_ATTR_VISIBILITY_HIDDEN
190 #elif defined(__GNUC__)
191 #define FOLLY_ATTR_VISIBILITY_HIDDEN __attribute__((__visibility__("hidden")))
192 #else
193 #define FOLLY_ATTR_VISIBILITY_HIDDEN
194 #endif
195 
196 // An attribute for marking symbols as weak, if supported
197 #if FOLLY_HAVE_WEAK_SYMBOLS
198 #define FOLLY_ATTR_WEAK __attribute__((__weak__))
199 #else
200 #define FOLLY_ATTR_WEAK
201 #endif
202 
203 // Microsoft ABI version (can be overridden manually if necessary)
204 #ifndef FOLLY_MICROSOFT_ABI_VER
205 #ifdef _MSC_VER
206 #define FOLLY_MICROSOFT_ABI_VER _MSC_VER
207 #endif
208 #endif
209 
210 //  FOLLY_ERASE
211 //
212 //  A conceptual attribute/syntax combo for erasing a function from the build
213 //  artifacts and forcing all call-sites to inline the callee, at least as far
214 //  as each compiler supports.
215 //
216 //  Semantically includes the inline specifier.
217 #define FOLLY_ERASE FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN
218 
219 //  FOLLY_ERASE_HACK_GCC
220 //
221 //  Equivalent to FOLLY_ERASE, but without hiding under gcc. Useful when applied
222 //  to a function which may sometimes be hidden separately, for example by being
223 //  declared in an anonymous namespace, since in such cases with -Wattributes
224 //  enabled, gcc would emit: 'visibility' attribute ignored.
225 //
226 //  Semantically includes the inline specifier.
227 #if defined(__GNUC__) && !defined(__clang__)
228 #define FOLLY_ERASE_HACK_GCC FOLLY_ALWAYS_INLINE
229 #else
230 #define FOLLY_ERASE_HACK_GCC FOLLY_ERASE
231 #endif
232 
233 //  FOLLY_ERASE_TRYCATCH
234 //
235 //  Equivalent to FOLLY_ERASE, but for code which might contain explicit
236 //  exception handling. Has the effect of FOLLY_ERASE, except under MSVC which
237 //  warns about __forceinline when functions contain exception handling.
238 //
239 //  Semantically includes the inline specifier.
240 #ifdef _MSC_VER
241 #define FOLLY_ERASE_TRYCATCH inline
242 #else
243 #define FOLLY_ERASE_TRYCATCH FOLLY_ERASE
244 #endif
245