1#ifndef BOOST_ASSERT_SOURCE_LOCATION_HPP_INCLUDED
2#define BOOST_ASSERT_SOURCE_LOCATION_HPP_INCLUDED
3
4// http://www.boost.org/libs/assert
5//
6// Copyright 2019, 2021 Peter Dimov
7// Distributed under the Boost Software License, Version 1.0.
8// http://www.boost.org/LICENSE_1_0.txt
9
10#include <boost/current_function.hpp>
11#include <boost/config.hpp>
12#include <boost/config/workaround.hpp>
13#include <boost/cstdint.hpp>
14#include <iosfwd>
15#include <string>
16#include <cstdio>
17#include <cstring>
18
19#if defined(__cpp_lib_source_location) && __cpp_lib_source_location >= 201907L
20# include <source_location>
21#endif
22
23namespace boost
24{
25
26struct source_location
27{
28private:
29
30 char const * file_;
31 char const * function_;
32 boost::uint_least32_t line_;
33 boost::uint_least32_t column_;
34
35public:
36
37 BOOST_CONSTEXPR source_location() BOOST_NOEXCEPT: file_( "" ), function_( "" ), line_( 0 ), column_( 0 )
38 {
39 }
40
41 BOOST_CONSTEXPR source_location( char const * file, boost::uint_least32_t ln, char const * function, boost::uint_least32_t col = 0 ) BOOST_NOEXCEPT: file_( file ), function_( function ), line_( ln ), column_( col )
42 {
43 }
44
45#if defined(__cpp_lib_source_location) && __cpp_lib_source_location >= 201907L
46
47 BOOST_CONSTEXPR source_location( std::source_location const& loc ) BOOST_NOEXCEPT: file_( loc.file_name() ), function_( loc.function_name() ), line_( loc.line() ), column_( loc.column() )
48 {
49 }
50
51#endif
52
53 BOOST_CONSTEXPR char const * file_name() const BOOST_NOEXCEPT
54 {
55 return file_;
56 }
57
58 BOOST_CONSTEXPR char const * function_name() const BOOST_NOEXCEPT
59 {
60 return function_;
61 }
62
63 BOOST_CONSTEXPR boost::uint_least32_t line() const BOOST_NOEXCEPT
64 {
65 return line_;
66 }
67
68 BOOST_CONSTEXPR boost::uint_least32_t column() const BOOST_NOEXCEPT
69 {
70 return column_;
71 }
72
73#if defined(BOOST_MSVC)
74# pragma warning( push )
75# pragma warning( disable: 4996 )
76#endif
77
78#if ( defined(_MSC_VER) && _MSC_VER < 1900 ) || ( defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) )
79# define BOOST_ASSERT_SNPRINTF(buffer, format, arg) std::sprintf(buffer, format, arg)
80#else
81# define BOOST_ASSERT_SNPRINTF(buffer, format, arg) std::snprintf(buffer, sizeof(buffer)/sizeof(buffer[0]), format, arg)
82#endif
83
84 std::string to_string() const
85 {
86 unsigned long ln = line();
87
88 if( ln == 0 )
89 {
90 return "(unknown source location)";
91 }
92
93 std::string r = file_name();
94
95 char buffer[ 16 ];
96
97 BOOST_ASSERT_SNPRINTF( buffer, ":%lu", ln );
98 r += buffer;
99
100 unsigned long co = column();
101
102 if( co )
103 {
104 BOOST_ASSERT_SNPRINTF( buffer, ":%lu", co );
105 r += buffer;
106 }
107
108 char const* fn = function_name();
109
110 if( *fn != 0 )
111 {
112 r += " in function '";
113 r += fn;
114 r += '\'';
115 }
116
117 return r;
118 }
119
120#undef BOOST_ASSERT_SNPRINTF
121
122#if defined(BOOST_MSVC)
123# pragma warning( pop )
124#endif
125
126 inline friend bool operator==( source_location const& s1, source_location const& s2 ) BOOST_NOEXCEPT
127 {
128 return std::strcmp( s1: s1.file_, s2: s2.file_ ) == 0 && std::strcmp( s1: s1.function_, s2: s2.function_ ) == 0 && s1.line_ == s2.line_ && s1.column_ == s2.column_;
129 }
130
131 inline friend bool operator!=( source_location const& s1, source_location const& s2 ) BOOST_NOEXCEPT
132 {
133 return !( s1 == s2 );
134 }
135};
136
137template<class E, class T> std::basic_ostream<E, T> & operator<<( std::basic_ostream<E, T> & os, source_location const & loc )
138{
139 os << loc.to_string();
140 return os;
141}
142
143} // namespace boost
144
145#if defined(BOOST_DISABLE_CURRENT_LOCATION)
146
147# define BOOST_CURRENT_LOCATION ::boost::source_location()
148
149#elif defined(BOOST_MSVC) && BOOST_MSVC >= 1926
150
151// std::source_location::current() is available in -std:c++20, but fails with consteval errors before 19.31, and doesn't produce
152// the correct result under 19.31, so prefer the built-ins
153# define BOOST_CURRENT_LOCATION ::boost::source_location(__builtin_FILE(), __builtin_LINE(), __builtin_FUNCTION(), __builtin_COLUMN())
154
155#elif defined(BOOST_MSVC)
156
157// __LINE__ is not a constant expression under /ZI (edit and continue) for 1925 and before
158
159# define BOOST_CURRENT_LOCATION_IMPL_1(x) BOOST_CURRENT_LOCATION_IMPL_2(x)
160# define BOOST_CURRENT_LOCATION_IMPL_2(x) (x##0 / 10)
161
162# define BOOST_CURRENT_LOCATION ::boost::source_location(__FILE__, BOOST_CURRENT_LOCATION_IMPL_1(__LINE__), "")
163
164#elif defined(__cpp_lib_source_location) && __cpp_lib_source_location >= 201907L && !defined(__NVCC__)
165
166// Under nvcc, __builtin_source_location is not constexpr
167// https://github.com/boostorg/assert/issues/32
168
169# define BOOST_CURRENT_LOCATION ::boost::source_location(::std::source_location::current())
170
171#elif defined(BOOST_CLANG) && BOOST_CLANG_VERSION >= 90000
172
173# define BOOST_CURRENT_LOCATION ::boost::source_location(__builtin_FILE(), __builtin_LINE(), __builtin_FUNCTION(), __builtin_COLUMN())
174
175#elif defined(BOOST_GCC) && BOOST_GCC >= 70000
176
177// The built-ins are available in 4.8+, but are not constant expressions until 7
178# define BOOST_CURRENT_LOCATION ::boost::source_location(__builtin_FILE(), __builtin_LINE(), __builtin_FUNCTION())
179
180#elif defined(BOOST_GCC) && BOOST_GCC >= 50000
181
182// __PRETTY_FUNCTION__ is allowed outside functions under GCC, but 4.x suffers from codegen bugs
183# define BOOST_CURRENT_LOCATION ::boost::source_location(__FILE__, __LINE__, __PRETTY_FUNCTION__)
184
185#else
186
187// __func__ macros aren't allowed outside functions, but BOOST_CURRENT_LOCATION is
188# define BOOST_CURRENT_LOCATION ::boost::source_location(__FILE__, __LINE__, "")
189
190#endif
191
192#endif // #ifndef BOOST_ASSERT_SOURCE_LOCATION_HPP_INCLUDED
193