/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * Licensed 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 <folly/CPortability.h> /** * Necessarily evil preprocessor-related amenities. */ // MSVC's preprocessor is a pain, so we have to // forcefully expand the VA args in some places. #define FB_VA_GLUE(a, b) … /** * FB_ONE_OR_NONE(hello, world) expands to hello and * FB_ONE_OR_NONE(hello) expands to nothing. This macro is used to * insert or eliminate text based on the presence of another argument. */ #define FB_ONE_OR_NONE(a, ...) … #define FB_THIRD(a, b, ...) … /** * Helper macro that extracts the first argument out of a list of any * number of arguments. */ #define FB_ARG_1(a, ...) … /** * Helper macro that extracts the second argument out of a list of any * number of arguments. If only one argument is given, it returns * that. */ #ifdef _MSC_VER // GCC refuses to expand this correctly if this macro itself was // called with FB_VA_GLUE :( #define FB_ARG_2_OR_1 … #else #define FB_ARG_2_OR_1(...) … #endif // Support macro for the above #define FB_ARG_2_OR_1_IMPL(a, b, ...) … /** * Helper macro that provides a way to pass argument with commas in it to * some other macro whose syntax doesn't allow using extra parentheses. * Example: * * #define MACRO(type, name) type name * MACRO(FB_SINGLE_ARG(std::pair<size_t, size_t>), x); * */ #define FB_SINGLE_ARG(...) … #define FOLLY_PP_DETAIL_APPEND_VA_ARG(...) … /** * Helper macro that just ignores its parameters. */ #define FOLLY_IGNORE(...) … /** * Helper macro that just ignores its parameters and inserts a semicolon. */ #define FOLLY_SEMICOLON(...) … /** * FB_ANONYMOUS_VARIABLE(str) introduces an identifier starting with * str and ending with a number that varies with the line. */ #ifndef FB_ANONYMOUS_VARIABLE #define FB_CONCATENATE_IMPL(s1, s2) … #define FB_CONCATENATE(s1, s2) … #ifdef __COUNTER__ // Modular builds build each module with its own preprocessor state, meaning // `__COUNTER__` no longer provides a unique number across a TU. Instead of // calling back to just `__LINE__`, use a mix of `__COUNTER__` and `__LINE__` // to try provide as much uniqueness as possible. #if FOLLY_HAS_FEATURE(modules) #define FB_ANONYMOUS_VARIABLE … #else #define FB_ANONYMOUS_VARIABLE(str) … #endif #else #define FB_ANONYMOUS_VARIABLE … #endif #endif /** * Use FOLLY_PP_STRINGIZE(x) when you'd want to do what #x does inside * another macro expansion. */ #define FOLLY_PP_STRINGIZE(x) … #define FOLLY_PP_DETAIL_NARGS_1( \ dummy, \ _15, \ _14, \ _13, \ _12, \ _11, \ _10, \ _9, \ _8, \ _7, \ _6, \ _5, \ _4, \ _3, \ _2, \ _1, \ _0, \ ...) … #define FOLLY_PP_DETAIL_NARGS(...) … #define FOLLY_PP_DETAIL_FOR_EACH_REC_0(fn, ...) … #define FOLLY_PP_DETAIL_FOR_EACH_REC_1(fn, a, ...) … #define FOLLY_PP_DETAIL_FOR_EACH_REC_2(fn, a, ...) … #define FOLLY_PP_DETAIL_FOR_EACH_REC_3(fn, a, ...) … #define FOLLY_PP_DETAIL_FOR_EACH_REC_4(fn, a, ...) … #define FOLLY_PP_DETAIL_FOR_EACH_REC_5(fn, a, ...) … #define FOLLY_PP_DETAIL_FOR_EACH_REC_6(fn, a, ...) … #define FOLLY_PP_DETAIL_FOR_EACH_REC_7(fn, a, ...) … #define FOLLY_PP_DETAIL_FOR_EACH_REC_8(fn, a, ...) … #define FOLLY_PP_DETAIL_FOR_EACH_REC_9(fn, a, ...) … #define FOLLY_PP_DETAIL_FOR_EACH_REC_10(fn, a, ...) … #define FOLLY_PP_DETAIL_FOR_EACH_REC_11(fn, a, ...) … #define FOLLY_PP_DETAIL_FOR_EACH_REC_12(fn, a, ...) … #define FOLLY_PP_DETAIL_FOR_EACH_REC_13(fn, a, ...) … #define FOLLY_PP_DETAIL_FOR_EACH_REC_14(fn, a, ...) … #define FOLLY_PP_DETAIL_FOR_EACH_REC_15(fn, a, ...) … #define FOLLY_PP_DETAIL_FOR_EACH_2(fn, n, ...) … #define FOLLY_PP_DETAIL_FOR_EACH_1(fn, n, ...) … /** * FOLLY_PP_FOR_EACH * * Used to invoke a preprocessor macro, the name of which is passed as the * first argument, once for each subsequent variadic argument. * * At present, supports [0, 16) arguments. * * This input: * * #define DOIT(a) go_do_it(a); * FOLLY_PP_FOR_EACH(DOIT, 3, 5, 7) * #undef DOIT * * Expands to this output (with whitespace adjusted for clarity): * * go_do_it(3); * go_do_it(5); * go_do_it(7); */ #define FOLLY_PP_FOR_EACH(fn, ...) … #if defined(U) #error defined(U) // literal U is used below #endif // FOLLY_PP_CONSTINIT_LINE_UNSIGNED // // MSVC with /ZI has a special backing variable for __LINE__ which is not a // literal - but token-pasting __LINE__ suppresses this backing variable. This // is done in MSVC to support its edit-and-continue feature. // // This macro evaluates to: // __LINE__ ## U // // So this macro may be ill-suited to cases which need exactly __LINE__. // // Documentation: // https://docs.microsoft.com/en-us/cpp/build/reference/z7-zi-zi-debug-information-format?view=msvc-170#zi-1 // Workaround: // https://stackoverflow.com/questions/57137351/line-is-not-constexpr-in-msvc #define FOLLY_PP_CONSTINIT_LINE_UNSIGNED …