From: JeanHeyd Meneide Date: Thu, 3 Dec 2020 19:17:13 +0000 (+0000) Subject: libtdc++: Define std::source_location for C++20 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=57d76ee9cf6265e012fad6286adfaeaba9414c11;p=gcc.git libtdc++: Define std::source_location for C++20 This doesn't define a new _GLIBCXX_HAVE_BUILTIN_SOURCE_LOCATION macro. because using __has_builtin(__builtin_source_location) is sufficient. Currently only GCC supports it, but if/when Clang and Intel add it the __has_builtin check should for them too. Co-authored-by: Jonathan Wakely libstdc++-v3/ChangeLog: * doc/doxygen/user.cfg.in (INPUT): Add . * include/Makefile.am: Add . * include/Makefile.in: Regenerate. * include/std/version (__cpp_lib_source_location): Define. * include/std/source_location: New file. * testsuite/18_support/source_location/1.cc: New test. * testsuite/18_support/source_location/consteval.cc: New test. * testsuite/18_support/source_location/srcloc.h: New test. * testsuite/18_support/source_location/version.cc: New test. --- diff --git a/libstdc++-v3/doc/doxygen/user.cfg.in b/libstdc++-v3/doc/doxygen/user.cfg.in index 1966055e675..2261d572efb 100644 --- a/libstdc++-v3/doc/doxygen/user.cfg.in +++ b/libstdc++-v3/doc/doxygen/user.cfg.in @@ -891,6 +891,7 @@ INPUT = @srcdir@/doc/doxygen/doxygroups.cc \ include/semaphore \ include/set \ include/shared_mutex \ + include/source_location \ include/span \ include/sstream \ include/stack \ diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am index ca413b8fdfe..9dbc7dcb32d 100644 --- a/libstdc++-v3/include/Makefile.am +++ b/libstdc++-v3/include/Makefile.am @@ -73,6 +73,7 @@ std_headers = \ ${std_srcdir}/semaphore \ ${std_srcdir}/set \ ${std_srcdir}/shared_mutex \ + ${std_srcdir}/source_location \ ${std_srcdir}/span \ ${std_srcdir}/sstream \ ${std_srcdir}/syncstream \ diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index ef2dc18965b..0cb0fdf5ef1 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -419,6 +419,7 @@ std_headers = \ ${std_srcdir}/semaphore \ ${std_srcdir}/set \ ${std_srcdir}/shared_mutex \ + ${std_srcdir}/source_location \ ${std_srcdir}/span \ ${std_srcdir}/sstream \ ${std_srcdir}/syncstream \ diff --git a/libstdc++-v3/include/std/source_location b/libstdc++-v3/include/std/source_location new file mode 100644 index 00000000000..13d4bd48857 --- /dev/null +++ b/libstdc++-v3/include/std/source_location @@ -0,0 +1,92 @@ +// -*- C++ -*- + +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/source_location + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_SRCLOC +#define _GLIBCXX_SRCLOC 1 + +#if __cplusplus > 201703L && __has_builtin(__builtin_source_location) +#include + +namespace std +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#define __cpp_lib_source_location 201907L + + /// A class that describes a location in source code. + struct source_location + { + private: + using uint_least32_t = __UINT_LEAST32_TYPE__; + + public: + + // [support.srcloc.cons], creation + static consteval source_location + current(const void* __p = __builtin_source_location()) noexcept + { + source_location __ret; + __ret._M_impl = static_cast (__p); + return __ret; + } + + constexpr source_location() noexcept { } + + // [support.srcloc.obs], observers + constexpr uint_least32_t + line() const noexcept + { return _M_impl ? _M_impl->_M_line : 0u; } + + constexpr uint_least32_t + column() const noexcept + { return _M_impl ? _M_impl->_M_column : 0u; } + + constexpr const char* + file_name() const noexcept + { return _M_impl ? _M_impl->_M_file_name : ""; } + + constexpr const char* + function_name() const noexcept + { return _M_impl ? _M_impl->_M_function_name : ""; } + + private: + struct __impl + { + const char* _M_file_name; + const char* _M_function_name; + unsigned _M_line; + unsigned _M_column; + }; + + const __impl* _M_impl = nullptr; + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 && __builtin_source_location +#endif // _GLIBCXX_SRCLOC diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version index 6e4bd99b361..e4a8bed52ab 100644 --- a/libstdc++-v3/include/std/version +++ b/libstdc++-v3/include/std/version @@ -238,6 +238,9 @@ # define __cpp_lib_semaphore 201907L #endif #define __cpp_lib_shift 201806L +#if __has_builtin(__builtin_source_location) +# define __cpp_lib_source_location 201907L +#endif #if __cpp_lib_concepts # define __cpp_lib_span 202002L #endif diff --git a/libstdc++-v3/testsuite/18_support/source_location/1.cc b/libstdc++-v3/testsuite/18_support/source_location/1.cc new file mode 100644 index 00000000000..c945aaa4d97 --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/source_location/1.cc @@ -0,0 +1,155 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// Example from C++ Standard Working Draft N4842, November 2019 Mailing +// Adapted for testing. + +// { dg-options "-std=gnu++2a -include string -include stdexcept" } +// { dg-do run { target c++2a } } + +#include + +#ifndef __cpp_lib_source_location +# error "Feature-test macro for source_location missing in " +#elif __cpp_lib_source_location != 201907L +# error "Feature-test macro for source_location has wrong value in " +#endif + +#include +#include +#include "srcloc.h" + + +struct s { + std::source_location member = std::source_location::current(); + int other_member = 1; + + s(std::source_location loc = std::source_location::current()) + : member(loc) // values of member refer to calling function + { } + + s(int blather) : // values of member refer to this location + other_member(blather) + { } +}; + +std::source_location +f(std::source_location a = std::source_location::current()); + +std::source_location +f(std::source_location a) +{ return a; } + +auto +g() +{ + struct srcloc_and_line + { + std::source_location sl; + unsigned line; + }; + + std::source_location c = std::source_location::current(); + return srcloc_and_line{ f(c), __LINE__ - 1 }; +} + +int main () +{ + std::source_location main_sl = std::source_location::current(); + unsigned main_sl_line = __LINE__ - 1; + std::source_location f_arg_sl = f(main_sl); + unsigned f_arg_sl_line = main_sl_line; + auto [g_sl, g_sl_line] = g(); + std::source_location f_sl = f(); + unsigned f_sl_line = __LINE__ - 1; + std::source_location h_sl = h(); // defined in ./srcloc.h + s member_main_sl(main_sl); + s member_defaulted_sl(1); + s member_sl = s{}; + const unsigned member_sl_line = __LINE__ - 1; + + using namespace std::string_view_literals; + + std::string_view main_sl_fn_name(main_sl.function_name()); + std::string_view main_sl_fi_name(main_sl.file_name()); + VERIFY(main_sl.line() == main_sl_line); + // closing paren of call + VERIFY(main_sl.column() == 64); + VERIFY(main_sl_fn_name.ends_with("main"sv)); + VERIFY(main_sl_fi_name.ends_with("1.cc"sv)); + + std::string_view f_arg_sl_fn_name(f_arg_sl.function_name()); + std::string_view f_arg_sl_fi_name(f_arg_sl.file_name()); + VERIFY(f_arg_sl.line() == f_arg_sl_line); + // closing paren of call + VERIFY(f_arg_sl.column() == 64); + VERIFY(f_arg_sl_fn_name.ends_with("main"sv)); + VERIFY(f_arg_sl_fi_name.ends_with("1.cc"sv)); + + std::string_view g_sl_fn_name(g_sl.function_name()); + std::string_view g_sl_fi_name(g_sl.file_name()); + VERIFY(g_sl.line() == g_sl_line); + VERIFY(g_sl.column() == 58); // closing paren of call + VERIFY(g_sl_fn_name.ends_with("g"sv)); + VERIFY(g_sl_fi_name.ends_with("1.cc"sv)); + + std::string_view h_sl_fn_name(h_sl.function_name()); + std::string_view h_sl_fi_name(h_sl.file_name()); + VERIFY(h_sl.line() == 23); + VERIFY(h_sl.column() == 58); // closing paren of call + VERIFY(h_sl_fn_name.ends_with("h"sv)); + VERIFY(h_sl_fi_name.ends_with("srcloc.h"sv)); + + std::string_view member_main_sl_fn_name(member_main_sl.member.function_name()); + std::string_view member_main_sl_fi_name(member_main_sl.member.file_name()); + VERIFY(member_main_sl.member.line() == main_sl_line); + VERIFY(member_main_sl.member.column() == 64); + VERIFY(member_main_sl_fn_name.ends_with("main"sv)); + VERIFY(member_main_sl_fi_name.ends_with("1.cc"sv)); + + std::string_view member_defaulted_sl_fi_name( + member_defaulted_sl.member.file_name()); + std::string_view member_defaulted_sl_fn_name( + member_defaulted_sl.member.function_name()); + VERIFY(member_defaulted_sl.member.line() == 46); + // closing paren of constructor declaration + VERIFY(member_defaulted_sl.member.column() == 25); +#if 0 + VERIFY(member_defaulted_sl_fn_name.starts_with("s::s(int)"sv)); +#endif + VERIFY(member_defaulted_sl_fi_name.ends_with("1.cc"sv)); + + std::string_view member_sl_fi_name( + member_sl.member.file_name()); + std::string_view member_sl_fn_name( + member_sl.member.function_name()); + VERIFY(member_sl.member.line() == member_sl_line); + // closing brace/paren of constructor + VERIFY(member_sl.member.column() == 19); + VERIFY(member_sl_fn_name.starts_with("main"sv)); + VERIFY(member_sl_fi_name.ends_with("1.cc"sv)); + + std::string_view f_sl_fi_name(f_sl.file_name()); + std::string_view f_sl_fn_name(f_sl.function_name()); + VERIFY(f_sl.line() == f_sl_line); + // closing paren of call + VERIFY(f_sl.column() == 33); + VERIFY(f_sl_fn_name.ends_with("main"sv)); + VERIFY(f_sl_fi_name.ends_with("1.cc"sv)); + + return 0; +} diff --git a/libstdc++-v3/testsuite/18_support/source_location/consteval.cc b/libstdc++-v3/testsuite/18_support/source_location/consteval.cc new file mode 100644 index 00000000000..9b137f8641d --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/source_location/consteval.cc @@ -0,0 +1,149 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// Example from C++ Standard Working Draft N4842, November 2019 Mailing +// Adapted for testing. + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include +#include + +struct s { + std::source_location member = std::source_location::current(); + int other_member = 1; + + constexpr s(std::source_location loc = std::source_location::current()) + : member(loc) // values of member refer to calling function + { } + + constexpr s(int blather) : // values of member refer to this location + other_member(blather) + { } +}; + +constexpr std::source_location +f(std::source_location a = std::source_location::current()) +{ return a; } + +constexpr auto +g() +{ + struct srcloc_and_line + { + std::source_location sl; + unsigned line; + }; + + std::source_location c = std::source_location::current(); + return srcloc_and_line{ f(c), __LINE__ - 1 }; +} + +#include "srcloc.h" + +int main () +{ + constexpr std::source_location main_sl = std::source_location::current(); + constexpr unsigned main_sl_line = __LINE__ - 1; + constexpr std::source_location f_arg_sl = f(main_sl); + constexpr unsigned f_arg_sl_line = main_sl_line; + constexpr std::source_location g_sl = g().sl; + constexpr unsigned g_sl_line = g().line; + constexpr std::source_location f_sl = f(); + constexpr unsigned f_sl_line = __LINE__ - 1; + constexpr std::source_location h_sl = h(); // defined in ./srcloc.h + constexpr s member_main_sl(main_sl); + constexpr s member_defaulted_sl(1); + constexpr s member_sl = s{}; + constexpr unsigned member_sl_line = __LINE__ - 1; + + using namespace std::string_view_literals; + + static_assert (std::source_location::current ().line () == __LINE__); + static_assert (std::source_location::current ().column () == 49); + + + constexpr std::string_view main_sl_fn_name(main_sl.function_name()); + constexpr std::string_view main_sl_fi_name(main_sl.file_name()); + static_assert(main_sl.line() == main_sl_line); + // closing paren of call + static_assert(main_sl.column() == 74); + static_assert(main_sl_fn_name.ends_with("main"sv)); + static_assert(main_sl_fi_name.ends_with("consteval.cc"sv)); + + constexpr std::string_view f_arg_sl_fn_name(f_arg_sl.function_name()); + constexpr std::string_view f_arg_sl_fi_name(f_arg_sl.file_name()); + static_assert(f_arg_sl.line() == f_arg_sl_line); + // closing paren of call + static_assert(f_arg_sl.column() == 74); + static_assert(f_arg_sl_fn_name.ends_with("main"sv)); + static_assert(f_arg_sl_fi_name.ends_with("consteval.cc"sv)); + + constexpr std::string_view g_sl_fn_name(g_sl.function_name()); + constexpr std::string_view g_sl_fi_name(g_sl.file_name()); + static_assert(g_sl.line() == g_sl_line); + static_assert(g_sl.column() == 58); // closing paren of call + static_assert(g_sl_fn_name.ends_with("g"sv)); + static_assert(g_sl_fi_name.ends_with("consteval.cc"sv)); + + constexpr std::string_view h_sl_fn_name(h_sl.function_name()); + constexpr std::string_view h_sl_fi_name(h_sl.file_name()); + static_assert(h_sl.line() == 23); + static_assert(h_sl.column() == 58); // closing paren of call + static_assert(h_sl_fn_name.ends_with("h"sv)); + static_assert(h_sl_fi_name.ends_with("srcloc.h"sv)); + + constexpr std::string_view member_main_sl_fn_name(member_main_sl.member.function_name()); + constexpr std::string_view member_main_sl_fi_name(member_main_sl.member.file_name()); + static_assert(member_main_sl.member.line() == main_sl_line); + static_assert(member_main_sl.member.column() == 74); + static_assert(member_main_sl_fn_name.ends_with("main"sv)); + static_assert(member_main_sl_fi_name.ends_with("consteval.cc"sv)); + + constexpr std::string_view member_defaulted_sl_fi_name( + member_defaulted_sl.member.file_name()); + constexpr std::string_view member_defaulted_sl_fn_name( + member_defaulted_sl.member.function_name()); + static_assert(member_defaulted_sl.member.line() == 36); + // closing paren of constructor declaration + static_assert(member_defaulted_sl.member.column() == 25); +#if 0 + static_assert(member_defaulted_sl_fn_name.ends_with("s::s(int)"sv)); +#endif + static_assert(member_defaulted_sl_fi_name.ends_with("consteval.cc"sv)); + + constexpr std::string_view member_sl_fi_name( + member_sl.member.file_name()); + constexpr std::string_view member_sl_fn_name( + member_sl.member.function_name()); + static_assert(member_sl.member.line() == member_sl_line); + // closing brace/paren of constructor + static_assert(member_sl.member.column() == 29); + static_assert(member_sl_fn_name.starts_with("main"sv)); + static_assert(member_sl_fi_name.ends_with("consteval.cc"sv)); + + constexpr std::string_view f_sl_fi_name(f_sl.file_name()); + constexpr std::string_view f_sl_fn_name(f_sl.function_name()); + static_assert(f_sl.line() == f_sl_line); + // closing paren of call + static_assert(f_sl.column() == 43); + static_assert(f_sl_fn_name.ends_with("main"sv)); + static_assert(f_sl_fi_name.ends_with("consteval.cc"sv)); + + return 0; +} diff --git a/libstdc++-v3/testsuite/18_support/source_location/srcloc.h b/libstdc++-v3/testsuite/18_support/source_location/srcloc.h new file mode 100644 index 00000000000..9b05458ee2f --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/source_location/srcloc.h @@ -0,0 +1,25 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +#include + +constexpr std::source_location +h() +{ + std::source_location a = std::source_location::current(); + return a; +} diff --git a/libstdc++-v3/testsuite/18_support/source_location/version.cc b/libstdc++-v3/testsuite/18_support/source_location/version.cc new file mode 100644 index 00000000000..f2b3bf6fa1e --- /dev/null +++ b/libstdc++-v3/testsuite/18_support/source_location/version.cc @@ -0,0 +1,27 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License along +// with this library; see the file COPYING3. If not see +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do preprocess { target c++2a } } + +#include + +#ifndef __cpp_lib_source_location +# error "Feature-test macro for source_location missing in " +#elif __cpp_lib_source_location != 201907L +# error "Feature-test macro for source_location has wrong value in " +#endif