#ifndef BOOST_ASSERT_SOURCE_LOCATION_HPP_INCLUDED
#define BOOST_ASSERT_SOURCE_LOCATION_HPP_INCLUDED
-// http://www.boost.org/libs/assert
+// http://www.boost.org/libs/assert
//
-// Copyright 2019 Peter Dimov
-// Distributed under the Boost Software License, Version 1.0.
-// http://www.boost.org/LICENSE_1_0.txt
+// Copyright 2019, 2021 Peter Dimov
+// Distributed under the Boost Software License, Version 1.0.
+// http://www.boost.org/LICENSE_1_0.txt
#include <boost/current_function.hpp>
#include <boost/config.hpp>
+#include <boost/config/workaround.hpp>
#include <boost/cstdint.hpp>
#include <iosfwd>
+#include <string>
+#include <cstdio>
+#include <cstring>
+
+#if defined(__cpp_lib_source_location) && __cpp_lib_source_location >= 201907L
+# include <source_location>
+#endif
namespace boost
{
public:
- BOOST_CONSTEXPR source_location() BOOST_NOEXCEPT: file_( "(unknown)" ), function_( "(unknown)" ), line_( 0 ), column_( 0 )
+ BOOST_CONSTEXPR source_location() BOOST_NOEXCEPT: file_( "" ), function_( "" ), line_( 0 ), column_( 0 )
{
}
{
}
+#if defined(__cpp_lib_source_location) && __cpp_lib_source_location >= 201907L
+
+ 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() )
+ {
+ }
+
+#endif
+
BOOST_CONSTEXPR char const * file_name() const BOOST_NOEXCEPT
{
return file_;
{
return column_;
}
-};
-template<class E, class T> std::basic_ostream<E, T> & operator<<( std::basic_ostream<E, T> & os, source_location const & loc )
-{
- os.width( 0 );
+#if defined(BOOST_MSVC)
+# pragma warning( push )
+# pragma warning( disable: 4996 )
+#endif
- if( loc.line() == 0 )
- {
- os << "(unknown source location)";
- }
- else
+ std::string to_string() const
{
- os << loc.file_name() << ':' << loc.line();
+ unsigned long ln = line();
+
+ if( ln == 0 )
+ {
+ return "(unknown source location)";
+ }
+
+ std::string r = file_name();
+
+ char buffer[ 16 ];
+
+ std::sprintf( buffer, ":%lu", ln );
+ r += buffer;
+
+ unsigned long co = column();
- if( loc.column() )
+ if( co )
{
- os << ':' << loc.column();
+ std::sprintf( buffer, ":%lu", co );
+ r += buffer;
}
- os << ": in function '" << loc.function_name() << '\'';
+ char const* fn = function_name();
+
+ if( *fn != 0 )
+ {
+ r += " in function '";
+ r += fn;
+ r += '\'';
+ }
+
+ return r;
}
+#if defined(BOOST_MSVC)
+# pragma warning( pop )
+#endif
+
+};
+
+template<class E, class T> std::basic_ostream<E, T> & operator<<( std::basic_ostream<E, T> & os, source_location const & loc )
+{
+ os << loc.to_string();
return os;
}
} // namespace boost
-#if defined( BOOST_DISABLE_CURRENT_LOCATION )
+#if defined(BOOST_DISABLE_CURRENT_LOCATION)
+
+# define BOOST_CURRENT_LOCATION ::boost::source_location()
+
+#elif defined(BOOST_MSVC) && BOOST_MSVC >= 1926
+
+// std::source_location::current() is available in -std:c++20, but fails with consteval errors before 19.31, and doesn't produce
+// the correct result under 19.31, so prefer the built-ins
+# define BOOST_CURRENT_LOCATION ::boost::source_location(__builtin_FILE(), __builtin_LINE(), __builtin_FUNCTION(), __builtin_COLUMN())
+
+#elif defined(__cpp_lib_source_location) && __cpp_lib_source_location >= 201907L
+
+# define BOOST_CURRENT_LOCATION ::boost::source_location(::std::source_location::current())
+
+#elif defined(BOOST_CLANG) && BOOST_CLANG_VERSION >= 90000
+
+# define BOOST_CURRENT_LOCATION ::boost::source_location(__builtin_FILE(), __builtin_LINE(), __builtin_FUNCTION(), __builtin_COLUMN())
+
+#elif defined(BOOST_GCC) && BOOST_GCC >= 70000
+
+// The built-ins are available in 4.8+, but are not constant expressions until 7
+# define BOOST_CURRENT_LOCATION ::boost::source_location(__builtin_FILE(), __builtin_LINE(), __builtin_FUNCTION())
+
+#elif defined(BOOST_GCC) && BOOST_GCC >= 50000
-# define BOOST_CURRENT_LOCATION ::boost::source_location()
+// __PRETTY_FUNCTION__ is allowed outside functions under GCC, but 4.x suffers from codegen bugs
+# define BOOST_CURRENT_LOCATION ::boost::source_location(__FILE__, __LINE__, __PRETTY_FUNCTION__)
#else
-# define BOOST_CURRENT_LOCATION ::boost::source_location(__FILE__, __LINE__, BOOST_CURRENT_FUNCTION)
+// __func__ macros aren't allowed outside functions, but BOOST_CURRENT_LOCATION is
+# define BOOST_CURRENT_LOCATION ::boost::source_location(__FILE__, __LINE__, "")
#endif