blob: 8be25de078004eedc06eb71fb2f9c7c9398924f4 [file] [log] [blame]
Jeroen Dhollandercda36982022-11-30 10:12:321// Copyright 2022 The Chromium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "base/check.h"
6#include "base/compiler_specific.h"
7
8#if CHECK_WILL_STREAM()
9#include "base/logging.h"
10#endif // CHECK_WILL_STREAM()
11
12#ifndef BASE_CHECK_DEREF_H_
13#define BASE_CHECK_DEREF_H_
14
15namespace logging {
16
17// Returns a reference to pointee of `ptr` if `ptr` is not null, or dies if
18// `ptr` is null.
19//
20// It is useful in initializers and direct assignments, where a direct `CHECK`
21// call can't be used:
22//
23// MyType& type_ref = CHECK_DEREF(MethodReturningAPointer());
24//
25// If your raw pointer is stored in a wrapped type like `unique_ptr` or
26// `raw_ptr`, you should use their `.get()` methods to get the raw pointer
27// before calling `CHECK_DEREF()`:
28//
29// MyType& type_ref = CHECK_DEREF(your_wrapped_pointer.get());
30//
31#define CHECK_DEREF(ptr) \
32 ::logging::CheckDeref(ptr, #ptr " != nullptr", __FILE__, __LINE__)
33
34template <typename T>
35T& CheckDeref(T* ptr, const char* message, const char* file, int line) {
36 // Note: we can't just call `CHECK_NE(ptr, nullptr)` here, as that would
37 // cause the error to be reported from this header, and we want the error
38 // to be reported at the file and line of the caller.
39 if (UNLIKELY(ptr == nullptr)) {
40#if !CHECK_WILL_STREAM()
41 CheckFailure();
42#else
43 // `LogMessage` will die with a fatal error in its destructor.
44 LogMessage(file, line, message);
45#endif // !CHECK_WILL_STREAM()
46 }
47 return *ptr;
48}
49
50} // namespace logging
51
52#endif // BASE_CHECK_DEREF_H_