// Licensed to the Apache Software Foundation (ASF) under one // or more contributor license agreements. See the NOTICE file // distributed with this work for additional information // regarding copyright ownership. The ASF licenses this file // to you under the Apache License, Version 2.0 (the // "License"); you may not use this file except in compliance // with the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // 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 #include #define ARROW_EXPAND(x) x #define ARROW_STRINGIFY(x) #x #define ARROW_CONCAT(x, y) x##y // From Google gutil #ifndef ARROW_DISALLOW_COPY_AND_ASSIGN # define ARROW_DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName&) = delete; \ void operator=(const TypeName&) = delete #endif #ifndef ARROW_DEFAULT_MOVE_AND_ASSIGN # define ARROW_DEFAULT_MOVE_AND_ASSIGN(TypeName) \ TypeName(TypeName&&) = default; \ TypeName& operator=(TypeName&&) = default #endif // With ARROW_PREDICT_FALSE, GCC and clang can be told that a certain branch is // not likely to be taken (for instance, a CHECK failure), and use that information in // static analysis. Giving the compiler this information can affect the generated code // layout in the absence of better information (i.e. -fprofile-arcs). [1] explains how // this feature can be used to improve code generation. It was written as a positive // comment to a negative article about the use of these annotations. // // ARROW_COMPILER_ASSUME allows the compiler to assume that a given expression is // true, without evaluating it, and to optimise based on this assumption [2]. If this // condition is violated at runtime, the behavior is undefined. This can be useful to // generate both faster and smaller code in compute kernels. // // IMPORTANT: Different optimisers are likely to react differently to this annotation! // It should be used with care when we can prove by some means that the assumption // is (1) guaranteed to always hold and (2) is useful for optimization [3]. If the // assumption is pessimistic, it might even block the compiler from decisions that // could lead to better code [4]. If you have a good intuition for what the compiler // can do with assumptions [5], you can use this macro to guide it and end up with // results you would only get with more complex code transformations. // `clang -S -emit-llvm` can be used to check how the generated code changes with // your specific use of this macro. // // [1] https://lobste.rs/s/uwgtkt/don_t_use_likely_unlikely_attributes#c_xi3wmc // [2] "Portable assumptions" // https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1774r4.pdf // [3] "Assertions Are Pessimistic, Assumptions Are Optimistic" // https://blog.regehr.org/archives/1096 // [4] https://discourse.llvm.org/t/llvm-assume-blocks-optimization/71609 // [5] J. Doerfert et al. 2019. "Performance Exploration Through Optimistic Static // Program Annotations". https://github.com/jdoerfert/PETOSPA/blob/master/ISC19.pdf #define ARROW_UNUSED(x) (void)(x) #ifdef ARROW_WARN_DOCUMENTATION # define ARROW_ARG_UNUSED(x) x #else # define ARROW_ARG_UNUSED(x) #endif #if defined(__GNUC__) // GCC and compatible compilers (clang, Intel ICC) # define ARROW_NORETURN __attribute__((noreturn)) # define ARROW_NOINLINE __attribute__((noinline)) # define ARROW_FORCE_INLINE __attribute__((always_inline)) # define ARROW_PREDICT_FALSE(x) (__builtin_expect(!!(x), 0)) # define ARROW_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) # define ARROW_RESTRICT __restrict # if defined(__clang__) // clang-specific # define ARROW_COMPILER_ASSUME(expr) __builtin_assume(expr) # else // GCC-specific # if __GNUC__ >= 13 # define ARROW_COMPILER_ASSUME(expr) __attribute__((assume(expr))) # else // GCC does not have a built-in assume intrinsic before GCC 13, so we use an // if statement and __builtin_unreachable() to achieve the same effect [2]. // Unlike clang's __builtin_assume and C++23's [[assume(expr)]], using this // on GCC won't warn about side-effects in the expression, so make sure expr // is side-effect free when working with GCC versions before 13 (Jan-2024), // otherwise clang/MSVC builds will fail in CI. # define ARROW_COMPILER_ASSUME(expr) \ if (expr) { \ } else { \ __builtin_unreachable(); \ } # endif // __GNUC__ >= 13 # endif #elif defined(_MSC_VER) // MSVC # define ARROW_NORETURN __declspec(noreturn) # define ARROW_NOINLINE __declspec(noinline) # define ARROW_FORCE_INLINE __forceinline # define ARROW_PREDICT_FALSE(x) (x) # define ARROW_PREDICT_TRUE(x) (x) # define ARROW_RESTRICT __restrict # define ARROW_COMPILER_ASSUME(expr) __assume(expr) #else # define ARROW_NORETURN # define ARROW_NOINLINE # define ARROW_FORCE_INLINE # define ARROW_PREDICT_FALSE(x) (x) # define ARROW_PREDICT_TRUE(x) (x) # define ARROW_RESTRICT # define ARROW_COMPILER_ASSUME(expr) #endif // ---------------------------------------------------------------------- // C++/CLI support macros (see ARROW-1134) #ifndef NULLPTR # ifdef __cplusplus_cli # define NULLPTR __nullptr # else # define NULLPTR nullptr # endif #endif // ifndef NULLPTR // ---------------------------------------------------------------------- // clang-format off // [[deprecated]] is only available in C++14, use this for the time being // This macro takes an optional deprecation message #ifdef __COVERITY__ # define ARROW_DEPRECATED(...) #else # define ARROW_DEPRECATED(...) [[deprecated(__VA_ARGS__)]] #endif #ifdef __COVERITY__ # define ARROW_DEPRECATED_ENUM_VALUE(...) #else # define ARROW_DEPRECATED_ENUM_VALUE(...) [[deprecated(__VA_ARGS__)]] #endif // clang-format on // Macros to disable deprecation warnings #ifdef __clang__ # define ARROW_SUPPRESS_DEPRECATION_WARNING \ _Pragma("clang diagnostic push"); \ _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") # define ARROW_UNSUPPRESS_DEPRECATION_WARNING _Pragma("clang diagnostic pop") #elif defined(__GNUC__) # define ARROW_SUPPRESS_DEPRECATION_WARNING \ _Pragma("GCC diagnostic push"); \ _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") # define ARROW_UNSUPPRESS_DEPRECATION_WARNING _Pragma("GCC diagnostic pop") #elif defined(_MSC_VER) # define ARROW_SUPPRESS_DEPRECATION_WARNING \ __pragma(warning(push)) __pragma(warning(disable : 4996)) # define ARROW_UNSUPPRESS_DEPRECATION_WARNING __pragma(warning(pop)) #else # define ARROW_SUPPRESS_DEPRECATION_WARNING # define ARROW_UNSUPPRESS_DEPRECATION_WARNING #endif // ---------------------------------------------------------------------- // macros to disable padding // these macros are portable across different compilers and platforms //[https://github.com/google/flatbuffers/blob/master/include/flatbuffers/flatbuffers.h#L1355] #if !defined(MANUALLY_ALIGNED_STRUCT) # if defined(_MSC_VER) # define MANUALLY_ALIGNED_STRUCT(alignment) \ __pragma(pack(1)); \ struct __declspec(align(alignment)) # define STRUCT_END(name, size) \ __pragma(pack()); \ static_assert(sizeof(name) == size, "compiler breaks packing rules") # elif defined(__GNUC__) || defined(__clang__) # define MANUALLY_ALIGNED_STRUCT(alignment) \ _Pragma("pack(1)") struct __attribute__((aligned(alignment))) # define STRUCT_END(name, size) \ _Pragma("pack()") static_assert(sizeof(name) == size, \ "compiler breaks packing rules") # else # error Unknown compiler, please define structure alignment macros # endif #endif // !defined(MANUALLY_ALIGNED_STRUCT) // ---------------------------------------------------------------------- // Convenience macro disabling a particular UBSan check in a function #if defined(__clang__) # define ARROW_DISABLE_UBSAN(feature) __attribute__((no_sanitize(feature))) #else # define ARROW_DISABLE_UBSAN(feature) #endif // ---------------------------------------------------------------------- // Machine information #if INTPTR_MAX == INT64_MAX # define ARROW_BITNESS 64 #elif INTPTR_MAX == INT32_MAX # define ARROW_BITNESS 32 #else # error Unexpected INTPTR_MAX #endif // ---------------------------------------------------------------------- // From googletest // (also in parquet-cpp) // When you need to test the private or protected members of a class, // use the FRIEND_TEST macro to declare your tests as friends of the // class. For example: // // class MyClass { // private: // void MyMethod(); // FRIEND_TEST(MyClassTest, MyMethod); // }; // // class MyClassTest : public testing::Test { // // ... // }; // // TEST_F(MyClassTest, MyMethod) { // // Can call MyClass::MyMethod() here. // } #define FRIEND_TEST(test_case_name, test_name) \ friend class test_case_name##_##test_name##_Test