158a75c6aSSiva Chandra Reddy //===-- Definition of a libc internal assert macro --------------*- C++ -*-===// 258a75c6aSSiva Chandra Reddy // 358a75c6aSSiva Chandra Reddy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 458a75c6aSSiva Chandra Reddy // See https://llvm.org/LICENSE.txt for license information. 558a75c6aSSiva Chandra Reddy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 658a75c6aSSiva Chandra Reddy // 758a75c6aSSiva Chandra Reddy //===----------------------------------------------------------------------===// 858a75c6aSSiva Chandra Reddy 9270547f3SGuillaume Chatelet #ifndef LLVM_LIBC_SRC___SUPPORT_LIBC_ASSERT_H 10270547f3SGuillaume Chatelet #define LLVM_LIBC_SRC___SUPPORT_LIBC_ASSERT_H 1158a75c6aSSiva Chandra Reddy 125ff3ff33SPetr Hosek #include "src/__support/macros/config.h" 1365825cd5SJoseph Huber #if defined(LIBC_COPT_USE_C_ASSERT) || !defined(LIBC_FULL_BUILD) 1465c78933SRoland McGrath 1565c78933SRoland McGrath // The build is configured to just use the public <assert.h> API 1665c78933SRoland McGrath // for libc's internal assertions. 1765c78933SRoland McGrath 1865c78933SRoland McGrath #include <assert.h> 1965c78933SRoland McGrath 2065c78933SRoland McGrath #define LIBC_ASSERT(COND) assert(COND) 2165c78933SRoland McGrath 2265c78933SRoland McGrath #else // Not LIBC_COPT_USE_C_ASSERT 2365c78933SRoland McGrath 2407bd4394SRoseZhang03 #include "src/__support/OSUtil/exit.h" 2558a75c6aSSiva Chandra Reddy #include "src/__support/OSUtil/io.h" 2658a75c6aSSiva Chandra Reddy #include "src/__support/integer_to_string.h" 2758a75c6aSSiva Chandra Reddy #include "src/__support/macros/attributes.h" // For LIBC_INLINE 28*45c84d59Sgoldsteinn #include "src/__support/macros/optimization.h" // For LIBC_UNLIKELY 2958a75c6aSSiva Chandra Reddy 305ff3ff33SPetr Hosek namespace LIBC_NAMESPACE_DECL { 3149eb1aedSMichael Jones 3249eb1aedSMichael Jones // This is intended to be removed in a future patch to use a similar design to 3349eb1aedSMichael Jones // below, but it's necessary for the external assert. 3449eb1aedSMichael Jones LIBC_INLINE void report_assertion_failure(const char *assertion, 3549eb1aedSMichael Jones const char *filename, unsigned line, 3649eb1aedSMichael Jones const char *funcname) { 37b555912eSGuillaume Chatelet const IntegerToString<unsigned> line_buffer(line); 38b555912eSGuillaume Chatelet write_to_stderr(filename); 39b555912eSGuillaume Chatelet write_to_stderr(":"); 40b555912eSGuillaume Chatelet write_to_stderr(line_buffer.view()); 41b555912eSGuillaume Chatelet write_to_stderr(": Assertion failed: '"); 42b555912eSGuillaume Chatelet write_to_stderr(assertion); 43b555912eSGuillaume Chatelet write_to_stderr("' in function: '"); 44b555912eSGuillaume Chatelet write_to_stderr(funcname); 45b555912eSGuillaume Chatelet write_to_stderr("'\n"); 4649eb1aedSMichael Jones } 4749eb1aedSMichael Jones 485ff3ff33SPetr Hosek } // namespace LIBC_NAMESPACE_DECL 4949eb1aedSMichael Jones 5058a75c6aSSiva Chandra Reddy #ifdef LIBC_ASSERT 5158a75c6aSSiva Chandra Reddy #error "Unexpected: LIBC_ASSERT macro already defined" 5258a75c6aSSiva Chandra Reddy #endif 5358a75c6aSSiva Chandra Reddy 5458a75c6aSSiva Chandra Reddy // The public "assert" macro calls abort on failure. Should it be same here? 55c76a3e79SGuillaume Chatelet // The libc internal assert can fire from anywhere inside the libc. So, to 5607bd4394SRoseZhang03 // avoid potential chicken-and-egg problems, it is simple to do an exit 5758a75c6aSSiva Chandra Reddy // on assertion failure instead of calling abort. We also don't want to use 5858a75c6aSSiva Chandra Reddy // __builtin_trap as it could potentially be implemented using illegal 5958a75c6aSSiva Chandra Reddy // instructions which can be very misleading when debugging. 6058a75c6aSSiva Chandra Reddy #ifdef NDEBUG 6158a75c6aSSiva Chandra Reddy #define LIBC_ASSERT(COND) \ 6258a75c6aSSiva Chandra Reddy do { \ 6358a75c6aSSiva Chandra Reddy } while (false) 6458a75c6aSSiva Chandra Reddy #else 6565fe1ac3SMichael Jones 6665fe1ac3SMichael Jones // Convert __LINE__ to a string using macros. The indirection is necessary 6765fe1ac3SMichael Jones // because otherwise it will turn "__LINE__" into a string, not its value. The 6865fe1ac3SMichael Jones // value is evaluated in the indirection step. 6965fe1ac3SMichael Jones #define __LIBC_MACRO_TO_STR(x) #x 7065fe1ac3SMichael Jones #define __LIBC_MACRO_TO_STR_INDIR(y) __LIBC_MACRO_TO_STR(y) 7165fe1ac3SMichael Jones #define __LIBC_LINE_STR__ __LIBC_MACRO_TO_STR_INDIR(__LINE__) 7265fe1ac3SMichael Jones 7358a75c6aSSiva Chandra Reddy #define LIBC_ASSERT(COND) \ 7458a75c6aSSiva Chandra Reddy do { \ 75*45c84d59Sgoldsteinn if (LIBC_UNLIKELY(!(COND))) { \ 76b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::write_to_stderr(__FILE__ ":" __LIBC_LINE_STR__ \ 7765fe1ac3SMichael Jones ": Assertion failed: '" #COND \ 7865fe1ac3SMichael Jones "' in function: '"); \ 79b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::write_to_stderr(__PRETTY_FUNCTION__); \ 80b6bc9d72SGuillaume Chatelet LIBC_NAMESPACE::write_to_stderr("'\n"); \ 8107bd4394SRoseZhang03 LIBC_NAMESPACE::internal::exit(0xFF); \ 8258a75c6aSSiva Chandra Reddy } \ 8358a75c6aSSiva Chandra Reddy } while (false) 8458a75c6aSSiva Chandra Reddy #endif // NDEBUG 8558a75c6aSSiva Chandra Reddy 8665c78933SRoland McGrath #endif // LIBC_COPT_USE_C_ASSERT 8765c78933SRoland McGrath 88270547f3SGuillaume Chatelet #endif // LLVM_LIBC_SRC___SUPPORT_LIBC_ASSERT_H 89