1//===-- Definition of a libc internal assert macro --------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_LIBC_SRC___SUPPORT_LIBC_ASSERT_H
10#define LLVM_LIBC_SRC___SUPPORT_LIBC_ASSERT_H
11
12#ifdef LIBC_COPT_USE_C_ASSERT
13
14// The build is configured to just use the public <assert.h> API
15// for libc's internal assertions.
16
17#include <assert.h>
18
19#define LIBC_ASSERT(COND) assert(COND)
20
21#else // Not LIBC_COPT_USE_C_ASSERT
22
23#include "src/__support/OSUtil/io.h"
24#include "src/__support/OSUtil/quick_exit.h"
25#include "src/__support/integer_to_string.h"
26#include "src/__support/macros/attributes.h" // For LIBC_INLINE
27
28namespace LIBC_NAMESPACE {
29
30// This is intended to be removed in a future patch to use a similar design to
31// below, but it's necessary for the external assert.
32LIBC_INLINE void report_assertion_failure(const char *assertion,
33 const char *filename, unsigned line,
34 const char *funcname) {
35 const IntegerToString<unsigned> line_buffer(line);
36 write_to_stderr(msg: filename);
37 write_to_stderr(msg: ":");
38 write_to_stderr(msg: line_buffer.view());
39 write_to_stderr(msg: ": Assertion failed: '");
40 write_to_stderr(msg: assertion);
41 write_to_stderr(msg: "' in function: '");
42 write_to_stderr(msg: funcname);
43 write_to_stderr(msg: "'\n");
44}
45
46} // namespace LIBC_NAMESPACE
47
48#ifdef LIBC_ASSERT
49#error "Unexpected: LIBC_ASSERT macro already defined"
50#endif
51
52// The public "assert" macro calls abort on failure. Should it be same here?
53// The libc internal assert can fire from anywhere inside the libc. So, to
54// avoid potential chicken-and-egg problems, it is simple to do a quick_exit
55// on assertion failure instead of calling abort. We also don't want to use
56// __builtin_trap as it could potentially be implemented using illegal
57// instructions which can be very misleading when debugging.
58#ifdef NDEBUG
59#define LIBC_ASSERT(COND) \
60 do { \
61 } while (false)
62#else
63
64// Convert __LINE__ to a string using macros. The indirection is necessary
65// because otherwise it will turn "__LINE__" into a string, not its value. The
66// value is evaluated in the indirection step.
67#define __LIBC_MACRO_TO_STR(x) #x
68#define __LIBC_MACRO_TO_STR_INDIR(y) __LIBC_MACRO_TO_STR(y)
69#define __LIBC_LINE_STR__ __LIBC_MACRO_TO_STR_INDIR(__LINE__)
70
71#define LIBC_ASSERT(COND) \
72 do { \
73 if (!(COND)) { \
74 LIBC_NAMESPACE::write_to_stderr(__FILE__ ":" __LIBC_LINE_STR__ \
75 ": Assertion failed: '" #COND \
76 "' in function: '"); \
77 LIBC_NAMESPACE::write_to_stderr(__PRETTY_FUNCTION__); \
78 LIBC_NAMESPACE::write_to_stderr("'\n"); \
79 LIBC_NAMESPACE::quick_exit(0xFF); \
80 } \
81 } while (false)
82#endif // NDEBUG
83
84#endif // LIBC_COPT_USE_C_ASSERT
85
86#endif // LLVM_LIBC_SRC___SUPPORT_LIBC_ASSERT_H
87

source code of libc/src/__support/libc_assert.h