X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=blobdiff_plain;f=folly%2FCPortability.h;h=3b362d2a885b96781ea4a7bbf000574694cb3387;hp=65ffa6f13536d380b4648aad1ae246d5b88a96cb;hb=67300dac6ed429facd7c6f5e03b7c245e32f8383;hpb=275ca94d04e44f28cfa411668eb1c1dd8db90b80 diff --git a/folly/CPortability.h b/folly/CPortability.h index 65ffa6f1..3b362d2a 100644 --- a/folly/CPortability.h +++ b/folly/CPortability.h @@ -1,5 +1,5 @@ /* - * Copyright 2015 Facebook, Inc. + * Copyright 2017 Facebook, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,21 +14,52 @@ * limitations under the License. */ -#ifndef CPORTABILITY_H -#define CPORTABILITY_H +#pragma once /* These definitions are in a separate file so that they * may be included from C- as well as C++-based projects. */ +/** + * Portable version check. + */ +#ifndef __GNUC_PREREQ +# if defined __GNUC__ && defined __GNUC_MINOR__ +/* nolint */ +# define __GNUC_PREREQ(maj, min) ((__GNUC__ << 16) + __GNUC_MINOR__ >= \ + ((maj) << 16) + (min)) +# else +/* nolint */ +# define __GNUC_PREREQ(maj, min) 0 +# endif +#endif + +// portable version check for clang +#ifndef __CLANG_PREREQ +# if defined __clang__ && defined __clang_major__ && defined __clang_minor__ +/* nolint */ +# define __CLANG_PREREQ(maj, min) \ + ((__clang_major__ << 16) + __clang_minor__ >= ((maj) << 16) + (min)) +# else +/* nolint */ +# define __CLANG_PREREQ(maj, min) 0 +# endif +#endif + +#if defined(__has_builtin) +#define FOLLY_HAS_BUILTIN(...) __has_builtin(__VA_ARGS__) +#else +#define FOLLY_HAS_BUILTIN(...) 0 +#endif + +#if defined(__has_feature) +#define FOLLY_HAS_FEATURE(...) __has_feature(__VA_ARGS__) +#else +#define FOLLY_HAS_FEATURE(...) 0 +#endif + /* Define a convenience macro to test when address sanitizer is being used * across the different compilers (e.g. clang, gcc) */ -#if defined(__clang__) -# if __has_feature(address_sanitizer) -# define FOLLY_SANITIZE_ADDRESS 1 -# endif -#elif defined (__GNUC__) && \ - (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ >= 5)) && \ - __SANITIZE_ADDRESS__ +#if FOLLY_HAS_FEATURE(address_sanitizer) || __SANITIZE_ADDRESS__ # define FOLLY_SANITIZE_ADDRESS 1 #endif @@ -37,7 +68,10 @@ * has issues when inlining is used, so disable that as well. */ #ifdef FOLLY_SANITIZE_ADDRESS # if defined(__clang__) -# if __has_attribute(__no_address_safety_analysis__) +# if __has_attribute(__no_sanitize__) +# define FOLLY_DISABLE_ADDRESS_SANITIZER \ + __attribute__((__no_sanitize__("address"), __noinline__)) +# elif __has_attribute(__no_address_safety_analysis__) # define FOLLY_DISABLE_ADDRESS_SANITIZER \ __attribute__((__no_address_safety_analysis__, __noinline__)) # elif __has_attribute(__no_sanitize_address__) @@ -53,4 +87,74 @@ # define FOLLY_DISABLE_ADDRESS_SANITIZER #endif +/* Define a convenience macro to test when thread sanitizer is being used + * across the different compilers (e.g. clang, gcc) */ +#if FOLLY_HAS_FEATURE(thread_sanitizer) || __SANITIZE_THREAD__ +# define FOLLY_SANITIZE_THREAD 1 +#endif + +/** + * Define a convenience macro to test when ASAN, UBSAN or TSAN sanitizer are + * being used + */ +#if defined(FOLLY_SANITIZE_ADDRESS) || defined(FOLLY_SANITIZE_THREAD) || \ + defined(UNDEFINED_SANITIZER) +#define FOLLY_SANITIZE 1 +#endif + +/** + * ASAN/MSAN/TSAN define pre-processor symbols: + * ADDRESS_SANITIZER/MEMORY_SANITIZER/THREAD_SANITIZER. + * + * UBSAN doesn't define anything and makes it hard to + * conditionally compile. + * + * The build system should define UNDEFINED_SANITIZER=1 when UBSAN is + * used as folly whitelists some functions. + */ +#if UNDEFINED_SANITIZER +#define FOLLY_DISABLE_UNDEFINED_BEHAVIOR_SANITIZER(...) \ + __attribute__((no_sanitize(__VA_ARGS__))) +#else +#define FOLLY_DISABLE_UNDEFINED_BEHAVIOR_SANITIZER(...) +#endif // UNDEFINED_SANITIZER + +/** + * Macro for marking functions as having public visibility. + */ +#if defined(__GNUC__) +# if __GNUC_PREREQ(4, 9) +# define FOLLY_EXPORT [[gnu::visibility("default")]] +# else +# define FOLLY_EXPORT __attribute__((__visibility__("default"))) +# endif +#else +# define FOLLY_EXPORT +#endif + +// noinline +#ifdef _MSC_VER +# define FOLLY_NOINLINE __declspec(noinline) +#elif defined(__clang__) || defined(__GNUC__) +# define FOLLY_NOINLINE __attribute__((__noinline__)) +#else +# define FOLLY_NOINLINE +#endif + +// always inline +#ifdef _MSC_VER +# define FOLLY_ALWAYS_INLINE __forceinline +#elif defined(__clang__) || defined(__GNUC__) +# define FOLLY_ALWAYS_INLINE inline __attribute__((__always_inline__)) +#else +# define FOLLY_ALWAYS_INLINE inline +#endif + +// attribute hidden +#if _MSC_VER +#define FOLLY_ATTR_VISIBILITY_HIDDEN +#elif defined(__clang__) || defined(__GNUC__) +#define FOLLY_ATTR_VISIBILITY_HIDDEN __attribute__((__visibility__("hidden"))) +#else +#define FOLLY_ATTR_VISIBILITY_HIDDEN #endif