/* * 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 <cstdlib> #include <fmt/core.h> #include <folly/CPortability.h> #include <folly/Conv.h> #include <folly/ExceptionString.h> #include <folly/Portability.h> #include <folly/lang/Exception.h> #include <folly/logging/LogCategory.h> #include <folly/logging/LogMessage.h> #include <folly/logging/LogStream.h> #include <folly/logging/ObjectToString.h> namespace folly { template <bool IsInHeaderFile> class XlogCategoryInfo; class XlogFileScopeInfo; /** * LogStreamProcessor receives a LogStream and logs it. * * This class is primarily intended to be used through the FB_LOG*() macros. * Its API is designed to support these macros, and is not designed for other * use. * * The operator&() method is used to trigger the logging. * This operator is used because it has lower precedence than <<, but higher * precedence than the ? ternary operator, allowing it to bind with the correct * precedence in the log macro implementations. */ class LogStreamProcessor { … }; /** * LogStreamVoidify() is a helper class used in the FB_LOG() and XLOG() macros. * * It's only purpose is to provide an & operator overload that returns void. * This allows the log macros to expand roughly to: * * (logEnabled) ? (void)0 * : LogStreamVoidify{} & LogStreamProcessor{}.stream() << "msg"; * * This enables the right hand (':') side of the ternary ? expression to have a * void type, and allows various streaming operator expressions to be placed on * the right hand side of the expression. * * Operator & is used since it has higher precedence than ?:, but lower * precedence than <<. * * This class is templated on whether the log message is fatal so that the * operator& can be declared [[noreturn]] for fatal log messages. This * prevents the compiler from complaining about functions that do not return a * value after a fatal log statement. */ template <bool Fatal> class LogStreamVoidify { … }; template <> class LogStreamVoidify<true> { … }; /** * logDisabledHelper() is invoked in FB_LOG() and XLOG() statements if the log * admittance check fails. * * This function exists solely to ensure that both sides of the log check are * marked [[noreturn]] for fatal log messages. This allows the compiler to * recognize that the full statement is noreturn, preventing warnings about * missing return statements after fatal log messages. * * Unfortunately it does not appear possible to get the compiler to recognize * that the disabled side of the log statement should never be reached for * fatal messages. Even if we make the check something like * `(isLogLevelFatal(level) || realCheck)`, where isLogLevelFatal() is * constexpr, this is not sufficient for gcc or clang to recognize that the * full expression is noreturn. * * Ideally this would just be a template function specialized on a boolean * IsFatal parameter. Unfortunately this triggers a bug in clang, which does * not like differing noreturn behavior for different template instantiations. * Therefore we overload on integral_constant instead. * * clang-format also doesn't do a good job understanding this code and figuring * out how to format it. */ // clang-format off inline void logDisabledHelper(std::false_type) noexcept { … } [[noreturn]] void logDisabledHelper(std::true_type) noexcept; // clang-format on } // namespace folly