/* * Copyright (c) Facebook, Inc. and its affiliates. * * Licensed under the Apache License Version 2.0 with LLVM Exceptions * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * https://llvm.org/LICENSE.txt * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #pragma once // Get the library feature test macros: #if __has_include() # include #elif __has_include() # include #endif #include // the configured options and settings for unifex #define UNIFEX_VERSION_MAJOR 0 #define UNIFEX_VERSION_MINOR 1 #define UNIFEX_NO_MEMORY_RESOURCE 0 #define UNIFEX_MEMORY_RESOURCE_HEADER #define UNIFEX_MEMORY_RESOURCE_NAMESPACE std::pmr #if !defined(__has_cpp_attribute) #define UNIFEX_NO_UNIQUE_ADDRESS #elif !__has_cpp_attribute(no_unique_address) #define UNIFEX_NO_UNIQUE_ADDRESS // prior to clang-10, [[no_unique_address]] leads to bad codegen #elif defined(__clang__) && __clang_major__ < 10 #define UNIFEX_NO_UNIQUE_ADDRESS // GCC 10.3/11 introduced bug 98995, which fails to compile with no_uniq_addr. // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98995 // For simplicity, assume anything above 9 is broken. #elif !defined(__clang__) && defined(__GNUC__) && (__GNUC__ > 9) #define UNIFEX_NO_UNIQUE_ADDRESS #else #define UNIFEX_NO_UNIQUE_ADDRESS [[no_unique_address]] #endif #if !defined(UNIFEX_NO_COROUTINES) # if defined(__cpp_impl_coroutine) || defined(__cpp_coroutines) # define UNIFEX_NO_COROUTINES 0 # else # define UNIFEX_NO_COROUTINES 1 # endif #endif #if !UNIFEX_NO_COROUTINES # if __has_include() && defined(__cpp_lib_coroutine) # define UNIFEX_COROUTINES_HEADER # define UNIFEX_COROUTINES_NAMESPACE std # elif __has_include() && \ !(defined(_MSC_VER) && defined(__clang__)) // clang-cl.exe # define UNIFEX_COROUTINES_HEADER # define UNIFEX_COROUTINES_NAMESPACE std::experimental # else # undef UNIFEX_NO_COROUTINES # define UNIFEX_NO_COROUTINES 1 # endif #endif #if !defined(UNIFEX_NO_EPOLL) # if defined(__ANDROID_API__) && __ANDROID_API__ < 19 // Android makes timerfd_create and friend available as of API version 19; // before that, the epoll API exists but it's insufficient for our purposes. // https://android.googlesource.com/platform/bionic/+/master/libc/include/sys/timerfd.h#56 # define UNIFEX_NO_EPOLL 1 # endif #endif #if !defined(UNIFEX_NO_EPOLL) #define UNIFEX_NO_EPOLL 1 #endif #if !defined(UNIFEX_NO_LIBURING) #define UNIFEX_NO_LIBURING 1 #endif // UNIFEX_DECLARE_NON_DEDUCED_TYPE(type) // UNIFEX_USE_NON_DEDUCED_TYPE(type) // // These macros work around a bug in MSVC that causes it to try to specialize // all found function templates for which it can successfully deduce template // arguments even if there are parameters that do not participate in template // parameter deduction for which there is no conversion possible from the argument. // // This is most likely related to the core issue CWG1391 [*] which MSVC has not // yet implemented as of VS 2019.4. // // These macros are intended to be used in template functions, typically tag_invoke() // overloads, as follows. // // Where you would normally write: // // class foo_sender { // template< // typename Receiver, // std::enable_if_t, Receiver, foo>, int> = 0> // friend auto tag_invoke(tag_t, foo_sender&& s, Receiver&& r) -> foo_operation { // return ...; // } // }; // // You would instead write // // class foo_sender { // template< // typename Receiver, // UNIFEX_DECLARE_NON_DEDUCED_TYPE(CPO, tag_t), // UNIFEX_DECLARE_NON_DEDUCED_TYPE(S, foo_sender), // std::enable_if_t, Receiver, foo>, int> = 0? // friend auto tag_invoke( // UNIFEX_USE_NON_DEDUCED_TYPE(CPO, tag_t), // UNIFEX_USE_NON_DEDUCED_TYPE(S, foo_sender)&& s, // Receiver&& r) -> foo_operation { // return ...; // } // }; #if defined(_MSC_VER) # define UNIFEX_DECLARE_NON_DEDUCED_TYPE(NAME, ...) \ typename NAME = void, \ std::enable_if_t, int> = 0 # define UNIFEX_USE_NON_DEDUCED_TYPE(NAME, ...) NAME #else # define UNIFEX_DECLARE_NON_DEDUCED_TYPE(NAME, ...) typename NAME = __VA_ARGS__ # define UNIFEX_USE_NON_DEDUCED_TYPE(NAME, ...) __VA_ARGS__ #endif #if !defined(UNIFEX_CXX_CONCEPTS) #ifdef UNIFEX_DOXYGEN_INVOKED #define UNIFEX_CXX_CONCEPTS 201800L #elif defined(__cpp_concepts) && __cpp_concepts > 0 #define UNIFEX_CXX_CONCEPTS __cpp_concepts #else #define UNIFEX_CXX_CONCEPTS 0L #endif #endif #if __cpp_rtti >= 199711 # define UNIFEX_NO_RTTI 0 #else # define UNIFEX_NO_RTTI 1 #endif #if __cpp_exceptions >= 199711 # define UNIFEX_NO_EXCEPTIONS 0 # define UNIFEX_TRY try # define UNIFEX_CATCH(...) catch (__VA_ARGS__) # define UNIFEX_RETHROW() throw #else # define UNIFEX_NO_EXCEPTIONS 1 # define UNIFEX_TRY # define UNIFEX_CATCH(...) if constexpr (true) {} else # define UNIFEX_RETHROW() ((void)0) #endif #if defined(_MSC_VER) && !defined(__clang__) #define UNIFEX_DIAGNOSTIC_PUSH __pragma(warning(push)) #define UNIFEX_DIAGNOSTIC_POP __pragma(warning(pop)) #define UNIFEX_DIAGNOSTIC_IGNORE_INIT_LIST_LIFETIME #define UNIFEX_DIAGNOSTIC_IGNORE_FLOAT_EQUAL #define UNIFEX_DIAGNOSTIC_IGNORE_CPP2A_COMPAT #else // ^^^ defined(_MSC_VER) ^^^ / vvv !defined(_MSC_VER) vvv #if defined(__GNUC__) || defined(__clang__) #define UNIFEX_PRAGMA(X) _Pragma(#X) #define UNIFEX_DIAGNOSTIC_PUSH UNIFEX_PRAGMA(GCC diagnostic push) #define UNIFEX_DIAGNOSTIC_POP UNIFEX_PRAGMA(GCC diagnostic pop) #define UNIFEX_DIAGNOSTIC_IGNORE_PRAGMAS \ UNIFEX_PRAGMA(GCC diagnostic ignored "-Wpragmas") #define UNIFEX_DIAGNOSTIC_IGNORE(X) \ UNIFEX_DIAGNOSTIC_IGNORE_PRAGMAS \ UNIFEX_PRAGMA(GCC diagnostic ignored "-Wunknown-pragmas") \ UNIFEX_PRAGMA(GCC diagnostic ignored X) #define UNIFEX_DIAGNOSTIC_IGNORE_INIT_LIST_LIFETIME \ UNIFEX_DIAGNOSTIC_IGNORE("-Wunknown-warning-option") \ UNIFEX_DIAGNOSTIC_IGNORE("-Winit-list-lifetime") #define UNIFEX_DIAGNOSTIC_IGNORE_FLOAT_EQUAL \ UNIFEX_DIAGNOSTIC_IGNORE("-Wfloat-equal") #define UNIFEX_DIAGNOSTIC_IGNORE_CPP2A_COMPAT \ UNIFEX_DIAGNOSTIC_IGNORE("-Wc++2a-compat") #else #define UNIFEX_DIAGNOSTIC_PUSH #define UNIFEX_DIAGNOSTIC_POP #define UNIFEX_DIAGNOSTIC_IGNORE_INIT_LIST_LIFETIME #define UNIFEX_DIAGNOSTIC_IGNORE_FLOAT_EQUAL #define UNIFEX_DIAGNOSTIC_IGNORE_CPP2A_COMPAT #endif #endif // MSVC/Generic configuration switch #if defined(__GNUC__) || defined(__clang__) #define UNIFEX_ALWAYS_INLINE \ __attribute__((__always_inline__)) __attribute__((__visibility__("hidden"))) inline #elif defined(_MSC_VER) #define UNIFEX_ALWAYS_INLINE __forceinline #else #define UNIFEX_ALWAYS_INLINE inline #endif #if defined(__GNUC__) || defined(__clang__) #define UNIFEX_NO_INLINE __attribute__((__noinline__)) #elif defined(_MSC_VER) #define UNIFEX_NO_INLINE __declspec(noinline) #else #define UNIFEX_NO_INLINE #endif #if defined(__GNUC__) || defined(__clang__) #define UNIFEX_ASSUME_UNREACHABLE __builtin_unreachable() #elif defined(_MSC_VER) #define UNIFEX_ASSUME_UNREACHABLE __assume(0) #else #define UNIFEX_ASSUME_UNREACHABLE std::terminate() #endif #ifndef UNIFEX_ASSERT # define UNIFEX_ASSERT assert #endif #if defined(__clang__) // Clang's optimizer interacts badly with its address sanitizer. Certain // functions must have optimizations disabled in order to avoid triggering // stack-use-after-scope-exit errors. #if __has_feature(address_sanitizer) #define UNIFEX_CLANG_DISABLE_OPTIMIZATION __attribute__((__optnone__)) #else #define UNIFEX_CLANG_DISABLE_OPTIMIZATION #endif #else #define UNIFEX_CLANG_DISABLE_OPTIMIZATION #endif #if !defined(UNIFEX_DEPRECATED_HEADER) #ifdef __GNUC__ #define UNIFEX_PRAGMA(X) _Pragma(#X) #define UNIFEX_DEPRECATED_HEADER(MSG) UNIFEX_PRAGMA(GCC warning MSG) #elif defined(_MSC_VER) #define UNIFEX_STRINGIZE_(MSG) #MSG #define UNIFEX_STRINGIZE(MSG) UNIFEX_STRINGIZE_(MSG) #define UNIFEX_DEPRECATED_HEADER(MSG) \ __pragma(message(__FILE__ "(" UNIFEX_STRINGIZE(__LINE__) ") : Warning: " MSG)) #endif #else #define UNIFEX_DEPRECATED_HEADER(MSG) /**/ #endif