2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
24 #include <type_traits>
27 #include <folly/Format.h>
28 #include <folly/Preprocessor.h>
30 #include "hphp/util/portability.h"
32 ///////////////////////////////////////////////////////////////////////////////
34 #define IMPLIES(a, b) (!(a) || (b))
36 #define not_reached() /* gcc-4.5 supports __builtin_unreachable() */ \
39 __builtin_unreachable(); \
42 #define not_implemented() do { \
43 fprintf(stderr, "not implemented: %s:%d %s\n", \
44 __FILE__, __LINE__, __FUNCTION__); \
48 #define assert_not_implemented(pred) do { \
56 ///////////////////////////////////////////////////////////////////////////////
59 * Assertion abort and log functions.
61 * These are intended for use primarily by the assert macros below.
64 void assert_fail(const char* e
,
68 const std::string
& msg
);
70 ///////////////////////////////////////////////////////////////////////////////
73 * Stack-allocated detailed assertion logger.
75 struct AssertDetailImpl
{
77 * Reads the most recently added message, and removes it from the
78 * list. Returns true if there was a message to read.
80 static bool readAndRemove(std::string
& msg
);
82 explicit AssertDetailImpl(const char* name
)
87 if (m_name
== nullptr) std::abort();
91 ~AssertDetailImpl() { if (m_name
) s_head
= m_next
; }
93 AssertDetailImpl(AssertDetailImpl
&& other
) noexcept
{
95 if (s_head
!= &other
) std::abort();
97 m_name
= other
.m_name
;
98 m_next
= other
.m_next
;
100 other
.m_name
= nullptr; // prevents ~other from messing it up
103 AssertDetailImpl(const AssertDetailImpl
&) = delete;
104 AssertDetailImpl
& operator=(const AssertDetailImpl
&) = delete;
107 static std::pair
<std::string
,std::string
>
108 log_one(const AssertDetailImpl
* adi
, const char* name
);
109 virtual std::string
run() const = 0;
112 static __thread AssertDetailImpl
* s_head
;
115 AssertDetailImpl
* m_next
{nullptr};
119 struct AssertDetailT final
: AssertDetailImpl
{
120 AssertDetailT(const char* name
, F
&& f
)
121 : AssertDetailImpl(name
)
124 AssertDetailT(AssertDetailT
&&) = default;
127 std::string
run() const override
{ return m_f(); }
135 struct AssertDetailScopeMaker
{
136 explicit AssertDetailScopeMaker(const char* name
) : m_name(name
) {}
138 template <typename F
>
139 AssertDetailT
<typename
std::decay
<F
>::type
> operator+(F
&& f
) {
140 return AssertDetailT
<typename
std::decay
<F
>::type
>(
141 m_name
, std::forward
<F
>(f
));
150 #define SCOPE_ASSERT_DETAIL(name) \
151 auto const FB_ANONYMOUS_VARIABLE(SCOPE_ASSERT) \
152 = ::HPHP::detail::AssertDetailScopeMaker(name) + [&]()
154 ///////////////////////////////////////////////////////////////////////////////
156 # if !defined __GNUC__ || defined __STRICT_ANSI__
157 #define assert_impl(cond, fail) \
158 ((cond) ? static_cast<void>(0) : ((fail), static_cast<void>(0)))
161 * This is preferred, because "cond" is not over-parenthesized, and
162 * thus -Wparentheses can warn about errors like "always_assert(a=1)".
163 * With -pedantic, we cannot use "({...})" statement expressions,
164 * so must resort to the old way, above.
166 #define assert_impl(cond, fail) \
167 ({ if (cond) ; else { fail; } static_cast<void>(0); })
170 #define assert_fail_impl(e, msg) \
171 ::HPHP::assert_fail(#e, __FILE__, __LINE__, __PRETTY_FUNCTION__, msg)
173 #define always_assert(e) assert_impl(e, assert_fail_impl(e, ""))
174 #define always_assert_log(e, l) assert_impl(e, assert_fail_impl(e, l()))
175 #define always_assert_flog(e, ...) assert_impl(e, assert_fail_impl(e, \
176 ::folly::format(__VA_ARGS__).str()))
181 #define assert(e) always_assert(e)
182 #define assertx(e) always_assert(e)
183 #define assert_log(e, l) always_assert_log(e, l)
184 #define assert_flog(e, ...) always_assert_flog(e, __VA_ARGS__)
186 #define assert(e) static_cast<void>(0)
187 #define assertx(e) static_cast<void>(0)
188 #define assert_log(e, l) static_cast<void>(0)
189 #define assert_flog(e, ...) static_cast<void>(0)
192 ///////////////////////////////////////////////////////////////////////////////