diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -198,6 +198,8 @@ ------------------------------------------------- ----------------- ``__cpp_lib_ranges`` *unimplemented* ------------------------------------------------- ----------------- + ``__cpp_lib_source_location`` ``201907L`` + ------------------------------------------------- ----------------- ``__cpp_lib_span`` ``202002L`` ------------------------------------------------- ----------------- ``__cpp_lib_three_way_comparison`` *unimplemented* diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -129,6 +129,7 @@ set setjmp.h shared_mutex + source_location span sstream stack diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -594,6 +594,10 @@ header "experimental/set" export * } + module source_location { + header "source_location" + export * + } module span { header "span" export * diff --git a/libcxx/include/source_location b/libcxx/include/source_location new file mode 100644 --- /dev/null +++ b/libcxx/include/source_location @@ -0,0 +1,87 @@ +// -*- C++ -*- +//===------------------------------ source_location ----------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------===// + +#ifndef _LIBCPP_SOURCE_LOCATION +#define _LIBCPP_SOURCE_LOCATION + +/* + source_location synopsis + +namespace std { + struct source_location { + // source location construction + static consteval source_location current() noexcept; + constexpr source_location() noexcept; + + // source location field access + constexpr uint_least32_t line() const noexcept; + constexpr uint_least32_t column() const noexcept; + constexpr const char* file_name() const noexcept; + constexpr const char* function_name() const noexcept; + + private: + uint_least32_t line_; // exposition only + uint_least32_t column_; // exposition only + const char* file_name_; // exposition only + const char* function_name_; // exposition only + }; +} +*/ + +#include <__config> +#include +#include +#include + +_LIBCPP_BEGIN_NAMESPACE_STD + +#if _LIBCPP_STD_VER > 17 + +struct source_location { + // TODO: current() should be marked consteval instead of constexpr, + // but current compiler implementations seem buggy and return callee's location. + static constexpr source_location + current(const char* __file = __builtin_FILE(), + const char* __func = __builtin_FUNCTION(), + uint_least32_t __line = __builtin_LINE(), +#if __has_builtin(__builtin_COLUMN) + uint_least32_t __col = __builtin_COLUMN()) noexcept { +#else + uint_least32_t __col = 0) noexcept { +#endif + source_location __sloc; + __sloc.__file = __file; + __sloc.__func = __func; + __sloc.__line = __line; + __sloc.__col = __col; + return __sloc; + } + + constexpr source_location() noexcept : __file("unknown"), + __func(__file), + __line(0), + __col(0) {} + + constexpr uint_least32_t line() const noexcept { return __line; } + constexpr uint_least32_t column() const noexcept { return __col; } + constexpr const char* file_name() const noexcept { return __file; } + constexpr const char* function_name() const noexcept { return __func; } + +private: + const char* __file; + const char* __func; + uint_least32_t __line; + uint_least32_t __col; +}; + +#endif // _LIBCPP_STD_VER > 17 + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP_SOURCE_LOCATION diff --git a/libcxx/include/version b/libcxx/include/version --- a/libcxx/include/version +++ b/libcxx/include/version @@ -98,6 +98,7 @@ __cpp_lib_shared_ptr_arrays 201611L __cpp_lib_shared_ptr_weak_type 201606L __cpp_lib_shared_timed_mutex 201402L +__cpp_lib_source_location 201907L __cpp_lib_span 202002L __cpp_lib_string_udls 201304L __cpp_lib_string_view 201606L @@ -235,6 +236,7 @@ # endif # define __cpp_lib_list_remove_return_type 201806L // # define __cpp_lib_ranges 201811L +# define __cpp_lib_source_location 201907L # define __cpp_lib_span 202002L // # define __cpp_lib_three_way_comparison 201711L # define __cpp_lib_to_array 201907L diff --git a/libcxx/test/libcxx/double_include.sh.cpp b/libcxx/test/libcxx/double_include.sh.cpp --- a/libcxx/test/libcxx/double_include.sh.cpp +++ b/libcxx/test/libcxx/double_include.sh.cpp @@ -111,6 +111,7 @@ #ifndef _LIBCPP_HAS_NO_THREADS #include #endif +#include #include #include #include diff --git a/libcxx/test/std/language.support/reflection.src_loc/creation/current.pass.cpp b/libcxx/test/std/language.support/reflection.src_loc/creation/current.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/reflection.src_loc/creation/current.pass.cpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// source_location::current(); + +#include +#include + +#include "constexpr_char_traits.h" +#include "test_macros.h" + +bool test(std::source_location loc = std::source_location::current()) { + using SV = std::string_view; + + assert(loc.line() > __LINE__); // In main(). + assert(loc.column() != 0u); + assert(SV{loc.file_name()} == "current.pass.cpp"); + assert(SV{loc.function_name()} == "main"); + + ASSERT_NOEXCEPT(std::source_location::current()); + + return true; +} + +constexpr bool test_constexpr() { + using SV = std::basic_string_view >; + + constexpr std::source_location loc = std::source_location::current(); + + assert(loc.line() < __LINE__); + assert(loc.column() != 0u); + static_assert(SV{loc.file_name()} == "current.pass.cpp"); + static_assert(SV{loc.function_name()} == "test_constexpr"); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test_constexpr()); + + return 0; +} diff --git a/libcxx/test/std/language.support/reflection.src_loc/creation/source_location.pass.cpp b/libcxx/test/std/language.support/reflection.src_loc/creation/source_location.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/reflection.src_loc/creation/source_location.pass.cpp @@ -0,0 +1,55 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// source_location::source_location(); + +#include +#include +#include + +#include "constexpr_char_traits.h" +#include "test_macros.h" + +bool test() { + using SV = std::string_view; + + std::source_location loc; + + assert(loc.line() == 0u); + assert(loc.column() == 0u); + assert(SV{loc.file_name()} == "unknown"); + assert(SV{loc.function_name()} == "unknown"); + + ASSERT_NOEXCEPT(std::source_location()); + + return true; +} + +constexpr bool test_constexpr() { + using SV = std::basic_string_view >; + + constexpr std::source_location loc; + + assert(loc.line() == 0u); + assert(loc.column() == 0u); + static_assert(SV{loc.file_name()} == "unknown"); + static_assert(SV{loc.function_name()} == "unknown"); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test_constexpr()); + + return 0; +} diff --git a/libcxx/test/std/language.support/reflection.src_loc/fields/column.pass.cpp b/libcxx/test/std/language.support/reflection.src_loc/fields/column.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/reflection.src_loc/fields/column.pass.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// GCC does not have __builtin_COLUMN. +// UNSUPPORTED: gcc + +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// source_location::column(); + +#include +#include + +bool test() { + std::source_location loc1; + assert(loc1.column() == 0u); + std::source_location loc2 = std::source_location::current(); + assert(loc2.column() == 31u); + std::source_location loc3 = // Comment to change column. + std::source_location::current(); + assert(loc3.column() == 7u); + + return true; +} + +constexpr bool test_constexpr() { + constexpr std::source_location loc1; + static_assert(loc1.column() == 0u); + constexpr std::source_location loc2 = std::source_location::current(); + static_assert(loc2.column() == 41u); + constexpr std::source_location loc3 = // Comment to change column. + std::source_location::current(); + static_assert(loc3.column() == 7u); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test_constexpr()); + + return 0; +} diff --git a/libcxx/test/std/language.support/reflection.src_loc/fields/file_name.pass.cpp b/libcxx/test/std/language.support/reflection.src_loc/fields/file_name.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/reflection.src_loc/fields/file_name.pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// source_location::file_name(); + +#include +#include +#include + +#include "constexpr_char_traits.h" + +bool test() { + using SV = std::string_view; + + std::source_location loc1; + assert(SV{loc1.file_name()} == "unknown"); + std::source_location loc2 = std::source_location::current(); + assert(SV{loc2.file_name()} == "file_name.pass.cpp"); + + return true; +} + +constexpr bool test_constexpr() { + using SV = std::basic_string_view >; + + constexpr std::source_location loc1; + static_assert(SV{loc1.file_name()} == "unknown"); + constexpr std::source_location loc2 = std::source_location::current(); + static_assert(SV{loc2.file_name()} == "file_name.pass.cpp"); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test_constexpr()); + + return 0; +} diff --git a/libcxx/test/std/language.support/reflection.src_loc/fields/function_name.pass.cpp b/libcxx/test/std/language.support/reflection.src_loc/fields/function_name.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/reflection.src_loc/fields/function_name.pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// source_location::function_name(); + +#include +#include +#include + +#include "constexpr_char_traits.h" + +bool test() { + using SV = std::string_view; + + std::source_location loc1; + assert(SV{loc1.function_name()} == "unknown"); + std::source_location loc2 = std::source_location::current(); + assert(SV{loc2.function_name()} == "test"); + + return true; +} + +constexpr bool test_constexpr() { + using SV = std::basic_string_view >; + + constexpr std::source_location loc1; + static_assert(SV{loc1.function_name()} == "unknown"); + constexpr std::source_location loc2 = std::source_location::current(); + static_assert(SV{loc2.function_name()} == "test_constexpr"); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test_constexpr()); + + return 0; +} diff --git a/libcxx/test/std/language.support/reflection.src_loc/fields/line.pass.cpp b/libcxx/test/std/language.support/reflection.src_loc/fields/line.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/reflection.src_loc/fields/line.pass.cpp @@ -0,0 +1,58 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03, c++11, c++14, c++17 + +// + +// source_location::line(); + +#include +#include + +bool test_caller(std::source_location loc = std::source_location::current()) { + assert(loc.line() > __LINE__); + + return true; +} + +bool test() { + std::source_location loc1; + assert(loc1.line() == 0u); + std::source_location loc2 = std::source_location::current(); + assert(loc2.line() == __LINE__ - 1u); + + test_caller(); + + return true; +} + +constexpr bool test_caller_constexpr( + std::source_location loc = std::source_location::current()) { + assert(loc.line() > __LINE__); + + return true; +} + +constexpr bool test_constexpr() { + constexpr std::source_location loc1; + static_assert(loc1.line() == 0u); + constexpr std::source_location loc2 = std::source_location::current(); + static_assert(loc2.line() == __LINE__ - 1u); + + test_caller_constexpr(); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test_constexpr()); + + return 0; +} diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/source_location.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/source_location.version.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/source_location.version.pass.cpp @@ -0,0 +1,52 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// WARNING: This test was generated by generate_feature_test_macro_components.py +// and should not be edited manually. + +// + +// Test the feature test macros defined by + +/* Constant Value + __cpp_lib_source_location 201907L [C++2a] +*/ + +#include +#include "test_macros.h" + +#if TEST_STD_VER < 14 + +#ifdef __cpp_lib_source_location +#error "__cpp_lib_source_location should not be defined before c++2a" +#endif + +#elif TEST_STD_VER == 14 + +#ifdef __cpp_lib_source_location +#error "__cpp_lib_source_location should not be defined before c++2a" +#endif + +#elif TEST_STD_VER == 17 + +#ifdef __cpp_lib_source_location +#error "__cpp_lib_source_location should not be defined before c++2a" +#endif + +#elif TEST_STD_VER > 17 + +#ifndef __cpp_lib_source_location +#error "__cpp_lib_source_location should be defined in c++2a" +#endif +#if __cpp_lib_source_location != 201907L +#error "__cpp_lib_source_location should have the value 201907L in c++2a" +#endif + +#endif // TEST_STD_VER > 17 + +int main(int, char**) { return 0; } diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.pass.cpp @@ -85,6 +85,7 @@ __cpp_lib_shared_ptr_arrays 201611L [C++17] __cpp_lib_shared_ptr_weak_type 201606L [C++17] __cpp_lib_shared_timed_mutex 201402L [C++14] + __cpp_lib_source_location 201907L [C++2a] __cpp_lib_span 202002L [C++2a] __cpp_lib_string_udls 201304L [C++14] __cpp_lib_string_view 201606L [C++17] @@ -392,6 +393,10 @@ # error "__cpp_lib_shared_timed_mutex should not be defined before c++14" # endif +#ifdef __cpp_lib_source_location +#error "__cpp_lib_source_location should not be defined before c++2a" +#endif + # ifdef __cpp_lib_span # error "__cpp_lib_span should not be defined before c++2a" # endif @@ -789,6 +794,10 @@ # endif # endif +#ifdef __cpp_lib_source_location +#error "__cpp_lib_source_location should not be defined before c++2a" +#endif + # ifdef __cpp_lib_span # error "__cpp_lib_span should not be defined before c++2a" # endif @@ -1390,6 +1399,10 @@ # endif # endif +#ifdef __cpp_lib_source_location +#error "__cpp_lib_source_location should not be defined before c++2a" +#endif + # ifdef __cpp_lib_span # error "__cpp_lib_span should not be defined before c++2a" # endif @@ -2129,6 +2142,13 @@ # endif # endif +#ifndef __cpp_lib_source_location +#error "__cpp_lib_source_location should be defined in c++2a" +#endif +#if __cpp_lib_source_location != 201907L +#error "__cpp_lib_source_location should have the value 201907L in c++2a" +#endif + # ifndef __cpp_lib_span # error "__cpp_lib_span should be defined in c++2a" # endif diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -591,6 +591,12 @@ }, "headers": ["array"], }, + {"name": "__cpp_lib_source_location", + "values": { + "c++2a": int(201907), + }, + "headers": ["source_location"], + }, {"name": "__cpp_lib_span", "values": { "c++2a": int(202002), diff --git a/libcxx/www/cxx2a_status.html b/libcxx/www/cxx2a_status.html --- a/libcxx/www/cxx2a_status.html +++ b/libcxx/www/cxx2a_status.html @@ -171,7 +171,7 @@ P1065LWGConstexpr INVOKECologne P1135LWGThe C++20 Synchronization LibraryCologneComplete P1207LWGMovability of Single-pass IteratorsCologne - P1208LWGAdopt source_location for C++20Cologne + P1208LWGAdopt source_location for C++20CologneComplete11.0 P1355LWGExposing a narrow contract for ceil2CologneComplete9.0 P1361LWGIntegration of chrono with text formattingCologne P1423LWGchar8_t backward compatibility remediationCologne