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