1 /* 2 * Copyright (C) 2018 The Android Open Source Project 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 #ifndef LIBTEXTCLASSIFIER_UTILS_BASE_MACROS_H_ 18 #define LIBTEXTCLASSIFIER_UTILS_BASE_MACROS_H_ 19 20 #include "utils/base/config.h" 21 22 namespace libtextclassifier3 { 23 24 #define TC3_ARRAYSIZE(a) \ 25 ((sizeof(a) / sizeof(*(a))) / (size_t)(!(sizeof(a) % sizeof(*(a))))) 26 27 #if LANG_CXX11 28 #define TC3_DISALLOW_COPY_AND_ASSIGN(TypeName) \ 29 TypeName(const TypeName &) = delete; \ 30 TypeName &operator=(const TypeName &) = delete 31 #else // C++98 case follows 32 33 // Note that these C++98 implementations cannot completely disallow copying, 34 // as members and friends can still accidentally make elided copies without 35 // triggering a linker error. 36 #define TC3_DISALLOW_COPY_AND_ASSIGN(TypeName) \ 37 TypeName(const TypeName &); \ 38 TypeName &operator=(const TypeName &) 39 #endif // LANG_CXX11 40 41 // The TC3_FALLTHROUGH_INTENDED macro can be used to annotate implicit 42 // fall-through between switch labels: 43 // 44 // switch (x) { 45 // case 40: 46 // case 41: 47 // if (truth_is_out_there) { 48 // ++x; 49 // TC3_FALLTHROUGH_INTENDED; // Use instead of/along with annotations in 50 // // comments. 51 // } else { 52 // return x; 53 // } 54 // case 42: 55 // ... 56 // 57 // As shown in the example above, the TC3_FALLTHROUGH_INTENDED macro should be 58 // followed by a semicolon. It is designed to mimic control-flow statements 59 // like 'break;', so it can be placed in most places where 'break;' can, but 60 // only if there are no statements on the execution path between it and the 61 // next switch label. 62 // 63 // When compiled with clang in C++11 mode, the TC3_FALLTHROUGH_INTENDED macro 64 // is expanded to [[clang::fallthrough]] attribute, which is analysed when 65 // performing switch labels fall-through diagnostic ('-Wimplicit-fallthrough'). 66 // See clang documentation on language extensions for details: 67 // http://clang.llvm.org/docs/AttributeReference.html#fallthrough-clang-fallthrough 68 // 69 // When used with unsupported compilers, the TC3_FALLTHROUGH_INTENDED macro has 70 // no effect on diagnostics. 71 // 72 // In either case this macro has no effect on runtime behavior and performance 73 // of code. 74 #if defined(__clang__) && defined(__has_warning) 75 #if __has_feature(cxx_attributes) && __has_warning("-Wimplicit-fallthrough") 76 #define TC3_FALLTHROUGH_INTENDED [[clang::fallthrough]] 77 #endif 78 #elif defined(__GNUC__) && __GNUC__ >= 7 79 #define TC3_FALLTHROUGH_INTENDED [[gnu::fallthrough]] 80 #endif 81 82 #ifndef TC3_FALLTHROUGH_INTENDED 83 #define TC3_FALLTHROUGH_INTENDED \ 84 do { \ 85 } while (0) 86 #endif 87 88 #ifdef __has_builtin 89 #define TC3_HAS_BUILTIN(x) __has_builtin(x) 90 #else 91 #define TC3_HAS_BUILTIN(x) 0 92 #endif 93 94 // Compilers can be told that a certain branch is not likely to be taken 95 // (for instance, a CHECK failure), and use that information in static 96 // analysis. Giving it this information can help it optimize for the 97 // common case in the absence of better information (ie. 98 // -fprofile-arcs). 99 // 100 // We need to disable this for GPU builds, though, since nvcc8 and older 101 // don't recognize `__builtin_expect` as a builtin, and fail compilation. 102 #if (!defined(__NVCC__)) && (TC3_HAS_BUILTIN(__builtin_expect) || \ 103 (defined(__GNUC__) && __GNUC__ >= 3)) 104 #define TC3_PREDICT_FALSE(x) (__builtin_expect(x, 0)) 105 #define TC3_PREDICT_TRUE(x) (__builtin_expect(!!(x), 1)) 106 #else 107 #define TC3_PREDICT_FALSE(x) (x) 108 #define TC3_PREDICT_TRUE(x) (x) 109 #endif 110 111 // TC3_HAVE_ATTRIBUTE 112 // 113 // A function-like feature checking macro that is a wrapper around 114 // `__has_attribute`, which is defined by GCC 5+ and Clang and evaluates to a 115 // nonzero constant integer if the attribute is supported or 0 if not. 116 // 117 // It evaluates to zero if `__has_attribute` is not defined by the compiler. 118 // 119 // GCC: https://gcc.gnu.org/gcc-5/changes.html 120 // Clang: https://clang.llvm.org/docs/LanguageExtensions.html 121 #ifdef __has_attribute 122 #define TC3_HAVE_ATTRIBUTE(x) __has_attribute(x) 123 #else 124 #define TC3_HAVE_ATTRIBUTE(x) 0 125 #endif 126 127 // TC3_ATTRIBUTE_PACKED 128 // 129 // Prevents the compiler from padding a structure to natural alignment 130 #if TC3_HAVE_ATTRIBUTE(packed) || (defined(__GNUC__) && !defined(__clang__)) 131 #define TC3_ATTRIBUTE_PACKED __attribute__((__packed__)) 132 #else 133 #define TC3_ATTRIBUTE_PACKED 134 #endif 135 136 } // namespace libtextclassifier3 137 138 #endif // LIBTEXTCLASSIFIER_UTILS_BASE_MACROS_H_ 139