* [PATCH 1/2] Update ax_cv_cxx_compile_cxx.m4
@ 2018-03-17 23:49 Simon Marchi
2018-03-17 23:49 ` [PATCH 2/2] Add gdb::string_view Simon Marchi
0 siblings, 1 reply; 5+ messages in thread
From: Simon Marchi @ 2018-03-17 23:49 UTC (permalink / raw)
To: gdb-patches; +Cc: Simon Marchi
This file provides the AX_CXX_COMPILE_STDCXX macro. In the context of
the following patch, I wanted to build and test GDB in c++17 mode. The
version of the macro we have in the repo does not support detecting
c++17 compilers, but the upstream version has been updated to do so.
Since we have local modifications to the file, I had to reconcile our
modifications and the updated upstream version (which was relatively
straightforward).
gdb/ChangeLog:
* ax_cxx_compile_stdcxx.m4: Sync with upstream.
* configure: Re-generate.
---
gdb/ax_cxx_compile_stdcxx.m4 | 458 +++++++++++++++++++++++++++++++++++++++++--
gdb/configure | 28 +--
2 files changed, 455 insertions(+), 31 deletions(-)
diff --git a/gdb/ax_cxx_compile_stdcxx.m4 b/gdb/ax_cxx_compile_stdcxx.m4
index 444799a64678..9a9e9e713a53 100644
--- a/gdb/ax_cxx_compile_stdcxx.m4
+++ b/gdb/ax_cxx_compile_stdcxx.m4
@@ -8,7 +8,7 @@
# - AC_SUBST CXX_DIALECT instead of changing CXX/CXXCPP.
#
# ===========================================================================
-# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
+# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
# ===========================================================================
#
# SYNOPSIS
@@ -42,21 +42,22 @@
# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
# Copyright (c) 2015 Paul Norman <penorman@mac.com>
# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
+# Copyright (c) 2016 Krzesimir Nowak <qdlacz@gmail.com>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
-#serial 4
+#serial 8
dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
dnl (serial version number 13).
AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
- m4_if([$1], [11], [],
- [$1], [14], [],
- [$1], [17], [m4_fatal([support for C++17 not yet implemented in AX_CXX_COMPILE_STDCXX])],
+ m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
+ [$1], [14], [ax_cxx_compile_alternatives="14 1y"],
+ [$1], [17], [ax_cxx_compile_alternatives="17 1z"],
[m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
m4_if([$2], [], [],
[$2], [ext], [],
@@ -80,7 +81,8 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
m4_if([$2], [noext], [], [dnl
if test x$ac_success = xno; then
- for switch in -std=gnu++$1 -std=gnu++0x; do
+ for alternative in ${ax_cxx_compile_alternatives}; do
+ switch="-std=gnu++${alternative}"
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
$cachevar,
@@ -103,19 +105,24 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
dnl HP's aCC needs +std=c++11 according to:
dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
dnl Cray's crayCC needs "-h std=c++11"
- for switch in -std=c++$1 -std=c++0x +std=c++$1 "-h std=c++$1"; do
- cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
- AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
- $cachevar,
- [ac_save_CXX="$CXX"
- CXX="$CXX $switch"
- AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
- [eval $cachevar=yes],
- [eval $cachevar=no])
- CXX="$ac_save_CXX"])
- if eval test x\$$cachevar = xyes; then
- CXX_DIALECT="$switch"
- ac_success=yes
+ for alternative in ${ax_cxx_compile_alternatives}; do
+ for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do
+ cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
+ AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
+ $cachevar,
+ [ac_save_CXX="$CXX"
+ CXX="$CXX $switch"
+ AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+ [eval $cachevar=yes],
+ [eval $cachevar=no])
+ CXX="$ac_save_CXX"])
+ if eval test x\$$cachevar = xyes; then
+ CXX_DIALECT="$switch"
+ ac_success=yes
+ break
+ fi
+ done
+ if test x$ac_success = xyes; then
break
fi
done
@@ -153,6 +160,11 @@ m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
)
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
+ _AX_CXX_COMPILE_STDCXX_testbody_new_in_17
+)
dnl Tests for new features in C++11
@@ -523,7 +535,7 @@ namespace cxx14
}
- namespace test_digit_seperators
+ namespace test_digit_separators
{
constexpr auto ten_million = 100'000'000;
@@ -565,3 +577,409 @@ namespace cxx14
#endif // __cplusplus >= 201402L
]])
+
+
+dnl Tests for new features in C++17
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[
+
+// If the compiler admits that it is not ready for C++17, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus <= 201402L
+
+#error "This is not a C++17 compiler"
+
+#else
+
+#if defined(__clang__)
+ #define REALLY_CLANG
+#else
+ #if defined(__GNUC__)
+ #define REALLY_GCC
+ #endif
+#endif
+
+#include <initializer_list>
+#include <utility>
+#include <type_traits>
+
+namespace cxx17
+{
+
+#if !defined(REALLY_CLANG)
+ namespace test_constexpr_lambdas
+ {
+
+ // TODO: test it with clang++ from git
+
+ constexpr int foo = [](){return 42;}();
+
+ }
+#endif // !defined(REALLY_CLANG)
+
+ namespace test::nested_namespace::definitions
+ {
+
+ }
+
+ namespace test_fold_expression
+ {
+
+ template<typename... Args>
+ int multiply(Args... args)
+ {
+ return (args * ... * 1);
+ }
+
+ template<typename... Args>
+ bool all(Args... args)
+ {
+ return (args && ...);
+ }
+
+ }
+
+ namespace test_extended_static_assert
+ {
+
+ static_assert (true);
+
+ }
+
+ namespace test_auto_brace_init_list
+ {
+
+ auto foo = {5};
+ auto bar {5};
+
+ static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);
+ static_assert(std::is_same<int, decltype(bar)>::value);
+ }
+
+ namespace test_typename_in_template_template_parameter
+ {
+
+ template<template<typename> typename X> struct D;
+
+ }
+
+ namespace test_fallthrough_nodiscard_maybe_unused_attributes
+ {
+
+ int f1()
+ {
+ return 42;
+ }
+
+ [[nodiscard]] int f2()
+ {
+ [[maybe_unused]] auto unused = f1();
+
+ switch (f1())
+ {
+ case 17:
+ f1();
+ [[fallthrough]];
+ case 42:
+ f1();
+ }
+ return f1();
+ }
+
+ }
+
+ namespace test_extended_aggregate_initialization
+ {
+
+ struct base1
+ {
+ int b1, b2 = 42;
+ };
+
+ struct base2
+ {
+ base2() {
+ b3 = 42;
+ }
+ int b3;
+ };
+
+ struct derived : base1, base2
+ {
+ int d;
+ };
+
+ derived d1 {{1, 2}, {}, 4}; // full initialization
+ derived d2 {{}, {}, 4}; // value-initialized bases
+
+ }
+
+ namespace test_general_range_based_for_loop
+ {
+
+ struct iter
+ {
+ int i;
+
+ int& operator* ()
+ {
+ return i;
+ }
+
+ const int& operator* () const
+ {
+ return i;
+ }
+
+ iter& operator++()
+ {
+ ++i;
+ return *this;
+ }
+ };
+
+ struct sentinel
+ {
+ int i;
+ };
+
+ bool operator== (const iter& i, const sentinel& s)
+ {
+ return i.i == s.i;
+ }
+
+ bool operator!= (const iter& i, const sentinel& s)
+ {
+ return !(i == s);
+ }
+
+ struct range
+ {
+ iter begin() const
+ {
+ return {0};
+ }
+
+ sentinel end() const
+ {
+ return {5};
+ }
+ };
+
+ void f()
+ {
+ range r {};
+
+ for (auto i : r)
+ {
+ [[maybe_unused]] auto v = i;
+ }
+ }
+
+ }
+
+ namespace test_lambda_capture_asterisk_this_by_value
+ {
+
+ struct t
+ {
+ int i;
+ int foo()
+ {
+ return [*this]()
+ {
+ return i;
+ }();
+ }
+ };
+
+ }
+
+ namespace test_enum_class_construction
+ {
+
+ enum class byte : unsigned char
+ {};
+
+ byte foo {42};
+
+ }
+
+ namespace test_constexpr_if
+ {
+
+ template <bool cond>
+ int f ()
+ {
+ if constexpr(cond)
+ {
+ return 13;
+ }
+ else
+ {
+ return 42;
+ }
+ }
+
+ }
+
+ namespace test_selection_statement_with_initializer
+ {
+
+ int f()
+ {
+ return 13;
+ }
+
+ int f2()
+ {
+ if (auto i = f(); i > 0)
+ {
+ return 3;
+ }
+
+ switch (auto i = f(); i + 4)
+ {
+ case 17:
+ return 2;
+
+ default:
+ return 1;
+ }
+ }
+
+ }
+
+#if !defined(REALLY_CLANG)
+ namespace test_template_argument_deduction_for_class_templates
+ {
+
+ // TODO: test it with clang++ from git
+
+ template <typename T1, typename T2>
+ struct pair
+ {
+ pair (T1 p1, T2 p2)
+ : m1 {p1},
+ m2 {p2}
+ {}
+
+ T1 m1;
+ T2 m2;
+ };
+
+ void f()
+ {
+ [[maybe_unused]] auto p = pair{13, 42u};
+ }
+
+ }
+#endif // !defined(REALLY_CLANG)
+
+ namespace test_non_type_auto_template_parameters
+ {
+
+ template <auto n>
+ struct B
+ {};
+
+ B<5> b1;
+ B<'a'> b2;
+
+ }
+
+#if !defined(REALLY_CLANG)
+ namespace test_structured_bindings
+ {
+
+ // TODO: test it with clang++ from git
+
+ int arr[2] = { 1, 2 };
+ std::pair<int, int> pr = { 1, 2 };
+
+ auto f1() -> int(&)[2]
+ {
+ return arr;
+ }
+
+ auto f2() -> std::pair<int, int>&
+ {
+ return pr;
+ }
+
+ struct S
+ {
+ int x1 : 2;
+ volatile double y1;
+ };
+
+ S f3()
+ {
+ return {};
+ }
+
+ auto [ x1, y1 ] = f1();
+ auto& [ xr1, yr1 ] = f1();
+ auto [ x2, y2 ] = f2();
+ auto& [ xr2, yr2 ] = f2();
+ const auto [ x3, y3 ] = f3();
+
+ }
+#endif // !defined(REALLY_CLANG)
+
+#if !defined(REALLY_CLANG)
+ namespace test_exception_spec_type_system
+ {
+
+ // TODO: test it with clang++ from git
+
+ struct Good {};
+ struct Bad {};
+
+ void g1() noexcept;
+ void g2();
+
+ template<typename T>
+ Bad
+ f(T*, T*);
+
+ template<typename T1, typename T2>
+ Good
+ f(T1*, T2*);
+
+ static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);
+
+ }
+#endif // !defined(REALLY_CLANG)
+
+ namespace test_inline_variables
+ {
+
+ template<class T> void f(T)
+ {}
+
+ template<class T> inline T g(T)
+ {
+ return T{};
+ }
+
+ template<> inline void f<>(int)
+ {}
+
+ template<> int g<>(int)
+ {
+ return 5;
+ }
+
+ }
+
+} // namespace cxx17
+
+#endif // __cplusplus <= 201402L
+
+]])
diff --git a/gdb/configure b/gdb/configure
index ab5818785333..12b626aee30c 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -4967,7 +4967,7 @@ program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"`
# We require a C++11 compiler. Check if one is available, and if
# necessary, set CXX_DIALECT to some -std=xxx switch.
- ax_cxx_compile_cxx11_required=true
+ ax_cxx_compile_alternatives="11 0x" ax_cxx_compile_cxx11_required=true
ac_ext=cpp
ac_cpp='$CXXCPP $CPPFLAGS'
ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
@@ -5283,7 +5283,8 @@ $as_echo "$ax_cv_cxx_compile_cxx11" >&6; }
fi
if test x$ac_success = xno; then
- for switch in -std=gnu++11 -std=gnu++0x; do
+ for alternative in ${ax_cxx_compile_alternatives}; do
+ switch="-std=gnu++${alternative}"
cachevar=`$as_echo "ax_cv_cxx_compile_cxx11_$switch" | $as_tr_sh`
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features with $switch" >&5
$as_echo_n "checking whether $CXX supports C++11 features with $switch... " >&6; }
@@ -5601,16 +5602,17 @@ $as_echo "$ac_res" >&6; }
fi
if test x$ac_success = xno; then
- for switch in -std=c++11 -std=c++0x +std=c++11 "-h std=c++11"; do
- cachevar=`$as_echo "ax_cv_cxx_compile_cxx11_$switch" | $as_tr_sh`
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features with $switch" >&5
+ for alternative in ${ax_cxx_compile_alternatives}; do
+ for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do
+ cachevar=`$as_echo "ax_cv_cxx_compile_cxx11_$switch" | $as_tr_sh`
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features with $switch" >&5
$as_echo_n "checking whether $CXX supports C++11 features with $switch... " >&6; }
if { as_var=$cachevar; eval "test \"\${$as_var+set}\" = set"; }; then :
$as_echo_n "(cached) " >&6
else
ac_save_CXX="$CXX"
- CXX="$CXX $switch"
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+ CXX="$CXX $switch"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
@@ -5905,14 +5907,18 @@ else
eval $cachevar=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
- CXX="$ac_save_CXX"
+ CXX="$ac_save_CXX"
fi
eval ac_res=\$$cachevar
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
$as_echo "$ac_res" >&6; }
- if eval test x\$$cachevar = xyes; then
- CXX_DIALECT="$switch"
- ac_success=yes
+ if eval test x\$$cachevar = xyes; then
+ CXX_DIALECT="$switch"
+ ac_success=yes
+ break
+ fi
+ done
+ if test x$ac_success = xyes; then
break
fi
done
--
2.16.2
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 2/2] Add gdb::string_view
2018-03-17 23:49 [PATCH 1/2] Update ax_cv_cxx_compile_cxx.m4 Simon Marchi
@ 2018-03-17 23:49 ` Simon Marchi
2018-03-18 0:11 ` Simon Marchi
0 siblings, 1 reply; 5+ messages in thread
From: Simon Marchi @ 2018-03-17 23:49 UTC (permalink / raw)
To: gdb-patches; +Cc: Simon Marchi
We had a few times the need for a data structure that does essentially
what C++17's std::string_view does, which is to give an std::string-like
interface (only the read-only operations) to an arbitrary character
buffer.
I first copied the string_view file from today's gcc master
(b427286632d7) and adapted it (I don't think there should be any legal
issues since the copyright should already belong to the FSF):
- I removed things related to wstring_view, u16string_view and
u32string_view (I don't think we need them, but we can always add them
later).
- I removed usages of _GLIBCXX_BEGIN_NAMESPACE_VERSION and
_GLIBCXX_END_NAMESPACE_VERSION.
- I put the code in the gdb namespace. I had to add a few "std::" in front of
std type usages.
- I added a constructor that builds a string_view from an std::string,
so that we can pass strings to string_view parameters seamlessly.
Normally, that's handled by "operator __sv_type" in the std::string
declaration, but it only exists when building with c++17.
- When building with >= c++17, gdb::string_view is an alias of
std::string_view.
The result is close enough to the original file that if we ever need to
update it, it should be easy enough to compare it with the new version
in a diff editor and merge the new changes in.
gdb/ChangeLog:
* common/string_view.h: New file.
* cli/cli-script.c (user_args) <m_args>: Change element type to
gdb::string_view.
---
gdb/cli/cli-script.c | 17 +-
gdb/common/string_view.h | 594 +++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 597 insertions(+), 14 deletions(-)
create mode 100644 gdb/common/string_view.h
diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c
index 366c42227c62..e705b7a8da70 100644
--- a/gdb/cli/cli-script.c
+++ b/gdb/cli/cli-script.c
@@ -32,6 +32,7 @@
#include "extension.h"
#include "interps.h"
#include "compile/compile.h"
+#include "common/string_view.h"
#include <vector>
@@ -54,18 +55,6 @@ static int command_nest_depth = 1;
/* This is to prevent certain commands being printed twice. */
static int suppress_next_print_command_trace = 0;
-/* A non-owning slice of a string. */
-
-struct string_view
-{
- string_view (const char *str_, size_t len_)
- : str (str_), len (len_)
- {}
-
- const char *str;
- size_t len;
-};
-
/* Structure for arguments to user defined functions. */
class user_args
@@ -91,7 +80,7 @@ private:
std::string m_command_line;
/* The arguments. Each element points inside M_COMMAND_LINE. */
- std::vector<string_view> m_args;
+ std::vector<gdb::string_view> m_args;
};
/* The stack of arguments passed to user defined functions. We need a
@@ -827,7 +816,7 @@ user_args::insert_args (const char *line) const
error (_("Missing argument %ld in user function."), i);
else
{
- new_line.append (m_args[i].str, m_args[i].len);
+ new_line.append (m_args[i].data (), m_args[i].length ());
line = tmp;
}
}
diff --git a/gdb/common/string_view.h b/gdb/common/string_view.h
new file mode 100644
index 000000000000..710049dbf0eb
--- /dev/null
+++ b/gdb/common/string_view.h
@@ -0,0 +1,594 @@
+// Components for manipulating non-owning sequences of characters -*- C++ -*-
+
+// Note: This file has been stolen from the gcc repo
+// (libstdc++-v3/include/std/string_view) and has local modifications.
+
+// Copyright (C) 2013-2017 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/>.
+
+
+//
+// N3762 basic_string_view library
+//
+
+#ifndef STRING_VIEW_H
+#define STRING_VIEW_H 1
+
+#if __cplusplus >= 201703L
+
+#include <string_view>
+
+namespace gdb {
+ using string_view = std::string_view;
+} /* namespace gdb */
+
+#else /* __cplusplus >= 201703L */
+
+#include <limits>
+#include <iosfwd>
+#include <bits/char_traits.h>
+#include <bits/functional_hash.h>
+#include <bits/range_access.h>
+
+namespace gdb {
+ /**
+ * @class basic_string_view <string_view>
+ * @brief A non-owning reference to a string.
+ *
+ * @ingroup strings
+ * @ingroup sequences
+ *
+ * @tparam _CharT Type of character
+ * @tparam _Traits Traits for character type, defaults to
+ * char_traits<_CharT>.
+ *
+ * A basic_string_view looks like this:
+ *
+ * @code
+ * _CharT* _M_str
+ * size_t _M_len
+ * @endcode
+ */
+ template<typename _CharT, typename _Traits = std::char_traits<_CharT>>
+ class basic_string_view
+ {
+ public:
+
+ // types
+ using traits_type = _Traits;
+ using value_type = _CharT;
+ using pointer = const _CharT*;
+ using const_pointer = const _CharT*;
+ using reference = const _CharT&;
+ using const_reference = const _CharT&;
+ using const_iterator = const _CharT*;
+ using iterator = const_iterator;
+ using const_reverse_iterator = std::reverse_iterator<const_iterator>;
+ using reverse_iterator = const_reverse_iterator;
+ using size_type = size_t;
+ using difference_type = ptrdiff_t;
+ static constexpr size_type npos = size_type(-1);
+
+ // [string.view.cons], construct/copy
+
+ constexpr
+ basic_string_view() noexcept
+ : _M_len{0}, _M_str{nullptr}
+ { }
+
+ constexpr basic_string_view(const basic_string_view&) noexcept = default;
+
+ constexpr basic_string_view(const _CharT* __str) noexcept
+ : _M_len{__str == nullptr ? 0 : traits_type::length(__str)},
+ _M_str{__str}
+ { }
+
+ constexpr
+ basic_string_view(const _CharT* __str, size_type __len) noexcept
+ : _M_len{__len}, _M_str{__str}
+ { }
+
+ constexpr
+ basic_string_view(const std::string &__str) noexcept
+ : _M_len{__str.length()}, _M_str{__str.c_str()}
+ { }
+
+ constexpr basic_string_view&
+ operator=(const basic_string_view&) noexcept = default;
+
+ // [string.view.iterators], iterators
+
+ constexpr const_iterator
+ begin() const noexcept
+ { return this->_M_str; }
+
+ constexpr const_iterator
+ end() const noexcept
+ { return this->_M_str + this->_M_len; }
+
+ constexpr const_iterator
+ cbegin() const noexcept
+ { return this->_M_str; }
+
+ constexpr const_iterator
+ cend() const noexcept
+ { return this->_M_str + this->_M_len; }
+
+ constexpr const_reverse_iterator
+ rbegin() const noexcept
+ { return const_reverse_iterator(this->end()); }
+
+ constexpr const_reverse_iterator
+ rend() const noexcept
+ { return const_reverse_iterator(this->begin()); }
+
+ constexpr const_reverse_iterator
+ crbegin() const noexcept
+ { return const_reverse_iterator(this->end()); }
+
+ constexpr const_reverse_iterator
+ crend() const noexcept
+ { return const_reverse_iterator(this->begin()); }
+
+ // [string.view.capacity], capacity
+
+ constexpr size_type
+ size() const noexcept
+ { return this->_M_len; }
+
+ constexpr size_type
+ length() const noexcept
+ { return _M_len; }
+
+ constexpr size_type
+ max_size() const noexcept
+ {
+ return (npos - sizeof(size_type) - sizeof(void*))
+ / sizeof(value_type) / 4;
+ }
+
+ constexpr bool
+ empty() const noexcept
+ { return this->_M_len == 0; }
+
+ // [string.view.access], element access
+
+ constexpr const _CharT&
+ operator[](size_type __pos) const noexcept
+ {
+ // TODO: Assert to restore in a way compatible with the constexpr.
+ // __glibcxx_assert(__pos < this->_M_len);
+ return *(this->_M_str + __pos);
+ }
+
+ constexpr const _CharT&
+ at(size_type __pos) const
+ {
+ if (__pos >= _M_len)
+ __throw_out_of_range_fmt(__N("basic_string_view::at: __pos "
+ "(which is %zu) >= this->size() "
+ "(which is %zu)"), __pos, this->size());
+ return *(this->_M_str + __pos);
+ }
+
+ constexpr const _CharT&
+ front() const noexcept
+ {
+ // TODO: Assert to restore in a way compatible with the constexpr.
+ // __glibcxx_assert(this->_M_len > 0);
+ return *this->_M_str;
+ }
+
+ constexpr const _CharT&
+ back() const noexcept
+ {
+ // TODO: Assert to restore in a way compatible with the constexpr.
+ // __glibcxx_assert(this->_M_len > 0);
+ return *(this->_M_str + this->_M_len - 1);
+ }
+
+ constexpr const _CharT*
+ data() const noexcept
+ { return this->_M_str; }
+
+ // [string.view.modifiers], modifiers:
+
+ constexpr void
+ remove_prefix(size_type __n) noexcept
+ {
+ __glibcxx_assert(this->_M_len >= __n);
+ this->_M_str += __n;
+ this->_M_len -= __n;
+ }
+
+ constexpr void
+ remove_suffix(size_type __n) noexcept
+ { this->_M_len -= __n; }
+
+ constexpr void
+ swap(basic_string_view& __sv) noexcept
+ {
+ auto __tmp = *this;
+ *this = __sv;
+ __sv = __tmp;
+ }
+
+
+ // [string.view.ops], string operations:
+
+ size_type
+ copy(_CharT* __str, size_type __n, size_type __pos = 0) const
+ {
+ __glibcxx_requires_string_len(__str, __n);
+ __pos = _M_check(__pos, "basic_string_view::copy");
+ const size_type __rlen = std::min(__n, _M_len - __pos);
+ for (auto __begin = this->_M_str + __pos,
+ __end = __begin + __rlen; __begin != __end;)
+ *__str++ = *__begin++;
+ return __rlen;
+ }
+
+
+ // [string.view.ops], string operations:
+
+ constexpr basic_string_view
+ substr(size_type __pos, size_type __n = npos) const noexcept(false)
+ {
+ __pos = _M_check(__pos, "basic_string_view::substr");
+ const size_type __rlen = std::min(__n, _M_len - __pos);
+ return basic_string_view{_M_str + __pos, __rlen};
+ }
+
+ constexpr int
+ compare(basic_string_view __str) const noexcept
+ {
+ const size_type __rlen = std::min(this->_M_len, __str._M_len);
+ int __ret = traits_type::compare(this->_M_str, __str._M_str, __rlen);
+ if (__ret == 0)
+ __ret = _S_compare(this->_M_len, __str._M_len);
+ return __ret;
+ }
+
+ constexpr int
+ compare(size_type __pos1, size_type __n1, basic_string_view __str) const
+ { return this->substr(__pos1, __n1).compare(__str); }
+
+ constexpr int
+ compare(size_type __pos1, size_type __n1,
+ basic_string_view __str, size_type __pos2, size_type __n2) const
+ {
+ return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2));
+ }
+
+ constexpr int
+ compare(const _CharT* __str) const noexcept
+ { return this->compare(basic_string_view{__str}); }
+
+ constexpr int
+ compare(size_type __pos1, size_type __n1, const _CharT* __str) const
+ { return this->substr(__pos1, __n1).compare(basic_string_view{__str}); }
+
+ constexpr int
+ compare(size_type __pos1, size_type __n1,
+ const _CharT* __str, size_type __n2) const noexcept(false)
+ {
+ return this->substr(__pos1, __n1)
+ .compare(basic_string_view(__str, __n2));
+ }
+
+ constexpr size_type
+ find(basic_string_view __str, size_type __pos = 0) const noexcept
+ { return this->find(__str._M_str, __pos, __str._M_len); }
+
+ constexpr size_type
+ find(_CharT __c, size_type __pos = 0) const noexcept;
+
+ constexpr size_type
+ find(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
+
+ constexpr size_type
+ find(const _CharT* __str, size_type __pos = 0) const noexcept
+ { return this->find(__str, __pos, traits_type::length(__str)); }
+
+ constexpr size_type
+ rfind(basic_string_view __str, size_type __pos = npos) const noexcept
+ { return this->rfind(__str._M_str, __pos, __str._M_len); }
+
+ constexpr size_type
+ rfind(_CharT __c, size_type __pos = npos) const noexcept;
+
+ constexpr size_type
+ rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
+
+ constexpr size_type
+ rfind(const _CharT* __str, size_type __pos = npos) const noexcept
+ { return this->rfind(__str, __pos, traits_type::length(__str)); }
+
+ constexpr size_type
+ find_first_of(basic_string_view __str, size_type __pos = 0) const noexcept
+ { return this->find_first_of(__str._M_str, __pos, __str._M_len); }
+
+ constexpr size_type
+ find_first_of(_CharT __c, size_type __pos = 0) const noexcept
+ { return this->find(__c, __pos); }
+
+ constexpr size_type
+ find_first_of(const _CharT* __str, size_type __pos, size_type __n) const noexcept;
+
+ constexpr size_type
+ find_first_of(const _CharT* __str, size_type __pos = 0) const noexcept
+ { return this->find_first_of(__str, __pos, traits_type::length(__str)); }
+
+ constexpr size_type
+ find_last_of(basic_string_view __str,
+ size_type __pos = npos) const noexcept
+ { return this->find_last_of(__str._M_str, __pos, __str._M_len); }
+
+ constexpr size_type
+ find_last_of(_CharT __c, size_type __pos=npos) const noexcept
+ { return this->rfind(__c, __pos); }
+
+ constexpr size_type
+ find_last_of(const _CharT* __str, size_type __pos,
+ size_type __n) const noexcept;
+
+ constexpr size_type
+ find_last_of(const _CharT* __str, size_type __pos = npos) const noexcept
+ { return this->find_last_of(__str, __pos, traits_type::length(__str)); }
+
+ constexpr size_type
+ find_first_not_of(basic_string_view __str,
+ size_type __pos = 0) const noexcept
+ { return this->find_first_not_of(__str._M_str, __pos, __str._M_len); }
+
+ constexpr size_type
+ find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept;
+
+ constexpr size_type
+ find_first_not_of(const _CharT* __str,
+ size_type __pos, size_type __n) const noexcept;
+
+ constexpr size_type
+ find_first_not_of(const _CharT* __str, size_type __pos = 0) const noexcept
+ {
+ return this->find_first_not_of(__str, __pos,
+ traits_type::length(__str));
+ }
+
+ constexpr size_type
+ find_last_not_of(basic_string_view __str,
+ size_type __pos = npos) const noexcept
+ { return this->find_last_not_of(__str._M_str, __pos, __str._M_len); }
+
+ constexpr size_type
+ find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept;
+
+ constexpr size_type
+ find_last_not_of(const _CharT* __str,
+ size_type __pos, size_type __n) const noexcept;
+
+ constexpr size_type
+ find_last_not_of(const _CharT* __str,
+ size_type __pos = npos) const noexcept
+ {
+ return this->find_last_not_of(__str, __pos,
+ traits_type::length(__str));
+ }
+
+ constexpr size_type
+ _M_check(size_type __pos, const char* __s) const noexcept(false)
+ {
+ if (__pos > this->size())
+ __throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > "
+ "this->size() (which is %zu)"),
+ __s, __pos, this->size());
+ return __pos;
+ }
+
+ // NB: _M_limit doesn't check for a bad __pos value.
+ constexpr size_type
+ _M_limit(size_type __pos, size_type __off) const noexcept
+ {
+ const bool __testoff = __off < this->size() - __pos;
+ return __testoff ? __off : this->size() - __pos;
+ }
+
+ private:
+
+ static constexpr int
+ _S_compare(size_type __n1, size_type __n2) noexcept
+ {
+ const difference_type __diff = __n1 - __n2;
+ if (__diff > std::numeric_limits<int>::max())
+ return std::numeric_limits<int>::max();
+ if (__diff < std::numeric_limits<int>::min())
+ return std::numeric_limits<int>::min();
+ return static_cast<int>(__diff);
+ }
+
+ size_t _M_len;
+ const _CharT* _M_str;
+ };
+
+ // [string.view.comparison], non-member basic_string_view comparison function
+
+ namespace __detail
+ {
+ // Identity transform to create a non-deduced context, so that only one
+ // argument participates in template argument deduction and the other
+ // argument gets implicitly converted to the deduced type. See n3766.html.
+ template<typename _Tp>
+ using __idt = std::common_type_t<_Tp>;
+ }
+
+ template<typename _CharT, typename _Traits>
+ constexpr bool
+ operator==(basic_string_view<_CharT, _Traits> __x,
+ basic_string_view<_CharT, _Traits> __y) noexcept
+ { return __x.size() == __y.size() && __x.compare(__y) == 0; }
+
+ template<typename _CharT, typename _Traits>
+ constexpr bool
+ operator==(basic_string_view<_CharT, _Traits> __x,
+ __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
+ { return __x.size() == __y.size() && __x.compare(__y) == 0; }
+
+ template<typename _CharT, typename _Traits>
+ constexpr bool
+ operator==(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
+ basic_string_view<_CharT, _Traits> __y) noexcept
+ { return __x.size() == __y.size() && __x.compare(__y) == 0; }
+
+ template<typename _CharT, typename _Traits>
+ constexpr bool
+ operator!=(basic_string_view<_CharT, _Traits> __x,
+ basic_string_view<_CharT, _Traits> __y) noexcept
+ { return !(__x == __y); }
+
+ template<typename _CharT, typename _Traits>
+ constexpr bool
+ operator!=(basic_string_view<_CharT, _Traits> __x,
+ __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
+ { return !(__x == __y); }
+
+ template<typename _CharT, typename _Traits>
+ constexpr bool
+ operator!=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
+ basic_string_view<_CharT, _Traits> __y) noexcept
+ { return !(__x == __y); }
+
+ template<typename _CharT, typename _Traits>
+ constexpr bool
+ operator< (basic_string_view<_CharT, _Traits> __x,
+ basic_string_view<_CharT, _Traits> __y) noexcept
+ { return __x.compare(__y) < 0; }
+
+ template<typename _CharT, typename _Traits>
+ constexpr bool
+ operator< (basic_string_view<_CharT, _Traits> __x,
+ __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
+ { return __x.compare(__y) < 0; }
+
+ template<typename _CharT, typename _Traits>
+ constexpr bool
+ operator< (__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
+ basic_string_view<_CharT, _Traits> __y) noexcept
+ { return __x.compare(__y) < 0; }
+
+ template<typename _CharT, typename _Traits>
+ constexpr bool
+ operator> (basic_string_view<_CharT, _Traits> __x,
+ basic_string_view<_CharT, _Traits> __y) noexcept
+ { return __x.compare(__y) > 0; }
+
+ template<typename _CharT, typename _Traits>
+ constexpr bool
+ operator> (basic_string_view<_CharT, _Traits> __x,
+ __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
+ { return __x.compare(__y) > 0; }
+
+ template<typename _CharT, typename _Traits>
+ constexpr bool
+ operator> (__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
+ basic_string_view<_CharT, _Traits> __y) noexcept
+ { return __x.compare(__y) > 0; }
+
+ template<typename _CharT, typename _Traits>
+ constexpr bool
+ operator<=(basic_string_view<_CharT, _Traits> __x,
+ basic_string_view<_CharT, _Traits> __y) noexcept
+ { return __x.compare(__y) <= 0; }
+
+ template<typename _CharT, typename _Traits>
+ constexpr bool
+ operator<=(basic_string_view<_CharT, _Traits> __x,
+ __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
+ { return __x.compare(__y) <= 0; }
+
+ template<typename _CharT, typename _Traits>
+ constexpr bool
+ operator<=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
+ basic_string_view<_CharT, _Traits> __y) noexcept
+ { return __x.compare(__y) <= 0; }
+
+ template<typename _CharT, typename _Traits>
+ constexpr bool
+ operator>=(basic_string_view<_CharT, _Traits> __x,
+ basic_string_view<_CharT, _Traits> __y) noexcept
+ { return __x.compare(__y) >= 0; }
+
+ template<typename _CharT, typename _Traits>
+ constexpr bool
+ operator>=(basic_string_view<_CharT, _Traits> __x,
+ __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
+ { return __x.compare(__y) >= 0; }
+
+ template<typename _CharT, typename _Traits>
+ constexpr bool
+ operator>=(__detail::__idt<basic_string_view<_CharT, _Traits>> __x,
+ basic_string_view<_CharT, _Traits> __y) noexcept
+ { return __x.compare(__y) >= 0; }
+
+ // [string.view.io], Inserters and extractors
+ template<typename _CharT, typename _Traits>
+ inline std::basic_ostream<_CharT, _Traits>&
+ operator<<(std::basic_ostream<_CharT, _Traits>& __os,
+ basic_string_view<_CharT,_Traits> __str)
+ { return __ostream_insert(__os, __str.data(), __str.size()); }
+
+
+ // basic_string_view typedef names
+
+ using string_view = basic_string_view<char>;
+
+ // [string.view.hash], hash support:
+
+ template<typename _Tp>
+ struct hash;
+
+ template<>
+ struct hash<string_view>
+ : public std::__hash_base<size_t, string_view>
+ {
+ size_t
+ operator()(const string_view& __str) const noexcept
+ { return std::_Hash_impl::hash(__str.data(), __str.length()); }
+ };
+
+ inline namespace literals
+ {
+ inline namespace string_view_literals
+ {
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wliteral-suffix"
+ inline constexpr basic_string_view<char>
+ operator""sv(const char* __str, size_t __len) noexcept
+ { return basic_string_view<char>{__str, __len}; }
+#pragma GCC diagnostic pop
+ } // namespace string_literals
+ } // namespace literals
+
+} /* namespace gdb */
+
+#endif /* __cplusplus >= 201703L */
+
+#endif /* STRING_VIEW_H */
--
2.16.2
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] Add gdb::string_view
2018-03-17 23:49 ` [PATCH 2/2] Add gdb::string_view Simon Marchi
@ 2018-03-18 0:11 ` Simon Marchi
2018-03-19 12:21 ` Pedro Alves
0 siblings, 1 reply; 5+ messages in thread
From: Simon Marchi @ 2018-03-18 0:11 UTC (permalink / raw)
To: gdb-patches
On 2018-03-17 19:49, Simon Marchi wrote:
> We had a few times the need for a data structure that does essentially
> what C++17's std::string_view does, which is to give an std::string-like
> interface (only the read-only operations) to an arbitrary character
> buffer.
>
> I first copied the string_view file from today's gcc master
> (b427286632d7) and adapted it (I don't think there should be any legal
> issues since the copyright should already belong to the FSF):
>
> - I removed things related to wstring_view, u16string_view and
> u32string_view (I don't think we need them, but we can always add them
> later).
> - I removed usages of _GLIBCXX_BEGIN_NAMESPACE_VERSION and
> _GLIBCXX_END_NAMESPACE_VERSION.
> - I put the code in the gdb namespace. I had to add a few "std::" in front of
> std type usages.
> - I added a constructor that builds a string_view from an std::string,
> so that we can pass strings to string_view parameters seamlessly.
> Normally, that's handled by "operator __sv_type" in the std::string
> declaration, but it only exists when building with c++17.
> - When building with >= c++17, gdb::string_view is an alias of
> std::string_view.
>
> The result is close enough to the original file that if we ever need to
> update it, it should be easy enough to compare it with the new version
> in a diff editor and merge the new changes in.
Hmm, when building with older g++ (such as the aarch64 builders on the buildbot,
which have g++ 4.8), it trips on:
using __idt = std::common_type_t<_Tp>;
It looks like that release of g++ didn't have std::common_type_t. I guess it
would be possible to avoid using it, and change these:
operator==(basic_string_view<_CharT, _Traits> __x,
__detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
for
operator==(basic_string_view<_CharT, _Traits> __x,
basic_string_view<_CharT, _Traits> __y) noexcept
but I am not aware of what consequences it would have.
Simon
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] Add gdb::string_view
2018-03-18 0:11 ` Simon Marchi
@ 2018-03-19 12:21 ` Pedro Alves
2018-03-30 17:43 ` Simon Marchi
0 siblings, 1 reply; 5+ messages in thread
From: Pedro Alves @ 2018-03-19 12:21 UTC (permalink / raw)
To: Simon Marchi, gdb-patches
On 03/18/2018 12:10 AM, Simon Marchi wrote:
> On 2018-03-17 19:49, Simon Marchi wrote:
>> We had a few times the need for a data structure that does essentially
>> what C++17's std::string_view does, which is to give an std::string-like
>> interface (only the read-only operations) to an arbitrary character
>> buffer.
Great, I've been wanting to do something like this for a while.
>>
>> I first copied the string_view file from today's gcc master
>> (b427286632d7) and adapted it (I don't think there should be any legal
>> issues since the copyright should already belong to the FSF):
>>
>> - I removed things related to wstring_view, u16string_view and
>> u32string_view (I don't think we need them, but we can always add them
>> later).
>> - I removed usages of _GLIBCXX_BEGIN_NAMESPACE_VERSION and
>> _GLIBCXX_END_NAMESPACE_VERSION.
>> - I put the code in the gdb namespace. I had to add a few "std::" in front of
>> std type usages.
>> - I added a constructor that builds a string_view from an std::string,
>> so that we can pass strings to string_view parameters seamlessly.
>> Normally, that's handled by "operator __sv_type" in the std::string
>> declaration, but it only exists when building with c++17.
>> - When building with >= c++17, gdb::string_view is an alias of
>> std::string_view.
>>
>> The result is close enough to the original file that if we ever need to
>> update it, it should be easy enough to compare it with the new version
>> in a diff editor and merge the new changes in.
>
> Hmm, when building with older g++ (such as the aarch64 builders on the buildbot,
> which have g++ 4.8), it trips on:
>
> using __idt = std::common_type_t<_Tp>;
>
> It looks like that release of g++ didn't have std::common_type_t. I guess it
> would be possible to avoid using it, and change these:
It has std::common_type though. C++14 std::foo_t types are usually just a
helper/convenience alias template, like:
/// Alias template for common_type
template<typename... _Tp>
using common_type_t = typename common_type<_Tp...>::type;
So it sounds like we can just use the C++11 / ::type form directly, or
add gdb::common_type_t somewhere, like common/traits.h or to our
copy of string_view.
>
> operator==(basic_string_view<_CharT, _Traits> __x,
> __detail::__idt<basic_string_view<_CharT, _Traits>> __y) noexcept
>
> for
>
> operator==(basic_string_view<_CharT, _Traits> __x,
> basic_string_view<_CharT, _Traits> __y) noexcept
>
> but I am not aware of what consequences it would have.
Would it be possible to import some of the libstdc++'s relevant
testscases into our unit tests framework, like was done for
gdb::optional [1]?
[1] https://sourceware.org/ml/gdb-patches/2017-04/msg00239.html
Thanks,
Pedro Alves
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 2/2] Add gdb::string_view
2018-03-19 12:21 ` Pedro Alves
@ 2018-03-30 17:43 ` Simon Marchi
0 siblings, 0 replies; 5+ messages in thread
From: Simon Marchi @ 2018-03-30 17:43 UTC (permalink / raw)
To: Pedro Alves; +Cc: gdb-patches
On 2018-03-19 08:21, Pedro Alves wrote:
>> Hmm, when building with older g++ (such as the aarch64 builders on the
>> buildbot,
>> which have g++ 4.8), it trips on:
>>
>> using __idt = std::common_type_t<_Tp>;
>>
>> It looks like that release of g++ didn't have std::common_type_t. I
>> guess it
>> would be possible to avoid using it, and change these:
>
> It has std::common_type though. C++14 std::foo_t types are usually
> just a
> helper/convenience alias template, like:
>
> /// Alias template for common_type
> template<typename... _Tp>
> using common_type_t = typename common_type<_Tp...>::type;
>
> So it sounds like we can just use the C++11 / ::type form directly, or
> add gdb::common_type_t somewhere, like common/traits.h or to our
> copy of string_view.
Ok thanks I think I got it to work now.
>
>>
>> operator==(basic_string_view<_CharT, _Traits> __x,
>> __detail::__idt<basic_string_view<_CharT, _Traits>>
>> __y) noexcept
>>
>> for
>>
>> operator==(basic_string_view<_CharT, _Traits> __x,
>> basic_string_view<_CharT, _Traits> __y) noexcept
>>
>> but I am not aware of what consequences it would have.
>
> Would it be possible to import some of the libstdc++'s relevant
> testscases into our unit tests framework, like was done for
> gdb::optional [1]?
>
> [1] https://sourceware.org/ml/gdb-patches/2017-04/msg00239.html
Good idea, I did it and it caught a few important compilation issues!
I just need to clean up the patches and I'll send a v2.
Thanks,
Simon
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2018-03-30 17:43 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-03-17 23:49 [PATCH 1/2] Update ax_cv_cxx_compile_cxx.m4 Simon Marchi
2018-03-17 23:49 ` [PATCH 2/2] Add gdb::string_view Simon Marchi
2018-03-18 0:11 ` Simon Marchi
2018-03-19 12:21 ` Pedro Alves
2018-03-30 17:43 ` Simon Marchi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).