diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -200,6 +200,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 @@ -99,6 +99,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 @@ -238,6 +239,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 @@ -110,6 +110,7 @@ #ifndef _LIBCPP_HAS_NO_THREADS #include #endif +#include #include #include #include diff --git a/libcxx/test/libcxx/language.support/support.srcloc/source_location.pass.cpp b/libcxx/test/libcxx/language.support/support.srcloc/source_location.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/libcxx/language.support/support.srcloc/source_location.pass.cpp @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// UNSUPPORTED: clang-8, clang-7, clang-6 + +// + +// source_location::source_location(); + +#include +#include +#include + +#include "test_macros.h" + +constexpr 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; +} + +int main(int, char**) { + test(); + static_assert(test()); + + 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 @@ -86,6 +86,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] @@ -393,6 +394,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 @@ -790,6 +795,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 @@ -1397,6 +1406,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 @@ -2142,6 +2155,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/test/std/language.support/support.srcloc/class/source_location.pass.cpp b/libcxx/test/std/language.support/support.srcloc/class/source_location.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.srcloc/class/source_location.pass.cpp @@ -0,0 +1,56 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// UNSUPPORTED: clang-8, clang-7, clang-6 + +// + +// source_location::source_location(); + +#include +#include +#include +#include + +#include "test_macros.h" + +constexpr bool test() { + static_assert(std::is_nothrow_move_constructible_v, + "support.srcloc.cons (1.1)"); + static_assert(std::is_nothrow_move_assignable_v, + "support.srcloc.cons (1.2)"); + static_assert(std::is_nothrow_swappable_v, + "support.srcloc.cons (1.3)"); + + using SV = std::string_view; + + const std::source_location loc1 = std::source_location::current(); + + std::source_location loc2 = loc1; + assert(loc1.line() == loc2.line()); // (3.1) + assert(loc1.column() == loc2.column()); // (3.2) + assert(SV{loc1.file_name()} == SV{loc2.file_name()}); // (3.3) + assert(SV{loc1.function_name()} == SV{loc2.function_name()}); // (3.4) + + std::source_location loc3 = std::move(loc2); + assert(SV{loc1.file_name()} == SV{loc3.file_name()}); // (3.1) + assert(SV{loc1.function_name()} == SV{loc3.function_name()}); // (3.2) + assert(loc1.line() == loc3.line()); // (3.3) + assert(loc1.column() == loc3.column()); // (3.4) + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/language.support/support.srcloc/cons/current.pass.cpp b/libcxx/test/std/language.support/support.srcloc/cons/current.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.srcloc/cons/current.pass.cpp @@ -0,0 +1,93 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// UNSUPPORTED: clang-8, clang-7, clang-6 + +// + +// source_location::current(); + +#include +#include +#include + +#include "test_macros.h" + +using srcloc = std::source_location; + +struct s { + srcloc member = srcloc::current(); + int other_member{}; + + constexpr s(srcloc loc = srcloc::current()) + : member{loc} + // values of member refer to the location of the calling function ([dcl.fct.default]) + {} + + static constexpr srcloc before_int_ctor = srcloc::current(); + constexpr s(int blather) + : other_member(blather) // values of member refer to this location + {} + static constexpr srcloc after_int_ctor = srcloc::current(); + + static constexpr srcloc before_double_ctor = srcloc::current(); + constexpr s(double) // values of member refer to this location + {} + static constexpr srcloc after_double_ctor = srcloc::current(); +}; + +constexpr bool test_member() { + srcloc before = srcloc::current(); + s s_srcloc; + srcloc after = srcloc::current(); + assert(s_srcloc.member.line() > before.line()); + assert(s_srcloc.member.line() < after.line()); + + s s_int(int{}); + assert(s_int.member.line() > s::before_int_ctor.line()); + assert(s_int.member.line() < s::after_int_ctor.line()); + // clang returns ctor name location + // gcc returns end of initializer list location + + s s_double(double{}); + assert(s_double.member.line() > s::before_double_ctor.line()); + assert(s_double.member.line() < s::after_double_ctor.line()); + // clang returns ctor name location + // gcc returns opening brace location + + return true; +} + +constexpr bool test_parameter(srcloc loc = srcloc::current()) { + using SV = std::string_view; + + assert(loc.line() > __LINE__); // In test(). + // We do not test column here, as gcc always sets it to 0. + assert(SV{loc.file_name()}.ends_with("current.pass.cpp")); + assert(SV{loc.function_name()} == "test"); + + ASSERT_NOEXCEPT(srcloc::current()); + + return true; +} + +constexpr bool test() { + test_parameter(); + test_member(); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/language.support/support.srcloc/obs/column.pass.cpp b/libcxx/test/std/language.support/support.srcloc/obs/column.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.srcloc/obs/column.pass.cpp @@ -0,0 +1,43 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// GCC does not have __builtin_COLUMN. +// UNSUPPORTED: gcc-10, gcc-9, gcc-8 +// UNSUPPORTED: clang-8, clang-7, clang-6 + +// + +// source_location::column(); + +#include +#include + +#include "test_macros.h" + +constexpr 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); + + ASSERT_NOEXCEPT(loc1.column()); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/language.support/support.srcloc/obs/file_name.pass.cpp b/libcxx/test/std/language.support/support.srcloc/obs/file_name.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.srcloc/obs/file_name.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// UNSUPPORTED: clang-8, clang-7, clang-6 + +// + +// source_location::file_name(); + +#include +#include +#include + +#include "test_macros.h" + +constexpr bool test() { + using SV = std::string_view; + + std::source_location loc = std::source_location::current(); + assert(SV{loc.file_name()}.ends_with("file_name.pass.cpp")); + + ASSERT_NOEXCEPT(loc.file_name()); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/language.support/support.srcloc/obs/function_name.pass.cpp b/libcxx/test/std/language.support/support.srcloc/obs/function_name.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.srcloc/obs/function_name.pass.cpp @@ -0,0 +1,39 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// UNSUPPORTED: clang-8, clang-7, clang-6 + +// + +// source_location::function_name(); + +#include +#include +#include + +#include "test_macros.h" + +constexpr bool test() { + using SV = std::string_view; + + std::source_location loc = std::source_location::current(); + assert(SV{loc.function_name()} == "test"); + + ASSERT_NOEXCEPT(loc.function_name()); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} diff --git a/libcxx/test/std/language.support/support.srcloc/obs/line.pass.cpp b/libcxx/test/std/language.support/support.srcloc/obs/line.pass.cpp new file mode 100644 --- /dev/null +++ b/libcxx/test/std/language.support/support.srcloc/obs/line.pass.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// 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 + +// UNSUPPORTED: clang-8, clang-7, clang-6 + +// + +// source_location::line(); + +#include +#include + +#include "test_macros.h" + +constexpr bool +test_caller(std::source_location loc = std::source_location::current()) { + assert(loc.line() > __LINE__); + + return true; +} + +constexpr 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(); + + ASSERT_NOEXCEPT(loc1.line()); + + return true; +} + +int main(int, char**) { + test(); + static_assert(test()); + + return 0; +} 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 @@ -593,6 +593,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