On Thu, Jan 2, 2020 at 5:07 PM Jakub Jelinek <ja...@redhat.com> wrote: > > On Thu, Jan 02, 2020 at 04:57:01PM -0500, JeanHeyd Meneide wrote: > > +#if defined(_GLIBCXX_HAVE_BUILTIN_SOURCE_LOCATION) > > +# define __cpp_lib_source_location 201907L > > +#elif defined(_GLIBCXX_HAVE_BUILTIN_LINE) && > > defined(_GLIBCXX_HAVE_BUILTIN_COLUMN) > > +# define __cpp_lib_is_constant_evaluated 201907L > > How is __cpp_lib_is_constant_evaluated related to presence of __builtin_LINE > and __builtin_COLUMN?
Oops. Sorry; fat-fingered the diff a little!
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in index ae4a493ea65..c104ffb28ab 100644 --- a/libstdc++-v3/include/Makefile.in +++ b/libstdc++-v3/include/Makefile.in @@ -414,6 +414,7 @@ std_headers = \ ${std_srcdir}/scoped_allocator \ ${std_srcdir}/set \ ${std_srcdir}/shared_mutex \ + ${std_srcdir}/source_location \ ${std_srcdir}/span \ ${std_srcdir}/sstream \ ${std_srcdir}/stack \ diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config index f983743b052..6ca431b24ee 100644 --- a/libstdc++-v3/include/bits/c++config +++ b/libstdc++-v3/include/bits/c++config @@ -630,6 +630,7 @@ namespace std #if __GNUC__ >= 7 // Assume these are available if the compiler claims to be a recent GCC: # define _GLIBCXX_HAVE_BUILTIN_HAS_UNIQ_OBJ_REP 1 # define _GLIBCXX_HAVE_BUILTIN_IS_AGGREGATE 1 # define _GLIBCXX_HAVE_BUILTIN_LAUNDER 1 @@ -637,6 +638,9 @@ namespace std # if __GNUC__ >= 9 # define _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED 1 # endif +# if __GNUC__ >= 10 +# define _GLIBCXX_HAVE_BUILTIN_SOURCE_LOCATION 1 +# endif #elif defined(__is_identifier) && defined(__has_builtin) // For non-GNU compilers: # if ! __is_identifier(__has_unique_object_representations) @@ -654,6 +658,15 @@ namespace std # if ! __is_identifier(__is_same) # define _GLIBCXX_BUILTIN_IS_SAME_AS(T, U) __is_same(T, U) # endif +# if __has_builtin(__builtin_source_location) +# define _GLIBCXX_HAVE_BUILTIN_SOURCE_LOCATION 1 +# endif #endif // GCC // PSTL configuration diff --git a/libstdc++-v3/include/std/source_location b/libstdc++-v3/include/std/source_location new file mode 100644 index 00000000000..4c805df0dfa --- /dev/null +++ b/libstdc++-v3/include/std/source_location @@ -0,0 +1,101 @@ +// Component for retrieving function, line and column source info. -*- C++ -*- + +// Copyright (C) 2019-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 +// <http://www.gnu.org/licenses/>. + +/** @file source_location + * This is a Standard C++ Library header. + */ + +// +// P1208 source_location library +// Contributed by ThePhD with <3 +// + +#ifndef _GLIBCXX_SOURCE_LOCATION +#define _GLIBCXX_SOURCE_LOCATION 1 + +#pragma GCC system_header + +#include <bits/c++config.h> +#include <cstdint> + +#if __cplusplus > 201703L +#ifdef _GLIBCXX_HAVE_BUILTIN_SOURCE_LOCATION + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#define __cpp_lib_source_location 201907L + + struct source_location + { + private: + struct __impl + { + const char *_M_file_name; + const char *_M_function_name; + unsigned int _M_line, _M_column; + }; + + public: + static consteval source_location + current (const void *__src_loc_impl = __builtin_source_location ()) noexcept + { + source_location __ret; + __ret._M_data = static_cast<const __impl *>(__src_loc_impl); + return __ret; + } + + constexpr + source_location () noexcept + : _M_data () + { } + + constexpr const char * + file_name () const noexcept + { return _M_data ? _M_data->_M_file_name : ""; } + + constexpr const char * + function_name () const noexcept + { return _M_data ? _M_data->_M_function_name : ""; } + + constexpr uint_least32_t + line () const noexcept + { return _M_data ? _M_data->_M_line : 0; } + + constexpr uint_least32_t + column () const noexcept + { return _M_data ? _M_data->_M_column : 0; } + + private: + const __impl *_M_data; + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // has __builtin_source_location +#endif // C++20 + +#endif // _GLIBCXX_SOURCE_LOCATION diff --git a/libstdc++-v3/include/std/version b/libstdc++-v3/include/std/version index ab8111468e4..e482c87ac36 100644 --- a/libstdc++-v3/include/std/version +++ b/libstdc++-v3/include/std/version @@ -196,6 +196,11 @@ #endif #define __cpp_lib_to_array 201907L #endif +#if defined(_GLIBCXX_HAVE_BUILTIN_SOURCE_LOCATION) +# define __cpp_lib_source_location 201907L +#endif #endif // C++2a #endif // C++17 #endif // C++14 diff --git a/libstdc++-v3/testsuite/std/support/srcloc/consteval.std.n4842.C b/libstdc++-v3/testsuite/std/support/srcloc/consteval.std.n4842.C new file mode 100644 index 00000000000..7c057b60e48 --- /dev/null +++ b/libstdc++-v3/testsuite/std/support/srcloc/consteval.std.n4842.C @@ -0,0 +1,147 @@ +// Copyright (C) 2019-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 +// <http://www.gnu.org/licenses/>. + +// 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 <source_location> +#include <string_view> + +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 std::source_location +g() +{ + std::source_location c = std::source_location::current(); + return f(c); +} + +#include "std.n4842.h" + +int main () +{ + constexpr std::source_location main_sl = std::source_location::current(); + constexpr std::source_location f_arg_sl = f(main_sl); + constexpr std::source_location g_sl = g(); + constexpr std::source_location f_sl = f(); + constexpr std::source_location h_sl = h(); + constexpr s member_main_sl(main_sl); + constexpr s member_defaulted_sl(1); + constexpr s member_sl = s{}; + + 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() == 55); + // 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("std.n4842.C"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() == 55); + // 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("std.n4842.C"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() == 47); + 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("std.n4842.C"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("std.n4842.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() == 55); + 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("std.n4842.C"sv)); + + // FIXME: All 3 cases below are busted + // Which is user-hostile, but right now + // constant evaluation evaluates the call immediately + // and without call stack information... + constexpr std::string_view member_defaulted_sl_fi_name( + member_defaulted_sl.member.file_name()); +#if 0 + constexpr std::string_view member_defaulted_sl_fn_name( + member_defaulted_sl.member.function_name()); + static_assert(member_defaulted_sl.member.line() == 35); + // closing paren of constructor declaration + static_assert(member_defaulted_sl.member.column() == 26); + static_assert(member_defaulted_sl_fn_name.ends_with("s::s"sv)); +#endif + static_assert(member_defaulted_sl_fi_name.ends_with("std.n4842.C"sv)); + + constexpr std::string_view member_sl_fi_name( + member_sl.member.file_name()); +#if 0 + constexpr std::string_view member_sl_fn_name( + member_sl.member.function_name()); + static_assert(member_sl.member.line() == 62); + // closing brace/paren of constructor + static_assert(member_sl.member.column() == 29); + static_assert(member_sl_fn_name.ends_with("main"sv)); +#endif + static_assert(member_sl_fi_name.ends_with("std.n4842.C"sv)); + + constexpr std::string_view f_sl_fi_name(f_sl.file_name()); +#if 0 + constexpr std::string_view f_sl_fn_name(f_sl.function_name()); + static_assert(f_sl.line() == 58); + // closing paren of call + static_assert(f_sl.column() == 43); + static_assert(f_sl_fn_name.ends_with("main"sv)); +#endif + static_assert(f_sl_fi_name.ends_with("std.n4842.C"sv)); + + return 0; +} diff --git a/libstdc++-v3/testsuite/std/support/srcloc/std.n4842.C b/libstdc++-v3/testsuite/std/support/srcloc/std.n4842.C new file mode 100644 index 00000000000..fecd79d139a --- /dev/null +++ b/libstdc++-v3/testsuite/std/support/srcloc/std.n4842.C @@ -0,0 +1,149 @@ +// Copyright (C) 2019-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 +// <http://www.gnu.org/licenses/>. + +// Example from C++ Standard Working Draft N4842, November 2019 Mailing +// Adapted for testing. + +// { dg-options "-std=gnu++2a" } +// { dg-do run { target c++2a } } + +#include <source_location> +#include <string_view> +#include <testsuite_hooks.h> +#include "std.n4842.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; } + +std::source_location +g() +{ + std::source_location c = std::source_location::current(); + return f(c); +} + +int main () +{ + std::source_location main_sl = std::source_location::current(); + std::source_location f_arg_sl = f(main_sl); + std::source_location g_sl = g(); + std::source_location f_sl = f(); + std::source_location h_sl = h(); + s member_main_sl(main_sl); + s member_defaulted_sl(1); + s member_sl = s{}; + + 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() == 58); + // 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("std.n4842.C"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() == 58); + // 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("std.n4842.C"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() == 52); + 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("std.n4842.C"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("std.n4842.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() == 58); + 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("std.n4842.C"sv)); + + // FIXME: the following cases are all busted + // despite the standard giving examples to the contrary. + // Unfortunately GCC's constant folder / evaluator + // (and the standard's) manifestly constant evaluates + // default arguments, and at that point GCC has no + // call stack information for anyone to + // produce additional information. + // It will require extra work to make these work with it. + std::string_view member_defaulted_sl_fi_name( + member_defaulted_sl.member.file_name()); +#if 0 + std::string_view member_defaulted_sl_fn_name( + member_defaulted_sl.member.function_name()); + VERIFY(member_defaulted_sl.member.line() == 37); + // closing paren of constructor declaration + VERIFY(member_defaulted_sl.member.column() == 26); + VERIFY(member_defaulted_sl_fn_name.ends_with("s::s"sv)); +#endif + VERIFY(member_defaulted_sl_fi_name.ends_with("std.n4842.C"sv)); + + std::string_view member_sl_fi_name( + member_sl.member.file_name()); +#if 0 + std::string_view member_sl_fn_name( + member_sl.member.function_name()); + VERIFY(member_sl.member.line() == 62); + // closing brace/paren of constructor + VERIFY(member_sl.member.column() == 29); + VERIFY(member_sl_fn_name.ends_with("main"sv)); +#endif + VERIFY(member_sl_fi_name.ends_with("std.n4842.C"sv)); + + std::string_view f_sl_fi_name(f_sl.file_name()); +#if 0 + std::string_view f_sl_fn_name(f_sl.function_name()); + VERIFY(f_sl.line() == 58); + // closing paren of call + VERIFY(f_sl.column() == 43); + VERIFY(f_sl_fn_name.ends_with("main"sv)); +#endif + VERIFY(f_sl_fi_name.ends_with("std.n4842.C"sv)); + + return 0; +} diff --git a/libstdc++-v3/testsuite/std/support/srcloc/std.n4842.h b/libstdc++-v3/testsuite/std/support/srcloc/std.n4842.h new file mode 100644 index 00000000000..50ff5c41bea --- /dev/null +++ b/libstdc++-v3/testsuite/std/support/srcloc/std.n4842.h @@ -0,0 +1,25 @@ +// Copyright (C) 2019 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 +// <http://www.gnu.org/licenses/>. + +#include <source_location> + +constexpr std::source_location +h () +{ + std::source_location a = std::source_location::current(); + return a; +}