// Copyright 2020 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef BASE_NOTREACHED_H_ #define BASE_NOTREACHED_H_ #include "base/base_export.h" #include "base/check.h" #include "base/dcheck_is_on.h" #include "base/logging_buildflags.h" namespace logging { // NOTREACHED() annotates should-be unreachable code. Under the // kNotReachedIsFatal experiment all NOTREACHED()s that happen after FeatureList // initialization are fatal. As of 2023-06-06 this experiment is disabled // everywhere. // // For paths that are intended to eventually be NOTREACHED() but are not yet // ready for migration (stability risk, known pre-existing failures), consider // the DUMP_WILL_BE_NOTREACHED_NORETURN() macro below. // // Outside the kNotReachedIsFatal experiment behavior is as follows: // // On DCHECK builds NOTREACHED() match the fatality of DCHECKs. When DCHECKs are // non-FATAL a crash report will be generated for the first NOTREACHED() that // hits per process. // // Outside DCHECK builds NOTREACHED() will LOG(ERROR) and also upload a crash // report without crashing in order to weed out prevalent NOTREACHED()s in the // wild before always turning NOTREACHED()s FATAL. // // TODO(crbug.com/851128): Migrate NOTREACHED() callers to NOTREACHED_NORETURN() // which is [[noreturn]] and always FATAL. Once that's done, rename // NOTREACHED_NORETURN() back to NOTREACHED() and remove the non-FATAL version. // This migration will likely happen through the kNotReachedIsFatal experiment // for most code as we'll be able to avoid stability issues for pre-existing // failures. #if CHECK_WILL_STREAM() || BUILDFLAG(ENABLE_LOG_ERROR_NOT_REACHED) #define NOTREACHED() \ LOGGING_CHECK_FUNCTION_IMPL(::logging::NotReachedError::NotReached(), false) #else #define NOTREACHED() \ (true) ? ::logging::NotReachedError::TriggerNotReached() \ : EAT_CHECK_STREAM_PARAMS() #endif // NOTREACHED_NORETURN() annotates paths that are supposed to be unreachable. // They crash if they are ever hit. // TODO(crbug.com/851128): Rename back to NOTREACHED() once there are no callers // of the old non-CHECK-fatal macro. #if CHECK_WILL_STREAM() #define NOTREACHED_NORETURN() ::logging::NotReachedNoreturnError() #else // This function is used to be able to detect NOTREACHED() failures in stack // traces where this symbol is preserved (even if inlined). Its implementation // matches logging::CheckFailure() but intentionally uses a different signature. [[noreturn]] IMMEDIATE_CRASH_ALWAYS_INLINE void NotReachedFailure() { base::ImmediateCrash(); } #define NOTREACHED_NORETURN() \ (true) ? ::logging::NotReachedFailure() : EAT_CHECK_STREAM_PARAMS() #endif // The DUMP_WILL_BE_NOTREACHED_NORETURN() macro provides a convenient way to // non-fatally dump in official builds if ever hit. See DUMP_WILL_BE_CHECK for // suggested usage. #define DUMP_WILL_BE_NOTREACHED_NORETURN() \ ::logging::CheckError::DumpWillBeNotReachedNoreturn() // The NOTIMPLEMENTED() macro annotates codepaths which have not been // implemented yet. If output spam is a serious concern, // NOTIMPLEMENTED_LOG_ONCE can be used. // Note that the NOTIMPLEMENTED_LOG_ONCE() macro does not allow custom error // messages to be appended to the macro to log, unlike NOTIMPLEMENTED() which // does support the pattern of appending a custom error message. As in, the // NOTIMPLEMENTED_LOG_ONCE() << "foo message"; pattern is not supported. #if DCHECK_IS_ON() #define NOTIMPLEMENTED() \ ::logging::CheckError::NotImplemented(__PRETTY_FUNCTION__) #else #define NOTIMPLEMENTED() EAT_CHECK_STREAM_PARAMS() #endif #define NOTIMPLEMENTED_LOG_ONCE() \ { \ static bool logged_once = false; \ if (!logged_once) { \ NOTIMPLEMENTED(); \ logged_once = true; \ } \ } } // namespace logging #endif // BASE_NOTREACHED_H_