1/*
2 * Copyright 2013-present Facebook, Inc.
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_ASAN_ENABLED (defined in folly-config.h) to check if folly itself
72 * was compiled with ASAN enabled.
73 */
74#if FOLLY_HAS_FEATURE(address_sanitizer) || __SANITIZE_ADDRESS__
75#define FOLLY_SANITIZE_ADDRESS 1
76#endif
77
78/* Define attribute wrapper for function attribute used to disable
79 * address sanitizer instrumentation. Unfortunately, this attribute
80 * has issues when inlining is used, so disable that as well. */
81#ifdef FOLLY_SANITIZE_ADDRESS
82#if defined(__clang__)
83#if __has_attribute(__no_sanitize__)
84#define FOLLY_DISABLE_ADDRESS_SANITIZER \
85 __attribute__((__no_sanitize__("address"), __noinline__))
86#elif __has_attribute(__no_address_safety_analysis__)
87#define FOLLY_DISABLE_ADDRESS_SANITIZER \
88 __attribute__((__no_address_safety_analysis__, __noinline__))
89#elif __has_attribute(__no_sanitize_address__)
90#define FOLLY_DISABLE_ADDRESS_SANITIZER \
91 __attribute__((__no_sanitize_address__, __noinline__))
92#endif
93#elif defined(__GNUC__)
94#define FOLLY_DISABLE_ADDRESS_SANITIZER \
95 __attribute__((__no_address_safety_analysis__, __noinline__))
96#endif
97#endif
98#ifndef FOLLY_DISABLE_ADDRESS_SANITIZER
99#define FOLLY_DISABLE_ADDRESS_SANITIZER
100#endif
101
102/* Define a convenience macro to test when thread sanitizer is being used
103 * across the different compilers (e.g. clang, gcc) */
104#if FOLLY_HAS_FEATURE(thread_sanitizer) || __SANITIZE_THREAD__
105#define FOLLY_SANITIZE_THREAD 1
106#endif
107
108#if FOLLY_SANITIZE_THREAD
109#define FOLLY_DISABLE_THREAD_SANITIZER \
110 __attribute__((no_sanitize_thread, noinline))
111#else
112#define FOLLY_DISABLE_THREAD_SANITIZER
113#endif
114
115/**
116 * Define a convenience macro to test when ASAN, UBSAN or TSAN sanitizer are
117 * being used
118 */
119#if defined(FOLLY_SANITIZE_ADDRESS) || defined(FOLLY_SANITIZE_THREAD)
120#define FOLLY_SANITIZE 1
121#endif
122
123#if FOLLY_SANITIZE
124#define FOLLY_DISABLE_UNDEFINED_BEHAVIOR_SANITIZER(...) \
125 __attribute__((no_sanitize(__VA_ARGS__)))
126#else
127#define FOLLY_DISABLE_UNDEFINED_BEHAVIOR_SANITIZER(...)
128#endif // FOLLY_SANITIZE
129
130#define FOLLY_DISABLE_SANITIZERS \
131 FOLLY_DISABLE_ADDRESS_SANITIZER FOLLY_DISABLE_THREAD_SANITIZER \
132 FOLLY_DISABLE_UNDEFINED_BEHAVIOR_SANITIZER("undefined")
133
134/**
135 * Macro for marking functions as having public visibility.
136 */
137#if defined(__GNUC__)
138#if __GNUC_PREREQ(4, 9)
139#define FOLLY_EXPORT [[gnu::visibility("default")]]
140#else
141#define FOLLY_EXPORT __attribute__((__visibility__("default")))
142#endif
143#else
144#define FOLLY_EXPORT
145#endif
146
147// noinline
148#ifdef _MSC_VER
149#define FOLLY_NOINLINE __declspec(noinline)
150#elif defined(__clang__) || defined(__GNUC__)
151#define FOLLY_NOINLINE __attribute__((__noinline__))
152#else
153#define FOLLY_NOINLINE
154#endif
155
156// always inline
157#ifdef _MSC_VER
158#define FOLLY_ALWAYS_INLINE __forceinline
159#elif defined(__clang__) || defined(__GNUC__)
160#define FOLLY_ALWAYS_INLINE inline __attribute__((__always_inline__))
161#else
162#define FOLLY_ALWAYS_INLINE inline
163#endif
164
165// attribute hidden
166#if _MSC_VER
167#define FOLLY_ATTR_VISIBILITY_HIDDEN
168#elif defined(__clang__) || defined(__GNUC__)
169#define FOLLY_ATTR_VISIBILITY_HIDDEN __attribute__((__visibility__("hidden")))
170#else
171#define FOLLY_ATTR_VISIBILITY_HIDDEN
172#endif
173
174// An attribute for marking symbols as weak, if supported
175#if FOLLY_HAVE_WEAK_SYMBOLS
176#define FOLLY_ATTR_WEAK __attribute__((__weak__))
177#else
178#define FOLLY_ATTR_WEAK
179#endif
180
181// Microsoft ABI version (can be overridden manually if necessary)
182#ifndef FOLLY_MICROSOFT_ABI_VER
183#ifdef _MSC_VER
184#define FOLLY_MICROSOFT_ABI_VER _MSC_VER
185#endif
186#endif
187