* [PATCH 0/3] More cleanup elimination / gdb::unique_ptr
@ 2016-10-10 16:46 Pedro Alves
2016-10-10 16:46 ` [PATCH 1/3] Introduce gdb::unique_ptr Pedro Alves
` (2 more replies)
0 siblings, 3 replies; 72+ messages in thread
From: Pedro Alves @ 2016-10-10 16:46 UTC (permalink / raw)
To: gdb-patches
This patch series aims at removing more cleanups.
It eliminates ~90 out of the ~1800 make_cleanup calls left in the
tree.
It also tries to answer the "which smart pointer?" question. Many
make_cleanup uses in the code base are best eliminated by using a
"owning" smart pointer to manage ownership of the resource
automatically.
We don't require C++11 yet, but OTOH, std::unique_ptr is quite nice.
C++03 has std::auto_ptr, but, that's best avoided. I'd also like to
have a smart pointer that manages malloc'ed objects, so std::auto_ptr
alone won't cut it.
The solution proposed by this series is a new gdb::unique_ptr smart
pointer that is mapped to std::unique_ptr when compiling with a C++11
compiler (really, just a template alias), and is a simple
std::unique_ptr emulation when compiled with a C++03 compiler.
The patch series first adds the smart pointer to the tree, and then
follows up with examples of C++fycation that use it, and more.
Series tested on:
- NetBSD 5.1 (gcc70 on the compile farm), w/ gcc 4.1.3
- x86-64 Fedora 23, gcc 5.3.1 (gnu++03) native/gdbserver
- x86-64 Fedora 23, and gcc 7.0 (gnu++14)
Note that while the series' diffstat is practically a wash
linecount-wise:
87 files changed, 1450 insertions(+), 1429 deletions(-)
if we don't count the first patch, i.e., the new smart pointer, then
we get:
84 files changed, 1017 insertions(+), 1429 deletions(-)
So while there's a lot of churn, there's a significant drop in number
of lines of code.
Pedro Alves (3):
Introduce gdb::unique_ptr
ui_file_xstrdup -> std::string
'struct parse_expression *' -> gdb::unique_ptr<expression>
gdb/ada-lang.c | 83 +++------
gdb/ada-lang.h | 2 +-
gdb/ada-valprint.c | 53 +++---
gdb/ada-varobj.c | 130 ++++++--------
gdb/arm-tdep.c | 6 +-
gdb/ax-gdb.c | 15 +-
gdb/break-catch-sig.c | 2 +-
gdb/break-catch-syscall.c | 2 +-
gdb/break-catch-throw.c | 26 +--
gdb/breakpoint.c | 144 +++++++---------
gdb/breakpoint.h | 8 +-
gdb/c-exp.y | 9 +-
gdb/c-lang.c | 9 +-
gdb/c-lang.h | 7 +-
gdb/c-typeprint.c | 5 +-
gdb/c-varobj.c | 142 ++++++++--------
gdb/cli/cli-script.c | 130 +++++---------
gdb/cli/cli-setshow.c | 7 +-
gdb/common/common-defs.h | 3 +
gdb/common/common-utils.c | 31 ++++
gdb/common/common-utils.h | 6 +
gdb/common/gdb_unique_ptr.h | 363 ++++++++++++++++++++++++++++++++++++++++
gdb/common/safe-bool.h | 67 ++++++++
gdb/compile/compile-c-support.c | 6 +-
gdb/compile/compile.c | 70 ++++----
gdb/cp-abi.c | 2 +-
gdb/cp-abi.h | 7 +-
gdb/cp-support.c | 60 +++----
gdb/cp-support.h | 10 +-
gdb/dbxread.c | 22 +--
gdb/dtrace-probe.c | 6 +-
gdb/dwarf2read.c | 25 ++-
gdb/eval.c | 43 ++---
gdb/expression.h | 12 +-
gdb/gdbarch.c | 8 +-
gdb/gdbarch.sh | 8 +-
gdb/gdbcmd.h | 2 +-
gdb/gdbtypes.c | 12 +-
gdb/gnu-v3-abi.c | 55 ++----
gdb/guile/guile.c | 18 +-
gdb/guile/scm-breakpoint.c | 6 +-
gdb/guile/scm-disasm.c | 6 +-
gdb/guile/scm-frame.c | 6 +-
gdb/guile/scm-type.c | 27 ++-
gdb/guile/scm-value.c | 18 +-
gdb/infcmd.c | 9 +-
gdb/infrun.c | 6 +-
gdb/language.c | 7 +-
gdb/language.h | 14 +-
gdb/linespec.c | 53 +++---
gdb/location.c | 11 +-
gdb/location.h | 6 -
gdb/mi/mi-cmd-var.c | 70 +++-----
gdb/mi/mi-main.c | 41 ++---
gdb/minsyms.c | 17 +-
gdb/objc-lang.c | 7 +-
gdb/parse.c | 50 +++---
gdb/printcmd.c | 65 +++----
gdb/python/py-arch.c | 10 +-
gdb/python/py-breakpoint.c | 8 +-
gdb/python/py-frame.c | 8 +-
gdb/python/py-type.c | 10 +-
gdb/python/py-unwind.c | 7 +-
gdb/python/py-value.c | 7 +-
gdb/python/py-varobj.c | 4 +-
gdb/python/python.c | 19 +--
gdb/remote.c | 56 ++-----
gdb/rust-exp.y | 11 +-
gdb/rust-lang.c | 50 ++----
gdb/stabsread.c | 21 ++-
gdb/stack.c | 6 +-
gdb/symtab.c | 61 +++----
gdb/symtab.h | 19 ++-
gdb/top.c | 13 +-
gdb/tracepoint.c | 143 +++++-----------
gdb/tracepoint.h | 18 +-
gdb/typeprint.c | 21 +--
gdb/ui-file.c | 24 ++-
gdb/ui-file.h | 9 +-
gdb/ui-out.c | 9 +-
gdb/utils.c | 5 +-
gdb/value.c | 8 +-
gdb/value.h | 2 +-
gdb/varobj-iter.h | 4 +-
gdb/varobj.c | 216 +++++++++++-------------
gdb/varobj.h | 66 ++++----
gdb/xtensa-tdep.c | 9 +-
87 files changed, 1450 insertions(+), 1429 deletions(-)
create mode 100644 gdb/common/gdb_unique_ptr.h
create mode 100644 gdb/common/safe-bool.h
--
2.5.5
^ permalink raw reply [flat|nested] 72+ messages in thread* [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-10 16:46 [PATCH 0/3] More cleanup elimination / gdb::unique_ptr Pedro Alves @ 2016-10-10 16:46 ` Pedro Alves 2016-10-10 17:49 ` Simon Marchi 2016-10-11 6:48 ` Metzger, Markus T 2016-10-10 16:46 ` [PATCH 3/3] 'struct parse_expression *' -> gdb::unique_ptr<expression> Pedro Alves 2016-10-10 16:58 ` [PATCH 0/3] More cleanup elimination / gdb::unique_ptr Pedro Alves 2 siblings, 2 replies; 72+ messages in thread From: Pedro Alves @ 2016-10-10 16:46 UTC (permalink / raw) To: gdb-patches Many make_cleanup uses in the code base are best eliminated by using a "owning" smart pointer to manage ownership of the resource automatically. The question is _which_ smart pointer. We have std::auto_ptr in C++03, but, as is collective wisdom by now, that's too easy to misuse, and has therefore been deprecated in C++11 and finally removed in C++17. It'd be nice to be able to use std::unique_ptr instead, which is the modern, safe std::auto_ptr replacement in C++11. In addition to extra safety -- ownership transfer must be explicit -- std::unique_ptr has (among others) one nice feature that std::auto_ptr doesn't --- ability to specify a custom deleter as template parameter. In gdb's context, that allows easily creating a smart pointer for memory allocated with xmalloc -- the smart pointer then knows to release with xfree instead of delete. This is particularly interesting when managing objects allocated in C libraries, and also, for C++-fying parts of GDB that interact with other parts that still return object allocated with malloc. Since std::unique_ptr is supposedly mostly a drop-in replacement for std::auto_ptr -- basically "upgrading" is usually a matter of find/replace and then fix the "bad" implicit ownership transfer cases, I thought of actually taking advantage of std::unique_ptr when GDB is compiled with a C++11 compiler. And then since we don't require C++11 yet, I wrote a very lightweight std::unique_ptr "emulation" for C++03. The emulation started out as a copy of GCC 7's std::auto_ptr, and then heavilly customized to make it behave more like std::unique_ptr: - unique_ptr<T[]> specialization. auto_ptr<T> does not know to use delete[]. - custom deleters (though only stateless deleters --- support for stateful deleters could be added, but I saw no need for those at this point). - support for all of 'ptr != NULL', 'ptr == NULL' and 'if (ptr)' using the safe bool idiom. - initialization and assignment from NULL (std::unique_ptr allows "ptr = nullptr" instead, while std::auto_ptr allows neither.) The "emulation" isn't perfect in the sense that just like std::auto_ptr, it defines a copy constructor with greedy ownership transfer. However, since if compiling gdb with a C++11 (or newer) compiler, we're actually using the real std::unique_ptr, as long as GDB builds with GCC 6 or later, or any other compiler that defaults to C++11 or later, then we know we're not misusing the C++03 version. I thought of putting the "emulation" / shim in the "std" namespace, so that when we start requiring C++11 at some point, no actual changes to users of the smart pointer throughout would be necessary. Putting things in the std namespace is technically undefined, however in practice it doesn't cause any issue with any compiler. However, thinking that people might be confused with seeing std::unique_ptr and thinking that we're actually requiring C++11 already, I put the new types in the "gdb" namespace instead. For managing malloc pointers, this adds a gdb::unique_malloc_ptr<T> "specialization" with a custom xfree deleter. No actual use of any smart pointer is introduced in this patch. That'll be done in following patches. Tested (along with the rest of the series) on: - NetBSD 5.1 (gcc70 on the compile farm), w/ gcc 4.1.3 - x86-64 Fedora 23, gcc 5.3.1 (gnu++03) - x86-64 Fedora 23, and gcc 7.0 (gnu++14) gdb/ChangeLog: yyyy-mm-dd Pedro Alves <palves@redhat.com> * common/common-defs.h: Include "gdb_unique_ptr.h". * common/gdb_unique_ptr.h: New. * common/safe-bool.h: New. --- gdb/common/common-defs.h | 3 + gdb/common/gdb_unique_ptr.h | 363 ++++++++++++++++++++++++++++++++++++++++++++ gdb/common/safe-bool.h | 67 ++++++++ 3 files changed, 433 insertions(+) create mode 100644 gdb/common/gdb_unique_ptr.h create mode 100644 gdb/common/safe-bool.h diff --git a/gdb/common/common-defs.h b/gdb/common/common-defs.h index 0d8d100..52ecb08 100644 --- a/gdb/common/common-defs.h +++ b/gdb/common/common-defs.h @@ -79,4 +79,7 @@ #define EXTERN_C_PUSH extern "C" { #define EXTERN_C_POP } +/* Pull in gdb::unique_ptr and gdb::unique_malloc_ptr. */ +#include "common/gdb_unique_ptr.h" + #endif /* COMMON_DEFS_H */ diff --git a/gdb/common/gdb_unique_ptr.h b/gdb/common/gdb_unique_ptr.h new file mode 100644 index 0000000..1cda298 --- /dev/null +++ b/gdb/common/gdb_unique_ptr.h @@ -0,0 +1,363 @@ +/* gdb::unique_ptr, a simple std::unique_ptr replacement for C++03. + + Copyright (C) 2007-2016 Free Software Foundation, Inc. + + This file is part of GDB. + + This program 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 of the License, or + (at your option) any later version. + + This program 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 program. If not, see <http://www.gnu.org/licenses/>. */ + +/* gdb::unique_ptr maps to std::unique_ptr in C++11 mode, and to a + simplified emulation in C++03 mode. + + The emulation code was originally based on GCC 7.0's std::auto_ptr + and then heavily customized to behave more like std::unique_ptr + (T[] specialization, assignment from NULL, explicit bool + conversion, etc.). + + Our emulation actually lets you shoot yourself in the foot, just + like std::auto_ptr, since the copy ctor actually moves, but we know + that if gdb builds in C++11 mode, then we're not doing anything + unsafe. + + Note, our emulation does NOT support "stateful" custom deleters. + You can't pass a deleter argument to the constructor. Only the + managed pointer is stored. Turns out that we don't really need + stateful custom deleters in practice. + + At the end of the file you'll find a gdb::unique_ptr specialization + that uses a custom (stateless) deleter -- gdb::unique_malloc_ptr. +*/ + +#ifndef GDB_UNIQUE_PTR_H +#define GDB_UNIQUE_PTR_H 1 + +#include <memory> + +#include "safe-bool.h" + +namespace gdb +{ + +#if __cplusplus >= 201103 + +/* In C++ mode, all we need is import the standard + std::unique_ptr. */ +template<typename T> using unique_ptr + = std::unique_ptr<T>; + +/* Pull in move as well. */ +using std::move; + +#else /* C++11 */ + +/* Default destruction policy used by gdb::unique_ptr when no + deleter is specified. Uses delete. */ + +template<typename T> +struct default_delete +{ + void operator () (T *ptr) const { delete ptr; } +}; + +/* Specialization for arrays. Uses delete[]. */ + +template<typename T> +struct default_delete<T[]> +{ + void operator () (T *ptr) const { delete [] ptr; } +}; + +/* Type used to support assignment from NULL: + + gdb::unique_ptr<foo> ptr (....); + ... + ptr = NULL; +*/ +struct unique_ptr_nullptr_t +{ +private: + struct private_type; +public: + /* Since null_type is private, the only way to construct this class + is by passing a NULL pointer. See unique_ptr_base::operator= + further below. */ + unique_ptr_nullptr_t (private_type *) {} +}; + +/* Base class of our unique_ptr emulation. Contains code common to + both the unique_ptr<T, D> and unique_ptr<T[], D>. */ + +template<typename T, typename D> +class unique_ptr_base : public safe_bool <unique_ptr_base<T, D> > +{ +public: + typedef T *pointer; + typedef T element_type; + typedef D deleter_type; + + template <typename T1> + struct unique_ptr_base_ref + { + T1 *m_ptr; + + explicit unique_ptr_base_ref (T1 *p): m_ptr (p) {} + }; + + typedef unique_ptr_base_ref<T> ref_type; + + /* An unique_ptr is usually constructed from a raw pointer. P - a + pointer (defaults to NULL). This object now owns the object + pointed to by P. */ + explicit unique_ptr_base (element_type *p = NULL) throw() : m_ptr (p) {} + + /* Even though std::unique_ptr is not copyable, our little simpler + emulation allows it, because RVO/NRVO requires an accessible copy + constructor, and also because our move emulation relies on this. + + An unique_ptr_base can be constructed from another + unique_ptr_base. A is another unique_ptr_base of the same type. + + This object now owns the object previously owned by A, which has + given up ownership. */ + unique_ptr_base (unique_ptr_base& a) throw() : m_ptr (a.release ()) {} + + /* Similarly, we implement this simply to allow std::swap work + without having to provide our own implementation. We know that + if GDB compiles with real std::unique_ptr, this won't be called + "incorrectly". + + Assignment operator. A is another unique_ptr_base of the same + type. This object now owns the object previously owned by A, + which has given up ownership. The object that this one used to + own and track has been deleted. */ + unique_ptr_base& + operator= (unique_ptr_base &a) throw() + { + reset (a.release ()); + return *this; + } + + /* std::unique_ptr does not allow assignment, except from nullptr. + nullptr doesn't exist before C++11, so we allowing assignment + from NULL instead: + ptr = NULL; + */ + unique_ptr_base & + operator= (const unique_ptr_nullptr_t &) throw() + { + reset (); + return *this; + } + + /* When the unique_ptr_base goes out of scope, the object it owns is + deleted. If it no longer owns anything (i.e., get() is NULL, + then this has no effect. */ + ~unique_ptr_base () { call_deleter (); } + + /* "explicit operator bool" emulation using the safe bool idiom. */ + bool explicit_operator_bool () const + { + return m_ptr != NULL; + } + + /* Bypassing the smart pointer. + Returns the raw pointer being managed. + + You can get a copy of the pointer that this object owns, for + situations such as passing to a function which only accepts a raw + pointer. Note, this smarts pointer still owns the memory. */ + element_type *get () const throw() { return m_ptr; } + + /* Bypassing the smart pointer. Returns the raw pointer being + managed. + + You can get a copy of the pointer that this object owns, for + situations such as passing to a function which only accepts a raw + pointer. + + Note, this smart pointer no longer owns the memory. When this + object goes out of scope, nothing will happen. */ + element_type *release () throw() + { + pointer tmp = m_ptr; + m_ptr = NULL; + return tmp; + } + + /* Forcibly delete the managed object. P is a pointer (defaults to + NULL). This object now owns the object pointed to by P. The + previous object has been deleted. */ + void reset (element_type *p = NULL) throw() + { + if (p != m_ptr) + { + call_deleter (); + m_ptr = p; + } + } + + /* Automatic conversions. + + These operations convert an unique_ptr_base into and from an + unique_ptr_base_ref automatically as needed. This allows + constructs such as: + + unique_ptr<Derived> func_returning_unique_ptr (.....); + ... + unique_ptr<Base> ptr = func_returning_unique_ptr (.....); + */ + unique_ptr_base (unique_ptr_base_ref<element_type> ref) throw() + : m_ptr (ref.m_ptr) {} + + unique_ptr_base & + operator= (unique_ptr_base_ref<element_type> ref) throw() + { + if (ref.m_ptr != this->get()) + { + call_deleter (); + m_ptr = ref.m_ptr; + } + return *this; + } + + template<typename T1> + operator unique_ptr_base_ref<T1> () throw() + { return unique_ptr_base_ref<T1> (this->release ()); } + + template<typename T1, typename D1> + operator unique_ptr_base<T1, D1> () throw() + { return unique_ptr_base<T1, D1> (this->release ()); } + +private: + + /* Call the deleter. Note we assume the deleter is "stateless". */ + void call_deleter () + { + D d; + + d (m_ptr); + } + + element_type *m_ptr; +}; + +/* Macro used to create a unique_ptr_base "specialization" -- a + subclass that uses a specific deleter. Basically this re-defines + the necessary constructors. This is necessary because we can't + inherit constructors with "using" without C++11. While at it, we + inherit the assignment operator. TYPE is the name of the type + being defined. Assumes that 'base_type' is a typedef of the + baseclass UNIQUE_PTR is inheriting from. */ +#define DEFINE_UNIQUE_PTR(TYPE) \ + public: \ + explicit TYPE (T *p = NULL) throw() \ + : base_type (p) {} \ + TYPE (typename base_type::ref_type ref) throw() \ + : base_type (ref.m_ptr) {} \ + \ + using base_type::operator=; + +/* Finally, define gdb::unique_ptr. */ + +template <typename T, typename D = default_delete<T> > +class unique_ptr : public unique_ptr_base<T, D> +{ + typedef unique_ptr_base<T, D> base_type; + + DEFINE_UNIQUE_PTR (unique_ptr) + + /* Dereferencing. */ + T &operator* () const throw() { return *this->get (); } + T *operator-> () const throw() { return this->get (); } +}; + +/* gdb::unique_ptr specialization for T[]. */ + +template <typename T, typename D> +class unique_ptr<T[], D> : public unique_ptr_base<T, D> +{ + typedef unique_ptr_base<T, D> base_type; + + DEFINE_UNIQUE_PTR (unique_ptr) + + /* Indexing operator. */ + T& operator[] (size_t i) const + { return this->get ()[i]; } +}; + +/* Comparison operators. */ + +template <typename T, typename D, + typename U, typename E> +inline bool +operator== (const unique_ptr_base<T, D>& x, + const unique_ptr_base<U, E>& y) +{ return x.get() == y.get(); } + +template <typename T, typename D, + typename U, typename E> +inline bool +operator!= (const unique_ptr_base<T, D>& x, + const unique_ptr_base<U, E>& y) +{ return x.get() != y.get(); } + +/* std::move "emulation". This is as simple as it can be -- relies on + the fact that our std::unique_ptr emulation actually behaves like + std::auto_ptr -- copy/assignment actually moves. */ + +template<typename T, typename D> +unique_ptr_base<T, D> +move (unique_ptr_base<T, D> v) +{ + return v; +} + +#endif /* C++11 */ + +/* Define gdb::unique_malloc_ptr, a gdb::unique_ptr that manages + malloc'ed memory. */ + +/* The deleter for gdb::unique_malloc_ptr. Uses xfree. */ +template <typename T> +struct xfree_deleter +{ + void operator() (T *ptr) const { xfree (ptr); } +}; + +#if __cplusplus >= 201103 + +/* In C++11, we just import the standard unique_ptr to our + namespace with a custom deleter. */ + +template<typename T> using unique_malloc_ptr + = std::unique_ptr<T, xfree_deleter<T>>; + +#else /* C++11 */ + +/* In C++03 mode, we need to define a subclass instead (and re-define + the constructors). */ + +template <typename T> +class unique_malloc_ptr : public unique_ptr<T, xfree_deleter<T> > +{ + typedef unique_ptr<T, xfree_deleter<T> > base_type; + + DEFINE_UNIQUE_PTR (unique_malloc_ptr) +}; + +#endif /* C++11 */ + +} /* namespace gdb */ + +#endif /* GDB_UNIQUE_PTR_H */ diff --git a/gdb/common/safe-bool.h b/gdb/common/safe-bool.h new file mode 100644 index 0000000..b0075c3 --- /dev/null +++ b/gdb/common/safe-bool.h @@ -0,0 +1,67 @@ +/* Safe bool idiom implementation. + + Copyright (C) 2016 Free Software Foundation, Inc. + + This file is part of GDB. + + This program 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 of the License, or + (at your option) any later version. + + This program 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 program. If not, see <http://www.gnu.org/licenses/>. */ + +#ifndef SAFE_BOOL_H +#define SAFE_BOOL_H 1 + +/* Helper classes used to implement the safe bool idiom, for compilers + that don't support "explicit operator bool()" (C++11). Classes + that want to support explicit boolean conversion inherit from + safe_bool (using CRTP) and implement the explicit_operator_bool + method. */ + +class safe_bool_base +{ +protected: + typedef void (safe_bool_base::*bool_type) () const; + void this_type_does_not_support_comparisons () const {} +}; + +/* Baseclass, using CRTP. */ + +template <typename T = void> +class safe_bool : public safe_bool_base { +public: + operator bool_type () const + { + return (static_cast<const T *>(this))->explicit_operator_bool () + ? &safe_bool_base::this_type_does_not_support_comparisons : 0; + } + +protected: + ~safe_bool () {} +}; + +/* Comparison operators. */ + +template <typename T, typename U> +bool operator== (const safe_bool<T> &lhs, const safe_bool<U> &rhs) +{ + lhs.this_type_does_not_support_comparisons (); + return false; +} + +template <typename T,typename U> +bool operator!= (const safe_bool<T> &lhs, const safe_bool<U> &rhs) +{ + lhs.this_type_does_not_support_comparisons (); + return false; +} + +#endif /* SAFE_BOOL_H */ -- 2.5.5 ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-10 16:46 ` [PATCH 1/3] Introduce gdb::unique_ptr Pedro Alves @ 2016-10-10 17:49 ` Simon Marchi 2016-10-10 18:03 ` Pedro Alves 2016-10-11 6:48 ` Metzger, Markus T 1 sibling, 1 reply; 72+ messages in thread From: Simon Marchi @ 2016-10-10 17:49 UTC (permalink / raw) To: Pedro Alves; +Cc: gdb-patches This is clearly way above my C++ skill level, I feel like I'm reading boost code. But since it's well encapsulated in a "support" file and mimics the standard behaviors, I think it's good. I just hope the whole codebase won't end up lookup like this :). On 2016-10-10 12:46, Pedro Alves wrote: > - support for all of 'ptr != NULL', 'ptr == NULL' and 'if (ptr)' > using the safe bool idiom. Since our coding style doesn't allow the "if (ptr)" form, is it possible to make it cause a compile error? > +/* Base class of our unique_ptr emulation. Contains code common to > + both the unique_ptr<T, D> and unique_ptr<T[], D>. */ > + > +template<typename T, typename D> > +class unique_ptr_base : public safe_bool <unique_ptr_base<T, D> > > +{ > +public: > + typedef T *pointer; pointer_type? ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-10 17:49 ` Simon Marchi @ 2016-10-10 18:03 ` Pedro Alves 0 siblings, 0 replies; 72+ messages in thread From: Pedro Alves @ 2016-10-10 18:03 UTC (permalink / raw) To: Simon Marchi; +Cc: gdb-patches On 10/10/2016 06:49 PM, Simon Marchi wrote: > This is clearly way above my C++ skill level, I feel like I'm reading > boost code. Oh, boost has a unique_ptr emulation, and _that_ one is almost impenetrable. ;-) This version is trivial in comparison. That said, it has the advantage that is fully transparent on the "client" side, for routine usage. Other than std vs gdb namespace, that is. > But since it's well encapsulated in a "support" file and > mimics the standard behaviors, I think it's good. I just hope the whole > codebase won't end up lookup like this :). Yeah. This, just like the operator new patch, this is foundational work. A smart pointer is the major gaping hole right now. With this in place, I expect that we'll add lots of uses like in patches #2 and #3, but don't expect to need to touch the "library" code all that much or at all. > > On 2016-10-10 12:46, Pedro Alves wrote: >> - support for all of 'ptr != NULL', 'ptr == NULL' and 'if (ptr)' >> using the safe bool idiom. > > Since our coding style doesn't allow the "if (ptr)" form, is it possible > to make it cause a compile error? The point is that std::unique_ptr allows it, so I'd rather allow it in C++03 as well, otherwise we'd potentially introduce unnoticed build errors when developing with GCC >= 6. I found the need for that with patch #2 (expression_up). As soon as you convert a raw pointer to a smart pointer, all old code that was working with the raw pointer is now going through the smart pointer. And it's that old code that surprisingly has the "if (ptr)" form in several places. > >> +/* Base class of our unique_ptr emulation. Contains code common to >> + both the unique_ptr<T, D> and unique_ptr<T[], D>. */ >> + >> +template<typename T, typename D> >> +class unique_ptr_base : public safe_bool <unique_ptr_base<T, D> > >> +{ >> +public: >> + typedef T *pointer; > > pointer_type? That's part of the std::unique_ptr interface: http://en.cppreference.com/w/cpp/memory/unique_ptr Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 72+ messages in thread
* RE: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-10 16:46 ` [PATCH 1/3] Introduce gdb::unique_ptr Pedro Alves 2016-10-10 17:49 ` Simon Marchi @ 2016-10-11 6:48 ` Metzger, Markus T 2016-10-11 10:23 ` Pedro Alves 1 sibling, 1 reply; 72+ messages in thread From: Metzger, Markus T @ 2016-10-11 6:48 UTC (permalink / raw) To: Pedro Alves, gdb-patches > -----Original Message----- > From: gdb-patches-owner@sourceware.org [mailto:gdb-patches- > owner@sourceware.org] On Behalf Of Pedro Alves > Sent: Monday, October 10, 2016 6:47 PM > To: gdb-patches@sourceware.org > Subject: [PATCH 1/3] Introduce gdb::unique_ptr Hello Pedro, > Many make_cleanup uses in the code base are best eliminated by using a > "owning" smart pointer to manage ownership of the resource > automatically. > > The question is _which_ smart pointer. > > We have std::auto_ptr in C++03, but, as is collective wisdom by now, > that's too easy to misuse, and has therefore been deprecated in C++11 > and finally removed in C++17. Would it make sense to switch to C++11, instead? Or delay this work until we can make this move? Thanks, Markus. Intel Deutschland GmbH Registered Address: Am Campeon 10-12, 85579 Neubiberg, Germany Tel: +49 89 99 8853-0, www.intel.de Managing Directors: Christin Eisenschmid, Christian Lamprechter Chairperson of the Supervisory Board: Nicole Lau Registered Office: Munich Commercial Register: Amtsgericht Muenchen HRB 186928 ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 6:48 ` Metzger, Markus T @ 2016-10-11 10:23 ` Pedro Alves 2016-10-11 10:53 ` Andreas Schwab ` (2 more replies) 0 siblings, 3 replies; 72+ messages in thread From: Pedro Alves @ 2016-10-11 10:23 UTC (permalink / raw) To: Metzger, Markus T, gdb-patches On 10/11/2016 07:47 AM, Metzger, Markus T wrote: >> -----Original Message----- >> From: gdb-patches-owner@sourceware.org [mailto:gdb-patches- >> owner@sourceware.org] On Behalf Of Pedro Alves >> Sent: Monday, October 10, 2016 6:47 PM >> To: gdb-patches@sourceware.org >> Subject: [PATCH 1/3] Introduce gdb::unique_ptr > > Hello Pedro, Hi Markus, > >> Many make_cleanup uses in the code base are best eliminated by using a >> "owning" smart pointer to manage ownership of the resource >> automatically. >> >> The question is _which_ smart pointer. >> >> We have std::auto_ptr in C++03, but, as is collective wisdom by now, >> that's too easy to misuse, and has therefore been deprecated in C++11 >> and finally removed in C++17. > > Would it make sense to switch to C++11, instead? I think it would make a lot of sense to switch to C++11. I'd love that. rvalue references support, move-aware containers, "auto", std::unique_ptr and std::shared_ptr would be all very nice to have. The only question in my mind is -- are people OK with requiring gcc 4.8 or later? I think gcc 4.8 or newer were available in Fedora 20. I believe Ubuntu 12.04 had it available as an option. On older RHEL systems, it's available in DTS. On older systems, you'd need to compile a newer gcc or clang first before building gdb. Would people find that acceptable? Or put another way, would anyone find that unacceptable? But meanwhile, I don't want C++ conversion to be blocked by that. Hence this new shim. Even if we don't require C++11, I think it'd make sense to compile in C++11 mode if we have a capable compiler. I.e., if you have gcc 4.8 or newer, pass -std=gnu++11/-std=gnu++0x if necessary. > Or delay this work until we can make this move? No, I don't think so. I think we need _some_ owning smart pointer. An alternative is some separate RAII object that destroys a pointer when leaving a scope: template <class T> struct cleanup_pointer { explicit cleanup_pointer(T *p) : m_ptr (p) {} cleanup_pointer { if (m_ptr != NULL) delete m_ptr; } void discard () { m_ptr = NULL; } T *m_ptr; }; // Document that this returns a new object that must // be released with "delete". struct foo *function_returning_new_ptr (); // Document that this uses P, ownership is still with the caller. // May throw. void foo (struct foo *p); // Document that P is no longer owned by the caller after this. // May throw. void bar (struct foo *p); void some_function () { struct foo *ptr = function_returning_new_ptr (); cleanup_pointer<struct foo *> cleanup (ptr); ptr->foo = .....; bar (ptr); // whoops, bar now owns the pointer, but // cleanup_pointer will delete it anyway // once we leave this scope // would need to remember to call this. // cleanup.discard (); } That looks very much like our current cleanups, except we no longer need the "do_cleanups" call. But it's far from idiomatic C++. And, ends up being more code to write/maintain than using a smart pointer. We can do better. E.g.,: // (gdb::unique_ptr is like std::unique_ptr and // gdb::move is like std::move for gdb::unique_ptr) // prototype clearly tells you this returns a new object. gdb::unique_ptr <struct foo> function_returning_new_ptr (); // Uses P, ownership is still with the caller. void foo (struct foo *p); // Clearly tells you this transfers ownership. void bar (gdb::unique_ptr <struct foo> p); void some_function () { // struct foo *ptr = function_returning_new_ptr (); // would not compile. gdb::unique_ptr <struct foo> ptr = function_returning_new_ptr (); // OK, ownership clearly transferred to caller. ptr->foo = .....; foo (ptr.get ()); // clearly foo borrows the pointer. bar (gdb::move (ptr)); // clearly transfers ownership. } The other use case a smart pointer clarifies is making a structure/class be the owner of some pointer. Like: struct foo { gdb::unique_ptr <struct foo> ptr; }; When a "foo" is destroyed, then ptr is destroyed automatically as well. Without the smart pointer, we'd have to explicitly write delete ptr in a destructor: struct foo { ~foo() { delete ptr; } struct foo *ptr; }; Most C++03 projects past a size/history will bake their own custom smart pointers for the use cases above. Most large projects will have invented theirs before std::unique_ptr existed though, so they'll differ in API details. However in our case, std::unique_ptr is already there, so I think it makes a lot of sense to reuse the same API, and take advantage of newer compilers as "lints", since that's what people will be using for development anyway. Once we do require C++11, then we won't have to relearn a new smart pointer API. Even if we were to use std::auto_ptr only, I would still think that that would be an improvement over raw pointers, since with raw pointers it's even easier to confuse "borrowing pointers" from "owning pointers", since you have 0 zero help from the type system. The potential problems with std::auto_ptr stem from its "move semantics", and are of the form: std::auto_ptr<type> ptr = function_returning_type (); std::auto_ptr<type> ptr2 = ptr; // this moves instead of // copying. I.e., ptr is NULL after this. and: void function (std::auto_ptr<type> ptr); function (ptr); // This moves instead of copying. ptr is NULL after this. ptr->foo = 1; // crash. In the latter case, the function prototype indicates that the caller wants to transfer ownership of the pointer to the callee. But that's not clear at the call site. So in C++03 mode, gdb::unique_ptr "allows" that too. I.e., the compiler won't complain. However, that _won't_ compile in C++11 mode, forcing you to write instead: gdb::unique_ptr<type> ptr2 = gdb::move (ptr); // OK, now move is clearly // what was intended. function (gdb::move (ptr2)); // Likewise. ptr2->foo = 1; // crash, but, obviously incorrect. And of course the C++03 gdb::unique_ptr version supports this as well. There's also the advantage that gdb::unique_ptr works with malloced objects, and arrays (for 'new some_type[];'). We'd need _some_ smart pointer for those, so std::auto_ptr alone won't be sufficient anyway... WDYT? Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 10:23 ` Pedro Alves @ 2016-10-11 10:53 ` Andreas Schwab 2016-10-11 11:17 ` Metzger, Markus T 2016-10-11 12:16 ` Joel Brobecker 2 siblings, 0 replies; 72+ messages in thread From: Andreas Schwab @ 2016-10-11 10:53 UTC (permalink / raw) To: Pedro Alves; +Cc: Metzger, Markus T, gdb-patches On Okt 11 2016, Pedro Alves <palves@redhat.com> wrote: > I think gcc 4.8 or newer were available in Fedora 20. I believe > Ubuntu 12.04 had it available as an option. On older RHEL systems, > it's available in DTS. It is also available for SLES11 on the SDK. Andreas. -- Andreas Schwab, SUSE Labs, schwab@suse.de GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE 1748 E4D4 88E3 0EEA B9D7 "And now for something completely different." ^ permalink raw reply [flat|nested] 72+ messages in thread
* RE: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 10:23 ` Pedro Alves 2016-10-11 10:53 ` Andreas Schwab @ 2016-10-11 11:17 ` Metzger, Markus T 2016-10-11 11:43 ` Pedro Alves 2016-10-11 12:16 ` Joel Brobecker 2 siblings, 1 reply; 72+ messages in thread From: Metzger, Markus T @ 2016-10-11 11:17 UTC (permalink / raw) To: Pedro Alves, gdb-patches > -----Original Message----- > From: Pedro Alves [mailto:palves@redhat.com] > Sent: Tuesday, October 11, 2016 12:23 PM > To: Metzger, Markus T <markus.t.metzger@intel.com>; gdb- > patches@sourceware.org > Subject: Re: [PATCH 1/3] Introduce gdb::unique_ptr > > Would it make sense to switch to C++11, instead? > > I think it would make a lot of sense to switch to C++11. I'd love > that. rvalue references support, move-aware containers, "auto", > std::unique_ptr and std::shared_ptr would be all very nice to have. > > The only question in my mind is -- are people OK with requiring > gcc 4.8 or later? > > I think gcc 4.8 or newer were available in Fedora 20. I believe > Ubuntu 12.04 had it available as an option. On older RHEL systems, > it's available in DTS. > > On older systems, you'd need to compile a newer gcc or clang first > before building gdb. Would people find that acceptable? Or put > another way, would anyone find that unacceptable? [...] > WDYT? Wow, that was a long reply to such a small question. I was mainly wondering if it makes sense to write (and maintain) ones own version of a standard library feature. The big step was not supporting C any longer. Requiring C++11 looks small, by comparison. BTW, I noticed that maintainers seem very busy these days and patches are waiting unusually long for review. Regards, Markus. Intel Deutschland GmbH Registered Address: Am Campeon 10-12, 85579 Neubiberg, Germany Tel: +49 89 99 8853-0, www.intel.de Managing Directors: Christin Eisenschmid, Christian Lamprechter Chairperson of the Supervisory Board: Nicole Lau Registered Office: Munich Commercial Register: Amtsgericht Muenchen HRB 186928 ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 11:17 ` Metzger, Markus T @ 2016-10-11 11:43 ` Pedro Alves 2016-10-11 13:58 ` Yao Qi 2016-10-11 14:05 ` Trevor Saunders 0 siblings, 2 replies; 72+ messages in thread From: Pedro Alves @ 2016-10-11 11:43 UTC (permalink / raw) To: Metzger, Markus T, gdb-patches On 10/11/2016 12:16 PM, Metzger, Markus T wrote: > Wow, that was a long reply to such a small question. I was mainly > wondering if it makes sense to write (and maintain) ones own version > of a standard library feature. > > The big step was not supporting C any longer. Requiring C++11 looks > small, by comparison. Agreed, from language perspective. The question is one of _compiler_ access and convenience. But it looks like I might have been wrong in my previous perception that dropping support for older GCCs would be unrealistic at this point. I'd love to hear other's opinions. > BTW, I noticed that maintainers seem very busy these days and patches > are waiting unusually long for review. Yeah. Myself, I don't really know nowadays what it means to not be very busy, and also getting the 7.12 release/branch ready took me significant effort. Over the past few releases, I've been considering whether an explicit "bugfixes/regressions only" state, like gcc's stages would help -- because what happens is that people send in patches for master and the pings and if they're not following development closely, they won't realize the reason people are not looking at their patches is the focus on the release, and everyone is frustrated. At least I am. Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 11:43 ` Pedro Alves @ 2016-10-11 13:58 ` Yao Qi 2016-10-11 14:05 ` Trevor Saunders 1 sibling, 0 replies; 72+ messages in thread From: Yao Qi @ 2016-10-11 13:58 UTC (permalink / raw) To: Pedro Alves; +Cc: Metzger, Markus T, gdb-patches On Tue, Oct 11, 2016 at 12:43 PM, Pedro Alves <palves@redhat.com> wrote: >> BTW, I noticed that maintainers seem very busy these days and patches >> are waiting unusually long for review. > > Yeah. Myself, I don't really know nowadays what it means to not be very busy, and > also getting the 7.12 release/branch ready took me significant effort. Over the > past few releases, I've been considering whether an explicit "bugfixes/regressions > only" state, like gcc's stages would help -- because what happens is that > people send in patches for master and the pings and if they're not following > development closely, they won't realize the reason people are not > looking at their patches is the focus on the release, and everyone is > frustrated. At least I am. That is helpful to manage people's expectation... In every release, it takes me about 1~2 months on seriously test, bug fix and regression fix. I'd like to see the gcc-like stages in gdb development. -- Yao (齐尧) ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 11:43 ` Pedro Alves 2016-10-11 13:58 ` Yao Qi @ 2016-10-11 14:05 ` Trevor Saunders 1 sibling, 0 replies; 72+ messages in thread From: Trevor Saunders @ 2016-10-11 14:05 UTC (permalink / raw) To: Pedro Alves; +Cc: Metzger, Markus T, gdb-patches On Tue, Oct 11, 2016 at 12:43:09PM +0100, Pedro Alves wrote: > On 10/11/2016 12:16 PM, Metzger, Markus T wrote: > > > Wow, that was a long reply to such a small question. I was mainly > > wondering if it makes sense to write (and maintain) ones own version > > of a standard library feature. fwiw, I've been meaning to add this to gcc at some point for the same reasons. Since I doubt gcc is interested in requiring C++11 that will probably happen and it will stay around for a while either way. In addition its not terribly complex code, and I expect it won't change much. > > The big step was not supporting C any longer. Requiring C++11 looks > > small, by comparison. > > Agreed, from language perspective. The question is one of _compiler_ access > and convenience. But it looks like I might have been wrong in my previous > perception that dropping support for older GCCs would be unrealistic at > this point. I'd love to hear other's opinions. > > > BTW, I noticed that maintainers seem very busy these days and patches > > are waiting unusually long for review. > > Yeah. Myself, I don't really know nowadays what it means to not be very busy, and > also getting the 7.12 release/branch ready took me significant effort. Over the > past few releases, I've been considering whether an explicit "bugfixes/regressions > only" state, like gcc's stages would help -- because what happens is that > people send in patches for master and the pings and if they're not following > development closely, they won't realize the reason people are not > looking at their patches is the focus on the release, and everyone is > frustrated. At least I am. Personally I find the gcc setup frustrating too, and I imagine its a real pain if you just want to get one patch in. The ideal answer is probably get more people who can review, with enough people the cut branches and keep developing trunk seems to work well enough ime, but I'm definitely busy ;) Trev > > Thanks, > Pedro Alves > ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 10:23 ` Pedro Alves 2016-10-11 10:53 ` Andreas Schwab 2016-10-11 11:17 ` Metzger, Markus T @ 2016-10-11 12:16 ` Joel Brobecker 2016-10-11 13:46 ` Pedro Alves 2 siblings, 1 reply; 72+ messages in thread From: Joel Brobecker @ 2016-10-11 12:16 UTC (permalink / raw) To: Pedro Alves; +Cc: Metzger, Markus T, gdb-patches > I think it would make a lot of sense to switch to C++11. I'd love > that. rvalue references support, move-aware containers, "auto", > std::unique_ptr and std::shared_ptr would be all very nice to have. > > The only question in my mind is -- are people OK with requiring > gcc 4.8 or later? FWIW, I think it is fine to require C++11 if there are sufficient benefits we can derive from it. This seems like a good example of something we could simplify greatly if we did? Note that I wouldn't necessarily think in purely in terms of which version of GCC supports it, but also consider whether want to support building GDB with non-GCC compilers, particularly on the more exotic systems out there, where it can be hard to build GDB. Do all these compilers support C++11? Probably not. This is where it becomes a judgment call for me. Making it easy to build with other compilers by limiting which parts of the language we can use helps getting wider use of GDB; but on the other hand, if it comes at too much of a cost in terms of the code and its maintenance, then it seems better overall to increase our list of requirements. -- Joel ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 12:16 ` Joel Brobecker @ 2016-10-11 13:46 ` Pedro Alves 2016-10-11 14:47 ` Joel Brobecker 0 siblings, 1 reply; 72+ messages in thread From: Pedro Alves @ 2016-10-11 13:46 UTC (permalink / raw) To: Joel Brobecker; +Cc: Metzger, Markus T, gdb-patches On 10/11/2016 01:16 PM, Joel Brobecker wrote: >> I think it would make a lot of sense to switch to C++11. I'd love >> that. rvalue references support, move-aware containers, "auto", >> std::unique_ptr and std::shared_ptr would be all very nice to have. >> >> The only question in my mind is -- are people OK with requiring >> gcc 4.8 or later? > > FWIW, I think it is fine to require C++11 if there are sufficient > benefits we can derive from it. This seems like a good example > of something we could simplify greatly if we did? In the particular issue of an owning smart pointer, I think the shim as I'm proposing buys us some time, and unblocks a lot more struct cleanup elimination and simplification of the codebase. I'd still propose going forward with it immediately. It's really not a complicated template, IMO. I've removed generic comments that basically were explaining how all smart pointers behave anyway, and inlined the safe bool idiom into gdb::unique_ptr directly, and removed the C++11 bits, and the result is only around 250 lines of still-commented code. See patch pasted below (just for reference). Of course, this version misses the benefit of using C++11 when available as a "lint", so it's as "unsafe" as std::auto_ptr, because it _is_ actually std::auto_ptr on steroids. Going full C++11 would certainly give us good benefits. It's a much cleaner language overall. Beyond the benefits mentioned above, there's also std::unordered_map as standard type-safe hash table and other containers. Lambda expressions probably came in handy in many places. Likewise std::function. variadic templates would help simplify template code we might want to add -- see Tromey's observers-in-C++ series. For gcc's older than 6.1, we'd need to force-enable c++11 mode, with -std=gnu++11/-std=gnu++0x, and I think that needs to be done by the top level configure, because CXX is passed down to subdirs. Since the top level is shared with gcc, that may not be trivial. It gets particularly more interesting if different project subdirs have different ideas of level of C++11 support they tolerate. So a staged approach would do the "prefer C++11-if-available" first (w/ -std=...), in order to make use of C++11 features when possible and make sure virtually everyone developing gdb is using the "safer" gdb::unique_ptr version. Once that works and is all in place and breaks nothing else, switching to "require C++11", if designed right, should then be an easy change. > > Note that I wouldn't necessarily think in purely in terms of which > version of GCC supports it, but also consider whether want to support > building GDB with non-GCC compilers, particularly on the more exotic > systems out there, where it can be hard to build GDB. Do all these > compilers support C++11? Probably not. Looking at: https://sourceware.org/gdb/wiki/Systems I think we're pretty much down to not-that-exotic hosts nowadays. At least, all hosts there seem to me like should have working gcc or clang ports. The AIX system on the gcc compile farm has gcc 4.8.1 (AIX 7.1). For BSDs, there's clang and gcc. Of course old BSDs won't have new gcc/clang, you'd have to build a new compiler. But that's the same as old GNU/Linux distros. FWIW, building clang/llvm/lldb requires a C++11 compiler too. > This is where it becomes > a judgment call for me. Making it easy to build with other compilers > by limiting which parts of the language we can use helps getting wider > use of GDB; but on the other hand, if it comes at too much of a cost > in terms of the code and its maintenance, then it seems better overall > to increase our list of requirements. Thanks, Pedro Alves #ifndef GDB_UNIQUE_PTR_H #define GDB_UNIQUE_PTR_H 1 namespace gdb { /* Default destruction policy used by gdb::unique_ptr when no deleter is specified. Uses delete. */ template<typename T> struct default_delete { void operator () (T *ptr) const { delete ptr; } }; /* Specialization for arrays. Uses delete[]. */ template<typename T> struct default_delete<T[]> { void operator () (T *ptr) const { delete [] ptr; } }; /* Type used to support assignment from NULL: gdb::unique_ptr<foo> ptr (....); ... ptr = NULL; */ struct unique_ptr_nullptr_t { private: struct private_type; public: /* Since null_type is private, the only way to construct this class is by passing a NULL pointer. See unique_ptr_base::operator= further below. */ unique_ptr_nullptr_t (private_type *) {} }; /* Base class of our unique_ptr emulation. Contains code common to both the unique_ptr<T, D> and unique_ptr<T[], D>. */ template<typename T, typename D> class unique_ptr_base { public: typedef T *pointer; typedef T element_type; typedef D deleter_type; template <typename T1> struct unique_ptr_base_ref { T1 *m_ptr; explicit unique_ptr_base_ref (T1 *p): m_ptr (p) {} }; typedef unique_ptr_base_ref<T> ref_type; explicit unique_ptr_base (element_type *p = NULL) throw() : m_ptr (p) {} /* Even though std::unique_ptr is not copyable, our little simpler emulation allows it (behaves like std::auto_ptr), because RVO/NRVO requires an accessible copy constructor, and also because our move emulation relies on this. */ unique_ptr_base (unique_ptr_base& a) throw() : m_ptr (a.release ()) {} /* Assignment operator. Actually moves. We implement this simply to allow std::swap work without having to provide our own swap implementation. We know that if GDB compiles with real std::unique_ptr, this won't be called "incorrectly". */ unique_ptr_base & operator= (unique_ptr_base &a) throw() { reset (a.release ()); return *this; } /* std::unique_ptr does not allow assignment, except from nullptr. nullptr doesn't exist before C++11, so we allowing assignment from NULL instead: ptr = NULL; */ unique_ptr_base & operator= (const unique_ptr_nullptr_t &) throw() { reset (); return *this; } ~unique_ptr_base () { call_deleter (); } /* "explicit operator bool ()" emulation using the safe bool idiom. */ private: typedef void (unique_ptr_base::*bool_type) () const; void this_type_does_not_support_comparisons () const {} public: operator bool_type () const { return (m_ptr != NULL ? &unique_ptr_base::this_type_does_not_support_comparisons : 0); } element_type *get () const throw() { return m_ptr; } element_type *release () throw() { pointer tmp = m_ptr; m_ptr = NULL; return tmp; } void reset (element_type *p = NULL) throw() { if (p != m_ptr) { call_deleter (); m_ptr = p; } } /* Automatic conversions. These operations convert an unique_ptr_base into and from an unique_ptr_base_ref automatically as needed. This allows constructs such as: unique_ptr<Derived> func_returning_unique_ptr (.....); ... unique_ptr<Base> ptr = func_returning_unique_ptr (.....); */ unique_ptr_base (unique_ptr_base_ref<element_type> ref) throw() : m_ptr (ref.m_ptr) {} unique_ptr_base & operator= (unique_ptr_base_ref<element_type> ref) throw() { if (ref.m_ptr != this->get()) { call_deleter (); m_ptr = ref.m_ptr; } return *this; } template<typename T1> operator unique_ptr_base_ref<T1> () throw() { return unique_ptr_base_ref<T1> (this->release ()); } template<typename T1, typename D1> operator unique_ptr_base<T1, D1> () throw() { return unique_ptr_base<T1, D1> (this->release ()); } private: /* Call the deleter. Note we assume the deleter is "stateless". */ void call_deleter () { D d; d (m_ptr); } element_type *m_ptr; }; /* Macro used to create a unique_ptr_base "specialization" -- a subclass that uses a specific deleter. Basically this re-defines the necessary constructors. This is necessary because we can't inherit constructors with "using" without C++11. While at it, we inherit the assignment operator. TYPE is the name of the type being defined. Assumes that 'base_type' is a typedef of the baseclass UNIQUE_PTR is inheriting from. */ #define DEFINE_UNIQUE_PTR(TYPE) \ public: \ explicit TYPE (T *p = NULL) throw() \ : base_type (p) {} \ TYPE (typename base_type::ref_type ref) throw() \ : base_type (ref.m_ptr) {} \ \ using base_type::operator=; /* Define non-array gdb::unique_ptr. */ template <typename T, typename D = default_delete<T> > class unique_ptr : public unique_ptr_base<T, D> { typedef unique_ptr_base<T, D> base_type; DEFINE_UNIQUE_PTR (unique_ptr) /* Dereferencing. */ T &operator* () const throw() { return *this->get (); } T *operator-> () const throw() { return this->get (); } }; /* gdb::unique_ptr specialization for T[]. */ template <typename T, typename D> class unique_ptr<T[], D> : public unique_ptr_base<T, D> { typedef unique_ptr_base<T, D> base_type; DEFINE_UNIQUE_PTR (unique_ptr) /* Indexing operator. */ T& operator[] (size_t i) const { return this->get ()[i]; } }; /* Comparison operators. */ template <typename T, typename D, typename U, typename E> inline bool operator== (const unique_ptr_base<T, D>& x, const unique_ptr_base<U, E>& y) { return x.get() == y.get(); } template <typename T, typename D, typename U, typename E> inline bool operator!= (const unique_ptr_base<T, D>& x, const unique_ptr_base<U, E>& y) { return x.get() != y.get(); } /* std::move "emulation". This is as simple as it can be -- relies on the fact that our std::unique_ptr emulation actually behaves like std::auto_ptr -- copy/assignment actually moves. */ template<typename T, typename D> unique_ptr_base<T, D> move (unique_ptr_base<T, D> v) { return v; } /* Define gdb::unique_malloc_ptr, a gdb::unique_ptr that manages malloc'ed memory. */ /* The deleter for gdb::unique_malloc_ptr. Uses xfree. */ template <typename T> struct xfree_deleter { void operator() (T *ptr) const { xfree (ptr); } }; /* In C++03, we don't have template aliases, so we need to define a subclass instead (and re-define the constructors, because we don't have inheriting constructors either). */ template <typename T> class unique_malloc_ptr : public unique_ptr<T, xfree_deleter<T> > { typedef unique_ptr<T, xfree_deleter<T> > base_type; DEFINE_UNIQUE_PTR (unique_malloc_ptr) }; } /* namespace gdb */ #endif /* GDB_UNIQUE_PTR_H */ ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 13:46 ` Pedro Alves @ 2016-10-11 14:47 ` Joel Brobecker 2016-10-11 15:17 ` Eli Zaretskii 0 siblings, 1 reply; 72+ messages in thread From: Joel Brobecker @ 2016-10-11 14:47 UTC (permalink / raw) To: Pedro Alves; +Cc: Metzger, Markus T, gdb-patches > In the particular issue of an owning smart pointer, I think the > shim as I'm proposing buys us some time, and unblocks a lot more > struct cleanup elimination and simplification of the codebase. > I'd still propose going forward with it immediately. That would make sense to me. > > Note that I wouldn't necessarily think in purely in terms of which > > version of GCC supports it, but also consider whether want to support > > building GDB with non-GCC compilers, particularly on the more exotic > > systems out there, where it can be hard to build GDB. Do all these > > compilers support C++11? Probably not. > > Looking at: > > https://sourceware.org/gdb/wiki/Systems > > I think we're pretty much down to not-that-exotic hosts nowadays. > At least, all hosts there seem to me like should have working > gcc or clang ports. Agreed. Mostly, I was thinking of seeing if we can avoid the requirement to build a GCC first, if all you are interested in is actually building GDB. But, if C++11 is a much cleaner language overall, and its runtime provides some nice additions, I think it makes better sense technically to align ourselves to it. We've already made a huge requirement jump; let's just do it right all the way. That increment doesn't seem all that significant compared to requiring a C++ compiler. -- Joel ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 14:47 ` Joel Brobecker @ 2016-10-11 15:17 ` Eli Zaretskii 2016-10-11 16:24 ` Pedro Alves 0 siblings, 1 reply; 72+ messages in thread From: Eli Zaretskii @ 2016-10-11 15:17 UTC (permalink / raw) To: Joel Brobecker; +Cc: palves, markus.t.metzger, gdb-patches > Date: Tue, 11 Oct 2016 07:47:41 -0700 > From: Joel Brobecker <brobecker@adacore.com> > Cc: "Metzger, Markus T" <markus.t.metzger@intel.com>, "gdb-patches@sourceware.org" <gdb-patches@sourceware.org> > > > I think we're pretty much down to not-that-exotic hosts nowadays. > > At least, all hosts there seem to me like should have working > > gcc or clang ports. > > Agreed. Mostly, I was thinking of seeing if we can avoid the requirement > to build a GCC first, if all you are interested in is actually building > GDB. But, if C++11 is a much cleaner language overall, and its runtime > provides some nice additions, I think it makes better sense technically > to align ourselves to it. We've already made a huge requirement jump; > let's just do it right all the way. That increment doesn't seem all > that significant compared to requiring a C++ compiler. IMO, requiring to build GCC as a prerequisite for building GDB is a major setback. Building GDB is a relatively easy and straightforward task today, even a native MS-Windows build. By contrast, building GCC requires quite a few additional prerequisites, which will also need to be built correctly. It also requires to configure the GCC being built itself, which involves considering a large number of opt-in and opt-out features, whose descriptions are not well suited for casual users, and therefore whose consequences cannot be easily understood. Please don't do that. As someone who builds GDB since v7.4 (and offers it for other MinGW users as prebuilt binary package), such a requirement will be a death blow for me, because building GCC on MS-Windows is even more complicated than doing that on Posix platforms. Yes, I use GCC, of course, but I just upgraded to 5.3.0 here a few months ago, while you seem to be already talking about 6.x. If we start on this slippery slope, I can easily envision the requirement to go up to 7.x very soon, exactly like switching to C++-compatible GDB caused, within just few months, a massive rewrite of GDB in complex C++, something that IMO was never planned or discussed before actually doing it. It's only natural: one out of the bottle, no genie can be constrained anymore. So please let's not start on this slippery slope. Let's continue requiring only the standards that are widely available with the compiler versions out there, which in practice means we should always support GCC versions from at least 5 years ago, and at least 2 major releases ago. I don't expect my request to be honored, or even considered seriously. But I cannot let this pass without voicing my very strong opposition to such a requirement. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 15:17 ` Eli Zaretskii @ 2016-10-11 16:24 ` Pedro Alves 2016-10-11 16:58 ` Eli Zaretskii 2016-10-11 17:15 ` Luis Machado 0 siblings, 2 replies; 72+ messages in thread From: Pedro Alves @ 2016-10-11 16:24 UTC (permalink / raw) To: Eli Zaretskii, Joel Brobecker; +Cc: markus.t.metzger, gdb-patches On 10/11/2016 04:16 PM, Eli Zaretskii wrote: > IMO, requiring to build GCC as a prerequisite for building GDB is a > major setback. Building GDB is a relatively easy and straightforward > task today, even a native MS-Windows build. By contrast, building GCC > requires quite a few additional prerequisites, which will also need to > be built correctly. It also requires to configure the GCC being built > itself, which involves considering a large number of opt-in and > opt-out features, whose descriptions are not well suited for casual > users, and therefore whose consequences cannot be easily understood. Windows may be one of the hardest systems on which to build GCC. For Unix systems, it's relatively painless. It's easy to find scripts around the web that download the necessary dependencies and build gcc, all in one go. I think the GCC source tree has contrib patches for at least the downloading part. > Yes, I use GCC, of course, but I just upgraded to 5.3.0 here a few > months ago, while you seem to be already talking about 6.x. If we > start on this slippery slope, I can easily envision the requirement to > go up to 7.x very soon, exactly like switching to C++-compatible GDB > caused, within just few months, That's a misunderstanding. Full C++11 support is available in gcc 4.8 already. I believe it's easy to find binary mingw gcc's of (at least) that vintage easily, for both mingw and mingw-64. mingw talks about gcc 4.8 binaries here: http://www.mingw.org/wiki/howto_install_the_mingw_gcc_compiler_suite I don't expect anyone to _have_ to build any mingw compiler to be able to build gdb for mingw. It's just that gcc 6.x is the first version that has switched the _default_ mode for C++ to -std=gnu++14. So until someone writes a patch that make gdb's build system enable C++11 support with gcc < 6, then the C++11-only code in the gdb::unique_ptr patch that I'm proposing will only be active with gcc 6.1 onward. But really I'm not proposing to _require_ 6.x at all. > a massive rewrite of GDB in complex C++. Most of the changes have been around using std::string, destructors, and RAII, which are basic everyday C++ things. The latter two are mainly about using compiler support for things we have to manually today (make_cleanup). std::string just makes code shorter and safer, I don't see a real downside or anything complex about it. A few patches that build supporting widgets will naturally use a bit more complex C++ internally, all in the name of making _users_ of such widgets significantly simpler. This patch is one such example. These kinds of support patches naturally will need to come before we can make use of the features they add support for, so while it may appear we're going to keep adding lots of magic things, I don't think that's true. Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 16:24 ` Pedro Alves @ 2016-10-11 16:58 ` Eli Zaretskii 2016-10-11 17:41 ` Pedro Alves 2016-10-11 17:15 ` Luis Machado 1 sibling, 1 reply; 72+ messages in thread From: Eli Zaretskii @ 2016-10-11 16:58 UTC (permalink / raw) To: Pedro Alves; +Cc: brobecker, markus.t.metzger, gdb-patches > Cc: markus.t.metzger@intel.com, gdb-patches@sourceware.org > From: Pedro Alves <palves@redhat.com> > Date: Tue, 11 Oct 2016 17:24:09 +0100 > > On 10/11/2016 04:16 PM, Eli Zaretskii wrote: > > > IMO, requiring to build GCC as a prerequisite for building GDB is a > > major setback. Building GDB is a relatively easy and straightforward > > task today, even a native MS-Windows build. By contrast, building GCC > > requires quite a few additional prerequisites, which will also need to > > be built correctly. It also requires to configure the GCC being built > > itself, which involves considering a large number of opt-in and > > opt-out features, whose descriptions are not well suited for casual > > users, and therefore whose consequences cannot be easily understood. > > Windows may be one of the hardest systems on which to build GCC. > For Unix systems, it's relatively painless. It's easy to find scripts > around the web that download the necessary dependencies and build gcc, > all in one go. I think the GCC source tree has contrib patches for > at least the downloading part. I take your word for it, as the last time I built GCC was a long time ago. I just know that I've read the latest GCC installation instructions and found myself utterly confused wrt which options I did or did not want/need. Asking around didn't really help, because everyone whom I asked basically told me "this is what I do, most of it is taken from someone else before me". Even if scripts are available that already have that decision figured out, how is the user to know that decision is good for him/her? You don't build and install a compiler for a single job of building GDB, you build it to make it your system compiler henceforth. So this decision, which options are and aren't needed is a serious one, and I for one am unlikely to trust others with that decision (and have trench stories to tell how not trusting them gave me a better package than was available out there). > > Yes, I use GCC, of course, but I just upgraded to 5.3.0 here a few > > months ago, while you seem to be already talking about 6.x. If we > > start on this slippery slope, I can easily envision the requirement to > > go up to 7.x very soon, exactly like switching to C++-compatible GDB > > caused, within just few months, > > That's a misunderstanding. Full C++11 support is available > in gcc 4.8 already. Yes, I know. I'm just envisioning that once we require to build GCC, we will soon require a new enough version of it. Like Joel says: > We've already made a huge requirement jump; let's just do it right > all the way. That increment doesn't seem all that significant > compared to requiring a C++ compiler. I see where it's going, and I don't like it. We will make it hard on users to build GDB. Just 7 months ago all you needed was a C90 compiler, and look where we are now. > I believe it's easy to find binary mingw gcc's of (at least) that > vintage easily, for both mingw and mingw-64. If we stay with 4.8 for long enough, I have no problem. But we must record this decision somewhere and stick to it, because otherwise it will be one more domino to fall, and soon enough. > I don't expect anyone to _have_ to build any mingw compiler to be able > to build gdb for mingw. If you suddenly require 6.x or 7.x, they will have no choice. > It's just that gcc 6.x is the first version that has switched > the _default_ mode for C++ to -std=gnu++14. So until someone writes a > patch that make gdb's build system enable C++11 support with gcc < 6, > then the C++11-only code in the gdb::unique_ptr patch that I'm proposing > will only be active with gcc 6.1 onward. But really I'm not > proposing to _require_ 6.x at all. How's above not requiring 6.x? "Until someone writes a patch that make gdb's build system enable C++11 support with gcc < 6" one must have 6.x, or some code will not work or be unavailable for them, right? (And isn't there confusion between gnu++14 and C++11?) > > a massive rewrite of GDB in complex C++. > > Most of the changes have been around using std::string, destructors, > and RAII, which are basic everyday C++ things. The latter two are > mainly about using compiler support for things we have to manually > today (make_cleanup). std::string just makes code shorter and safer, > I don't see a real downside or anything complex about it. > > A few patches that build supporting widgets will naturally use a > bit more complex C++ internally, all in the name of making _users_ of > such widgets significantly simpler. This patch is one such example. > These kinds of support patches naturally will need to come > before we can make use of the features they add support for, so > while it may appear we're going to keep adding lots of magic > things, I don't think that's true. Maybe you are 110% right; all I know is that these C++ surprises started pouring on us with increasing rate without any prior discussion, that's all. But I don't want to argue about C++, that was just an example of a slippery slope similar to what I fear will happen once we require a new enough GCC to be able to compile GDB. I think that would be a bad mistake. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 16:58 ` Eli Zaretskii @ 2016-10-11 17:41 ` Pedro Alves 2016-10-11 18:37 ` Eli Zaretskii 0 siblings, 1 reply; 72+ messages in thread From: Pedro Alves @ 2016-10-11 17:41 UTC (permalink / raw) To: Eli Zaretskii; +Cc: brobecker, markus.t.metzger, gdb-patches On 10/11/2016 05:57 PM, Eli Zaretskii wrote: >> That's a misunderstanding. Full C++11 support is available >> in gcc 4.8 already. > > Yes, I know. I'm just envisioning that once we require to build GCC, > we will soon require a new enough version of it. Like Joel says: That still sounds like a misunderstanding, because we're not requiring that you build GCC. We're talking about requiring C++11 support. There's a difference. If you don't have a compiler that supports C++11, _then_ you'd have to build one. That is, we're mainly talking about the trade off between getting access to C++11 and how that would improve the codebase and maintainability vs convenience of getting a new gdb built on an older system with an old system compiler. > >> We've already made a huge requirement jump; let's just do it right >> all the way. That increment doesn't seem all that significant >> compared to requiring a C++ compiler. > > I see where it's going, and I don't like it. We will make it hard on > users to build GDB. Just 7 months ago all you needed was a C90 > compiler, and look where we are now. There's no sekrit conspiracy here. We all want gdb to succeed, don't we? All we're talking about is being able to use features that our friends on the gcc side have been working hard at making available to users, because well, they're actually useful. Of course there's a balance between wanting to use the latest features, and waiting until compiler availability is reasonably widespread. > >> I believe it's easy to find binary mingw gcc's of (at least) that >> vintage easily, for both mingw and mingw-64. > > If we stay with 4.8 for long enough, I have no problem. But we must > record this decision somewhere and stick to it, because otherwise it > will be one more domino to fall, and soon enough. Yes, of course if we move forward with a requirement change we'll document it. It'll naturally end up reevaluated at some point, maybe years from now. The jump from C++03 -> C++11 is _huge_. C++11 -> C++14 not that much. > >> I don't expect anyone to _have_ to build any mingw compiler to be able >> to build gdb for mingw. > > If you suddenly require 6.x or 7.x, they will have no choice. Well, that's (an unintended, no doubt) strawman, because no one is suggesting that. > >> It's just that gcc 6.x is the first version that has switched >> the _default_ mode for C++ to -std=gnu++14. So until someone writes a >> patch that make gdb's build system enable C++11 support with gcc < 6, >> then the C++11-only code in the gdb::unique_ptr patch that I'm proposing >> will only be active with gcc 6.1 onward. But really I'm not >> proposing to _require_ 6.x at all. > > How's above not requiring 6.x? "Until someone writes a patch that > make gdb's build system enable C++11 support with gcc < 6" one must > have 6.x, or some code will not work or be unavailable for them, > right? (And isn't there confusion between gnu++14 and C++11?) The code still works with older gccs, and just as efficiently. I'll make an analogy. Think of it as if GCC 6.x enabled some useful warning flag by default that used to be disabled by default. Until someone enables the warning on older GCCs that support it, some styles of code we don't want to allow compile successfully, while with 6.x, we get a hard error due to -Werror. So code smells that might get into the tree because they were only tested against an old GCC will will be caught quickly by whoever next builds gdb with a newer GCC that enables the warning by default. The C++11-only code in question that I'm proposing is just what enables the "warning". The C++03 version of the same code does not trigger any "warning", but it still runs. > Maybe you are 110% right; all I know is that these C++ surprises > started pouring on us with increasing rate without any prior > discussion, that's all. First, it's not true that these C++ changes have not been planned. They've been part of the plan ever since the very beginning. See here, step 5 of the original version of the plan I originally circulated in 2014: https://sourceware.org/gdb/wiki/cxx-conversion?action=recall&rev=1 Current version is here: https://sourceware.org/gdb/wiki/cxx-conversion#Transition_plan Note the not-done-yet bullet points in step 8 (step 5 in rev 1). That's exactly what's going on right now. I've also discussed the next steps of the transition on my Cauldron talk this September, though that was indeed recent: https://gcc.gnu.org/wiki/cauldron2016#Slides.2C_Videos_and_Notes Still, that's just rehashing what was already planned. But truth be told, I wasn't expecting patches to appear so fast either! Most of my C++ patches had been on the "enablement" form thus far, with the bigger ones in sourceware branches. But if people are willing to spend the effort to contributing nice C++ conversion series (which is awesome, IMO), that means they care significantly about the health of the codebase and the project, and thus I'll try to review those patches quickly, in order to keep the contributor's motivation alive. So I see the recent rush as a _good_ thing. > > But I don't want to argue about C++, that was just an example of a > slippery slope similar to what I fear will happen once we require a > new enough GCC to be able to compile GDB. I think that would be a bad > mistake. Again, no one's proposed that. Heck, until today I was under the impression that gcc 4.8 was too new and had assumed proposing to require that for C++11 would be out of question. But I'm very happy to learn that I've been mistaken! Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 17:41 ` Pedro Alves @ 2016-10-11 18:37 ` Eli Zaretskii 2016-10-11 19:19 ` Pedro Alves 2016-10-11 19:23 ` Simon Marchi 0 siblings, 2 replies; 72+ messages in thread From: Eli Zaretskii @ 2016-10-11 18:37 UTC (permalink / raw) To: Pedro Alves; +Cc: brobecker, markus.t.metzger, gdb-patches > Cc: brobecker@adacore.com, markus.t.metzger@intel.com, > gdb-patches@sourceware.org > From: Pedro Alves <palves@redhat.com> > Date: Tue, 11 Oct 2016 18:41:01 +0100 > > On 10/11/2016 05:57 PM, Eli Zaretskii wrote: > > >> That's a misunderstanding. Full C++11 support is available > >> in gcc 4.8 already. > > > > Yes, I know. I'm just envisioning that once we require to build GCC, > > we will soon require a new enough version of it. Like Joel says: > > That still sounds like a misunderstanding, because we're not > requiring that you build GCC. Maybe it is indeed a misunderstanding, but then perhaps you could re-read what you and Joel were saying, to see how such a misunderstanding could happen, and avoid saying things in the future that could be misinterpreted. > We're talking about requiring C++11 support. There's a difference. > If you don't have a compiler that supports C++11, _then_ you'd have > to build one. As long as we stay with C++11, I have no problem (although it does look like a huge jump, which we perhaps should have taken more slowly, and stay with C++03 for now). My problem begins where we will in a few months jump so easily to C++14 and whatever else is after that. I see no reason not to fear this, do you? Where are the rules and decisions that we won't? > That is, we're mainly talking about the trade off between getting > access to C++11 and how that would improve the codebase and > maintainability vs convenience of getting a new gdb built on an > older system with an old system compiler. Please don't forget that you look at these problems from the POV of someone who always have the newest tools available. I'm trying to keep these decisions in their proper perspective by taking a POV of someone whose tools are one or 2 major GCC releases older. > > I see where it's going, and I don't like it. We will make it hard on > > users to build GDB. Just 7 months ago all you needed was a C90 > > compiler, and look where we are now. > > There's no sekrit conspiracy here. I didn't think there were a conspiracy. But that doesn't help, does it? Such slippery slopes are known human tendency, the only way to avoid that is not to step on the slope in the first place. > > If we stay with 4.8 for long enough, I have no problem. But we must > > record this decision somewhere and stick to it, because otherwise it > > will be one more domino to fall, and soon enough. > > Yes, of course if we move forward with a requirement change we'll > document it. I think we need to document that before we more forward. Otherwise we won't know whether we are moving forward or not, and won't know to stop and think a bit before we do. > It'll naturally end up reevaluated at some point, maybe years from > now. The jump from C++03 -> C++11 is _huge_. C++11 -> C++14 not > that much. Then maybe we shouldn't make that huge jump, not just yet. It was never discussed seriously, AFAIK. > >> I don't expect anyone to _have_ to build any mingw compiler to be able > >> to build gdb for mingw. > > > > If you suddenly require 6.x or 7.x, they will have no choice. > > Well, that's (an unintended, no doubt) strawman, because no one is > suggesting that. That's not how I read your messages. Apologies for my misunderstanding, but I can show you how your words actually made that sound as if you were. > I'll make an analogy. Think of it as if GCC 6.x enabled some > useful warning flag by default that used to be disabled by default. I don't think it's a good analogy. You are not talking about warning switches, are you? > First, it's not true that these C++ changes have not been planned. > They've been part of the plan ever since the very beginning. See > here, step 5 of the original version of the plan I originally > circulated in 2014: > > https://sourceware.org/gdb/wiki/cxx-conversion?action=recall&rev=1 > > Current version is here: > > https://sourceware.org/gdb/wiki/cxx-conversion#Transition_plan > > Note the not-done-yet bullet points in step 8 (step 5 in rev 1). > That's exactly what's going on right now. Where does it say that we should require C++11? Or any specific version of the C++ standard, for that matter? AFAIR, this was never discussed. > > But I don't want to argue about C++, that was just an example of a > > slippery slope similar to what I fear will happen once we require a > > new enough GCC to be able to compile GDB. I think that would be a bad > > mistake. > > Again, no one's proposed that. Heck, until today I was under the > impression that gcc 4.8 was too new and had assumed proposing to require > that for C++11 would be out of question. But I'm very happy to > learn that I've been mistaken! I'd still be happier if you were not mistaken. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 18:37 ` Eli Zaretskii @ 2016-10-11 19:19 ` Pedro Alves 2016-10-11 20:47 ` Eli Zaretskii 2016-10-11 19:23 ` Simon Marchi 1 sibling, 1 reply; 72+ messages in thread From: Pedro Alves @ 2016-10-11 19:19 UTC (permalink / raw) To: Eli Zaretskii; +Cc: brobecker, markus.t.metzger, gdb-patches On 10/11/2016 07:36 PM, Eli Zaretskii wrote: > As long as we stay with C++11, I have no problem (although it does > look like a huge jump, which we perhaps should have taken more slowly, > and stay with C++03 for now). My problem begins where we will in a > few months jump so easily to C++14 and whatever else is after that. I > see no reason not to fear this, do you? I see no reason to fear this at all. Yes, I think it'd be great to be able to use C++14. It's still C++, but with extra features that make our lives easier. No questions there, IMO. The impediment would be _compiler availability_. The reason you don't have to fear this is that in a few months, C++14 compiler availability will not really have changed much. In a few years, it'll be likely that every 4-year-old-or-some-such-by-then distro will have a C++14 compiler handy. And likely so will you. But maybe someone brings up the topic then and we'll still decide it's not worth to require C++14 anyway. We'll surely reevaluate and figure out what is going to be reasonable _then_. > Where are the rules and decisions that we won't? What sort of rules are you expecting? > >> That is, we're mainly talking about the trade off between getting >> access to C++11 and how that would improve the codebase and >> maintainability vs convenience of getting a new gdb built on an >> older system with an old system compiler. > > Please don't forget that you look at these problems from the POV of > someone who always have the newest tools available. That's plain false. I've been asked about "why not C++11" many times recently, and I've always said that we likely wouldn't be able to assume that C++11 compilers were readily available sufficiently yet. There are examples of that on this list just recently, even. I've even had heated discussions internally, fencing off from C++11 even, exactly due to concern of causing too much inconvenience on people! > I'm trying to > keep these decisions in their proper perspective by taking a POV of > someone whose tools are one or 2 major GCC releases older. And that's the perspective I'm taking as well! My system compiler is gcc 5.3, for example. And as I've said several times already, we're talking about gcc 4.8, not gcc 7. I don't understand why you keep bringing up that point. > >>> I see where it's going, and I don't like it. We will make it hard on >>> users to build GDB. Just 7 months ago all you needed was a C90 >>> compiler, and look where we are now. >> >> There's no sekrit conspiracy here. > > I didn't think there were a conspiracy. But that doesn't help, does > it? I guess it helps as much as suggesting that we'll suddenly require 6.x or 7.x, as if we'd do that without considering community consensus or doing a reasonable evaluation of general availability / convenience. That sounds borderline insulting, even, but I know that you don't mean that. > Such slippery slopes are known human tendency, the only way to > avoid that is not to step on the slope in the first place. I want to climb the slope. That's the only way out, and I don't want to stay. But I'll take my time. If we go slow, I won't slip. > >>> If we stay with 4.8 for long enough, I have no problem. But we must >>> record this decision somewhere and stick to it, because otherwise it >>> will be one more domino to fall, and soon enough. >> >> Yes, of course if we move forward with a requirement change we'll >> document it. > > I think we need to document that before we more forward. Otherwise we > won't know whether we are moving forward or not, and won't know to > stop and think a bit before we do. > >> It'll naturally end up reevaluated at some point, maybe years from >> now. The jump from C++03 -> C++11 is _huge_. C++11 -> C++14 not >> that much. > > Then maybe we shouldn't make that huge jump, not just yet. It was > never discussed seriously, AFAIK. Well, we're discussing it right now, in several threads, even. By "huge", I meant that having access to C++11 would be super awesome. It makes it possible to do things in way less "magic" ways. C++03 requires lots of weird contortions. So if we could use C++11, you'd see _less_ complex C++! C++14 is an improvement over C++11, but the improvement is not so much as the improvement from C++03 to C++11. That's what I meant. > >>>> I don't expect anyone to _have_ to build any mingw compiler to be able >>>> to build gdb for mingw. >>> >>> If you suddenly require 6.x or 7.x, they will have no choice. >> >> Well, that's (an unintended, no doubt) strawman, because no one is >> suggesting that. > > That's not how I read your messages. Apologies for my > misunderstanding, but I can show you how your words actually made that > sound as if you were. Please do. I'd love to learn to be clearer. > >> I'll make an analogy. Think of it as if GCC 6.x enabled some >> useful warning flag by default that used to be disabled by default. > > I don't think it's a good analogy. You are not talking about warning > switches, are you? I think it's an excellent analogy, actually. Of course I'm not talking about warning switches -- it's an _analogy_. I'm talking about something that has the _exact same effect_. A new default warning on GCC often triggers new build errors, because we use -Werror. See all the recent -Wimplicit-fallthrough on this list and on binutils@. Exact same thing. Newer GCCs catch more problems. That's exactly what I'm proposing with the C++11-only bits in this patch. > >> First, it's not true that these C++ changes have not been planned. >> They've been part of the plan ever since the very beginning. See >> here, step 5 of the original version of the plan I originally >> circulated in 2014: >> >> https://sourceware.org/gdb/wiki/cxx-conversion?action=recall&rev=1 >> >> Current version is here: >> >> https://sourceware.org/gdb/wiki/cxx-conversion#Transition_plan >> >> Note the not-done-yet bullet points in step 8 (step 5 in rev 1). >> That's exactly what's going on right now. > > Where does it say that we should require C++11? Or any specific > version of the C++ standard, for that matter? AFAIR, this was never > discussed. Eli, the require-C++11 discussion was not this particular subthread. Look back to what you're replying to. The context is, you argued: >> a massive rewrite of GDB in complex C++. I pointed out that the rewrites going on are not that complex, they're basic C++. You then said: > Maybe you are 110% right; all I know is that these C++ surprises > started pouring on us with increasing rate without any prior > discussion, that's all. And I pointed out that it's not true that these "complex C++" changes that you were referring to (the existing patches pending on the lists) have not been planned. > >>> But I don't want to argue about C++, that was just an example of a >>> slippery slope similar to what I fear will happen once we require a >>> new enough GCC to be able to compile GDB. I think that would be a bad >>> mistake. >> >> Again, no one's proposed that. Heck, until today I was under the >> impression that gcc 4.8 was too new and had assumed proposing to require >> that for C++11 would be out of question. But I'm very happy to >> learn that I've been mistaken! > > I'd still be happier if you were not mistaken. You yourself said that you have gcc 5.x available. I don't really understand why we're still arguing about this. Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 19:19 ` Pedro Alves @ 2016-10-11 20:47 ` Eli Zaretskii 2016-10-11 21:32 ` Pedro Alves 0 siblings, 1 reply; 72+ messages in thread From: Eli Zaretskii @ 2016-10-11 20:47 UTC (permalink / raw) To: Pedro Alves; +Cc: brobecker, markus.t.metzger, gdb-patches > From: Pedro Alves <palves@redhat.com> > Date: Tue, 11 Oct 2016 20:19:14 +0100 > > > Where are the rules and decisions that we won't? > > What sort of rules are you expecting? What is the oldest version of GCC and C/C++ we are willing to support, and how many months/years from now we plan to reconsider that, for example. > >>> If you suddenly require 6.x or 7.x, they will have no choice. > >> > >> Well, that's (an unintended, no doubt) strawman, because no one is > >> suggesting that. > > > > That's not how I read your messages. Apologies for my > > misunderstanding, but I can show you how your words actually made that > > sound as if you were. > > Please do. I'd love to learn to be clearer. Joel: > Agreed. Mostly, I was thinking of seeing if we can avoid the requirement > to build a GCC first, if all you are interested in is actually building > GDB. But, if C++11 is a much cleaner language overall, and its runtime > provides some nice additions, I think it makes better sense technically > to align ourselves to it. We've already made a huge requirement jump; > let's just do it right all the way. That increment doesn't seem all > that significant compared to requiring a C++ compiler. You: > It's just that gcc 6.x is the first version that has switched > the _default_ mode for C++ to -std=gnu++14. So until someone writes a > patch that make gdb's build system enable C++11 support with gcc < 6, > then the C++11-only code in the gdb::unique_ptr patch that I'm proposing > will only be active with gcc 6.1 onward. But really I'm not > proposing to _require_ 6.x at all. > You yourself said that you have gcc 5.x available. I don't really > understand why we're still arguing about this. I'm still arguing because you all but decided to declare that to enjoy GDB to its fullest one has from now on to have GCC 6.x. GCC 6.1 was released just this April, so it sounds too drastic to require it only a few months later. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 20:47 ` Eli Zaretskii @ 2016-10-11 21:32 ` Pedro Alves 2016-10-12 6:34 ` Eli Zaretskii 0 siblings, 1 reply; 72+ messages in thread From: Pedro Alves @ 2016-10-11 21:32 UTC (permalink / raw) To: Eli Zaretskii; +Cc: brobecker, markus.t.metzger, gdb-patches On 10/11/2016 09:47 PM, Eli Zaretskii wrote: >> From: Pedro Alves <palves@redhat.com> >> Date: Tue, 11 Oct 2016 20:19:14 +0100 >> >>> Where are the rules and decisions that we won't? >> >> What sort of rules are you expecting? > > What is the oldest version of GCC and C/C++ we are willing to support, Please reread the whole thread... That was _my_ question. IMO, that should be decided based on what's the oldest version people really care about _in practice_, and are willing to routinely test and send fixes for. Claiming we support gcc 3.4 and then not testing it is pointless. IMO, it'd be reasonable to say we only make an effort to support gcc >= 4.8. We have buildbots testing that. > and how many months/years from now we plan to reconsider that, for > example. I don't think this matters in practice. We may reconsider every week, and decide "no change" for 2 years. Or reconsider every 2 years, and decide "change". Same result. I don't when or whether in practice we'll stumble on some thing that it'd be significantly easier to write if we required a newer compiler. Time will tell. > >>>>> If you suddenly require 6.x or 7.x, they will have no choice. >>>> >>>> Well, that's (an unintended, no doubt) strawman, because no one is >>>> suggesting that. >>> >>> That's not how I read your messages. Apologies for my >>> misunderstanding, but I can show you how your words actually made that >>> sound as if you were. >> >> Please do. I'd love to learn to be clearer. > > Joel: > >> Agreed. Mostly, I was thinking of seeing if we can avoid the requirement >> to build a GCC first, if all you are interested in is actually building >> GDB. But, if C++11 is a much cleaner language overall, and its runtime >> provides some nice additions, I think it makes better sense technically >> to align ourselves to it. We've already made a huge requirement jump; >> let's just do it right all the way. That increment doesn't seem all >> that significant compared to requiring a C++ compiler. (this was in context of building a new gdb on old systems with no C++11 compiler available.) > > You: > >> It's just that gcc 6.x is the first version that has switched >> the _default_ mode for C++ to -std=gnu++14. So until someone writes a >> patch that make gdb's build system enable C++11 support with gcc < 6, >> then the C++11-only code in the gdb::unique_ptr patch that I'm proposing >> will only be active with gcc 6.1 onward. But really I'm not >> proposing to _require_ 6.x at all. I don't understand what's not clear here. Conceptually, the gdb::unique_ptr patch (this thread) does: #if HAVE_STD_UNIQUE_PTR // just use it #else // write replacement #endif The replacement is fully functional. If I push the patch in now, HAVE_STD_UNIQUE_PTR will only be true when compiling GDB with GCC >= 6.x, because G++ 6.1 targets G++14 by default, which is a superset of C++11. The replacement works with all other GCCs. It'd be possible to make HAVE_STD_UNIQUE_PTR be true with GCC >= 4.x too, but nobody wrote that patch yet. As Simon said, this is just like making use of some gnulib module to make up for some missing bit in the system's C runtime. I fail to see the worry here. It's not like I'm proposing to only enable some user-visible feature if GDB is built with some compiler versions. >> You yourself said that you have gcc 5.x available. I don't really >> understand why we're still arguing about this. > > I'm still arguing because you all but decided to declare that to enjoy > GDB to its fullest one has from now on to have GCC 6.x. GCC 6.1 was > released just this April, so it sounds too drastic to require it only > a few months later. Eli, I've repeatedly told you that that's completely false. No one is suggesting that. At this point I have to wonder whether you're not listening on purpose. Please re-read the whole thread from the top, including the series's intro. It will be amply clear that _the whole point of the patch_ is to keep supporting older compilers. Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 21:32 ` Pedro Alves @ 2016-10-12 6:34 ` Eli Zaretskii 2016-10-12 8:11 ` Metzger, Markus T 2016-10-12 9:37 ` [PATCH 1/3] Introduce gdb::unique_ptr Pedro Alves 0 siblings, 2 replies; 72+ messages in thread From: Eli Zaretskii @ 2016-10-12 6:34 UTC (permalink / raw) To: Pedro Alves; +Cc: brobecker, markus.t.metzger, gdb-patches > Cc: brobecker@adacore.com, markus.t.metzger@intel.com, > gdb-patches@sourceware.org > From: Pedro Alves <palves@redhat.com> > Date: Tue, 11 Oct 2016 22:32:09 +0100 > > As Simon said, this is just like making use of some gnulib module > to make up for some missing bit in the system's C runtime. A new version of a language is entirely different from a missing library function. > I fail to see the worry here. It's not like I'm proposing to only > enable some user-visible feature if GDB is built with some compiler > versions. Rest assured, very soon we will. It's not that different from what you are suggesting now, so once allowed, we will have no good arguments to disallow that in the future, including when it affects user-visible features. Someone will come up and say "how is that different from having features on GNU/Linux that are not available on other OSes?" And we will have no good answer for them. The _only_ good answer in these cases is the established coding standards and project-wide regulations. Nothing else stands in the face of the "why not?" arguments. > > I'm still arguing because you all but decided to declare that to enjoy > > GDB to its fullest one has from now on to have GCC 6.x. GCC 6.1 was > > released just this April, so it sounds too drastic to require it only > > a few months later. > > Eli, I've repeatedly told you that that's completely false. No one > is suggesting that. Jan just did. So "completely false" is completely false. And what you are suggesting, while not as radical as what Jan says, will still get us there soon enough. > At this point I have to wonder whether you're not listening on > purpose. This goes both ways, you know. And I hope you understand how it could be an insult when actually written in a discussion. Why do we need to get to this level each time I happen to disagree with something here? It's the reason why I speak so little here about my opinions on the various matters. ^ permalink raw reply [flat|nested] 72+ messages in thread
* RE: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-12 6:34 ` Eli Zaretskii @ 2016-10-12 8:11 ` Metzger, Markus T 2016-10-12 9:31 ` Eli Zaretskii 2016-10-12 10:28 ` Pedro Alves 2016-10-12 9:37 ` [PATCH 1/3] Introduce gdb::unique_ptr Pedro Alves 1 sibling, 2 replies; 72+ messages in thread From: Metzger, Markus T @ 2016-10-12 8:11 UTC (permalink / raw) To: Eli Zaretskii, Pedro Alves Cc: brobecker, gdb-patches, Jan Kratochvil (jan.kratochvil@redhat.com), Simon Marchi Sorry, I did not intend to start such a heated discussion. I think we got hung up on the perceived requirement of having to build your own GCC. The discussion got a bit too abstract and mentioning GCC 6 as the first to default to C++11 may have been confusing in the heat of the discussion as "GCC 6 defaults to C++11" may have been misread as "C++11 requires GCC 6". A simple and pragmatic solution would be a patch to add -std=c++11 to GDB's compiler options. Pedro already mentioned it but I'm afraid it got lost. This documents the required language version and also prevents people from accidentally using C++14/17/?? features and not noticing it until one of the buildbot builders complained. I don't think that requiring C++11 is entirely unreasonable and IMHO preferable to back-porting standard library features. Should I be wrong and C++11 is really not doable, I like Pedro's patch for giving the direction towards C++11. I would still add a compiler option to enforce C++03 for the above reasons. Regards, Markus. Intel Deutschland GmbH Registered Address: Am Campeon 10-12, 85579 Neubiberg, Germany Tel: +49 89 99 8853-0, www.intel.de Managing Directors: Christin Eisenschmid, Christian Lamprechter Chairperson of the Supervisory Board: Nicole Lau Registered Office: Munich Commercial Register: Amtsgericht Muenchen HRB 186928 ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-12 8:11 ` Metzger, Markus T @ 2016-10-12 9:31 ` Eli Zaretskii 2016-10-12 10:12 ` Pedro Alves 2016-10-12 10:28 ` Pedro Alves 1 sibling, 1 reply; 72+ messages in thread From: Eli Zaretskii @ 2016-10-12 9:31 UTC (permalink / raw) To: Metzger, Markus T Cc: palves, brobecker, gdb-patches, jan.kratochvil, simon.marchi > From: "Metzger, Markus T" <markus.t.metzger@intel.com> > CC: "brobecker@adacore.com" <brobecker@adacore.com>, > "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>, "Jan Kratochvil > (jan.kratochvil@redhat.com)" <jan.kratochvil@redhat.com>, Simon Marchi > <simon.marchi@ericsson.com> > Date: Wed, 12 Oct 2016 08:11:44 +0000 > > I think we got hung up on the perceived requirement of having to build > your own GCC. The discussion got a bit too abstract and mentioning GCC 6 > as the first to default to C++11 may have been confusing in the heat of the > discussion as "GCC 6 defaults to C++11" may have been misread as "C++11 > requires GCC 6". I don't think that's what happened. In my interpretation, there are simply several issues intertwined in this discussion (which probably adds to confusion): . Should we start using C++11 features in GDB? . If the answer to the above is YES, then should we require a C++11 capable compiler as a prerequisite, or should we provide fallback code for compilers that don't support C++11, not even with a non-default command-line option? . Should we document these decisions and also decide to abide by them for some reasonably long stretch of time? > A simple and pragmatic solution would be a patch to add -std=c++11 > to GDB's compiler options. Pedro already mentioned it but I'm afraid it > got lost. > > This documents the required language version and also prevents people > from accidentally using C++14/17/?? features and not noticing it until one of > the buildbot builders complained. > > I don't think that requiring C++11 is entirely unreasonable and IMHO > preferable to back-porting standard library features. > > Should I be wrong and C++11 is really not doable, I like Pedro's patch > for giving the direction towards C++11. I would still add a compiler option > to enforce C++03 for the above reasons. Here are my opinions on the above 3 issues: . I think we should stay with C++03 for at least a year. Jumping from C90 to C++11 sounds too huge a jump. Setting the bar on C++03 would mean we still allow GCC 4.3, AFAIU, which was released in 2008. That's less than 10 years from today, so not too old IMO. We could also decide to switch to C99-level compilers, which AFAIU means GCC 4.5, released in 2010. (GCC 4.8.1, with its C++11 support, was released in 2013.) . Whatever standard we decide to aim, we should require a compiler that is capable of supporting that standard, whether with or without optional command-line switches, and we should use those switches if necessary (detected by configure) during the build. We should not provide any fallback code for compilers that don't support the standard we decide to use -- such fallback code is just maintenance headache and in the long run means code that is rarely if ever tested. . We should clearly document these decisions, and abide by them. Resetting the bar to a higher standard should IMO be based on the number of years since the release of the first GCC that supports that standard. The number of years we would like to aim for should also be a documented decision. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-12 9:31 ` Eli Zaretskii @ 2016-10-12 10:12 ` Pedro Alves 2016-10-12 11:05 ` Eli Zaretskii 0 siblings, 1 reply; 72+ messages in thread From: Pedro Alves @ 2016-10-12 10:12 UTC (permalink / raw) To: Eli Zaretskii, Metzger, Markus T Cc: brobecker, gdb-patches, jan.kratochvil, simon.marchi On 10/12/2016 10:31 AM, Eli Zaretskii wrote: >> From: "Metzger, Markus T" <markus.t.metzger@intel.com> >> CC: "brobecker@adacore.com" <brobecker@adacore.com>, >> "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>, "Jan Kratochvil >> (jan.kratochvil@redhat.com)" <jan.kratochvil@redhat.com>, Simon Marchi >> <simon.marchi@ericsson.com> >> Date: Wed, 12 Oct 2016 08:11:44 +0000 >> >> I think we got hung up on the perceived requirement of having to build >> your own GCC. The discussion got a bit too abstract and mentioning GCC 6 >> as the first to default to C++11 may have been confusing in the heat of the >> discussion as "GCC 6 defaults to C++11" may have been misread as "C++11 >> requires GCC 6". > > I don't think that's what happened. In my interpretation, there are > simply several issues intertwined in this discussion (which probably > adds to confusion): > > . Should we start using C++11 features in GDB? I would hope that no one would suggest that we shouldn't use C++11 features just because they like C++03 better than C++11. That would make no sense. In my mind, the only reason you'd not use C++11 over C++03 is simply because you couldn't because you don't have a compiler that supports it. IMO, at this point, the number of systems that don't have a C++11 compiler handy AND where you'd absolutely need to build a new GDB is sufficiently small that the desire to use C++11 features overwhelms the inconvenience of having to build a new compiler first, on those specific cases. Many of the larger projects around the free software community require C++11 nowadays. It's quite likely that even on older systems you'll have arranged to set up a newer compiler that supports C++11, because it is dependency on the programs that you'll likely want to debug with gdb. Alternatives to GDB, like lldb, already require a C++11 compiler anyway, so C++11 alone won't be a reason that would cause people to try alternatives on those systems. But even if we don't _require_ C++11, IMO, yes, we should still use select C++11 features when available, in implementation details of gdb's general utilities, when they add extra safety or efficiency that is simply not possible in C++03. TBC, I would reject patches that added: #if cxx11 ... #else ... #endif sprinkled around the codebase in non-utility code. > . Should we document these decisions and also decide to abide by > them for some reasonably long stretch of time? Sure, we should document the decisions. But I see no point in locking ourselves to past decisions on a timed basis. Past decisions should be reevaluated simply when they longer make sense. I.e., apply past reasoning to current reality and see if the same answer comes out. Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-12 10:12 ` Pedro Alves @ 2016-10-12 11:05 ` Eli Zaretskii 2016-10-12 11:25 ` Pedro Alves 0 siblings, 1 reply; 72+ messages in thread From: Eli Zaretskii @ 2016-10-12 11:05 UTC (permalink / raw) To: Pedro Alves Cc: markus.t.metzger, brobecker, gdb-patches, jan.kratochvil, simon.marchi > Cc: brobecker@adacore.com, gdb-patches@sourceware.org, > jan.kratochvil@redhat.com, simon.marchi@ericsson.com > From: Pedro Alves <palves@redhat.com> > Date: Wed, 12 Oct 2016 11:11:50 +0100 > > > . Should we start using C++11 features in GDB? > > I would hope that no one would suggest that we shouldn't use > C++11 features just because they like C++03 better than C++11. > That would make no sense. It would make perfect sense if we decide to require a version of GCC older than 4.8.1 as a prerequisite for building GDB. > In my mind, the only reason you'd not use C++11 over C++03 > is simply because you couldn't because you don't have a > compiler that supports it. IMO, at this point, the number > of systems that don't have a C++11 compiler handy AND where > you'd absolutely need to build a new GDB is sufficiently small that > the desire to use C++11 features overwhelms the inconvenience > of having to build a new compiler first, on those specific cases. These are qualitative arguments. We need a quantitative criteria for when to raise the bar for the minimum supported language standard. Such a criterion could be the number of years since the release of the GCC version that fully supports that standard. If this is an acceptable criterion, can we talk about the number of years we would like to set up as the quantitative parameter here? Can we then commit ourselves to upholding that criterion for the observable future? > Many of the larger projects around the free software community > require C++11 nowadays. And many still support C90. E.g., Emacs started requiring C99 in version 25.1, released just a month ago. GNU Make still supports C90, as does Gawk. So I don't think this is a useful argument, because there are examples either way. > But even if we don't _require_ C++11, IMO, yes, we should > still use select C++11 features when available, in implementation > details of gdb's general utilities, when they add extra safety or > efficiency that is simply not possible in C++03. If these features are supported by whatever versions of the compiler we decide to require, I agree. > TBC, I would reject patches that added: > > #if cxx11 > ... > #else > ... > #endif > > sprinkled around the codebase in non-utility code. Agreed. > > . Should we document these decisions and also decide to abide by > > them for some reasonably long stretch of time? > > Sure, we should document the decisions. But I see no point in locking > ourselves to past decisions on a timed basis. Past decisions should > be reevaluated simply when they longer make sense. I.e., > apply past reasoning to current reality and see if the same answer > comes out. "No longer make sense" is again too vague to be efficient in preventing arguments like this one. We should decide on firm principles and stick to them. Even if that means we will keep the bar lower for longer than absolutely necessary (and it doesn't have to mean that), that's hardly a catastrophe. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-12 11:05 ` Eli Zaretskii @ 2016-10-12 11:25 ` Pedro Alves 2016-10-12 11:45 ` Eli Zaretskii 0 siblings, 1 reply; 72+ messages in thread From: Pedro Alves @ 2016-10-12 11:25 UTC (permalink / raw) To: Eli Zaretskii Cc: markus.t.metzger, brobecker, gdb-patches, jan.kratochvil, simon.marchi On 10/12/2016 12:04 PM, Eli Zaretskii wrote: >> Cc: brobecker@adacore.com, gdb-patches@sourceware.org, >> jan.kratochvil@redhat.com, simon.marchi@ericsson.com >> From: Pedro Alves <palves@redhat.com> >> Date: Wed, 12 Oct 2016 11:11:50 +0100 >> >>> . Should we start using C++11 features in GDB? >> >> I would hope that no one would suggest that we shouldn't use >> C++11 features just because they like C++03 better than C++11. >> That would make no sense. > > It would make perfect sense if we decide to require a version of GCC > older than 4.8.1 as a prerequisite for building GDB. I can't see how that is a reply to what I said. I said _liking_ C++11 better over C++03. As in: "I'm just not going to use C++11 features, because I hate C++11, but C++03 is perfectly fine". I wouldn't find such position reasonable. Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-12 11:25 ` Pedro Alves @ 2016-10-12 11:45 ` Eli Zaretskii 2016-10-13 12:12 ` Pedro Alves 0 siblings, 1 reply; 72+ messages in thread From: Eli Zaretskii @ 2016-10-12 11:45 UTC (permalink / raw) To: Pedro Alves Cc: markus.t.metzger, brobecker, gdb-patches, jan.kratochvil, simon.marchi > Cc: markus.t.metzger@intel.com, brobecker@adacore.com, > gdb-patches@sourceware.org, jan.kratochvil@redhat.com, > simon.marchi@ericsson.com > From: Pedro Alves <palves@redhat.com> > Date: Wed, 12 Oct 2016 12:25:21 +0100 > > On 10/12/2016 12:04 PM, Eli Zaretskii wrote: > >> Cc: brobecker@adacore.com, gdb-patches@sourceware.org, > >> jan.kratochvil@redhat.com, simon.marchi@ericsson.com > >> From: Pedro Alves <palves@redhat.com> > >> Date: Wed, 12 Oct 2016 11:11:50 +0100 > >> > >>> . Should we start using C++11 features in GDB? > >> > >> I would hope that no one would suggest that we shouldn't use > >> C++11 features just because they like C++03 better than C++11. > >> That would make no sense. > > > > It would make perfect sense if we decide to require a version of GCC > > older than 4.8.1 as a prerequisite for building GDB. > > I can't see how that is a reply to what I said. I said _liking_ C++11 > better over C++03. As in: "I'm just not going to use > C++11 features, because I hate C++11, but C++03 is perfectly > fine". That's a no-brainer, but if that was the only thing you were saying, then how does it relate to the issue to which you responded, i.e. whether we should decide to start using C++11 now? That decision has IMO very little to do with whether we like C++03 more or not, because if we go by that criterion alone, we should take Jan's suggestion and switch to the latest version as soon as it is released, right? ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-12 11:45 ` Eli Zaretskii @ 2016-10-13 12:12 ` Pedro Alves 0 siblings, 0 replies; 72+ messages in thread From: Pedro Alves @ 2016-10-13 12:12 UTC (permalink / raw) To: Eli Zaretskii Cc: markus.t.metzger, brobecker, gdb-patches, jan.kratochvil, simon.marchi On 10/12/2016 12:44 PM, Eli Zaretskii wrote: >> Cc: markus.t.metzger@intel.com, brobecker@adacore.com, >> gdb-patches@sourceware.org, jan.kratochvil@redhat.com, >> simon.marchi@ericsson.com >> From: Pedro Alves <palves@redhat.com> >> Date: Wed, 12 Oct 2016 12:25:21 +0100 >> >> On 10/12/2016 12:04 PM, Eli Zaretskii wrote: >>>> Cc: brobecker@adacore.com, gdb-patches@sourceware.org, >>>> jan.kratochvil@redhat.com, simon.marchi@ericsson.com >>>> From: Pedro Alves <palves@redhat.com> >>>> Date: Wed, 12 Oct 2016 11:11:50 +0100 >>>> >>>>> . Should we start using C++11 features in GDB? >>>> >>>> I would hope that no one would suggest that we shouldn't use >>>> C++11 features just because they like C++03 better than C++11. >>>> That would make no sense. >>> >>> It would make perfect sense if we decide to require a version of GCC >>> older than 4.8.1 as a prerequisite for building GDB. >> >> I can't see how that is a reply to what I said. I said _liking_ C++11 >> better over C++03. As in: "I'm just not going to use >> C++11 features, because I hate C++11, but C++03 is perfectly >> fine". > > That's a no-brainer, Good that you agree. > but if that was the only thing you were saying, That was not the only thing I was saying... That was preamble for the next paragraph: "In my mind, the only reason you'd not use C++11 over C++03 is simply because you couldn't because you don't have a ..." It seems like we keep talking past each other. > That decision > has IMO very little to do with whether we like C++03 more or not, > because if we go by that criterion alone, we should take Jan's > suggestion and switch to the latest version as soon as it is released, > right? Right. By that criteria, I'd switch to C++17 in a heart beat. C++17 can make C++ code look significantly simpler and clearer. Class template deduction makes me drool a bit: http://en.cppreference.com/w/cpp/language/class_template_deduction Yet, I won't miss it nowhere nearly as badly as I miss C++11 features. As I've been saying, IMO it's reasonable compiler availability in distros that should matter. GCC 7, which will be the first release to fully support C++17 (or at least close enough) is not even released yet. Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-12 8:11 ` Metzger, Markus T 2016-10-12 9:31 ` Eli Zaretskii @ 2016-10-12 10:28 ` Pedro Alves 2016-10-12 11:07 ` Eli Zaretskii 2016-10-13 0:38 ` [PATCH] Enable C++11 starting with gcc 4.8 (was: Re: [PATCH 1/3] Introduce gdb::unique_ptr) Pedro Alves 1 sibling, 2 replies; 72+ messages in thread From: Pedro Alves @ 2016-10-12 10:28 UTC (permalink / raw) To: Metzger, Markus T, Eli Zaretskii Cc: brobecker, gdb-patches, Jan Kratochvil (jan.kratochvil@redhat.com), Simon Marchi On 10/12/2016 09:11 AM, Metzger, Markus T wrote: > A simple and pragmatic solution would be a patch to add -std=c++11 > to GDB's compiler options. Pedro already mentioned it but I'm afraid it > got lost. Looks like it, yes. As I've explained, we can't do it on src/gdb/ alone, because the CXX make variable is passed down from the top level, which would override whatever we set in gdb/'s configure/Makefile. I want to give it a try, though. It just requires time and getting the patch into gcc and merged back. I don't think that should hold back the proposed series (or pieces of it). I wasn't originally meaning to unconditionally add -std=c++11 though, but instead to only add it if the compiler supports it, in order to conservatively still support C++03-only compilers. But if we agree to go full-on C++11, then I'll be more than happy to make gdb's configure error out on non-C++11 compilers. Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-12 10:28 ` Pedro Alves @ 2016-10-12 11:07 ` Eli Zaretskii 2016-10-12 11:19 ` Pedro Alves 2016-10-13 0:38 ` [PATCH] Enable C++11 starting with gcc 4.8 (was: Re: [PATCH 1/3] Introduce gdb::unique_ptr) Pedro Alves 1 sibling, 1 reply; 72+ messages in thread From: Eli Zaretskii @ 2016-10-12 11:07 UTC (permalink / raw) To: Pedro Alves Cc: markus.t.metzger, brobecker, gdb-patches, jan.kratochvil, simon.marchi > Cc: "brobecker@adacore.com" <brobecker@adacore.com>, > "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>, > "Jan Kratochvil (jan.kratochvil@redhat.com)" <jan.kratochvil@redhat.com>, > Simon Marchi <simon.marchi@ericsson.com> > From: Pedro Alves <palves@redhat.com> > Date: Wed, 12 Oct 2016 11:28:41 +0100 > > But if we agree to go full-on C++11, then I'll be more than > happy to make gdb's configure error out on non-C++11 compilers. I think part of this agreement -- if there is indeed an agreement -- should be documentation of this fact in NEWS and in our coding standards. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-12 11:07 ` Eli Zaretskii @ 2016-10-12 11:19 ` Pedro Alves 2016-10-12 11:41 ` Eli Zaretskii 0 siblings, 1 reply; 72+ messages in thread From: Pedro Alves @ 2016-10-12 11:19 UTC (permalink / raw) To: Eli Zaretskii Cc: markus.t.metzger, brobecker, gdb-patches, jan.kratochvil, simon.marchi On 10/12/2016 12:06 PM, Eli Zaretskii wrote: >> Cc: "brobecker@adacore.com" <brobecker@adacore.com>, >> "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>, >> "Jan Kratochvil (jan.kratochvil@redhat.com)" <jan.kratochvil@redhat.com>, >> Simon Marchi <simon.marchi@ericsson.com> >> From: Pedro Alves <palves@redhat.com> >> Date: Wed, 12 Oct 2016 11:28:41 +0100 >> >> But if we agree to go full-on C++11, then I'll be more than >> happy to make gdb's configure error out on non-C++11 compilers. > > I think part of this agreement -- if there is indeed an agreement -- > should be documentation of this fact in NEWS and in our coding > standards. Of course. Our coding standards haven't been updated to mention C++ yet, but hadn't managed to give it top priority yet. But consider it done. Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-12 11:19 ` Pedro Alves @ 2016-10-12 11:41 ` Eli Zaretskii 2016-10-12 11:55 ` Pedro Alves 0 siblings, 1 reply; 72+ messages in thread From: Eli Zaretskii @ 2016-10-12 11:41 UTC (permalink / raw) To: Pedro Alves Cc: markus.t.metzger, brobecker, gdb-patches, jan.kratochvil, simon.marchi > Cc: markus.t.metzger@intel.com, brobecker@adacore.com, > gdb-patches@sourceware.org, jan.kratochvil@redhat.com, > simon.marchi@ericsson.com > From: Pedro Alves <palves@redhat.com> > Date: Wed, 12 Oct 2016 12:19:25 +0100 > > > I think part of this agreement -- if there is indeed an agreement -- > > should be documentation of this fact in NEWS and in our coding > > standards. > > Of course. > > Our coding standards haven't been updated to mention C++ yet, > but hadn't managed to give it top priority yet. But consider it done. Thank you. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-12 11:41 ` Eli Zaretskii @ 2016-10-12 11:55 ` Pedro Alves 0 siblings, 0 replies; 72+ messages in thread From: Pedro Alves @ 2016-10-12 11:55 UTC (permalink / raw) To: Eli Zaretskii Cc: markus.t.metzger, brobecker, gdb-patches, jan.kratochvil, simon.marchi On 10/12/2016 12:40 PM, Eli Zaretskii wrote: >> Cc: markus.t.metzger@intel.com, brobecker@adacore.com, >> gdb-patches@sourceware.org, jan.kratochvil@redhat.com, >> simon.marchi@ericsson.com >> From: Pedro Alves <palves@redhat.com> >> Date: Wed, 12 Oct 2016 12:19:25 +0100 >> >>> I think part of this agreement -- if there is indeed an agreement -- >>> should be documentation of this fact in NEWS and in our coding >>> standards. >> >> Of course. >> >> Our coding standards haven't been updated to mention C++ yet, >> but hadn't managed to give it top priority yet. But consider it done. > > Thank you. I've done the minimal update now to match current C++03 reality: https://sourceware.org/gdb/wiki/Internals%20GDB-C-Coding-Standards?action=diff&rev1=18&rev2=19 Let's keep adding things as we decide them. Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 72+ messages in thread
* [PATCH] Enable C++11 starting with gcc 4.8 (was: Re: [PATCH 1/3] Introduce gdb::unique_ptr) 2016-10-12 10:28 ` Pedro Alves 2016-10-12 11:07 ` Eli Zaretskii @ 2016-10-13 0:38 ` Pedro Alves 2016-10-13 0:45 ` [PATCH 2/2] gdb: Enable C++11 if available Pedro Alves 2016-10-13 0:45 ` [PATCH 1/2] gdb: Import AX_CXX_COMPILE_STDCXX from the GNU Autoconf Archive Pedro Alves 1 sibling, 2 replies; 72+ messages in thread From: Pedro Alves @ 2016-10-13 0:38 UTC (permalink / raw) To: Metzger, Markus T, Eli Zaretskii Cc: brobecker, gdb-patches, Jan Kratochvil (jan.kratochvil@redhat.com), Simon Marchi On 10/12/2016 11:28 AM, Pedro Alves wrote: > On 10/12/2016 09:11 AM, Metzger, Markus T wrote: > >> A simple and pragmatic solution would be a patch to add -std=c++11 >> to GDB's compiler options. Pedro already mentioned it but I'm afraid it >> got lost. > > Looks like it, yes. As I've explained, we can't do it on src/gdb/ > alone, because the CXX make variable is passed down from the top level, > which would override whatever we set in gdb/'s configure/Makefile. > > I want to give it a try, though. It just requires time and getting > the patch into gcc and merged back. I don't think that should hold > back the proposed series (or pieces of it). > > I wasn't originally meaning to unconditionally add -std=c++11 though, > but instead to only add it if the compiler supports it, in order > to conservatively still support C++03-only compilers. OK, I spend a few hours tonight working on this. I was thinking ahead that we'll like have other C++ libraries in the top level that we'd be using (code shared with gcc, and also gdbserver moving to top level, maybe parts split to libraries, etc.). And I was mistakenly under the impression that all subdirs would have to be built with the same C++ dialect, given the C++11 ABI change. I.e., use the same dialect throughout to avoid ABI conflicts. So I first wrote a patch that had the top level configure source a file in each subdir that would tell the top level the minimum and maximum C++ dialect versions each subdir supported, and then the top level could compute the dialect to set CXX to. But, https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html explains how mixing dialects is not really a problem. So I was over complicating. However, the issue with CXX being passed by the top level overriding whatever gdb's configure/Makefile decide to set CXX to is real though. But I solved it in a different way, all within gdb/ Instead of having configure append -std=xxx to CXX, simply set a separate CXX_DIALECT variable, and tweak the Makefile to use "$CXX CXX_DIALECT" to compile/link. In order to detect whether the compiler supports C++11 (i.e., if we're using gcc 4.8 or later, or a clang that supports C++11, etc.), I'm reusing a macro from the GNU Autoconf Archive, at: http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html To recap: > Conceptually, the gdb::unique_ptr patch (this thread) does: > > #if HAVE_STD_UNIQUE_PTR > > // just use it > > #else > > // write replacement > > #endif > > The replacement is fully functional. > > If I push the patch in now, HAVE_STD_UNIQUE_PTR will only be true > when compiling GDB with GCC >= 6.x, because G++ 6.1 targets G++14 > by default, which is a superset of C++11. The replacement > works with all other GCCs. It'd be possible to make > HAVE_STD_UNIQUE_PTR be true with GCC >= 4.x too, but nobody wrote > that patch yet. So I wrote that patch now. IOW, the idea is that gdb::unique_ptr maps to C++11 std::unique_ptr iff C++11 is available and to a replacement otherwise. The C++03 replacement works just as well, however the C++11 version catches more bugs at compile time. Full C++11 support is available starting with gcc 4.8, however only gcc 6.1 switched to default to C++11 (C++14, actually). So for gcc 4.8 till gcc 6.1, we need to explicitly pass -std=gnu++11 to the compiler. That's what the patch I wrote tonight does. I'll send it as reply to this email. Two patches actually. > But if we agree to go full-on C++11, then I'll be more than > happy to make gdb's configure error out on non-C++11 compilers. The patches add this to configure: AX_CXX_COMPILE_STDCXX(11, , optional) "optional" means that not having a C++11 compiler is OK. IOW, "try to enable C++11 iff possible". If we decide to _require_ C++11 (i.e., drop support for C++03-only), then it's a simple matter of changing that to: AX_CXX_COMPILE_STDCXX(11, , mandatory) Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 72+ messages in thread
* [PATCH 2/2] gdb: Enable C++11 if available 2016-10-13 0:38 ` [PATCH] Enable C++11 starting with gcc 4.8 (was: Re: [PATCH 1/3] Introduce gdb::unique_ptr) Pedro Alves @ 2016-10-13 0:45 ` Pedro Alves 2016-10-13 0:45 ` [PATCH 1/2] gdb: Import AX_CXX_COMPILE_STDCXX from the GNU Autoconf Archive Pedro Alves 1 sibling, 0 replies; 72+ messages in thread From: Pedro Alves @ 2016-10-13 0:45 UTC (permalink / raw) To: gdb-patches ... and continue using C++03 if not. Use AX_CXX_COMPILE_STDCXX to enable C++11 if available. We need to tweak it a bit though. Pristine upstream AX_CXX_COMPILE_STDCXX appends -std=gnu++11 to CXX directly, if necessary. That doesn't work for us, because the top level Makefile passes CXX down to subdirs, and that overrides whatever our gdb/Makefile is set to use. The result would be that a make invocation from the build/gdb/ directory would use "g++ -std=gnu++11" as expected, while a make invocation at the top level would not. So instead of having AX_CXX_COMPILE_STDCXX set CXX directly, tweak it to AC_SUBST a separate variable -- CXX_DIALECT -- and use '$(CXX) (CXX_DIALECT)' to compile/link. Confirmed that this enables C++11 starting with gcc 4.8, the first gcc release with full C++11 support. Confirmed that older releases continue building in C++03 mode. gdb/ChangeLog: yyyy-mm-dd Pedro Alves <palves@redhat.com> * Makefile.in (CXX_DIALECT): Get from configure. (COMPILE.pre, CC_LD): Append $(CXX_DIALECT). (FLAGS_TO_PASS): Pass CXX_DIALECT. * acinclude.m4: Include ax_cxx_compile_stdcxx.m4. * ax_cxx_compile_stdcxx.m4: Add FSF copyright header. Set and AC_SUBST CXX_DIALECT instead of changing CXX/CXXCPP. * configure.ac: Call AX_CXX_COMPILE_STDCXX. * config.in: Regenerate. * configure: Regenerate. gdb/gdbserver/ChangeLog: yyyy-mm-dd Pedro Alves <palves@redhat.com> * Makefile.in (CXX_DIALECT): Get from configure. (COMPILE.pre, CC_LD): Append $(CXX_DIALECT). * acinclude.m4: Include ../ax_cxx_compile_stdcxx.m4. * configure.ac: Call AX_CXX_COMPILE_STDCXX. * config.in: Regenerate. * configure: Regenerate. --- gdb/Makefile.in | 6 +- gdb/acinclude.m4 | 2 + gdb/ax_cxx_compile_stdcxx.m4 | 21 +- gdb/config.in | 3 + gdb/configure | 999 ++++++++++++++++++++++++++++++++++++++++++- gdb/configure.ac | 3 + gdb/gdbserver/Makefile.in | 5 +- gdb/gdbserver/acinclude.m4 | 2 + gdb/gdbserver/config.in | 3 + gdb/gdbserver/configure | 998 +++++++++++++++++++++++++++++++++++++++++- gdb/gdbserver/configure.ac | 2 + 11 files changed, 2030 insertions(+), 14 deletions(-) diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 2c88434..d035d8e 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -86,6 +86,7 @@ CATALOGS = @CATALOGS@ # distribution will fix your include files up. CC=@CC@ CXX=@CXX@ +CXX_DIALECT= @CXX_DIALECT@ # Dependency tracking information. DEPMODE = @CCDEPMODE@ @@ -94,7 +95,7 @@ depcomp = $(SHELL) $(srcdir)/../depcomp # Note that these are overridden by GNU make-specific code below if # GNU make is used. The overrides implement dependency tracking. -COMPILE.pre = $(CXX) +COMPILE.pre = $(CXX) $(CXX_DIALECT) COMPILE.post = -c -o $@ COMPILE = $(COMPILE.pre) $(INTERNAL_CFLAGS) $(COMPILE.post) POSTCOMPILE = @true @@ -125,7 +126,7 @@ MAKEHTMLFLAGS = # Set this up with gcc if you have gnu ld and the loader will print out # line numbers for undefined references. #CC_LD=g++ -static -CC_LD=$(CXX) +CC_LD=$(CXX) $(CXX_DIALECT) # Where is our "include" directory? Typically $(srcdir)/../include. # This is essentially the header file directory for the library @@ -742,6 +743,7 @@ FLAGS_TO_PASS = \ "CC=$(CC)" \ "CFLAGS=$(CFLAGS)" \ "CXX=$(CXX)" \ + "CXX_DIALECT=$(CXX_DIALECT)" \ "CXXFLAGS=$(CXXFLAGS)" \ "DLLTOOL=$(DLLTOOL)" \ "LDFLAGS=$(LDFLAGS)" \ diff --git a/gdb/acinclude.m4 b/gdb/acinclude.m4 index 4b3f7fc..daf4a91 100644 --- a/gdb/acinclude.m4 +++ b/gdb/acinclude.m4 @@ -68,6 +68,8 @@ m4_include(libiberty.m4) dnl For GDB_AC_PTRACE. m4_include(ptrace.m4) +m4_include(ax_cxx_compile_stdcxx.m4) + ## ----------------------------------------- ## ## ANSIfy the C compiler whenever possible. ## ## From Franc,ois Pinard ## diff --git a/gdb/ax_cxx_compile_stdcxx.m4 b/gdb/ax_cxx_compile_stdcxx.m4 index 2c18e49..ffaeb6e 100644 --- a/gdb/ax_cxx_compile_stdcxx.m4 +++ b/gdb/ax_cxx_compile_stdcxx.m4 @@ -1,3 +1,12 @@ +# Copyright (c) 2016 Free Software Foundation, Inc. +# +# Originally based on the AX_CXX_COMPILE_STDCXX macro found at the url +# below. +# +# Local GDB customizations: +# +# - AC_SUBST CXX_DIALECT instead of changing CXX/CXXCPP. +# # =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html # =========================================================================== @@ -58,6 +67,7 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl [$3], [optional], [ax_cxx_compile_cxx$1_required=false], [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) AC_LANG_PUSH([C++])dnl + CXX_DIALECT="" ac_success=no AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, ax_cv_cxx_compile_cxx$1, @@ -81,10 +91,7 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl [eval $cachevar=no]) CXX="$ac_save_CXX"]) if eval test x\$$cachevar = xyes; then - CXX="$CXX $switch" - if test -n "$CXXCPP" ; then - CXXCPP="$CXXCPP $switch" - fi + CXX_DIALECT="$switch" ac_success=yes break fi @@ -107,10 +114,7 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl [eval $cachevar=no]) CXX="$ac_save_CXX"]) if eval test x\$$cachevar = xyes; then - CXX="$CXX $switch" - if test -n "$CXXCPP" ; then - CXXCPP="$CXXCPP $switch" - fi + CXX_DIALECT="$switch" ac_success=yes break fi @@ -131,6 +135,7 @@ AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl [define if the compiler supports basic C++$1 syntax]) fi AC_SUBST(HAVE_CXX$1) + AC_SUBST(CXX_DIALECT) ]) diff --git a/gdb/config.in b/gdb/config.in index 3790d10..9c841ba 100644 --- a/gdb/config.in +++ b/gdb/config.in @@ -84,6 +84,9 @@ /* Define to 1 if you have the <curses.h> header file. */ #undef HAVE_CURSES_H +/* define if the compiler supports basic C++11 syntax */ +#undef HAVE_CXX11 + /* Define to 1 if you have the declaration of `ADDR_NO_RANDOMIZE', and to 0 if you don't. */ #undef HAVE_DECL_ADDR_NO_RANDOMIZE diff --git a/gdb/configure b/gdb/configure index e2d853d..933f582 100755 --- a/gdb/configure +++ b/gdb/configure @@ -732,6 +732,8 @@ MAKE CCDEPMODE DEPDIR am__leading_dot +CXX_DIALECT +HAVE_CXX11 INSTALL_STRIP_PROGRAM STRIP install_sh @@ -4951,6 +4953,1002 @@ ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` +# Enable C++11, if available. + + ax_cxx_compile_cxx11_required=falsednl + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + CXX_DIALECT="" + ac_success=no + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features by default" >&5 +$as_echo_n "checking whether $CXX supports C++11 features by default... " >&6; } +if test "${ax_cv_cxx_compile_cxx11+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201103L + +#error "This is not a C++11 compiler" + +#else + +#ifndef CLAIM + +namespace cxx11 +{ + + namespace test_static_assert + { + + template <typename T> + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual void f() {} + }; + + struct Derived : public Base + { + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check<void> single_type; + typedef check<check<void>> double_type; + typedef check<check<check<void>>> triple_type; + typedef check<check<check<check<void>>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same<T, T> + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same<int, decltype(0)>::value == true, ""); + static_assert(is_same<int, decltype(c)>::value == false, ""); + static_assert(is_same<int, decltype(v)>::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same<int, decltype(ac)>::value == true, ""); + static_assert(is_same<int, decltype(av)>::value == true, ""); + static_assert(is_same<int, decltype(sumi)>::value == true, ""); + static_assert(is_same<int, decltype(sumf)>::value == false, ""); + static_assert(is_same<int, decltype(add(c, v))>::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template <int...> + struct sum; + + template <int N0, int... N1toN> + struct sum<N0, N1toN...> + { + static constexpr auto value = N0 + sum<N1toN...>::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template<typename T> + using member = typename T::member_type; + + template<typename T> + void func(...) {} + + template<typename T> + void func(member<T>*) {} + + void test(); + + void test() { func<foo>(0); } + + } + +} // namespace cxx11 + +#endif // CLAIM + +#endif // __cplusplus >= 201103L + + + +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ax_cv_cxx_compile_cxx11=yes +else + ax_cv_cxx_compile_cxx11=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx11" >&5 +$as_echo "$ax_cv_cxx_compile_cxx11" >&6; } + if test x$ax_cv_cxx_compile_cxx11 = xyes; then + ac_success=yes + fi + + if test x$ac_success = xno; then + for switch in -std=gnu++11 -std=gnu++0x; 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" + if test x = xclaim; then + CXX="$CXX -DCLAIM" + fi + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201103L + +#error "This is not a C++11 compiler" + +#else + +#ifndef CLAIM + +namespace cxx11 +{ + + namespace test_static_assert + { + + template <typename T> + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual void f() {} + }; + + struct Derived : public Base + { + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check<void> single_type; + typedef check<check<void>> double_type; + typedef check<check<check<void>>> triple_type; + typedef check<check<check<check<void>>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same<T, T> + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same<int, decltype(0)>::value == true, ""); + static_assert(is_same<int, decltype(c)>::value == false, ""); + static_assert(is_same<int, decltype(v)>::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same<int, decltype(ac)>::value == true, ""); + static_assert(is_same<int, decltype(av)>::value == true, ""); + static_assert(is_same<int, decltype(sumi)>::value == true, ""); + static_assert(is_same<int, decltype(sumf)>::value == false, ""); + static_assert(is_same<int, decltype(add(c, v))>::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template <int...> + struct sum; + + template <int N0, int... N1toN> + struct sum<N0, N1toN...> + { + static constexpr auto value = N0 + sum<N1toN...>::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template<typename T> + using member = typename T::member_type; + + template<typename T> + void func(...) {} + + template<typename T> + void func(member<T>*) {} + + void test(); + + void test() { func<foo>(0); } + + } + +} // namespace cxx11 + +#endif // CLAIM + +#endif // __cplusplus >= 201103L + + + +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval $cachevar=yes +else + eval $cachevar=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + 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 + break + fi + done + 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 +$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" + if test x = xclaim; then + CXX="$CXX -DCLAIM" + fi + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201103L + +#error "This is not a C++11 compiler" + +#else + +#ifndef CLAIM + +namespace cxx11 +{ + + namespace test_static_assert + { + + template <typename T> + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual void f() {} + }; + + struct Derived : public Base + { + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check<void> single_type; + typedef check<check<void>> double_type; + typedef check<check<check<void>>> triple_type; + typedef check<check<check<check<void>>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same<T, T> + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same<int, decltype(0)>::value == true, ""); + static_assert(is_same<int, decltype(c)>::value == false, ""); + static_assert(is_same<int, decltype(v)>::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same<int, decltype(ac)>::value == true, ""); + static_assert(is_same<int, decltype(av)>::value == true, ""); + static_assert(is_same<int, decltype(sumi)>::value == true, ""); + static_assert(is_same<int, decltype(sumf)>::value == false, ""); + static_assert(is_same<int, decltype(add(c, v))>::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template <int...> + struct sum; + + template <int N0, int... N1toN> + struct sum<N0, N1toN...> + { + static constexpr auto value = N0 + sum<N1toN...>::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template<typename T> + using member = typename T::member_type; + + template<typename T> + void func(...) {} + + template<typename T> + void func(member<T>*) {} + + void test(); + + void test() { func<foo>(0); } + + } + +} // namespace cxx11 + +#endif // CLAIM + +#endif // __cplusplus >= 201103L + + + +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval $cachevar=yes +else + eval $cachevar=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + 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 + break + fi + done + fi + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + if test x$ax_cxx_compile_cxx11_required = xtrue; then + if test x$ac_success = xno; then + as_fn_error "*** A compiler with support for C++11 language features is required." "$LINENO" 5 + fi + fi + if test x$ac_success = xno; then + HAVE_CXX11=0 + { $as_echo "$as_me:${as_lineno-$LINENO}: No compiler with C++11 support was found" >&5 +$as_echo "$as_me: No compiler with C++11 support was found" >&6;} + else + HAVE_CXX11=1 + +$as_echo "#define HAVE_CXX11 1" >>confdefs.h + + fi + + + + # Dependency checking. rm -rf .tst 2>/dev/null mkdir .tst 2>/dev/null @@ -14202,7 +15200,6 @@ _ACEOF - # Check whether --enable-werror was given. if test "${enable_werror+set}" = set; then : enableval=$enable_werror; case "${enableval}" in diff --git a/gdb/configure.ac b/gdb/configure.ac index e451e60..e079099 100644 --- a/gdb/configure.ac +++ b/gdb/configure.ac @@ -38,6 +38,9 @@ AC_CONFIG_AUX_DIR(..) AC_CANONICAL_SYSTEM AC_ARG_PROGRAM +# Enable C++11, if available. +AX_CXX_COMPILE_STDCXX(11, , optional) + # Dependency checking. ZW_CREATE_DEPDIR ZW_PROG_COMPILER_DEPENDENCIES([CC]) diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in index 0db5287..5ba559c 100644 --- a/gdb/gdbserver/Makefile.in +++ b/gdb/gdbserver/Makefile.in @@ -51,6 +51,7 @@ RANLIB = @RANLIB@ CC = @CC@ CXX = @CXX@ +CXX_DIALECT= @CXX_DIALECT@ AR = @AR@ AR_FLAGS = rc @@ -61,7 +62,7 @@ depcomp = $(SHELL) $(srcdir)/../depcomp # Note that these are overridden by GNU make-specific code below if # GNU make is used. The overrides implement dependency tracking. -COMPILE.pre = $(CXX) +COMPILE.pre = $(CXX) $(CXX_DIALECT) COMPILE.post = -c -o $@ COMPILE = $(COMPILE.pre) $(INTERNAL_CFLAGS) $(COMPILE.post) POSTCOMPILE = @true @@ -80,7 +81,7 @@ VPATH = @srcdir@ # Set this up with gcc if you have gnu ld and the loader will print out # line numbers for undefinded refs. #CC_LD=g++ -static -CC_LD=$(CXX) +CC_LD=$(CXX) $(CXX_DIALECT) # Where is the "include" directory? Traditionally ../include or ./include INCLUDE_DIR = ${srcdir}/../../include diff --git a/gdb/gdbserver/acinclude.m4 b/gdb/gdbserver/acinclude.m4 index 8ec9188..c75d783 100644 --- a/gdb/gdbserver/acinclude.m4 +++ b/gdb/gdbserver/acinclude.m4 @@ -29,6 +29,8 @@ m4_include(../libiberty.m4) dnl For GDB_AC_PTRACE. m4_include(../ptrace.m4) +m4_include(../ax_cxx_compile_stdcxx.m4) + dnl Check for existence of a type $1 in libthread_db.h dnl Based on BFD_HAVE_SYS_PROCFS_TYPE in bfd/bfd.m4. diff --git a/gdb/gdbserver/config.in b/gdb/gdbserver/config.in index 04072cf..b721ea8 100644 --- a/gdb/gdbserver/config.in +++ b/gdb/gdbserver/config.in @@ -18,6 +18,9 @@ /* Define to 1 if you have the <arpa/inet.h> header file. */ #undef HAVE_ARPA_INET_H +/* define if the compiler supports basic C++11 syntax */ +#undef HAVE_CXX11 + /* Define to 1 if you have the declaration of `ADDR_NO_RANDOMIZE', and to 0 if you don't. */ #undef HAVE_DECL_ADDR_NO_RANDOMIZE diff --git a/gdb/gdbserver/configure b/gdb/gdbserver/configure index f112517..232d09d 100755 --- a/gdb/gdbserver/configure +++ b/gdb/gdbserver/configure @@ -615,6 +615,8 @@ DEPDIR am__leading_dot host_noncanonical target_noncanonical +CXX_DIALECT +HAVE_CXX11 RANLIB AR INSTALL_DATA @@ -4656,6 +4658,1001 @@ ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + + ax_cxx_compile_cxx11_required=falsednl + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + CXX_DIALECT="" + ac_success=no + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX supports C++11 features by default" >&5 +$as_echo_n "checking whether $CXX supports C++11 features by default... " >&6; } +if test "${ax_cv_cxx_compile_cxx11+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201103L + +#error "This is not a C++11 compiler" + +#else + +#ifndef CLAIM + +namespace cxx11 +{ + + namespace test_static_assert + { + + template <typename T> + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual void f() {} + }; + + struct Derived : public Base + { + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check<void> single_type; + typedef check<check<void>> double_type; + typedef check<check<check<void>>> triple_type; + typedef check<check<check<check<void>>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same<T, T> + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same<int, decltype(0)>::value == true, ""); + static_assert(is_same<int, decltype(c)>::value == false, ""); + static_assert(is_same<int, decltype(v)>::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same<int, decltype(ac)>::value == true, ""); + static_assert(is_same<int, decltype(av)>::value == true, ""); + static_assert(is_same<int, decltype(sumi)>::value == true, ""); + static_assert(is_same<int, decltype(sumf)>::value == false, ""); + static_assert(is_same<int, decltype(add(c, v))>::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template <int...> + struct sum; + + template <int N0, int... N1toN> + struct sum<N0, N1toN...> + { + static constexpr auto value = N0 + sum<N1toN...>::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template<typename T> + using member = typename T::member_type; + + template<typename T> + void func(...) {} + + template<typename T> + void func(member<T>*) {} + + void test(); + + void test() { func<foo>(0); } + + } + +} // namespace cxx11 + +#endif // CLAIM + +#endif // __cplusplus >= 201103L + + + +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ax_cv_cxx_compile_cxx11=yes +else + ax_cv_cxx_compile_cxx11=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ax_cv_cxx_compile_cxx11" >&5 +$as_echo "$ax_cv_cxx_compile_cxx11" >&6; } + if test x$ax_cv_cxx_compile_cxx11 = xyes; then + ac_success=yes + fi + + if test x$ac_success = xno; then + for switch in -std=gnu++11 -std=gnu++0x; 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" + if test x = xclaim; then + CXX="$CXX -DCLAIM" + fi + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201103L + +#error "This is not a C++11 compiler" + +#else + +#ifndef CLAIM + +namespace cxx11 +{ + + namespace test_static_assert + { + + template <typename T> + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual void f() {} + }; + + struct Derived : public Base + { + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check<void> single_type; + typedef check<check<void>> double_type; + typedef check<check<check<void>>> triple_type; + typedef check<check<check<check<void>>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same<T, T> + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same<int, decltype(0)>::value == true, ""); + static_assert(is_same<int, decltype(c)>::value == false, ""); + static_assert(is_same<int, decltype(v)>::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same<int, decltype(ac)>::value == true, ""); + static_assert(is_same<int, decltype(av)>::value == true, ""); + static_assert(is_same<int, decltype(sumi)>::value == true, ""); + static_assert(is_same<int, decltype(sumf)>::value == false, ""); + static_assert(is_same<int, decltype(add(c, v))>::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template <int...> + struct sum; + + template <int N0, int... N1toN> + struct sum<N0, N1toN...> + { + static constexpr auto value = N0 + sum<N1toN...>::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template<typename T> + using member = typename T::member_type; + + template<typename T> + void func(...) {} + + template<typename T> + void func(member<T>*) {} + + void test(); + + void test() { func<foo>(0); } + + } + +} // namespace cxx11 + +#endif // CLAIM + +#endif // __cplusplus >= 201103L + + + +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval $cachevar=yes +else + eval $cachevar=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + 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 + break + fi + done + 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 +$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" + if test x = xclaim; then + CXX="$CXX -DCLAIM" + fi + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201103L + +#error "This is not a C++11 compiler" + +#else + +#ifndef CLAIM + +namespace cxx11 +{ + + namespace test_static_assert + { + + template <typename T> + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual void f() {} + }; + + struct Derived : public Base + { + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check<void> single_type; + typedef check<check<void>> double_type; + typedef check<check<check<void>>> triple_type; + typedef check<check<check<check<void>>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same<T, T> + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same<int, decltype(0)>::value == true, ""); + static_assert(is_same<int, decltype(c)>::value == false, ""); + static_assert(is_same<int, decltype(v)>::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same<int, decltype(ac)>::value == true, ""); + static_assert(is_same<int, decltype(av)>::value == true, ""); + static_assert(is_same<int, decltype(sumi)>::value == true, ""); + static_assert(is_same<int, decltype(sumf)>::value == false, ""); + static_assert(is_same<int, decltype(add(c, v))>::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template <int...> + struct sum; + + template <int N0, int... N1toN> + struct sum<N0, N1toN...> + { + static constexpr auto value = N0 + sum<N1toN...>::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template<typename T> + using member = typename T::member_type; + + template<typename T> + void func(...) {} + + template<typename T> + void func(member<T>*) {} + + void test(); + + void test() { func<foo>(0); } + + } + +} // namespace cxx11 + +#endif // CLAIM + +#endif // __cplusplus >= 201103L + + + +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval $cachevar=yes +else + eval $cachevar=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + 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 + break + fi + done + fi + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + if test x$ax_cxx_compile_cxx11_required = xtrue; then + if test x$ac_success = xno; then + as_fn_error "*** A compiler with support for C++11 language features is required." "$LINENO" 5 + fi + fi + if test x$ac_success = xno; then + HAVE_CXX11=0 + { $as_echo "$as_me:${as_lineno-$LINENO}: No compiler with C++11 support was found" >&5 +$as_echo "$as_me: No compiler with C++11 support was found" >&6;} + else + HAVE_CXX11=1 + +$as_echo "#define HAVE_CXX11 1" >>confdefs.h + + fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 $as_echo_n "checking for ANSI C header files... " >&6; } if test "${ac_cv_header_stdc+set}" = set; then : @@ -6236,7 +7233,6 @@ fi - # Check whether --enable-werror was given. if test "${enable_werror+set}" = set; then : enableval=$enable_werror; case "${enableval}" in diff --git a/gdb/gdbserver/configure.ac b/gdb/gdbserver/configure.ac index 6d5907b..7ad34ac 100644 --- a/gdb/gdbserver/configure.ac +++ b/gdb/gdbserver/configure.ac @@ -38,6 +38,8 @@ AC_PROG_RANLIB AC_ARG_PROGRAM +AX_CXX_COMPILE_STDCXX(11, , optional) + AC_HEADER_STDC # Set the 'development' global. -- 2.5.5 ^ permalink raw reply [flat|nested] 72+ messages in thread
* [PATCH 1/2] gdb: Import AX_CXX_COMPILE_STDCXX from the GNU Autoconf Archive 2016-10-13 0:38 ` [PATCH] Enable C++11 starting with gcc 4.8 (was: Re: [PATCH 1/3] Introduce gdb::unique_ptr) Pedro Alves 2016-10-13 0:45 ` [PATCH 2/2] gdb: Enable C++11 if available Pedro Alves @ 2016-10-13 0:45 ` Pedro Alves 1 sibling, 0 replies; 72+ messages in thread From: Pedro Alves @ 2016-10-13 0:45 UTC (permalink / raw) To: gdb-patches This macro throws C++11 code at the compiler in order to check whether it supports C++11. final/override, rvalue references, static_assert, decltype, auto, constexpr, etc., and adds -std=gnu++11 to CXX if necessary. Nothing uses the macro yet. Simply adding it as separate preliminary step because we'll need local changes. gdb/ChangeLog yyyy-mm-dd Pedro Alves <palves@redhat.com> * ax_cxx_compile_stdcxx.m4: New file. --- gdb/ax_cxx_compile_stdcxx.m4 | 562 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 562 insertions(+) create mode 100644 gdb/ax_cxx_compile_stdcxx.m4 diff --git a/gdb/ax_cxx_compile_stdcxx.m4 b/gdb/ax_cxx_compile_stdcxx.m4 new file mode 100644 index 0000000..2c18e49 --- /dev/null +++ b/gdb/ax_cxx_compile_stdcxx.m4 @@ -0,0 +1,562 @@ +# =========================================================================== +# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the specified +# version of the C++ standard. If necessary, add switches to CXX and +# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) +# or '14' (for the C++14 standard). +# +# The second argument, if specified, indicates whether you insist on an +# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. +# -std=c++11). If neither is specified, you get whatever works, with +# preference for an extended mode. +# +# The third argument, if specified 'mandatory' or if left unspecified, +# indicates that baseline support for the specified C++ standard is +# required and that the macro should error out if no mode with that +# support is found. If specified 'optional', then configuration proceeds +# regardless, after defining HAVE_CXX${VERSION} if and only if a +# supporting mode is found. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com> +# Copyright (c) 2012 Zack Weinberg <zackw@panix.com> +# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu> +# 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> +# +# 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 + +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_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$2], [], [], + [$2], [ext], [], + [$2], [noext], [], + [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], + [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], + [$3], [optional], [ax_cxx_compile_cxx$1_required=false], + [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) + AC_LANG_PUSH([C++])dnl + ac_success=no + AC_CACHE_CHECK(whether $CXX supports C++$1 features by default, + ax_cv_cxx_compile_cxx$1, + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [ax_cv_cxx_compile_cxx$1=yes], + [ax_cv_cxx_compile_cxx$1=no])]) + if test x$ax_cv_cxx_compile_cxx$1 = xyes; then + ac_success=yes + fi + + m4_if([$2], [noext], [], [dnl + if test x$ac_success = xno; then + for switch in -std=gnu++$1 -std=gnu++0x; 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="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + fi]) + + m4_if([$2], [ext], [], [dnl + if test x$ac_success = xno; then + 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="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + fi]) + AC_LANG_POP([C++]) + if test x$ax_cxx_compile_cxx$1_required = xtrue; then + if test x$ac_success = xno; then + AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) + fi + fi + if test x$ac_success = xno; then + HAVE_CXX$1=0 + AC_MSG_NOTICE([No compiler with C++$1 support was found]) + else + HAVE_CXX$1=1 + AC_DEFINE(HAVE_CXX$1,1, + [define if the compiler supports basic C++$1 syntax]) + fi + AC_SUBST(HAVE_CXX$1) +]) + + +dnl Test body for checking C++11 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 +) + + +dnl Test body for checking C++14 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 +) + + +dnl Tests for new features in C++11 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201103L + +#error "This is not a C++11 compiler" + +#else + +namespace cxx11 +{ + + namespace test_static_assert + { + + template <typename T> + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual void f() {} + }; + + struct Derived : public Base + { + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check<void> single_type; + typedef check<check<void>> double_type; + typedef check<check<check<void>>> triple_type; + typedef check<check<check<check<void>>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same<T, T> + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same<int, decltype(0)>::value == true, ""); + static_assert(is_same<int, decltype(c)>::value == false, ""); + static_assert(is_same<int, decltype(v)>::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same<int, decltype(ac)>::value == true, ""); + static_assert(is_same<int, decltype(av)>::value == true, ""); + static_assert(is_same<int, decltype(sumi)>::value == true, ""); + static_assert(is_same<int, decltype(sumf)>::value == false, ""); + static_assert(is_same<int, decltype(add(c, v))>::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template <int...> + struct sum; + + template <int N0, int... N1toN> + struct sum<N0, N1toN...> + { + static constexpr auto value = N0 + sum<N1toN...>::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template<typename T> + using member = typename T::member_type; + + template<typename T> + void func(...) {} + + template<typename T> + void func(member<T>*) {} + + void test(); + + void test() { func<foo>(0); } + + } + +} // namespace cxx11 + +#endif // __cplusplus >= 201103L + +]]) + + +dnl Tests for new features in C++14 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ + +// If the compiler admits that it is not ready for C++14, 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++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_seperators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same<T, T> + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same<int, decltype(f(x))>::value, ""); + static_assert(is_same<int&, decltype(g(x))>::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + +]]) -- 2.5.5 ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-12 6:34 ` Eli Zaretskii 2016-10-12 8:11 ` Metzger, Markus T @ 2016-10-12 9:37 ` Pedro Alves 2016-10-12 10:51 ` Eli Zaretskii 1 sibling, 1 reply; 72+ messages in thread From: Pedro Alves @ 2016-10-12 9:37 UTC (permalink / raw) To: Eli Zaretskii; +Cc: brobecker, markus.t.metzger, gdb-patches On 10/12/2016 07:34 AM, Eli Zaretskii wrote: >>> I'm still arguing because you all but decided to declare that to enjoy >>> GDB to its fullest one has from now on to have GCC 6.x. GCC 6.1 was >>> released just this April, so it sounds too drastic to require it only >>> a few months later. >> >> Eli, I've repeatedly told you that that's completely false. No one >> is suggesting that. > > Jan just did. No he didn't. That's another straw man argument. Jan said, in full: > The discussion is about C++11. LLVM+LLDB have switched to C++11 in 2014 and > they haven't looked back. > > I see the C++11 discussion pointless, where is the system which really needs > GDB and which still cannot compile C++11? Why to waste manyears on bugs which > can no longer exist with C++11? > > The discussion should be when to switch to C++17 as that removes another tons > of crap like gnulib. He's saying that we should just require C++11 and be done with it. And then he concluded with a (hopefully tongue-in-cheek) remark about C++17, which (hopefully) is obvious we're not going to be requiring that anytime soon... Fact: Nowhere did he say that we will now require GCC 6.1. Requiring C++11 would mean requiring GCC around 4.8, NOT GCC 6.1. > So "completely false" is completely false. You're repeated claims that people are suggesting to require GCC 6.1 are provably false. In any case, Jan's reply came after all our discussions, and I'm not Jan. If someone comes in and suggests to actually require GCC 6.1, then I'll stop saying that nobody is suggesting that, and instead say that I'd strongly object it. > And what > you are suggesting, while not as radical as what Jan says, will still > get us there soon enough. There's no Trojan here. If you don't trust me, then I don't know what else I can do... >> At this point I have to wonder whether you're not listening on >> purpose. > > This goes both ways, you know. And I hope you understand how it could > be an insult when actually written in a discussion. I did not mean it as an insult. I apologize if it sounded that way. And conversely, I hope you understand how repeated straw man arguments even after they're categorically dismissed could be taken as an insult. > Why do we need to get to this level each time I happen to disagree with something here? > It's the reason why I speak so little here about my opinions on the > various matters. I don't know. IMO, it would have helped a lot if the discussion would have not had so many straw man arguments thrown my way. Can we please redirect all this energy to actual technical discussions, please? Does anyone want to comment on the the patch itself and on the smart pointer design? Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-12 9:37 ` [PATCH 1/3] Introduce gdb::unique_ptr Pedro Alves @ 2016-10-12 10:51 ` Eli Zaretskii 2016-10-12 11:15 ` Pedro Alves 2016-10-12 11:45 ` Jan Kratochvil 0 siblings, 2 replies; 72+ messages in thread From: Eli Zaretskii @ 2016-10-12 10:51 UTC (permalink / raw) To: Pedro Alves; +Cc: brobecker, markus.t.metzger, gdb-patches > Cc: brobecker@adacore.com, markus.t.metzger@intel.com, > gdb-patches@sourceware.org > From: Pedro Alves <palves@redhat.com> > Date: Wed, 12 Oct 2016 10:37:01 +0100 > > On 10/12/2016 07:34 AM, Eli Zaretskii wrote: > > >>> I'm still arguing because you all but decided to declare that to enjoy > >>> GDB to its fullest one has from now on to have GCC 6.x. GCC 6.1 was > >>> released just this April, so it sounds too drastic to require it only > >>> a few months later. > >> > >> Eli, I've repeatedly told you that that's completely false. No one > >> is suggesting that. > > > > Jan just did. > > No he didn't. That's another straw man argument. Would you please refrain from labeling my (or anyone else's) arguments with derogatory labels? Please always assume that anything like that is due to some misunderstanding, not to anything else. Otherwise, you are converting a technical argument into an ad-hominem, something that neither you nor anyone else wants. > Jan said, in full: > > > The discussion is about C++11. LLVM+LLDB have switched to C++11 in 2014 and > > they haven't looked back. > > > > I see the C++11 discussion pointless, where is the system which really needs > > GDB and which still cannot compile C++11? Why to waste manyears on bugs which > > can no longer exist with C++11? > > > > The discussion should be when to switch to C++17 as that removes another tons > > of crap like gnulib. > > He's saying that we should just require C++11 and be done with it. > And then he concluded with a (hopefully tongue-in-cheek) remark about > C++17, which (hopefully) is obvious we're not going to be requiring > that anytime soon... I have no reason to be sure that was tongue-in-cheek. And I have no reason to regard as obvious that no one will be requiring C++17 any time soon, not without anyone, nor our coding standards, saying that. So from my POV, that was no straw man argument at all. Jan is one of the more influential developers here, so his opinions certainly have a significant weight with me. I regard things that he writes very seriously. > Fact: Nowhere did he say that we will now require GCC 6.1. Not directly, no. But C++14 is not fully supported until GCC 5, AFAIK, so who knows what C++17 might mean; it certainly does mean a new enough GCC version, possibly GCC 6 or newer. Thus my reaction. > Requiring C++11 would mean requiring GCC around 4.8, NOT GCC 6.1. Agreed. But there wasn't any argument about this particular aspect, i.e. which GCC version would be needed for C++11 support. > > So "completely false" is completely false. > > You're repeated claims that people are suggesting to require > GCC 6.1 are provably false. See above: they are not provably false, or at least that's not the only possible interpretation of what's being said here. > In any case, Jan's reply came after all our discussions, and I'm > not Jan. If someone comes in and suggests to actually require GCC 6.1, > then I'll stop saying that nobody is suggesting that, and instead say > that I'd strongly object it. So we agree that requiring 6.1 at this point is not something we should do. Good. Now let's decide at some point for how long we will keep GCC 4.8 (or some older version, if we decide to stick to an older C++ standard) as the lowest version we require. Then these arguments will not happen anymore, at least for some time. > > And what > > you are suggesting, while not as radical as what Jan says, will still > > get us there soon enough. > > There's no Trojan here. If you don't trust me, then I don't know > what else I can do... This isn't about trusting you personally. I'm just old enough to know how these things develop and what is the social dynamics that facilitates them. It's our human nature. > And conversely, I hope you understand how repeated straw man > arguments even after they're categorically dismissed could be > taken as an insult. They are not straw men, they are good-faith arguments and concerns. Please treat them as such. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-12 10:51 ` Eli Zaretskii @ 2016-10-12 11:15 ` Pedro Alves 2016-10-12 11:40 ` Eli Zaretskii 2016-10-12 11:45 ` Jan Kratochvil 1 sibling, 1 reply; 72+ messages in thread From: Pedro Alves @ 2016-10-12 11:15 UTC (permalink / raw) To: Eli Zaretskii; +Cc: brobecker, markus.t.metzger, gdb-patches On 10/12/2016 11:51 AM, Eli Zaretskii wrote: > Would you please refrain from labeling my (or anyone else's) arguments > with derogatory labels? Please always assume that anything like that > is due to some misunderstanding, not to anything else. Will do, if you also start assuming good faith on my part. > I have no reason to be sure that was tongue-in-cheek. And I have no > reason to regard as obvious that no one will be requiring C++17 any > time soon, not without anyone, nor our coding standards, saying that. > > So from my POV, that was no straw man argument at all. Jan is one of > the more influential developers here, so his opinions certainly have a > significant weight with me. I regard things that he writes very > seriously. OK. I'll take that in consideration. >> Fact: Nowhere did he say that we will now require GCC 6.1. > > Not directly, no. But C++14 is not fully supported until GCC 5, > AFAIK, so who knows what C++17 might mean; it certainly does mean a > new enough GCC version, possibly GCC 6 or newer. Thus my reaction. I think worrying about language version requirements is seeing it backwards from what we should be looking at. IMO, we should be looking at the distribution sphere (and the distro versions people are likely to be using/developing on, e.g., latest Ubuntu LTS, past couple Fedora releases, etc.), and check what are the compiler versions that are shipped in them, either by default or as optional packages. And then from that, decide which most up to date language version / features we can require (if we'd really want to use them). I.e., if in 5 years, virtually everyone has convenient access to an C++14 compiler, why not make use of C++14 features if they'd make our lives easier? Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-12 11:15 ` Pedro Alves @ 2016-10-12 11:40 ` Eli Zaretskii 0 siblings, 0 replies; 72+ messages in thread From: Eli Zaretskii @ 2016-10-12 11:40 UTC (permalink / raw) To: Pedro Alves; +Cc: brobecker, markus.t.metzger, gdb-patches > Cc: brobecker@adacore.com, markus.t.metzger@intel.com, > gdb-patches@sourceware.org > From: Pedro Alves <palves@redhat.com> > Date: Wed, 12 Oct 2016 12:15:50 +0100 > > On 10/12/2016 11:51 AM, Eli Zaretskii wrote: > > > Would you please refrain from labeling my (or anyone else's) arguments > > with derogatory labels? Please always assume that anything like that > > is due to some misunderstanding, not to anything else. > > Will do, if you also start assuming good faith on my part. I always do. That's why my arguments weer only about technical aspects and about general human tendencies, not about you personally. > I think worrying about language version requirements is seeing > it backwards from what we should be looking at. IMO, we should > be looking at the distribution sphere (and the distro versions people > are likely to be using/developing on, e.g., latest Ubuntu LTS, past > couple Fedora releases, etc.), and check what are the compiler versions > that are shipped in them, either by default or as optional packages. We could do that, but IME we will not able to collect conclusive data that way. The latest distributions are clearly inappropriate (they always come with the latest compiler versions), and how do you tell how many users out there use which older versions? How do we collect statistics about that? That's why I suggested to use the "how far in the past" criteria. We could decide that N-year old compiler is reasonably old, and always go with the language supported by N-year old compilers. This is an easily testable criterion, and the decision about the value of N doesn't need to be reconsidered too frequently. > And then from that, decide which most up to date language version / > features we can require (if we'd really want to use them). I.e., if in > 5 years, virtually everyone has convenient access to an C++14 compiler, > why not make use of C++14 features if they'd make our lives easier? I question our ability to verify that "virtually everyone" part. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-12 10:51 ` Eli Zaretskii 2016-10-12 11:15 ` Pedro Alves @ 2016-10-12 11:45 ` Jan Kratochvil 2016-10-12 11:56 ` Luis Machado 2016-10-12 12:03 ` Eli Zaretskii 1 sibling, 2 replies; 72+ messages in thread From: Jan Kratochvil @ 2016-10-12 11:45 UTC (permalink / raw) To: Eli Zaretskii; +Cc: Pedro Alves, brobecker, markus.t.metzger, gdb-patches On Wed, 12 Oct 2016 12:51:16 +0200, Eli Zaretskii wrote: > > Jan said, in full: > > > > > The discussion is about C++11. LLVM+LLDB have switched to C++11 in 2014 and > > > they haven't looked back. > > > > > > I see the C++11 discussion pointless, where is the system which really needs > > > GDB and which still cannot compile C++11? Why to waste manyears on bugs which > > > can no longer exist with C++11? > > > > > > The discussion should be when to switch to C++17 as that removes another tons > > > of crap like gnulib. > > > > He's saying that we should just require C++11 and be done with it. > > And then he concluded with a (hopefully tongue-in-cheek) remark about > > C++17, which (hopefully) is obvious we're not going to be requiring > > that anytime soon... > > I have no reason to be sure that was tongue-in-cheek. And I have no > reason to regard as obvious that no one will be requiring C++17 any > time soon, not without anyone, nor our coding standards, saying that. > > So from my POV, that was no straw man argument at all. Jan is one of > the more influential developers here, so his opinions certainly have a > significant weight with me. I regard things that he writes very > seriously. I really think the C++11 discussion is pointless, everything everywhere does support C++11 now. My C++17 sentence was meant seriously - but literally as it is written - that I do not expect GDB should really start requiring C++17 right now. But in a few years GDB should really start requiring C++17 as it will increase GDB's developers productivity similarly to how C++11 will/would now. Please notice C++17 is really offtopic for this mail thread now. Nowadays software is no longer distributed on floppy disks by snail mail. I do not see a reason for artificial requirements of "5 years". Fixes are being delivered by automated update systems in days and new releases with integration testing happen in months. Jan ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-12 11:45 ` Jan Kratochvil @ 2016-10-12 11:56 ` Luis Machado 2016-10-12 12:03 ` Eli Zaretskii 1 sibling, 0 replies; 72+ messages in thread From: Luis Machado @ 2016-10-12 11:56 UTC (permalink / raw) To: Jan Kratochvil, Eli Zaretskii Cc: Pedro Alves, brobecker, markus.t.metzger, gdb-patches On 10/12/2016 06:45 AM, Jan Kratochvil wrote: > Nowadays software is no longer distributed on floppy disks by snail mail. > I do not see a reason for artificial requirements of "5 years". Fixes are > being delivered by automated update systems in days and new releases with > integration testing happen in months. It seems naive or wishful thinking to assume everyone is running on automated update systems. I wouldn't call that completely valid, nor it would be valid to force that on whoever is not using it. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-12 11:45 ` Jan Kratochvil 2016-10-12 11:56 ` Luis Machado @ 2016-10-12 12:03 ` Eli Zaretskii 2016-10-13 9:07 ` Jan Kratochvil 1 sibling, 1 reply; 72+ messages in thread From: Eli Zaretskii @ 2016-10-12 12:03 UTC (permalink / raw) To: Jan Kratochvil; +Cc: palves, brobecker, markus.t.metzger, gdb-patches > Date: Wed, 12 Oct 2016 13:45:15 +0200 > From: Jan Kratochvil <jan.kratochvil@redhat.com> > Cc: Pedro Alves <palves@redhat.com>, brobecker@adacore.com, > markus.t.metzger@intel.com, gdb-patches@sourceware.org > > Nowadays software is no longer distributed on floppy disks by snail mail. > I do not see a reason for artificial requirements of "5 years". Fixes are > being delivered by automated update systems in days and new releases with > integration testing happen in months. That may all be true, but changing the system compiler is still a serious decision, unrelated to distribution and/or update speeds, and not always even in the hands of the user who wants to build his or her GDB which was just released. The nuisance of having to upgrade half of your system just because you want to have one package of the latest release is real for users who need to do during most of their day something other than debug build failures and install updated dependencies. I was hoping we didn't want to increase those annoyances. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-12 12:03 ` Eli Zaretskii @ 2016-10-13 9:07 ` Jan Kratochvil 2016-10-13 10:07 ` Eli Zaretskii 0 siblings, 1 reply; 72+ messages in thread From: Jan Kratochvil @ 2016-10-13 9:07 UTC (permalink / raw) To: Eli Zaretskii; +Cc: palves, brobecker, markus.t.metzger, gdb-patches On Wed, 12 Oct 2016 14:03:06 +0200, Eli Zaretskii wrote: > That may all be true, but changing the system compiler is still a > serious decision, unrelated to distribution and/or update speeds, and > not always even in the hands of the user who wants to build his or her > GDB which was just released. > > The nuisance of having to upgrade half of your system just because you > want to have one package of the latest release is real for users who > need to do during most of their day something other than debug build > failures and install updated dependencies. I was hoping we didn't > want to increase those annoyances. GCC 4.8.1 has been released in May 2013 so any Linux distributions with at least annual releases already have it. The only exception are LTS https://en.wikipedia.org/wiki/Long-term_support distributions: {RHEL,CentOS}-5.0: gcc-4.1.1-52.el5 But there is Developer Toolset 2.1 compatible with RHEL-5 which provides: devtoolset-2-gcc-4.8.2-15.el5 DevToolset 2.1 is still available in RHN channel for RHEL-5 customers. Unfortunately it is currently unavailable for CentOS-5 users, hopefully it will become available soon on this URL but I sure cannot guarantee anything: https://www.softwarecollections.org/en/scls/?search=toolset {RHEL,CentOS}-6.0: gcc-4.4.4-13.el6 There is DevToolset available in RHN channel and for CentOS it is freely at: https://www.softwarecollections.org/en/scls/rhscl/devtoolset-4/ http://mirror.centos.org/centos/6/sclo/x86_64/rh/devtoolset-4/devtoolset-4-gcc-5.2.1-2.2.el6.x86_64.rpm {RHEL,CentOS}-7.0: gcc-4.8.2-16.el7 Debian stable: https://packages.debian.org/stable/gcc = 4:4.9.2-2 Ubuntu LTSes: https://en.wikipedia.org/wiki/Ubuntu_(operating_system)#Releases http://packages.ubuntu.com/search?keywords=gcc 12.04LTS = 4:4.6.3-1ubuntu5 I am not aware of anything like DevToolset for Ubuntu. 14.04LTS = 4:4.8.2-1ubuntu6 DevToolset is an add-on packaging in /opt/rh/ running independently from system GCC producing binaries compatible even with RHELs without DevToolset. Therefore there is no need of "changing the system compiler" or "upgrade half of your system" to compile C++11 there. As Pedro said the C++11 requirement is becoming common among other packages so it is probable one needs to install DevToolset anyway. Then there are systems without package management - like MS-Windows - where all the recent compilers are available installable into separate subdirectories. Jan ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-13 9:07 ` Jan Kratochvil @ 2016-10-13 10:07 ` Eli Zaretskii 2016-10-13 10:27 ` Pedro Alves 2016-10-13 10:46 ` Jan Kratochvil 0 siblings, 2 replies; 72+ messages in thread From: Eli Zaretskii @ 2016-10-13 10:07 UTC (permalink / raw) To: Jan Kratochvil; +Cc: palves, brobecker, markus.t.metzger, gdb-patches > Date: Thu, 13 Oct 2016 11:06:47 +0200 > From: Jan Kratochvil <jan.kratochvil@redhat.com> > Cc: palves@redhat.com, brobecker@adacore.com, markus.t.metzger@intel.com, > gdb-patches@sourceware.org > > GCC 4.8.1 has been released in May 2013 so any Linux distributions with at > least annual releases already have it. The only exception are LTS > https://en.wikipedia.org/wiki/Long-term_support > distributions: > > {RHEL,CentOS}-5.0: gcc-4.1.1-52.el5 > But there is Developer Toolset 2.1 compatible with RHEL-5 which provides: > devtoolset-2-gcc-4.8.2-15.el5 > DevToolset 2.1 is still available in RHN channel for RHEL-5 customers. > Unfortunately it is currently unavailable for CentOS-5 users, hopefully it > will become available soon on this URL but I sure cannot guarantee anything: > https://www.softwarecollections.org/en/scls/?search=toolset > > {RHEL,CentOS}-6.0: gcc-4.4.4-13.el6 > There is DevToolset available in RHN channel and for CentOS it is freely at: > https://www.softwarecollections.org/en/scls/rhscl/devtoolset-4/ > http://mirror.centos.org/centos/6/sclo/x86_64/rh/devtoolset-4/devtoolset-4-gcc-5.2.1-2.2.el6.x86_64.rpm > > {RHEL,CentOS}-7.0: gcc-4.8.2-16.el7 "Available" doesn't mean "installed". Places which use RHEL are IME extremely conservative in upgrading policies, and might not upgrade without a good reason. The shop where I get my paycheck is one such place. > Then there are systems without package management - like MS-Windows - where > all the recent compilers are available installable into separate > subdirectories. That depends. Mingw.org has only 5.3.0 as the latest offering, and recently enough (a few months ago) it only had 4.9.3. So please be very careful when you make assumptions about how widespread a certain compiler version is in n on-Posix world. Like I said before: upgrading the system compiler is a serious decision. Installing a newer compiler could easily break the build of several important packages, which then requires an avalanche of upgrading across the board, just to get those package to build again. That is why many shops which want stable environments and need to continue supporting existing products don't bother upgrading the compiler and the core libraries, unless someone pays for that. Personal machines are most probably another matter, but I don't think we should extrapolate from them. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-13 10:07 ` Eli Zaretskii @ 2016-10-13 10:27 ` Pedro Alves 2016-10-13 13:22 ` Eli Zaretskii 2016-10-13 10:46 ` Jan Kratochvil 1 sibling, 1 reply; 72+ messages in thread From: Pedro Alves @ 2016-10-13 10:27 UTC (permalink / raw) To: Eli Zaretskii, Jan Kratochvil; +Cc: brobecker, markus.t.metzger, gdb-patches On 10/13/2016 11:06 AM, Eli Zaretskii wrote: > Like I said before: upgrading the system compiler is a serious > decision. True. But that's not what these packages do. > Installing a newer compiler could easily break the build of > several important packages, which then requires an avalanche of > upgrading across the board, just to get those package to build again. True. But that's not what these packages do. > That is why many shops which want stable environments and need to > continue supporting existing products don't bother upgrading the > compiler and the core libraries, unless someone pays for that. True. But that's not what these packages do. The newer compilers available as packages on these old distros (e.g., DTS on RHEL) do _not_ replace the system compiler. They're installed in parallel, in separate directories. You willfully add them to the PATH or pass an overridden CXX to configure/make if you want to use them. Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-13 10:27 ` Pedro Alves @ 2016-10-13 13:22 ` Eli Zaretskii 2016-10-13 13:36 ` Pedro Alves 0 siblings, 1 reply; 72+ messages in thread From: Eli Zaretskii @ 2016-10-13 13:22 UTC (permalink / raw) To: Pedro Alves; +Cc: jan.kratochvil, brobecker, markus.t.metzger, gdb-patches > Cc: brobecker@adacore.com, markus.t.metzger@intel.com, > gdb-patches@sourceware.org > From: Pedro Alves <palves@redhat.com> > Date: Thu, 13 Oct 2016 11:27:03 +0100 > > The newer compilers available as packages on these old distros > (e.g., DTS on RHEL) do _not_ replace the system compiler. They're > installed in parallel, in separate directories. You willfully add them > to the PATH or pass an overridden CXX to configure/make if you want to > use them. I don't see the difference, except for the worse: instead of one compiler you now have two, so one could easily select the wrong one when compiling some package. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-13 13:22 ` Eli Zaretskii @ 2016-10-13 13:36 ` Pedro Alves 2016-10-13 13:59 ` Eli Zaretskii 0 siblings, 1 reply; 72+ messages in thread From: Pedro Alves @ 2016-10-13 13:36 UTC (permalink / raw) To: Eli Zaretskii; +Cc: jan.kratochvil, brobecker, markus.t.metzger, gdb-patches On 10/13/2016 02:22 PM, Eli Zaretskii wrote: >> Cc: brobecker@adacore.com, markus.t.metzger@intel.com, >> gdb-patches@sourceware.org >> From: Pedro Alves <palves@redhat.com> >> Date: Thu, 13 Oct 2016 11:27:03 +0100 >> >> The newer compilers available as packages on these old distros >> (e.g., DTS on RHEL) do _not_ replace the system compiler. They're >> installed in parallel, in separate directories. You willfully add them >> to the PATH or pass an overridden CXX to configure/make if you want to >> use them. > > I don't see the difference, except for the worse: instead of one > compiler you now have two, so one could easily select the wrong one > when compiling some package. You said: "upgrading the system compiler is a serious decision. Installing a newer compiler could easily break the build of several important packages (...)" And I'm telling you that the packages in question don't upgrade the system compiler at all. There's no risk of "easily break" things. Of course people can do all sorts of crazy things, even "sudo rm -rf /" But we're not in the business of protecting against all foolishness. > so one could easily select the wrong one when compiling some package. No you don't. The system one is still the default. There's nothing complicated here. Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-13 13:36 ` Pedro Alves @ 2016-10-13 13:59 ` Eli Zaretskii 2016-10-13 14:04 ` Pedro Alves 0 siblings, 1 reply; 72+ messages in thread From: Eli Zaretskii @ 2016-10-13 13:59 UTC (permalink / raw) To: Pedro Alves; +Cc: jan.kratochvil, brobecker, markus.t.metzger, gdb-patches > Cc: jan.kratochvil@redhat.com, brobecker@adacore.com, > markus.t.metzger@intel.com, gdb-patches@sourceware.org > From: Pedro Alves <palves@redhat.com> > Date: Thu, 13 Oct 2016 14:35:58 +0100 > > >> The newer compilers available as packages on these old distros > >> (e.g., DTS on RHEL) do _not_ replace the system compiler. They're > >> installed in parallel, in separate directories. You willfully add them > >> to the PATH or pass an overridden CXX to configure/make if you want to > >> use them. > > > > I don't see the difference, except for the worse: instead of one > > compiler you now have two, so one could easily select the wrong one > > when compiling some package. > > You said: > > "upgrading the system compiler is a serious decision. Installing a > newer compiler could easily break the build of several important > packages (...)" > > And I'm telling you that the packages in question don't upgrade > the system compiler at all. Of course, they do: you have a newer compiler on your system, which is about to be used for building some packages. > There's no risk of "easily break" things. Of course, there is: the new compiler will do that. That one can go back to the old one doesn't help at all, because that was also possible without a parallel installation: just uninstall the new one and install back the old one. Organizations rarely do this stuff. You want to install a compiler and let users use it without complications. Most of your users aren't hackers, they have no idea how to debug a package build problem. They will come back to you expecting that you fix the problem for them. > There's nothing complicated here. I respectfully disagree. We most probably have very different experience here, and very different users to deal with. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-13 13:59 ` Eli Zaretskii @ 2016-10-13 14:04 ` Pedro Alves 2016-10-13 15:06 ` Joel Brobecker 0 siblings, 1 reply; 72+ messages in thread From: Pedro Alves @ 2016-10-13 14:04 UTC (permalink / raw) To: Eli Zaretskii; +Cc: jan.kratochvil, brobecker, markus.t.metzger, gdb-patches On 10/13/2016 02:59 PM, Eli Zaretskii wrote: > I respectfully disagree. OK, we'll agree to disagree. Maybe someone else can share their experience as well. > We most probably have very different > experience here, and very different users to deal with. I have many different compilers installed in parallel on my Fedora system. I never once had a problem with a non-system compiler breaking my system. Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-13 14:04 ` Pedro Alves @ 2016-10-13 15:06 ` Joel Brobecker 0 siblings, 0 replies; 72+ messages in thread From: Joel Brobecker @ 2016-10-13 15:06 UTC (permalink / raw) To: Pedro Alves; +Cc: Eli Zaretskii, jan.kratochvil, markus.t.metzger, gdb-patches > > I respectfully disagree. > > OK, we'll agree to disagree. > Maybe someone else can share their experience as well. For us, having multiple compilers installed at non-standard locations is very common. I can't say I know where all our customers install our toolchains, but we routinely answer questions about parallel installs, and we also frequently recommend parallel installs as well. I've never viewed multiple-compiler installs as being a big complication. If we're really worried about requiring C++-11 and the impact on the users who build GDB, we could perhaps just organize a poll that asks users how this would impact them, and then request participation on gdb-announce. -- Joel ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-13 10:07 ` Eli Zaretskii 2016-10-13 10:27 ` Pedro Alves @ 2016-10-13 10:46 ` Jan Kratochvil 2016-10-13 11:15 ` Pedro Alves 2016-10-13 13:28 ` Eli Zaretskii 1 sibling, 2 replies; 72+ messages in thread From: Jan Kratochvil @ 2016-10-13 10:46 UTC (permalink / raw) To: Eli Zaretskii; +Cc: palves, brobecker, markus.t.metzger, gdb-patches On Thu, 13 Oct 2016 12:06:33 +0200, Eli Zaretskii wrote: > That depends. Mingw.org has only 5.3.0 as the latest offering, and > recently enough (a few months ago) it only had 4.9.3. So please be very > careful when you make assumptions about how widespread a certain > compiler version is in n on-Posix world. 5.3.0 was released 2016-04-27 https://sourceforge.net/projects/mingw/files/MinGW/Base/gcc/Version5/gcc-5.3.0-2/ 4.9.3 was released 2015-07-25 https://sourceforge.net/projects/mingw/files/MinGW/Base/gcc/Version4/gcc-4.9.3-1/ That was after 9 months. 4.8.1 was released May 2013 = 41 months ago. I find 9 and 41 months a big difference. Besides that AFAIK mingw.org is dead, it has been superseded by mingw-w64.org. What are you trying to say? A dead project makes releases 4.5x faster than what GDB would require for its build. You more justify that GDB could for example require even C++14. And even if someone does not have the C++11 compiler installed most of the users prefer to install applications (such as is GDB) in a binary form anyway. So even some very exceptional case we both cannot even imagine still does not prevent the user from running GDB. Jan ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-13 10:46 ` Jan Kratochvil @ 2016-10-13 11:15 ` Pedro Alves 2016-10-13 13:28 ` Eli Zaretskii 1 sibling, 0 replies; 72+ messages in thread From: Pedro Alves @ 2016-10-13 11:15 UTC (permalink / raw) To: Jan Kratochvil, Eli Zaretskii; +Cc: brobecker, markus.t.metzger, gdb-patches On 10/13/2016 11:45 AM, Jan Kratochvil wrote: > compiler installed most of the users prefer to install applications (such as > is GDB) in a binary form anyway. Definitely my perception as well. On the #gdb IRC channel, for example, it's rare for people to come in saying they've built a new gdb themselves for native debugging. Most often they'll be using the (old) system one, or maybe have gotten one from some binary side channel, like macports.org. It's in the embedded space where it's more frequent to hear about uses of newer gdb on old host systems. Still on that space most people prefer to use prebuilt and validated packages. And then people that build such toolchains themselves will most often be using recipe systems that scripts downloading and building everything, like crosstool-ng for example. Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-13 10:46 ` Jan Kratochvil 2016-10-13 11:15 ` Pedro Alves @ 2016-10-13 13:28 ` Eli Zaretskii 2016-10-13 13:42 ` Pedro Alves 1 sibling, 1 reply; 72+ messages in thread From: Eli Zaretskii @ 2016-10-13 13:28 UTC (permalink / raw) To: Jan Kratochvil; +Cc: palves, brobecker, markus.t.metzger, gdb-patches > Date: Thu, 13 Oct 2016 12:45:42 +0200 > From: Jan Kratochvil <jan.kratochvil@redhat.com> > Cc: palves@redhat.com, brobecker@adacore.com, markus.t.metzger@intel.com, > gdb-patches@sourceware.org > > On Thu, 13 Oct 2016 12:06:33 +0200, Eli Zaretskii wrote: > > That depends. Mingw.org has only 5.3.0 as the latest offering, and > > recently enough (a few months ago) it only had 4.9.3. So please be very > > careful when you make assumptions about how widespread a certain > > compiler version is in n on-Posix world. > > 5.3.0 was released 2016-04-27 > https://sourceforge.net/projects/mingw/files/MinGW/Base/gcc/Version5/gcc-5.3.0-2/ > 4.9.3 was released 2015-07-25 > https://sourceforge.net/projects/mingw/files/MinGW/Base/gcc/Version4/gcc-4.9.3-1/ That's what I said, without giving the exact numbers, no? > That was after 9 months. 4.8.1 was released May 2013 = 41 months ago. > > I find 9 and 41 months a big difference. Yes, 41 - 9 = 32. So? What is the significance of this for the issue at hand? > Besides that AFAIK mingw.org is dead, it has been superseded by mingw-w64.org. No, it isn't dead and isn't superseded. Your information is wrong. > What are you trying to say? That your assumptions about the availability of latest compiler versions are too optimistic, IMO. On GNU/Linux, and certainly on MS-Windows. > A dead project makes releases 4.5x faster than what GDB would > require for its build. You more justify that GDB could for example > require even C++14. Sorry, I cannot parse these 2 sentences. > And even if someone does not have the C++11 compiler installed most > of the users prefer to install applications (such as is GDB) in a > binary form anyway. Somebody must produce those binaries first. Someone like this guy, for example: https://sourceforge.net/projects/ezwinports/files/ That someone does need to have the required tools. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-13 13:28 ` Eli Zaretskii @ 2016-10-13 13:42 ` Pedro Alves 2016-10-13 14:07 ` Eli Zaretskii 0 siblings, 1 reply; 72+ messages in thread From: Pedro Alves @ 2016-10-13 13:42 UTC (permalink / raw) To: Eli Zaretskii, Jan Kratochvil; +Cc: brobecker, markus.t.metzger, gdb-patches On 10/13/2016 02:28 PM, Eli Zaretskii wrote: > > https://sourceforge.net/projects/ezwinports/files/ > > That someone does need to have the required tools. And you have them. So IIUC, from your side, we're all right. I'd like to hear from people that _might_ be affected. #1 - Is anyone here building gdb routinely on a distro that doesn't have a C++11 compiler handy? #2 - Is anyone here building gdb routinely on a distro that doesn't have a C++11 compiler handy _and_ it'd be too inconvenient to update to a newer version of the distro and/or find a newer compiler? Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-13 13:42 ` Pedro Alves @ 2016-10-13 14:07 ` Eli Zaretskii 0 siblings, 0 replies; 72+ messages in thread From: Eli Zaretskii @ 2016-10-13 14:07 UTC (permalink / raw) To: Pedro Alves; +Cc: jan.kratochvil, brobecker, markus.t.metzger, gdb-patches > Cc: brobecker@adacore.com, markus.t.metzger@intel.com, gdb-patches@sourceware.org > From: Pedro Alves <palves@redhat.com> > Date: Thu, 13 Oct 2016 14:42:18 +0100 > > On 10/13/2016 02:28 PM, Eli Zaretskii wrote: > > > > https://sourceforge.net/projects/ezwinports/files/ > > > > That someone does need to have the required tools. > > And you have them. So IIUC, from your side, we're all right. As long as we are talking about C++11, and no later. Once again, the discussion, from my side, was more general than about just this patch and just the current C++ standard we want to support. I'm sure I made that very clear on several occasions in this thread. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 18:37 ` Eli Zaretskii 2016-10-11 19:19 ` Pedro Alves @ 2016-10-11 19:23 ` Simon Marchi 2016-10-11 20:54 ` Eli Zaretskii 2016-10-11 21:16 ` Jan Kratochvil 1 sibling, 2 replies; 72+ messages in thread From: Simon Marchi @ 2016-10-11 19:23 UTC (permalink / raw) To: Eli Zaretskii; +Cc: Pedro Alves, brobecker, markus.t.metzger, gdb-patches On 2016-10-11 14:36, Eli Zaretskii wrote: >> First, it's not true that these C++ changes have not been planned. >> They've been part of the plan ever since the very beginning. See >> here, step 5 of the original version of the plan I originally >> circulated in 2014: >> >> https://sourceware.org/gdb/wiki/cxx-conversion?action=recall&rev=1 >> >> Current version is here: >> >> https://sourceware.org/gdb/wiki/cxx-conversion#Transition_plan >> >> Note the not-done-yet bullet points in step 8 (step 5 in rev 1). >> That's exactly what's going on right now. > > Where does it say that we should require C++11? Or any specific > version of the C++ standard, for that matter? AFAIR, this was never > discussed. I don't think anybody has seriously suggested requiring C++11 any time soon, other than in a very hypothetical formulation. I can see why there are some misunderstanding, especially for those who haven't followed closely the C++ conversion. Let me try to state what I understand from the situation. C++03 has been around for long enough that we can safely migrate to that (whereas it has value or not is another debate, although I think Pedro showed clearly that it has), without leaving many users behind. C++11 comes with some nice features in its standard library, such as std::unique_ptr. std::unique_ptr has some improvements over the old std::auto_ptr, which was too easy to misuse. However, I think we all agree that C++11 would be a too aggressive change, and will still be for some time. What Pedro chose to do is to create gdb::unique_ptr, our home-made version of std::unique_ptr. When building with a C++03 compiler, the hand-written version of the code is chosen and it works (see the #if __cplusplus >= 201103). However, it's possible to misuse it, the same way as it was possible to misuse std::auto_ptr (because of missing features in C++03 vs C++11 IIUC). If you happen to build with a C++11 compiler, instead of choosing the hand-written version, gdb::unique_ptr is more or less an alias for std::unique_ptr. So if there is a place in the code that is misusing it, the build will fail and either buildbot or another developer will let us know promptly. So it's not that the code is built in a way which requires C++11, it's built in a way that if you use C++11, you get the benefits of the newer checking mechanisms, while still being able to build with a C++03 compiler. IMO it's the best of both worlds. Actually, it's the same idea as gnulib, where we fill the gaps of the lacking platforms, rather than choosing a low common denominator. The warning analogy was perhaps not clearly expressed but I think it was good. Let's say somebody with an old compiler wrote this code: void foo() { int a; global = a; } The old compiler doesn't have a warning to tell you that "a" is being used without being initialized, so it accepts it. When another developer, with a newer compiler, tries to build gdb, he/she gets an error, and is able to report the bug. With unique_ptr, it's similar. Somebody with an old compiler gets less compiler checking. The difference is that we need to write a bit of code (this patch) to bridge the gap, whereas with warnings it comes for free. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 19:23 ` Simon Marchi @ 2016-10-11 20:54 ` Eli Zaretskii 2016-10-11 21:28 ` Simon Marchi 2016-10-11 21:16 ` Jan Kratochvil 1 sibling, 1 reply; 72+ messages in thread From: Eli Zaretskii @ 2016-10-11 20:54 UTC (permalink / raw) To: Simon Marchi; +Cc: palves, brobecker, markus.t.metzger, gdb-patches > Date: Tue, 11 Oct 2016 15:23:46 -0400 > From: Simon Marchi <simon.marchi@polymtl.ca> > Cc: Pedro Alves <palves@redhat.com>, brobecker@adacore.com, > markus.t.metzger@intel.com, gdb-patches@sourceware.org > > C++03 has been around for long enough that we can safely migrate to that > (whereas it has value or not is another debate, although I think Pedro > showed clearly that it has), without leaving many users behind. C++11 > comes with some nice features in its standard library, such as > std::unique_ptr. std::unique_ptr has some improvements over the old > std::auto_ptr, which was too easy to misuse. However, I think we all > agree that C++11 would be a too aggressive change, and will still be for > some time. Then why was there talk to use -std=gnu++11? > What Pedro chose to do is to create gdb::unique_ptr, our home-made > version of std::unique_ptr. When building with a C++03 compiler, the > hand-written version of the code is chosen and it works (see the #if > __cplusplus >= 201103). However, it's possible to misuse it, the same > way as it was possible to misuse std::auto_ptr (because of missing > features in C++03 vs C++11 IIUC). If you happen to build with a C++11 > compiler, instead of choosing the hand-written version, gdb::unique_ptr > is more or less an alias for std::unique_ptr. So if there is a place in > the code that is misusing it, the build will fail and either buildbot or > another developer will let us know promptly. > > So it's not that the code is built in a way which requires C++11, it's > built in a way that if you use C++11, you get the benefits of the newer > checking mechanisms, while still being able to build with a C++03 > compiler. IMO it's the best of both worlds. Actually, it's the same > idea as gnulib, where we fill the gaps of the lacking platforms, rather > than choosing a low common denominator. That's not "stick to C++03" in my book. Sticking to C++03 means not writing any code that requires a later standard at all. Exactly like we did when we required C90, but not C99: we had no code written for C99 compilers, #ifdef'ed away for C90 compilers. Everything was C90. > The warning analogy was perhaps not clearly expressed but I think it was > good. No, it wasn't: warnings don't affect code at all. This suggestion clearly will. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 20:54 ` Eli Zaretskii @ 2016-10-11 21:28 ` Simon Marchi 2016-10-12 6:23 ` Eli Zaretskii 0 siblings, 1 reply; 72+ messages in thread From: Simon Marchi @ 2016-10-11 21:28 UTC (permalink / raw) To: Eli Zaretskii; +Cc: palves, brobecker, markus.t.metzger, gdb-patches On 2016-10-11 16:54, Eli Zaretskii wrote: > Then why was there talk to use -std=gnu++11? For those compilers that support C++11, but default to C++03. If the feature is present and using it provides use with better error-checking, why not use it? > That's not "stick to C++03" in my book. Sticking to C++03 means not > writing any code that requires a later standard at all. That's your interpretation. I prefer to interpret it as compilable with a C++03 compiler, with no significant difference in the resulting behaviour. > Exactly like > we did when we required C90, but not C99: we had no code written for > C99 compilers, #ifdef'ed away for C90 compilers. Everything was C90. Maybe because there wasn't a need or reason to do so? In this case, there appears to be some value doing it. Do you question the fact that it brings value at all, or that that value is not worth the extra complexity? I am sure nobody wants to see the whole code base sprinkled with such #ifs. But here it's isolated in a file that we'll almost never touch again, and which will significantly improve the rest of the code base, with which we work with daily. >> The warning analogy was perhaps not clearly expressed but I think it >> was >> good. > > No, it wasn't: warnings don't affect code at all. This suggestion > clearly will. I made sure to point that out at the end of my paragraph, but anyway the analogy is not the important point here. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 21:28 ` Simon Marchi @ 2016-10-12 6:23 ` Eli Zaretskii 0 siblings, 0 replies; 72+ messages in thread From: Eli Zaretskii @ 2016-10-12 6:23 UTC (permalink / raw) To: Simon Marchi; +Cc: palves, brobecker, markus.t.metzger, gdb-patches > Date: Tue, 11 Oct 2016 17:28:24 -0400 > From: Simon Marchi <simon.marchi@polymtl.ca> > Cc: palves@redhat.com, brobecker@adacore.com, markus.t.metzger@intel.com, > gdb-patches@sourceware.org > > On 2016-10-11 16:54, Eli Zaretskii wrote: > > Then why was there talk to use -std=gnu++11? > > For those compilers that support C++11, but default to C++03. If the > feature is present and using it provides use with better error-checking, > why not use it? You are contradicting yourself. Previously, you said: > However, I think we all agree that C++11 would be a too aggressive > change, and will still be for some time. Now you are saying that we _should_ use C++11? Do you see how confusing all this is? I cannot even figure out what is it that people are arguing for or against. > > That's not "stick to C++03" in my book. Sticking to C++03 means not > > writing any code that requires a later standard at all. > > That's your interpretation. I prefer to interpret it as compilable with > a C++03 compiler, with no significant difference in the resulting > behaviour. > > > Exactly like > > we did when we required C90, but not C99: we had no code written for > > C99 compilers, #ifdef'ed away for C90 compilers. Everything was C90. > > Maybe because there wasn't a need or reason to do so? In this case, > there appears to be some value doing it. Do you question the fact that > it brings value at all, or that that value is not worth the extra > complexity? I question the honesty of the decision not to switch to standards supported only by recent versions of GCC. There's always a shining new version of the standards out there, which is normally much better than the previous ones. By that logic, we should switch to the latest version of standard C++ the moment it appears in draft, because it definitely brings some significant value. > I am sure nobody wants to see the whole code base sprinkled with such > #ifs. But here it's isolated in a file that we'll almost never touch > again, and which will significantly improve the rest of the code base, > with which we work with daily. Once admitted into the sources and allowed as acceptable practice, this will never remain limited to a single file. Let's not be naïve. ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 19:23 ` Simon Marchi 2016-10-11 20:54 ` Eli Zaretskii @ 2016-10-11 21:16 ` Jan Kratochvil 1 sibling, 0 replies; 72+ messages in thread From: Jan Kratochvil @ 2016-10-11 21:16 UTC (permalink / raw) To: Simon Marchi Cc: Eli Zaretskii, Pedro Alves, brobecker, markus.t.metzger, gdb-patches On Tue, 11 Oct 2016 21:23:46 +0200, Simon Marchi wrote: > I don't think anybody has seriously suggested requiring C++11 any time soon, The discussion is about C++11. LLVM+LLDB have switched to C++11 in 2014 and they haven't looked back. I see the C++11 discussion pointless, where is the system which really needs GDB and which still cannot compile C++11? Why to waste manyears on bugs which can no longer exist with C++11? The discussion should be when to switch to C++17 as that removes another tons of crap like gnulib. Jan ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 16:24 ` Pedro Alves 2016-10-11 16:58 ` Eli Zaretskii @ 2016-10-11 17:15 ` Luis Machado 2016-10-11 18:21 ` Pedro Alves 1 sibling, 1 reply; 72+ messages in thread From: Luis Machado @ 2016-10-11 17:15 UTC (permalink / raw) To: Pedro Alves, Eli Zaretskii, Joel Brobecker; +Cc: markus.t.metzger, gdb-patches On 10/11/2016 11:24 AM, Pedro Alves wrote: > On 10/11/2016 04:16 PM, Eli Zaretskii wrote: > >> IMO, requiring to build GCC as a prerequisite for building GDB is a >> major setback. Building GDB is a relatively easy and straightforward >> task today, even a native MS-Windows build. By contrast, building GCC >> requires quite a few additional prerequisites, which will also need to >> be built correctly. It also requires to configure the GCC being built >> itself, which involves considering a large number of opt-in and >> opt-out features, whose descriptions are not well suited for casual >> users, and therefore whose consequences cannot be easily understood. > > Windows may be one of the hardest systems on which to build GCC. > For Unix systems, it's relatively painless. It's easy to find scripts > around the web that download the necessary dependencies and build gcc, > all in one go. I think the GCC source tree has contrib patches for > at least the downloading part. > >> Yes, I use GCC, of course, but I just upgraded to 5.3.0 here a few >> months ago, while you seem to be already talking about 6.x. If we >> start on this slippery slope, I can easily envision the requirement to >> go up to 7.x very soon, exactly like switching to C++-compatible GDB >> caused, within just few months, > > That's a misunderstanding. Full C++11 support is available > in gcc 4.8 already. I believe it's easy to find binary mingw > gcc's of (at least) that vintage easily, for both mingw and mingw-64. > > mingw talks about gcc 4.8 binaries here: > > http://www.mingw.org/wiki/howto_install_the_mingw_gcc_compiler_suite > > I don't expect anyone to _have_ to build any mingw compiler to be able > to build gdb for mingw. > > It's just that gcc 6.x is the first version that has switched > the _default_ mode for C++ to -std=gnu++14. So until someone writes a > patch that make gdb's build system enable C++11 support with gcc < 6, > then the C++11-only code in the gdb::unique_ptr patch that I'm proposing > will only be active with gcc 6.1 onward. But really I'm not > proposing to _require_ 6.x at all. > >> a massive rewrite of GDB in complex C++. > > Most of the changes have been around using std::string, destructors, > and RAII, which are basic everyday C++ things. The latter two are > mainly about using compiler support for things we have to manually > today (make_cleanup). std::string just makes code shorter and safer, > I don't see a real downside or anything complex about it. > > A few patches that build supporting widgets will naturally use a > bit more complex C++ internally, all in the name of making _users_ of > such widgets significantly simpler. This patch is one such example. > These kinds of support patches naturally will need to come > before we can make use of the features they add support for, so > while it may appear we're going to keep adding lots of magic > things, I don't think that's true. Maybe this should be discussed in gdb@, but... Some of Eli's points resonate with me. It seems we just recently got the C++ compatibility sorted out and we're quickly moving on to try and C++-ify what we can with no clear goal, priority list or high level picture. So, just to make it C++ now that we require a C++ compiler. I thought i'd throw this question out there. Wasn't the goal of moving to C++ to help the implementation of features that were hard to implement with C like some of the Fortran bits with dynamic arrays? Also improve the poor experience with C++ debugging? I was asking myself, this week, if GCC went through such a big C++-ification effort when they moved away from C. Another point i worry about is that we will switch the focus, at least for a few months, to C++-ifying things "just because" instead of taking the opportunity of such a big change to review bits of GDB that need to be redesigned/dropped/go away. Maybe just converting existing things to C++ is not the right answer, even though it is fun to do and will provide enough hacking fun? I have another point about whether this will stimulate more contributors to send patches to GDB or not, but that's enough rambling for now. :-) ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 1/3] Introduce gdb::unique_ptr 2016-10-11 17:15 ` Luis Machado @ 2016-10-11 18:21 ` Pedro Alves 0 siblings, 0 replies; 72+ messages in thread From: Pedro Alves @ 2016-10-11 18:21 UTC (permalink / raw) To: Luis Machado, Eli Zaretskii, Joel Brobecker; +Cc: markus.t.metzger, gdb-patches On 10/11/2016 06:14 PM, Luis Machado wrote: > Some of Eli's points resonate with me. It seems we just recently got the > C++ compatibility sorted out and we're quickly moving on to try and > C++-ify what we can with no clear goal, priority list or high level > picture. So, just to make it C++ now that we require a C++ compiler. It's all described at: https://sourceware.org/gdb/wiki/cxx-conversion#Transition_plan One of the goals right now is to replace cleanups with something that the compiler does automatically. That is, completely eliminate the "forgot to call do_cleanups" bug by design. That generally involves: - replacing cleanups with either RAII objects (Tromey's scoped_restore class) - converting structs to classes with destructors. Make some classes be value objects allocated on the stack. - make use of std::string, which tends to simplify the code significantly anyway. > > I thought i'd throw this question out there. Wasn't the goal of moving > to C++ to help the implementation of features that were hard to > implement with C like some of the Fortran bits with dynamic arrays? Also > improve the poor experience with C++ debugging? All the above. Want to lend a hand? :-) See also: https://sourceware.org/ml/gdb-patches/2016-09/msg00162.html for another example. > Another point i worry about is that we will switch the focus, at least > for a few months, to C++-ifying things "just because" instead of taking > the opportunity of such a big change to review bits of GDB that need to > be redesigned/dropped/go away. Maybe just converting existing things to > C++ is not the right answer, even though it is fun to do and will > provide enough hacking fun? Well, IMO, it makes sense to first C++ify the code without changing much the design, and then redesign on top, because it'll tend to be easier once C++-yied. Also in order to do "atomic" changes; one concern per change. Another point is that I've heard time and time again (and have experienced it too) that redesigns don't happen exactly because the code is hard to massage! E.g., raise your hand if you've ever thought that it'd be nice to just use inheritance for something but didn't because doing it manually requires so much manual labor in C, and so you ended with some quicker hack adding to the mess instead. Ever looked at gdb/breakpoint.c, for example? (Rhetoric, I know you have ;-) ) Back to cleanups, here's an example (from patch #3) of how the code ends up so much more readable when using modern practices: @@ -95,14 +95,9 @@ evaluate_subexp (struct type *expect_type, struct expression *exp, CORE_ADDR parse_and_eval_address (const char *exp) { - struct expression *expr = parse_expression (exp); - CORE_ADDR addr; - struct cleanup *old_chain = - make_cleanup (free_current_contents, &expr); - - addr = value_as_address (evaluate_expression (expr)); - do_cleanups (old_chain); - return addr; + expression_up expr = parse_expression (exp); + + return value_as_address (evaluate_expression (expr.get ())); } I've mentioned this before, but I'm a big believer in keeping the code base inviting to work on. If there's people willing to work on cleaning up old ugly code, why not? If something breaks and we don't notice it, I'll blame it on lack of testsuite coverage. :-) > I have another point about whether this will stimulate more contributors > to send patches to GDB or not, but that's enough rambling for now. :-) Seems to be working so far, IMO. :-) Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 72+ messages in thread
* [PATCH 3/3] 'struct parse_expression *' -> gdb::unique_ptr<expression> 2016-10-10 16:46 [PATCH 0/3] More cleanup elimination / gdb::unique_ptr Pedro Alves 2016-10-10 16:46 ` [PATCH 1/3] Introduce gdb::unique_ptr Pedro Alves @ 2016-10-10 16:46 ` Pedro Alves 2016-10-10 16:58 ` [PATCH 0/3] More cleanup elimination / gdb::unique_ptr Pedro Alves 2 siblings, 0 replies; 72+ messages in thread From: Pedro Alves @ 2016-10-10 16:46 UTC (permalink / raw) To: gdb-patches This patch makes parse_expression and friends return a unique_ptr instead of raw pointer [1]: typedef gdb::unique_malloc_ptr<expression> expression_up; and then adjusts the codebase throughout to stop using cleanups to manage lifetime of expression pointers. Whenever I found a structure storing an expression pointer, I made it store a unique_ptr instead, which then requires using new/delete of the holding structure, instead of XNEW/xfree. [1] - I'd like to set the rule that types named with an "_up" suffix are unique_ptr typedefs. Note I used gdb::unique_malloc_ptr instead of gdb::unique_ptr as the subject suggests, simply because we still use xmalloc instead of new to allocate expression objects. Once that's changed, all we need to do is change the expression_up typedef and the smart pointer will then call delete instead of xfree. gdb/ChangeLog: yyyy-mm-dd Pedro Alves <palves@redhat.com> * ada-lang.c (ada_read_renaming_var_value): Use expression_up. (struct ada_catchpoint_location) <excep_cond_expr>: Now an expression_up. (ada_catchpoint_location_dtor): Reset excep_cond_expr instead of using xfree. (create_excep_cond_exprs): Use expression_up and gdb::move. (allocate_location_exception): Use new instead of XNEW. (should_stop_exception): Likewise. Adjust to use expression_up. (create_ada_exception_catchpoint): Use new instead of XNEW. * ax-gdb.c (agent_eval_command_one): Use expression_up instead of cleanups. (maint_agent_printf_command): Use expression_up. * break-catch-sig.c (create_signal_catchpoint): Use new instead of XNEW. * break-catch-syscall.c (create_syscall_event_catchpoint): Likewise. * break-catch-throw.c (handle_gnu_v3_exceptions): Use new instead of XCNEW. Use gdb::unique_ptr instead of cleanups. * breakpoint.c (set_breakpoint_condition): Adjust to expression_up change. (struct commands_info) <arg>: Constify. (commands_command_1): Constify 'arg' parameter. Use std::string and string_printf. (commands_from_control_command): Constify 'arg' parameter. Adjust to use expression_up. (parse_cmd_to_aexpr): Adjust to use expression_up. (bpstat_check_breakpoint_conditions): Likewise. (init_bp_location): Adjust. (free_bp_location): Use delete instead of xfree. (set_raw_breakpoint_without_location, set_raw_breakpoint) (add_solib_catchpoint, create_fork_vfork_event_catchpoint) (new_single_step_breakpoint, create_breakpoint_sal): Use new instead of XNEW. (find_condition_and_thread): Adjust to use expression_up. (create_breakpoint): Use new instead of XNEW. (dtor_watchpoint): Don't xfree expression pointers, they're unique_ptr's now. (insert_watchpoint, remove_watchpoint): Adjust. (watch_command_1): Use expression_up. Use new instead of XCNEW. (catch_exec_command_1): Use new instead of XNEW. (bp_location_dtor): Don't xfree expression pointers, they're unique_ptr's now. (base_breakpoint_allocate_location) (strace_marker_create_breakpoints_sal): Use new instead of XNEW. (delete_breakpoint): Use delete instead of xfree. (map_breakpoint_numbers): Constify 'args' parameter. * breakpoint.h (struct bp_location) <cond>: Now an unique_ptr<expression> instead of a raw pointer. (struct watchpoint) <exp, cond_exp>: Likewise. (commands_from_control_command): Constify 'arg' parameter. * cli/cli-script.c (do_execute_command): New function. (execute_control_command): Use expression_up instead of cleanups. Use std::string. (locate_arg): Constify return type. (insert_args): Constify 'line' parameter. Use std::string. * dtrace-probe.c (dtrace_process_dof_probe): Use expression_up. * eval.c (parse_and_eval_address, parse_and_eval_long) (parse_and_eval, parse_to_comma_and_eval, parse_and_eval_type): Use expression_up instead of cleanups. * expression.h (expression_up): New typedef. (parse_expression, parse_expression_with_language, parse_exp_1): Change return type to expression_up. * mi/mi-main.c (mi_cmd_data_evaluate_expression) (print_variable_or_computed): Use expression_up. * objc-lang.c (print_object_command): Use expression_up instead of cleanups. * parse.c (parse_exp_1, parse_exp_in_context) (parse_exp_in_context_1, parse_expression) (parse_expression_with_language): Return an expression_up instead of a raw pointer. (parse_expression_for_completion): Use expression_up. * printcmd.c (struct display) <exp>: Now an expression_up instead of a raw pointer. (print_command_1, output_command_const, set_command, x_command): Use expression_up instead of cleanups. (display_command): Likewise. Use new instead of XNEW. (free_display): Use delete instead of xfree. (do_one_display): Adjust to use expression_up. * remote.c (remote_download_tracepoint): Likewise. * stack.c (return_command): Likewise. * tracepoint.c (validate_actionline, encode_actions_1): Use expression_up instead of cleanups. * typeprint.c (whatis_exp, maintenance_print_type): Likewise. * value.c (init_if_undefined_command): Likewise. * varobj.c (struct varobj_root) <exp>: Now an expression_up instead of a raw pointer. (varobj_create): Adjust. (varobj_set_value): Use an expression_up instead of cleanups. (new_root_variable): Use new instead of XNEW. (free_variable): Use delete instead of xfree. (value_of_root_1): Use std::swap. --- gdb/ada-lang.c | 37 ++++--------- gdb/ax-gdb.c | 15 ++--- gdb/break-catch-sig.c | 2 +- gdb/break-catch-syscall.c | 2 +- gdb/break-catch-throw.c | 7 +-- gdb/breakpoint.c | 137 ++++++++++++++++++---------------------------- gdb/breakpoint.h | 8 +-- gdb/cli/cli-script.c | 130 ++++++++++++++----------------------------- gdb/dtrace-probe.c | 6 +- gdb/eval.c | 43 ++++----------- gdb/expression.h | 12 ++-- gdb/mi/mi-main.c | 16 ++---- gdb/objc-lang.c | 7 +-- gdb/parse.c | 50 +++++++---------- gdb/printcmd.c | 56 ++++++------------- gdb/remote.c | 2 +- gdb/stack.c | 6 +- gdb/tracepoint.c | 47 +++++++--------- gdb/typeprint.c | 14 ++--- gdb/value.c | 8 +-- gdb/varobj.c | 26 +++------ 21 files changed, 225 insertions(+), 406 deletions(-) diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index f7a3875..42baab1 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -4454,17 +4454,10 @@ ada_read_renaming_var_value (struct symbol *renaming_sym, const struct block *block) { const char *sym_name; - struct expression *expr; - struct value *value; - struct cleanup *old_chain = NULL; sym_name = SYMBOL_LINKAGE_NAME (renaming_sym); - expr = parse_exp_1 (&sym_name, 0, block, 0); - old_chain = make_cleanup (free_current_contents, &expr); - value = evaluate_expression (expr); - - do_cleanups (old_chain); - return value; + expression_up expr = parse_exp_1 (&sym_name, 0, block, 0); + return evaluate_expression (expr.get ()); } \f @@ -12284,7 +12277,7 @@ struct ada_catchpoint_location /* The condition that checks whether the exception that was raised is the specific exception the user specified on catchpoint creation. */ - struct expression *excep_cond_expr; + expression_up excep_cond_expr; }; /* Implement the DTOR method in the bp_location_ops structure for all @@ -12295,7 +12288,7 @@ ada_catchpoint_location_dtor (struct bp_location *bl) { struct ada_catchpoint_location *al = (struct ada_catchpoint_location *) bl; - xfree (al->excep_cond_expr); + al->excep_cond_expr.reset (); } /* The vtable to be used in Ada catchpoint locations. */ @@ -12347,7 +12340,7 @@ create_excep_cond_exprs (struct ada_catchpoint *c) { struct ada_catchpoint_location *ada_loc = (struct ada_catchpoint_location *) bl; - struct expression *exp = NULL; + expression_up exp; if (!bl->shlib_disabled) { @@ -12356,26 +12349,20 @@ create_excep_cond_exprs (struct ada_catchpoint *c) s = cond_string; TRY { - exp = parse_exp_1 (&s, bl->address, - block_for_pc (bl->address), 0); + exp = gdb::move (parse_exp_1 (&s, bl->address, + block_for_pc (bl->address), + 0)); } CATCH (e, RETURN_MASK_ERROR) { warning (_("failed to reevaluate internal exception condition " "for catchpoint %d: %s"), c->base.number, e.message); - /* There is a bug in GCC on sparc-solaris when building with - optimization which causes EXP to change unexpectedly - (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56982). - The problem should be fixed starting with GCC 4.9. - In the meantime, work around it by forcing EXP back - to NULL. */ - exp = NULL; } END_CATCH } - ada_loc->excep_cond_expr = exp; + ada_loc->excep_cond_expr = gdb::move (exp); } do_cleanups (old_chain); @@ -12403,7 +12390,7 @@ allocate_location_exception (enum ada_exception_catchpoint_kind ex, { struct ada_catchpoint_location *loc; - loc = XNEW (struct ada_catchpoint_location); + loc = new ada_catchpoint_location (); init_bp_location (&loc->base, &ada_catchpoint_location_ops, self); loc->excep_cond_expr = NULL; return &loc->base; @@ -12455,7 +12442,7 @@ should_stop_exception (const struct bp_location *bl) struct value *mark; mark = value_mark (); - stop = value_true (evaluate_expression (ada_loc->excep_cond_expr)); + stop = value_true (evaluate_expression (ada_loc->excep_cond_expr.get ())); value_free_to_mark (mark); } CATCH (ex, RETURN_MASK_ALL) @@ -13119,7 +13106,7 @@ create_ada_exception_catchpoint (struct gdbarch *gdbarch, struct symtab_and_line sal = ada_exception_sal (ex_kind, excep_string, &addr_string, &ops); - c = XNEW (struct ada_catchpoint); + c = new ada_catchpoint (); init_ada_exception_breakpoint (&c->base, gdbarch, sal, addr_string, ops, tempflag, disabled, from_tty); c->excep_string = excep_string; diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c index 7c6cb64..ccd16f2 100644 --- a/gdb/ax-gdb.c +++ b/gdb/ax-gdb.c @@ -2581,7 +2581,6 @@ static void agent_eval_command_one (const char *exp, int eval, CORE_ADDR pc) { struct cleanup *old_chain = 0; - struct expression *expr; struct agent_expr *agent; const char *arg; int trace_string = 0; @@ -2601,16 +2600,15 @@ agent_eval_command_one (const char *exp, int eval, CORE_ADDR pc) } else { - expr = parse_exp_1 (&arg, pc, block_for_pc (pc), 0); - old_chain = make_cleanup (free_current_contents, &expr); + expression_up expr = parse_exp_1 (&arg, pc, block_for_pc (pc), 0); if (eval) { gdb_assert (trace_string == 0); - agent = gen_eval_for_expr (pc, expr); + agent = gen_eval_for_expr (pc, expr.get ()); } else - agent = gen_trace_for_expr (pc, expr, trace_string); - make_cleanup_free_agent_expr (agent); + agent = gen_trace_for_expr (pc, expr.get (), trace_string); + old_chain = make_cleanup_free_agent_expr (agent); } ax_reqs (agent); @@ -2696,7 +2694,6 @@ static void maint_agent_printf_command (char *exp, int from_tty) { struct cleanup *old_chain = 0; - struct expression *expr; struct expression *argvec[100]; struct agent_expr *agent; struct frame_info *fi = get_current_frame (); /* need current scope */ @@ -2748,8 +2745,8 @@ maint_agent_printf_command (char *exp, int from_tty) const char *cmd1; cmd1 = cmdrest; - expr = parse_exp_1 (&cmd1, 0, (struct block *) 0, 1); - argvec[nargs] = expr; + expression_up expr = parse_exp_1 (&cmd1, 0, (struct block *) 0, 1); + argvec[nargs] = expr.release (); ++nargs; cmdrest = cmd1; if (*cmdrest == ',') diff --git a/gdb/break-catch-sig.c b/gdb/break-catch-sig.c index 296f900..e869a83 100644 --- a/gdb/break-catch-sig.c +++ b/gdb/break-catch-sig.c @@ -371,7 +371,7 @@ create_signal_catchpoint (int tempflag, VEC (gdb_signal_type) *filter, struct signal_catchpoint *c; struct gdbarch *gdbarch = get_current_arch (); - c = XNEW (struct signal_catchpoint); + c = new signal_catchpoint (); init_catchpoint (&c->base, gdbarch, tempflag, NULL, &signal_catchpoint_ops); c->signals_to_be_caught = filter; c->catch_all = catch_all; diff --git a/gdb/break-catch-syscall.c b/gdb/break-catch-syscall.c index 63b8cd2..a4df2ce 100644 --- a/gdb/break-catch-syscall.c +++ b/gdb/break-catch-syscall.c @@ -433,7 +433,7 @@ create_syscall_event_catchpoint (int tempflag, VEC(int) *filter, struct syscall_catchpoint *c; struct gdbarch *gdbarch = get_current_arch (); - c = XNEW (struct syscall_catchpoint); + c = new syscall_catchpoint (); init_catchpoint (&c->base, gdbarch, tempflag, NULL, ops); c->syscalls_to_be_caught = filter; diff --git a/gdb/break-catch-throw.c b/gdb/break-catch-throw.c index 4d686a7..6136a57 100644 --- a/gdb/break-catch-throw.c +++ b/gdb/break-catch-throw.c @@ -388,8 +388,6 @@ static void handle_gnu_v3_exceptions (int tempflag, char *except_rx, char *cond_string, enum exception_event_kind ex_event, int from_tty) { - struct exception_catchpoint *cp; - struct cleanup *cleanup = make_cleanup (null_cleanup, NULL); regex_t *pattern = NULL; if (except_rx != NULL) @@ -401,8 +399,7 @@ handle_gnu_v3_exceptions (int tempflag, char *except_rx, char *cond_string, _("invalid type-matching regexp")); } - cp = XCNEW (struct exception_catchpoint); - make_cleanup (xfree, cp); + gdb::unique_ptr<exception_catchpoint> cp (new exception_catchpoint ()); init_catchpoint (&cp->base, get_current_arch (), tempflag, cond_string, &gnu_v3_exception_catchpoint_ops); @@ -416,7 +413,7 @@ handle_gnu_v3_exceptions (int tempflag, char *except_rx, char *cond_string, re_set_exception_catchpoint (&cp->base); install_breakpoint (0, &cp->base, 1); - discard_cleanups (cleanup); + cp.release (); } /* Look for an "if" token in *STRING. The "if" token must be preceded diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c index 0e467ec..4cbaa94 100644 --- a/gdb/breakpoint.c +++ b/gdb/breakpoint.c @@ -102,8 +102,9 @@ static void disable_command (char *, int); static void enable_command (char *, int); -static void map_breakpoint_numbers (char *, void (*) (struct breakpoint *, - void *), +static void map_breakpoint_numbers (const char *, + void (*) (struct breakpoint *, + void *), void *); static void ignore_command (char *, int); @@ -980,8 +981,7 @@ set_breakpoint_condition (struct breakpoint *b, const char *exp, { struct watchpoint *w = (struct watchpoint *) b; - xfree (w->cond_exp); - w->cond_exp = NULL; + w->cond_exp.reset (); } else { @@ -989,8 +989,7 @@ set_breakpoint_condition (struct breakpoint *b, const char *exp, for (loc = b->loc; loc; loc = loc->next) { - xfree (loc->cond); - loc->cond = NULL; + loc->cond.reset (); /* No need to free the condition agent expression bytecode (if we have one). We will handle this @@ -1338,7 +1337,7 @@ struct commands_info int from_tty; /* The breakpoint range spec. */ - char *arg; + const char *arg; /* Non-NULL if the body of the commands are being read from this already-parsed command. */ @@ -1399,7 +1398,7 @@ do_map_commands_command (struct breakpoint *b, void *data) } static void -commands_command_1 (char *arg, int from_tty, +commands_command_1 (const char *arg, int from_tty, struct command_line *control) { struct cleanup *cleanups; @@ -1412,32 +1411,22 @@ commands_command_1 (char *arg, int from_tty, extra reference to the commands that we must clean up. */ cleanups = make_cleanup_decref_counted_command_line (&info.cmd); + std::string new_arg; + if (arg == NULL || !*arg) { if (breakpoint_count - prev_breakpoint_count > 1) - arg = xstrprintf ("%d-%d", prev_breakpoint_count + 1, - breakpoint_count); + new_arg = string_printf ("%d-%d", prev_breakpoint_count + 1, + breakpoint_count); else if (breakpoint_count > 0) - arg = xstrprintf ("%d", breakpoint_count); - else - { - /* So that we don't try to free the incoming non-NULL - argument in the cleanup below. Mapping breakpoint - numbers will fail in this case. */ - arg = NULL; - } + new_arg = string_printf ("%d", breakpoint_count); } else - /* The command loop has some static state, so we need to preserve - our argument. */ - arg = xstrdup (arg); - - if (arg != NULL) - make_cleanup (xfree, arg); + new_arg = arg; - info.arg = arg; + info.arg = new_arg.c_str (); - map_breakpoint_numbers (arg, do_map_commands_command, &info); + map_breakpoint_numbers (info.arg, do_map_commands_command, &info); if (info.cmd == NULL) error (_("No breakpoints specified.")); @@ -1457,7 +1446,7 @@ commands_command (char *arg, int from_tty) This is used by cli-script.c to DTRT with breakpoint commands that are part of if and while bodies. */ enum command_control_type -commands_from_control_command (char *arg, struct command_line *cmd) +commands_from_control_command (const char *arg, struct command_line *cmd) { commands_command_1 (arg, 0, cmd); return simple_control; @@ -1906,11 +1895,7 @@ update_watchpoint (struct watchpoint *b, int reparse) { const char *s; - if (b->exp) - { - xfree (b->exp); - b->exp = NULL; - } + b->exp.reset (); s = b->exp_string_reparse ? b->exp_string_reparse : b->exp_string; b->exp = parse_exp_1 (&s, 0, b->exp_valid_block, 0); /* If the meaning of expression itself changed, the old value is @@ -1926,11 +1911,7 @@ update_watchpoint (struct watchpoint *b, int reparse) locations (re)created below. */ if (b->base.cond_string != NULL) { - if (b->cond_exp != NULL) - { - xfree (b->cond_exp); - b->cond_exp = NULL; - } + b->cond_exp.reset (); s = b->base.cond_string; b->cond_exp = parse_exp_1 (&s, 0, b->cond_exp_valid_block, 0); @@ -1962,7 +1943,7 @@ update_watchpoint (struct watchpoint *b, int reparse) struct value *val_chain, *v, *result, *next; struct program_space *frame_pspace; - fetch_subexp_value (b->exp, &pc, &v, &result, &val_chain, 0); + fetch_subexp_value (b->exp.get (), &pc, &v, &result, &val_chain, 0); /* Avoid setting b->val if it's already set. The meaning of b->val is 'the last value' user saw, and we should update @@ -2346,7 +2327,7 @@ build_target_condition_list (struct bp_location *bl) case we already freed the condition bytecodes (see force_breakpoint_reinsertion). We just need to parse the condition to bytecodes again. */ - aexpr = parse_cond_to_aexpr (bl->address, loc->cond); + aexpr = parse_cond_to_aexpr (bl->address, loc->cond.get ()); loc->cond_bytecode = aexpr; } @@ -2411,7 +2392,7 @@ static struct agent_expr * parse_cmd_to_aexpr (CORE_ADDR scope, char *cmd) { struct cleanup *old_cleanups = 0; - struct expression *expr, **argvec; + struct expression **argvec; struct agent_expr *aexpr = NULL; const char *cmdrest; const char *format_start, *format_end; @@ -2462,8 +2443,8 @@ parse_cmd_to_aexpr (CORE_ADDR scope, char *cmd) const char *cmd1; cmd1 = cmdrest; - expr = parse_exp_1 (&cmd1, scope, block_for_pc (scope), 1); - argvec[nargs++] = expr; + expression_up expr = parse_exp_1 (&cmd1, scope, block_for_pc (scope), 1); + argvec[nargs++] = expr.release (); cmdrest = cmd1; if (*cmdrest == ',') ++cmdrest; @@ -5207,7 +5188,7 @@ watchpoint_check (void *p) return WP_VALUE_CHANGED; mark = value_mark (); - fetch_subexp_value (b->exp, &pc, &new_val, NULL, NULL, 0); + fetch_subexp_value (b->exp.get (), &pc, &new_val, NULL, NULL, 0); if (b->val_bitsize != 0) new_val = extract_bitfield_from_watchpoint_value (b, new_val); @@ -5512,10 +5493,10 @@ bpstat_check_breakpoint_conditions (bpstat bs, ptid_t ptid) { struct watchpoint *w = (struct watchpoint *) b; - cond = w->cond_exp; + cond = w->cond_exp.get (); } else - cond = bl->cond; + cond = bl->cond.get (); if (cond && b->disposition != disp_del_at_next_stop) { @@ -7138,12 +7119,12 @@ watchpoint_locations_match (struct bp_location *loc1, && target_can_accel_watchpoint_condition (loc1->address, loc1->length, loc1->watchpoint_type, - w1->cond_exp)) + w1->cond_exp.get ())) || (w2->cond_exp && target_can_accel_watchpoint_condition (loc2->address, loc2->length, loc2->watchpoint_type, - w2->cond_exp))) + w2->cond_exp.get ()))) return 0; /* Note that this checks the owner's type, not the location's. In @@ -7351,7 +7332,6 @@ init_bp_location (struct bp_location *loc, const struct bp_location_ops *ops, loc->ops = ops; loc->owner = owner; - loc->cond = NULL; loc->cond_bytecode = NULL; loc->shlib_disabled = 0; loc->enabled = 1; @@ -7420,7 +7400,7 @@ static void free_bp_location (struct bp_location *loc) { loc->ops->dtor (loc); - xfree (loc); + delete loc; } /* Increment reference count. */ @@ -7503,7 +7483,7 @@ set_raw_breakpoint_without_location (struct gdbarch *gdbarch, enum bptype bptype, const struct breakpoint_ops *ops) { - struct breakpoint *b = XNEW (struct breakpoint); + struct breakpoint *b = new breakpoint (); init_raw_breakpoint_without_location (b, gdbarch, bptype, ops); add_to_breakpoint_chain (b); @@ -7619,7 +7599,7 @@ set_raw_breakpoint (struct gdbarch *gdbarch, struct symtab_and_line sal, enum bptype bptype, const struct breakpoint_ops *ops) { - struct breakpoint *b = XNEW (struct breakpoint); + struct breakpoint *b = new breakpoint (); init_raw_breakpoint (b, gdbarch, sal, bptype, ops); add_to_breakpoint_chain (b); @@ -8554,7 +8534,7 @@ add_solib_catchpoint (char *arg, int is_load, int is_temp, int enabled) arg = ""; arg = skip_spaces (arg); - c = XCNEW (struct solib_catchpoint); + c = new solib_catchpoint (); cleanup = make_cleanup (xfree, c); if (*arg != '\0') @@ -8653,7 +8633,7 @@ create_fork_vfork_event_catchpoint (struct gdbarch *gdbarch, int tempflag, char *cond_string, const struct breakpoint_ops *ops) { - struct fork_catchpoint *c = XNEW (struct fork_catchpoint); + struct fork_catchpoint *c = new fork_catchpoint (); init_catchpoint (&c->base, gdbarch, tempflag, cond_string, ops); @@ -8914,7 +8894,7 @@ enable_breakpoints_after_startup (void) static struct breakpoint * new_single_step_breakpoint (int thread, struct gdbarch *gdbarch) { - struct breakpoint *b = XNEW (struct breakpoint); + struct breakpoint *b = new breakpoint (); init_raw_breakpoint_without_location (b, gdbarch, bp_single_step, &momentary_breakpoint_ops); @@ -9422,11 +9402,11 @@ create_breakpoint_sal (struct gdbarch *gdbarch, { struct tracepoint *t; - t = XCNEW (struct tracepoint); + t = new tracepoint (); b = &t->base; } else - b = XNEW (struct breakpoint); + b = new breakpoint (); old_chain = make_cleanup (xfree, b); @@ -9677,11 +9657,8 @@ find_condition_and_thread (const char *tok, CORE_ADDR pc, if (toklen >= 1 && strncmp (tok, "if", toklen) == 0) { - struct expression *expr; - tok = cond_start = end_tok + 1; - expr = parse_exp_1 (&tok, pc, block_for_pc (pc), 0); - xfree (expr); + parse_exp_1 (&tok, pc, block_for_pc (pc), 0); cond_end = tok; *cond_string = savestring (cond_start, cond_end - cond_start); } @@ -9926,11 +9903,11 @@ create_breakpoint (struct gdbarch *gdbarch, { struct tracepoint *t; - t = XCNEW (struct tracepoint); + t = new tracepoint (); b = &t->base; } else - b = XNEW (struct breakpoint); + b = new breakpoint (); init_raw_breakpoint_without_location (b, gdbarch, type_wanted, ops); b->location = copy_event_location (location); @@ -10651,8 +10628,6 @@ dtor_watchpoint (struct breakpoint *self) { struct watchpoint *w = (struct watchpoint *) self; - xfree (w->cond_exp); - xfree (w->exp); xfree (w->exp_string); xfree (w->exp_string_reparse); value_free (w->val); @@ -10704,7 +10679,7 @@ insert_watchpoint (struct bp_location *bl) int length = w->exact ? 1 : bl->length; return target_insert_watchpoint (bl->address, length, bl->watchpoint_type, - w->cond_exp); + w->cond_exp.get ()); } /* Implement the "remove" breakpoint_ops method for hardware watchpoints. */ @@ -10716,7 +10691,7 @@ remove_watchpoint (struct bp_location *bl, enum remove_bp_reason reason) int length = w->exact ? 1 : bl->length; return target_remove_watchpoint (bl->address, length, bl->watchpoint_type, - w->cond_exp); + w->cond_exp.get ()); } static int @@ -11147,7 +11122,6 @@ watch_command_1 (const char *arg, int accessflag, int from_tty, int just_location, int internal) { struct breakpoint *b, *scope_breakpoint = NULL; - struct expression *exp; const struct block *exp_valid_block = NULL, *cond_exp_valid_block = NULL; struct value *val, *mark, *result; int saved_bitpos = 0, saved_bitsize = 0; @@ -11259,7 +11233,7 @@ watch_command_1 (const char *arg, int accessflag, int from_tty, expression = savestring (arg, exp_end - arg); back_to = make_cleanup (xfree, expression); exp_start = arg = expression; - exp = parse_exp_1 (&arg, 0, 0, 0); + expression_up exp = parse_exp_1 (&arg, 0, 0, 0); exp_end = arg; /* Remove trailing whitespace from the expression before saving it. This makes the eventual display of the expression string a bit @@ -11268,7 +11242,7 @@ watch_command_1 (const char *arg, int accessflag, int from_tty, --exp_end; /* Checking if the expression is not constant. */ - if (watchpoint_exp_is_const (exp)) + if (watchpoint_exp_is_const (exp.get ())) { int len; @@ -11280,7 +11254,7 @@ watch_command_1 (const char *arg, int accessflag, int from_tty, exp_valid_block = innermost_block; mark = value_mark (); - fetch_subexp_value (exp, &pc, &val, &result, NULL, just_location); + fetch_subexp_value (exp.get (), &pc, &val, &result, NULL, just_location); if (val != NULL && just_location) { @@ -11316,17 +11290,14 @@ watch_command_1 (const char *arg, int accessflag, int from_tty, toklen = end_tok - tok; if (toklen >= 1 && strncmp (tok, "if", toklen) == 0) { - struct expression *cond; - innermost_block = NULL; tok = cond_start = end_tok + 1; - cond = parse_exp_1 (&tok, 0, 0, 0); + parse_exp_1 (&tok, 0, 0, 0); /* The watchpoint expression may not be local, but the condition may still be. E.g.: `watch global if local > 0'. */ cond_exp_valid_block = innermost_block; - xfree (cond); cond_end = tok; } if (*tok) @@ -11380,7 +11351,7 @@ watch_command_1 (const char *arg, int accessflag, int from_tty, else bp_type = bp_hardware_watchpoint; - w = XCNEW (struct watchpoint); + w = new watchpoint (); b = &w->base; if (use_mask) init_raw_breakpoint_without_location (b, NULL, bp_type, @@ -11391,7 +11362,7 @@ watch_command_1 (const char *arg, int accessflag, int from_tty, b->thread = thread; b->disposition = disp_donttouch; b->pspace = current_program_space; - w->exp = exp; + w->exp = gdb::move (exp); w->exp_valid_block = exp_valid_block; w->cond_exp_valid_block = cond_exp_valid_block; if (just_location) @@ -11938,7 +11909,7 @@ catch_exec_command_1 (char *arg, int from_tty, if ((*arg != '\0') && !isspace (*arg)) error (_("Junk at end of arguments.")); - c = XNEW (struct exec_catchpoint); + c = new exec_catchpoint (); init_catchpoint (&c->base, gdbarch, tempflag, cond_string, &catch_exec_breakpoint_ops); c->exec_pathname = NULL; @@ -12906,7 +12877,6 @@ say_where (struct breakpoint *b) static void bp_location_dtor (struct bp_location *self) { - xfree (self->cond); if (self->cond_bytecode) free_agent_expr (self->cond_bytecode); xfree (self->function_name); @@ -12939,7 +12909,7 @@ base_breakpoint_allocate_location (struct breakpoint *self) { struct bp_location *loc; - loc = XNEW (struct bp_location); + loc = new struct bp_location (); init_bp_location (loc, &bp_location_ops, self); return loc; } @@ -13791,7 +13761,7 @@ strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch, location = copy_event_location (canonical->location); old_chain = make_cleanup_delete_event_location (location); - tp = XCNEW (struct tracepoint); + tp = new tracepoint (); init_breakpoint_sal (&tp->base, gdbarch, expanded, location, NULL, cond_string, extra_string, @@ -13933,7 +13903,7 @@ delete_breakpoint (struct breakpoint *bpt) /* On the chance that someone will soon try again to delete this same bp, we mark it as deleted before freeing its storage. */ bpt->type = bp_none; - xfree (bpt); + delete bpt; } static void @@ -14768,8 +14738,9 @@ ignore_command (char *args, int from_tty) whose numbers are given in ARGS. */ static void -map_breakpoint_numbers (char *args, void (*function) (struct breakpoint *, - void *), +map_breakpoint_numbers (const char *args, + void (*function) (struct breakpoint *, + void *), void *data) { int num; diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h index 4bdf0d5..59aedf6 100644 --- a/gdb/breakpoint.h +++ b/gdb/breakpoint.h @@ -343,7 +343,7 @@ struct bp_location different for different locations. Only valid for real breakpoints; a watchpoint's conditional expression is stored in the owner breakpoint object. */ - struct expression *cond; + expression_up cond; /* Conditional expression in agent expression bytecode form. This is used for stub-side breakpoint @@ -798,12 +798,12 @@ struct watchpoint char *exp_string_reparse; /* The expression we are watching, or NULL if not a watchpoint. */ - struct expression *exp; + expression_up exp; /* The largest block within which it is valid, or NULL if it is valid anywhere (e.g. consists just of global symbols). */ const struct block *exp_valid_block; /* The conditional expression if any. */ - struct expression *cond_exp; + expression_up cond_exp; /* The largest block within which it is valid, or NULL if it is valid anywhere (e.g. consists just of global symbols). */ const struct block *cond_exp_valid_block; @@ -1456,7 +1456,7 @@ extern void enable_breakpoints_after_startup (void); after they've already read the commands into a struct command_line. */ extern enum command_control_type commands_from_control_command - (char *arg, struct command_line *cmd); + (const char *arg, struct command_line *cmd); extern void clear_breakpoint_hit_counts (void); diff --git a/gdb/cli/cli-script.c b/gdb/cli/cli-script.c index 579d0a4..0118795 100644 --- a/gdb/cli/cli-script.c +++ b/gdb/cli/cli-script.c @@ -41,7 +41,7 @@ recurse_read_control_structure (char * (*read_next_line_func) (void), void (*validator)(char *, void *), void *closure); -static char *insert_args (char *line); +static std::string insert_args (const char *line); static struct cleanup * setup_user_args (char *p); @@ -438,10 +438,23 @@ print_command_trace (const char *cmd) printf_filtered ("%s\n", cmd); } +/* Execute NEW_LINE. */ + +static void +do_execute_command (const std::string &new_line) +{ + /* execute_command writes to the passed in buffer. Make a deep + copy. */ + gdb::unique_ptr<char[]> buf (new char[new_line.length () + 1]); + + memcpy (buf.get (), new_line.c_str (), new_line.length () + 1); + + execute_command (buf.get (), 0); +} + enum command_control_type execute_control_command (struct command_line *cmd) { - struct expression *expr; struct command_line *current; struct cleanup *old_chain = make_cleanup (null_cleanup, 0); struct value *val; @@ -458,11 +471,7 @@ execute_control_command (struct command_line *cmd) { case simple_control: /* A simple command, execute it and return. */ - new_line = insert_args (cmd->line); - if (!new_line) - break; - make_cleanup (free_current_contents, &new_line); - execute_command (new_line, 0); + do_execute_command (insert_args (cmd->line)); ret = cmd->control_type; break; @@ -491,12 +500,7 @@ execute_control_command (struct command_line *cmd) print_command_trace (buffer); /* Parse the loop control expression for the while statement. */ - new_line = insert_args (cmd->line); - if (!new_line) - break; - make_cleanup (free_current_contents, &new_line); - expr = parse_expression (new_line); - make_cleanup (free_current_contents, &expr); + expression_up expr = parse_expression (insert_args (cmd->line).c_str ()); ret = simple_control; loop = 1; @@ -510,7 +514,7 @@ execute_control_command (struct command_line *cmd) /* Evaluate the expression. */ val_mark = value_mark (); - val = evaluate_expression (expr); + val = evaluate_expression (expr.get ()); cond_result = value_true (val); value_free_to_mark (val_mark); @@ -559,20 +563,16 @@ execute_control_command (struct command_line *cmd) xsnprintf (buffer, len, "if %s", cmd->line); print_command_trace (buffer); - new_line = insert_args (cmd->line); - if (!new_line) - break; - make_cleanup (free_current_contents, &new_line); + std::string new_line = insert_args (cmd->line); /* Parse the conditional for the if statement. */ - expr = parse_expression (new_line); - make_cleanup (free_current_contents, &expr); + expression_up expr = parse_expression (new_line.c_str ()); current = NULL; ret = simple_control; /* Evaluate the conditional. */ val_mark = value_mark (); - val = evaluate_expression (expr); + val = evaluate_expression (expr.get ()); /* Choose which arm to take commands from based on the value of the conditional expression. */ @@ -604,11 +604,8 @@ execute_control_command (struct command_line *cmd) { /* Breakpoint commands list, record the commands in the breakpoint's command list and return. */ - new_line = insert_args (cmd->line); - if (!new_line) - break; - make_cleanup (free_current_contents, &new_line); - ret = commands_from_control_command (new_line, cmd); + std::string new_line = insert_args (cmd->line); + ret = commands_from_control_command (new_line.c_str (), cmd); break; } @@ -794,8 +791,8 @@ setup_user_args (char *p) /* Given character string P, return a point to the first argument ($arg), or NULL if P contains no arguments. */ -static char * -locate_arg (char *p) +static const char * +locate_arg (const char *p) { while ((p = strchr (p, '$'))) { @@ -808,95 +805,52 @@ locate_arg (char *p) } /* Insert the user defined arguments stored in user_arg into the $arg - arguments found in line, with the updated copy being placed into - nline. */ + arguments found in line. */ -static char * -insert_args (char *line) +static std::string +insert_args (const char *line) { - char *p, *save_line, *new_line; - unsigned len, i; - /* If we are not in a user-defined function, treat $argc, $arg0, et cetera as normal convenience variables. */ if (user_args == NULL) - return xstrdup (line); + return line; - /* First we need to know how much memory to allocate for the new - line. */ - save_line = line; - len = 0; - while ((p = locate_arg (line))) - { - len += p - line; - i = p[4] - '0'; - - if (p[4] == 'c') - { - /* $argc. Number will be <=10. */ - len += user_args->count == 10 ? 2 : 1; - } - else if (i >= user_args->count) - { - error (_("Missing argument %d in user function."), i); - return NULL; - } - else - { - len += user_args->a[i].len; - } - line = p + 5; - } - - /* Don't forget the tail. */ - len += strlen (line); - - /* Allocate space for the new line and fill it in. */ - new_line = (char *) xmalloc (len + 1); - if (new_line == NULL) - return NULL; - - /* Restore pointer to beginning of old line. */ - line = save_line; - - /* Save pointer to beginning of new line. */ - save_line = new_line; + std::string new_line; + const char *p; while ((p = locate_arg (line))) { int i, len; - memcpy (new_line, line, p - line); - new_line += p - line; + new_line.append (line, p - line); if (p[4] == 'c') { gdb_assert (user_args->count >= 0 && user_args->count <= 10); if (user_args->count == 10) { - *(new_line++) = '1'; - *(new_line++) = '0'; + new_line += '1'; + new_line += '0'; } else - *(new_line++) = user_args->count + '0'; + new_line += user_args->count + '0'; } else { i = p[4] - '0'; + if (i >= user_args->count) + error (_("Missing argument %d in user function."), i); + len = user_args->a[i].len; - if (len) - { - memcpy (new_line, user_args->a[i].arg, len); - new_line += len; - } + if (len > 0) + new_line.append (user_args->a[i].arg, len); } line = p + 5; } /* Don't forget the tail. */ - strcpy (new_line, line); + new_line.append (line); - /* Return a pointer to the beginning of the new line. */ - return save_line; + return new_line; } \f diff --git a/gdb/dtrace-probe.c b/gdb/dtrace-probe.c index 242e316..cbeeea8 100644 --- a/gdb/dtrace-probe.c +++ b/gdb/dtrace-probe.c @@ -413,7 +413,7 @@ dtrace_process_dof_probe (struct objfile *objfile, for (j = 0; j < ret->probe_argc; j++) { struct dtrace_probe_arg arg; - struct expression *expr = NULL; + expression_up expr; /* Set arg.expr to ensure all fields in expr are initialized and the compiler will not warn when arg is used. */ @@ -430,11 +430,11 @@ dtrace_process_dof_probe (struct objfile *objfile, TRY { - expr = parse_expression_with_language (arg.type_str, language_c); + expr = gdb::move (parse_expression_with_language (arg.type_str, + language_c)); } CATCH (ex, RETURN_MASK_ERROR) { - expr = NULL; } END_CATCH diff --git a/gdb/eval.c b/gdb/eval.c index 00a107c..f30b8e1 100644 --- a/gdb/eval.c +++ b/gdb/eval.c @@ -95,14 +95,9 @@ evaluate_subexp (struct type *expect_type, struct expression *exp, CORE_ADDR parse_and_eval_address (const char *exp) { - struct expression *expr = parse_expression (exp); - CORE_ADDR addr; - struct cleanup *old_chain = - make_cleanup (free_current_contents, &expr); - - addr = value_as_address (evaluate_expression (expr)); - do_cleanups (old_chain); - return addr; + expression_up expr = parse_expression (exp); + + return value_as_address (evaluate_expression (expr.get ())); } /* Like parse_and_eval_address, but treats the value of the expression @@ -110,27 +105,17 @@ parse_and_eval_address (const char *exp) LONGEST parse_and_eval_long (const char *exp) { - struct expression *expr = parse_expression (exp); - LONGEST retval; - struct cleanup *old_chain = - make_cleanup (free_current_contents, &expr); - - retval = value_as_long (evaluate_expression (expr)); - do_cleanups (old_chain); - return (retval); + expression_up expr = parse_expression (exp); + + return value_as_long (evaluate_expression (expr.get ())); } struct value * parse_and_eval (const char *exp) { - struct expression *expr = parse_expression (exp); - struct value *val; - struct cleanup *old_chain = - make_cleanup (free_current_contents, &expr); + expression_up expr = parse_expression (exp); - val = evaluate_expression (expr); - do_cleanups (old_chain); - return val; + return evaluate_expression (expr.get ()); } /* Parse up to a comma (or to a closeparen) @@ -140,14 +125,9 @@ parse_and_eval (const char *exp) struct value * parse_to_comma_and_eval (const char **expp) { - struct expression *expr = parse_exp_1 (expp, 0, (struct block *) 0, 1); - struct value *val; - struct cleanup *old_chain = - make_cleanup (free_current_contents, &expr); + expression_up expr = parse_exp_1 (expp, 0, (struct block *) 0, 1); - val = evaluate_expression (expr); - do_cleanups (old_chain); - return val; + return evaluate_expression (expr.get ()); } \f /* Evaluate an expression in internal prefix form @@ -3104,14 +3084,13 @@ struct type * parse_and_eval_type (char *p, int length) { char *tmp = (char *) alloca (length + 4); - struct expression *expr; tmp[0] = '('; memcpy (tmp + 1, p, length); tmp[length + 1] = ')'; tmp[length + 2] = '0'; tmp[length + 3] = '\0'; - expr = parse_expression (tmp); + expression_up expr = parse_expression (tmp); if (expr->elts[0].opcode != UNOP_CAST) error (_("Internal error in eval_type.")); return expr->elts[1].type; diff --git a/gdb/expression.h b/gdb/expression.h index 4952d84..6f24b9a 100644 --- a/gdb/expression.h +++ b/gdb/expression.h @@ -85,6 +85,8 @@ struct expression union exp_element elts[1]; }; +typedef gdb::unique_malloc_ptr<expression> expression_up; + /* Macros for converting between number of expression elements and bytes to store that many expression elements. */ @@ -95,16 +97,16 @@ struct expression /* From parse.c */ -extern struct expression *parse_expression (const char *); +extern expression_up parse_expression (const char *); -extern struct expression *parse_expression_with_language (const char *string, - enum language lang); +extern expression_up parse_expression_with_language (const char *string, + enum language lang); extern struct type *parse_expression_for_completion (const char *, char **, enum type_code *); -extern struct expression *parse_exp_1 (const char **, CORE_ADDR pc, - const struct block *, int); +extern expression_up parse_exp_1 (const char **, CORE_ADDR pc, + const struct block *, int); /* For use by parsers; set if we want to parse an expression and attempt completion. */ diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c index 65841e0..98d53ca 100644 --- a/gdb/mi/mi-main.c +++ b/gdb/mi/mi-main.c @@ -1363,7 +1363,6 @@ mi_cmd_data_write_register_values (char *command, char **argv, int argc) void mi_cmd_data_evaluate_expression (char *command, char **argv, int argc) { - struct expression *expr; struct cleanup *old_chain; struct value *val; struct ui_file *stb; @@ -1377,11 +1376,9 @@ mi_cmd_data_evaluate_expression (char *command, char **argv, int argc) error (_("-data-evaluate-expression: " "Usage: -data-evaluate-expression expression")); - expr = parse_expression (argv[0]); + expression_up expr = parse_expression (argv[0]); - make_cleanup (free_current_contents, &expr); - - val = evaluate_expression (expr); + val = evaluate_expression (expr.get ()); /* Print the result of the expression evaluation. */ get_user_print_options (&opts); @@ -2742,7 +2739,6 @@ mi_cmd_ada_task_info (char *command, char **argv, int argc) static void print_variable_or_computed (const char *expression, enum print_values values) { - struct expression *expr; struct cleanup *old_chain; struct value *val; struct ui_file *stb; @@ -2752,14 +2748,12 @@ print_variable_or_computed (const char *expression, enum print_values values) stb = mem_fileopen (); old_chain = make_cleanup_ui_file_delete (stb); - expr = parse_expression (expression); - - make_cleanup (free_current_contents, &expr); + expression_up expr = parse_expression (expression); if (values == PRINT_SIMPLE_VALUES) - val = evaluate_type (expr); + val = evaluate_type (expr.get ()); else - val = evaluate_expression (expr); + val = evaluate_expression (expr.get ()); if (values != PRINT_NO_VALUES) make_cleanup_ui_out_tuple_begin_end (uiout, NULL); diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c index b2844b9..43d83da 100644 --- a/gdb/objc-lang.c +++ b/gdb/objc-lang.c @@ -1193,14 +1193,11 @@ print_object_command (char *args, int from_tty) "The 'print-object' command requires an argument (an Objective-C object)"); { - struct expression *expr = parse_expression (args); - struct cleanup *old_chain = - make_cleanup (free_current_contents, &expr); + expression_up expr = parse_expression (args); int pc = 0; object = evaluate_subexp (builtin_type (expr->gdbarch)->builtin_data_ptr, - expr, &pc, EVAL_NORMAL); - do_cleanups (old_chain); + expr.get (), &pc, EVAL_NORMAL); } /* Validate the address for sanity. */ diff --git a/gdb/parse.c b/gdb/parse.c index 231eebf..e921438 100644 --- a/gdb/parse.c +++ b/gdb/parse.c @@ -115,12 +115,12 @@ static void free_funcalls (void *ignore); static int prefixify_subexp (struct expression *, struct expression *, int, int); -static struct expression *parse_exp_in_context (const char **, CORE_ADDR, - const struct block *, int, - int, int *); -static struct expression *parse_exp_in_context_1 (const char **, CORE_ADDR, - const struct block *, int, - int, int *); +static expression_up parse_exp_in_context (const char **, CORE_ADDR, + const struct block *, int, + int, int *); +static expression_up parse_exp_in_context_1 (const char **, CORE_ADDR, + const struct block *, int, + int, int *); void _initialize_parse (void); @@ -1108,14 +1108,14 @@ prefixify_subexp (struct expression *inexpr, If COMMA is nonzero, stop if a comma is reached. */ -struct expression * +expression_up parse_exp_1 (const char **stringptr, CORE_ADDR pc, const struct block *block, int comma) { return parse_exp_in_context (stringptr, pc, block, comma, 0, NULL); } -static struct expression * +static expression_up parse_exp_in_context (const char **stringptr, CORE_ADDR pc, const struct block *block, int comma, int void_context_p, int *out_subexp) @@ -1131,7 +1131,7 @@ parse_exp_in_context (const char **stringptr, CORE_ADDR pc, left-hand-side of the struct op. If not doing such completion, it is left untouched. */ -static struct expression * +static expression_up parse_exp_in_context_1 (const char **stringptr, CORE_ADDR pc, const struct block *block, int comma, int void_context_p, int *out_subexp) @@ -1254,18 +1254,16 @@ parse_exp_in_context_1 (const char **stringptr, CORE_ADDR pc, discard_cleanups (old_chain); *stringptr = lexptr; - return ps.expout; + return expression_up (ps.expout); } /* Parse STRING as an expression, and complain if this fails to use up all of the contents of STRING. */ -struct expression * +expression_up parse_expression (const char *string) { - struct expression *exp; - - exp = parse_exp_1 (&string, 0, 0, 0); + expression_up exp = parse_exp_1 (&string, 0, 0, 0); if (*string) error (_("Junk after end of expression.")); return exp; @@ -1274,11 +1272,10 @@ parse_expression (const char *string) /* Same as parse_expression, but using the given language (LANG) to parse the expression. */ -struct expression * +expression_up parse_expression_with_language (const char *string, enum language lang) { struct cleanup *old_chain = NULL; - struct expression *expr; if (current_language->la_language != lang) { @@ -1286,7 +1283,7 @@ parse_expression_with_language (const char *string, enum language lang) set_language (lang); } - expr = parse_expression (string); + expression_up expr = parse_expression (string); if (old_chain != NULL) do_cleanups (old_chain); @@ -1305,14 +1302,14 @@ struct type * parse_expression_for_completion (const char *string, char **name, enum type_code *code) { - struct expression *exp = NULL; + expression_up exp; struct value *val; int subexp; TRY { parse_completion = 1; - exp = parse_exp_in_context (&string, 0, 0, 0, 0, &subexp); + exp = gdb::move (parse_exp_in_context (&string, 0, 0, 0, 0, &subexp)); } CATCH (except, RETURN_MASK_ERROR) { @@ -1333,24 +1330,17 @@ parse_expression_for_completion (const char *string, char **name, } if (expout_last_struct == -1) - { - xfree (exp); - return NULL; - } + return NULL; - *name = extract_field_op (exp, &subexp); + *name = extract_field_op (exp.get (), &subexp); if (!*name) - { - xfree (exp); - return NULL; - } + return NULL; /* This might throw an exception. If so, we want to let it propagate. */ - val = evaluate_subexpression_type (exp, subexp); + val = evaluate_subexpression_type (exp.get (), subexp); /* (*NAME) is a part of the EXP memory block freed below. */ *name = xstrdup (*name); - xfree (exp); return value_type (val); } diff --git a/gdb/printcmd.c b/gdb/printcmd.c index 58a86b1..bbd7e73 100644 --- a/gdb/printcmd.c +++ b/gdb/printcmd.c @@ -119,7 +119,7 @@ struct display char *exp_string; /* Expression to be evaluated and displayed. */ - struct expression *exp; + expression_up exp; /* Item number of this auto-display item. */ int number; @@ -1243,8 +1243,6 @@ print_value (struct value *val, const struct format_data *fmtp) static void print_command_1 (const char *exp, int voidprint) { - struct expression *expr; - struct cleanup *old_chain = make_cleanup (null_cleanup, NULL); struct value *val; struct format_data fmt; @@ -1252,9 +1250,8 @@ print_command_1 (const char *exp, int voidprint) if (exp && *exp) { - expr = parse_expression (exp); - make_cleanup (free_current_contents, &expr); - val = evaluate_expression (expr); + expression_up expr = parse_expression (exp); + val = evaluate_expression (expr.get ()); } else val = access_value_history (0); @@ -1262,8 +1259,6 @@ print_command_1 (const char *exp, int voidprint) if (voidprint || (val && value_type (val) && TYPE_CODE (value_type (val)) != TYPE_CODE_VOID)) print_value (val, &fmt); - - do_cleanups (old_chain); } static void @@ -1292,8 +1287,6 @@ output_command (char *exp, int from_tty) void output_command_const (const char *exp, int from_tty) { - struct expression *expr; - struct cleanup *old_chain; char format = 0; struct value *val; struct format_data fmt; @@ -1310,10 +1303,9 @@ output_command_const (const char *exp, int from_tty) format = fmt.format; } - expr = parse_expression (exp); - old_chain = make_cleanup (free_current_contents, &expr); + expression_up expr = parse_expression (exp); - val = evaluate_expression (expr); + val = evaluate_expression (expr.get ()); annotate_value_begin (value_type (val)); @@ -1325,16 +1317,12 @@ output_command_const (const char *exp, int from_tty) wrap_here (""); gdb_flush (gdb_stdout); - - do_cleanups (old_chain); } static void set_command (char *exp, int from_tty) { - struct expression *expr = parse_expression (exp); - struct cleanup *old_chain = - make_cleanup (free_current_contents, &expr); + expression_up expr = parse_expression (exp); if (expr->nelts >= 1) switch (expr->elts[0].opcode) @@ -1352,8 +1340,7 @@ set_command (char *exp, int from_tty) (_("Expression is not an assignment (and might have no effect)")); } - evaluate_expression (expr); - do_cleanups (old_chain); + evaluate_expression (expr.get ()); } static void @@ -1676,7 +1663,6 @@ address_info (char *exp, int from_tty) static void x_command (char *exp, int from_tty) { - struct expression *expr; struct format_data fmt; struct cleanup *old_chain; struct value *val; @@ -1698,14 +1684,13 @@ x_command (char *exp, int from_tty) if (exp != 0 && *exp != 0) { - expr = parse_expression (exp); + expression_up expr = parse_expression (exp); /* Cause expression not to be there any more if this command is repeated with Newline. But don't clobber a user-defined command's definition. */ if (from_tty) *exp = 0; - old_chain = make_cleanup (free_current_contents, &expr); - val = evaluate_expression (expr); + val = evaluate_expression (expr.get ()); if (TYPE_CODE (value_type (val)) == TYPE_CODE_REF) val = coerce_ref (val); /* In rvalue contexts, such as this, functions are coerced into @@ -1718,7 +1703,6 @@ x_command (char *exp, int from_tty) next_address = value_as_address (val); next_gdbarch = expr->gdbarch; - do_cleanups (old_chain); } if (!next_gdbarch) @@ -1764,7 +1748,6 @@ static void display_command (char *arg, int from_tty) { struct format_data fmt; - struct expression *expr; struct display *newobj; const char *exp = arg; @@ -1792,12 +1775,12 @@ display_command (char *arg, int from_tty) } innermost_block = NULL; - expr = parse_expression (exp); + expression_up expr = parse_expression (exp); - newobj = XNEW (struct display); + newobj = new display (); newobj->exp_string = xstrdup (exp); - newobj->exp = expr; + newobj->exp = gdb::move (expr); newobj->block = innermost_block; newobj->pspace = current_program_space; newobj->number = ++display_number; @@ -1826,8 +1809,7 @@ static void free_display (struct display *d) { xfree (d->exp_string); - xfree (d->exp); - xfree (d); + delete d; } /* Clear out the display_chain. Done when new symtabs are loaded, @@ -1953,8 +1935,7 @@ do_one_display (struct display *d) expression if the current architecture has changed. */ if (d->exp != NULL && d->exp->gdbarch != get_current_arch ()) { - xfree (d->exp); - d->exp = NULL; + d->exp.reset (); d->block = NULL; } @@ -2027,7 +2008,7 @@ do_one_display (struct display *d) struct value *val; CORE_ADDR addr; - val = evaluate_expression (d->exp); + val = evaluate_expression (d->exp.get ()); addr = value_as_address (val); if (d->format.format == 'i') addr = gdbarch_addr_bits_remove (d->exp->gdbarch, addr); @@ -2064,7 +2045,7 @@ do_one_display (struct display *d) { struct value *val; - val = evaluate_expression (d->exp); + val = evaluate_expression (d->exp.get ()); print_formatted (val, d->format.size, &opts, gdb_stdout); } CATCH (ex, RETURN_MASK_ERROR) @@ -2225,10 +2206,9 @@ clear_dangling_display_expressions (struct objfile *objfile) continue; if (lookup_objfile_from_block (d->block) == objfile - || (d->exp && exp_uses_objfile (d->exp, objfile))) + || (d->exp != NULL && exp_uses_objfile (d->exp.get (), objfile))) { - xfree (d->exp); - d->exp = NULL; + d->exp.reset (); d->block = NULL; } } diff --git a/gdb/remote.c b/gdb/remote.c index 919e2bd..e741a58 100644 --- a/gdb/remote.c +++ b/gdb/remote.c @@ -11914,7 +11914,7 @@ remote_download_tracepoint (struct target_ops *self, struct bp_location *loc) capabilities at definition time. */ if (remote_supports_cond_tracepoints ()) { - aexpr = gen_eval_for_expr (tpaddr, loc->cond); + aexpr = gen_eval_for_expr (tpaddr, loc->cond.get ()); aexpr_chain = make_cleanup_free_agent_expr (aexpr); xsnprintf (buf + strlen (buf), BUF_SIZE - strlen (buf), ":X%x,", aexpr->len); diff --git a/gdb/stack.c b/gdb/stack.c index 706dd51..0f8b336 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -2439,13 +2439,12 @@ return_command (char *retval_exp, int from_tty) message. */ if (retval_exp) { - struct expression *retval_expr = parse_expression (retval_exp); - struct cleanup *old_chain = make_cleanup (xfree, retval_expr); + expression_up retval_expr = parse_expression (retval_exp); struct type *return_type = NULL; /* Compute the return value. Should the computation fail, this call throws an error. */ - return_value = evaluate_expression (retval_expr); + return_value = evaluate_expression (retval_expr.get ()); /* Cast return value to the return type of the function. Should the cast fail, this call throws an error. */ @@ -2460,7 +2459,6 @@ return_command (char *retval_exp, int from_tty) "Please use an explicit cast of the value to return.")); return_type = value_type (return_value); } - do_cleanups (old_chain); return_type = check_typedef (return_type); return_value = value_cast (return_type, return_value); diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c index 40b27da..9fd409a 100644 --- a/gdb/tracepoint.c +++ b/gdb/tracepoint.c @@ -701,7 +701,6 @@ void validate_actionline (const char *line, struct breakpoint *b) { struct cmd_list_element *c; - struct expression *exp = NULL; struct cleanup *old_chain = NULL; const char *tmp_p; const char *p; @@ -755,9 +754,8 @@ validate_actionline (const char *line, struct breakpoint *b) for (loc = t->base.loc; loc; loc = loc->next) { p = tmp_p; - exp = parse_exp_1 (&p, loc->address, - block_for_pc (loc->address), 1); - old_chain = make_cleanup (free_current_contents, &exp); + expression_up exp = parse_exp_1 (&p, loc->address, + block_for_pc (loc->address), 1); if (exp->elts[0].opcode == OP_VAR_VALUE) { @@ -780,8 +778,8 @@ validate_actionline (const char *line, struct breakpoint *b) /* We have something to collect, make sure that the expr to bytecode translator can handle it and that it's not too long. */ - aexpr = gen_trace_for_expr (loc->address, exp, trace_string); - make_cleanup_free_agent_expr (aexpr); + aexpr = gen_trace_for_expr (loc->address, exp.get (), trace_string); + old_chain = make_cleanup_free_agent_expr (aexpr); if (aexpr->len > MAX_AGENT_EXPR_LEN) error (_("Expression is too complicated.")); @@ -809,15 +807,14 @@ validate_actionline (const char *line, struct breakpoint *b) p = tmp_p; /* Only expressions are allowed for this action. */ - exp = parse_exp_1 (&p, loc->address, - block_for_pc (loc->address), 1); - old_chain = make_cleanup (free_current_contents, &exp); + expression_up exp = parse_exp_1 (&p, loc->address, + block_for_pc (loc->address), 1); /* We have something to evaluate, make sure that the expr to bytecode translator can handle it and that it's not too long. */ - aexpr = gen_eval_for_expr (loc->address, exp); - make_cleanup_free_agent_expr (aexpr); + aexpr = gen_eval_for_expr (loc->address, exp.get ()); + old_chain = make_cleanup_free_agent_expr (aexpr); if (aexpr->len > MAX_AGENT_EXPR_LEN) error (_("Expression is too complicated.")); @@ -1376,7 +1373,6 @@ encode_actions_1 (struct command_line *action, struct collection_list *stepping_list) { const char *action_exp; - struct expression *exp = NULL; int i; struct value *tempval; struct cmd_list_element *cmd; @@ -1478,12 +1474,11 @@ encode_actions_1 (struct command_line *action, else { unsigned long addr; - struct cleanup *old_chain = NULL; struct cleanup *old_chain1 = NULL; - exp = parse_exp_1 (&action_exp, tloc->address, - block_for_pc (tloc->address), 1); - old_chain = make_cleanup (free_current_contents, &exp); + expression_up exp = parse_exp_1 (&action_exp, tloc->address, + block_for_pc (tloc->address), + 1); switch (exp->elts[0].opcode) { @@ -1505,13 +1500,13 @@ encode_actions_1 (struct command_line *action, case UNOP_MEMVAL: /* Safe because we know it's a simple expression. */ - tempval = evaluate_expression (exp); + tempval = evaluate_expression (exp.get ()); addr = value_address (tempval); /* Initialize the TYPE_LENGTH if it is a typedef. */ check_typedef (exp->elts[1].type); add_memrange (collect, memrange_absolute, addr, TYPE_LENGTH (exp->elts[1].type)); - append_exp (exp, &collect->computed); + append_exp (exp.get (), &collect->computed); break; case OP_VAR_VALUE: @@ -1531,7 +1526,7 @@ encode_actions_1 (struct command_line *action, break; default: /* Full-fledged expression. */ - aexpr = gen_trace_for_expr (tloc->address, exp, + aexpr = gen_trace_for_expr (tloc->address, exp.get (), trace_string); old_chain1 = make_cleanup_free_agent_expr (aexpr); @@ -1564,10 +1559,9 @@ encode_actions_1 (struct command_line *action, } } - append_exp (exp, &collect->computed); + append_exp (exp.get (), &collect->computed); break; } /* switch */ - do_cleanups (old_chain); } /* do */ } while (action_exp && *action_exp++ == ','); @@ -1580,14 +1574,13 @@ encode_actions_1 (struct command_line *action, action_exp = skip_spaces_const (action_exp); { - struct cleanup *old_chain = NULL; struct cleanup *old_chain1 = NULL; - exp = parse_exp_1 (&action_exp, tloc->address, - block_for_pc (tloc->address), 1); - old_chain = make_cleanup (free_current_contents, &exp); + expression_up exp = parse_exp_1 (&action_exp, tloc->address, + block_for_pc (tloc->address), + 1); - aexpr = gen_eval_for_expr (tloc->address, exp); + aexpr = gen_eval_for_expr (tloc->address, exp.get ()); old_chain1 = make_cleanup_free_agent_expr (aexpr); ax_reqs (aexpr); @@ -1597,8 +1590,6 @@ encode_actions_1 (struct command_line *action, /* Even though we're not officially collecting, add to the collect list anyway. */ add_aexpr (collect, aexpr); - - do_cleanups (old_chain); } /* do */ } while (action_exp && *action_exp++ == ','); diff --git a/gdb/typeprint.c b/gdb/typeprint.c index 03fed0a..c1b46be 100644 --- a/gdb/typeprint.c +++ b/gdb/typeprint.c @@ -399,7 +399,6 @@ type_to_string (struct type *type) static void whatis_exp (char *exp, int show) { - struct expression *expr; struct value *val; struct cleanup *old_chain; struct type *real_type = NULL; @@ -450,9 +449,8 @@ whatis_exp (char *exp, int show) exp = skip_spaces (exp); } - expr = parse_expression (exp); - make_cleanup (free_current_contents, &expr); - val = evaluate_type (expr); + expression_up expr = parse_expression (exp); + val = evaluate_type (expr.get ()); } else val = access_value_history (0); @@ -599,13 +597,10 @@ maintenance_print_type (char *type_name, int from_tty) { struct value *val; struct type *type; - struct cleanup *old_chain; - struct expression *expr; if (type_name != NULL) { - expr = parse_expression (type_name); - old_chain = make_cleanup (free_current_contents, &expr); + expression_up expr = parse_expression (type_name); if (expr->elts[0].opcode == OP_TYPE) { /* The user expression names a type directly, just use that type. */ @@ -615,14 +610,13 @@ maintenance_print_type (char *type_name, int from_tty) { /* The user expression may name a type indirectly by naming an object of that type. Find that indirectly named type. */ - val = evaluate_type (expr); + val = evaluate_type (expr.get ()); type = value_type (val); } if (type != NULL) { recursive_dump_type (type, 0); } - do_cleanups (old_chain); } } \f diff --git a/gdb/value.c b/gdb/value.c index b825aec..62c5e37 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -2113,9 +2113,7 @@ init_if_undefined_command (char* args, int from_tty) struct internalvar* intvar; /* Parse the expression - this is taken from set_command(). */ - struct expression *expr = parse_expression (args); - register struct cleanup *old_chain = - make_cleanup (free_current_contents, &expr); + expression_up expr = parse_expression (args); /* Validate the expression. Was the expression an assignment? @@ -2133,9 +2131,7 @@ init_if_undefined_command (char* args, int from_tty) /* Only evaluate the expression if the lvalue is void. This may still fail if the expresssion is invalid. */ if (intvar->kind == INTERNALVAR_VOID) - evaluate_expression (expr); - - do_cleanups (old_chain); + evaluate_expression (expr.get ()); } diff --git a/gdb/varobj.c b/gdb/varobj.c index d56bb59..ba2db6e 100644 --- a/gdb/varobj.c +++ b/gdb/varobj.c @@ -69,7 +69,7 @@ struct varobj_root { /* Alloc'd expression for this parent. */ - struct expression *exp; + expression_up exp; /* Block for which this expression is valid. */ const struct block *valid_block; @@ -379,13 +379,13 @@ varobj_create (const char *objname, But if it fails, we still go on with a call to evaluate_type(). */ TRY { - value = evaluate_expression (var->root->exp); + value = evaluate_expression (var->root->exp.get ()); } CATCH (except, RETURN_MASK_ERROR) { /* Error getting the value. Try to at least get the right type. */ - struct value *type_only_value = evaluate_type (var->root->exp); + struct value *type_only_value = evaluate_type (var->root->exp.get ()); var->type = value_type (type_only_value); } @@ -1050,7 +1050,6 @@ varobj_set_value (struct varobj *var, const char *expression) /* The argument "expression" contains the variable's new value. We need to first construct a legal expression for this -- ugh! */ /* Does this cover all the bases? */ - struct expression *exp; struct value *value = NULL; /* Initialize to keep gcc happy. */ int saved_input_radix = input_radix; const char *s = expression; @@ -1058,16 +1057,15 @@ varobj_set_value (struct varobj *var, const char *expression) gdb_assert (varobj_editable_p (var)); input_radix = 10; /* ALWAYS reset to decimal temporarily. */ - exp = parse_exp_1 (&s, 0, 0, 0); + expression_up exp = parse_exp_1 (&s, 0, 0, 0); TRY { - value = evaluate_expression (exp); + value = evaluate_expression (exp.get ()); } CATCH (except, RETURN_MASK_ERROR) { /* We cannot proceed without a valid expression. */ - xfree (exp); return 0; } END_CATCH @@ -2082,7 +2080,7 @@ new_root_variable (void) { struct varobj *var = new_variable (); - var->root = XNEW (struct varobj_root); + var->root = new varobj_root (); var->root->lang_ops = NULL; var->root->exp = NULL; var->root->valid_block = NULL; @@ -2115,10 +2113,7 @@ free_variable (struct varobj *var) /* Free the expression if this is a root variable. */ if (is_root_p (var)) - { - xfree (var->root->exp); - xfree (var->root); - } + delete var->root; xfree (var->dynamic); delete var; @@ -2279,7 +2274,7 @@ value_of_root_1 (struct varobj **var_handle) expression fails we want to just return NULL. */ TRY { - new_val = evaluate_expression (var->root->exp); + new_val = evaluate_expression (var->root->exp.get ()); } CATCH (except, RETURN_MASK_ERROR) { @@ -2337,10 +2332,7 @@ value_of_root (struct varobj **var_handle, int *type_changed) button, for example). Naturally, those locations are not correct in other frames, so update the expression. */ - struct expression *tmp_exp = var->root->exp; - - var->root->exp = tmp_var->root->exp; - tmp_var->root->exp = tmp_exp; + std::swap (var->root->exp, tmp_var->root->exp); varobj_delete (tmp_var, 0); *type_changed = 0; -- 2.5.5 ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 0/3] More cleanup elimination / gdb::unique_ptr 2016-10-10 16:46 [PATCH 0/3] More cleanup elimination / gdb::unique_ptr Pedro Alves 2016-10-10 16:46 ` [PATCH 1/3] Introduce gdb::unique_ptr Pedro Alves 2016-10-10 16:46 ` [PATCH 3/3] 'struct parse_expression *' -> gdb::unique_ptr<expression> Pedro Alves @ 2016-10-10 16:58 ` Pedro Alves 2016-10-16 7:05 ` Tom Tromey 2016-10-20 13:46 ` Pedro Alves 2 siblings, 2 replies; 72+ messages in thread From: Pedro Alves @ 2016-10-10 16:58 UTC (permalink / raw) To: gdb-patches I'm not sure whether patch #2 is just delayed, or whether it was too big for the list (172K on disk). Meanwhile, I've force-pushed the series to the users/palves/cxx-eliminate-cleanups branch. Thanks, Pedro Alves On 10/10/2016 05:46 PM, Pedro Alves wrote: > This patch series aims at removing more cleanups. > > It eliminates ~90 out of the ~1800 make_cleanup calls left in the > tree. > > It also tries to answer the "which smart pointer?" question. Many > make_cleanup uses in the code base are best eliminated by using a > "owning" smart pointer to manage ownership of the resource > automatically. > > We don't require C++11 yet, but OTOH, std::unique_ptr is quite nice. > C++03 has std::auto_ptr, but, that's best avoided. I'd also like to > have a smart pointer that manages malloc'ed objects, so std::auto_ptr > alone won't cut it. > > The solution proposed by this series is a new gdb::unique_ptr smart > pointer that is mapped to std::unique_ptr when compiling with a C++11 > compiler (really, just a template alias), and is a simple > std::unique_ptr emulation when compiled with a C++03 compiler. > > The patch series first adds the smart pointer to the tree, and then > follows up with examples of C++fycation that use it, and more. > > Series tested on: > > - NetBSD 5.1 (gcc70 on the compile farm), w/ gcc 4.1.3 > - x86-64 Fedora 23, gcc 5.3.1 (gnu++03) native/gdbserver > - x86-64 Fedora 23, and gcc 7.0 (gnu++14) > > Note that while the series' diffstat is practically a wash > linecount-wise: > > 87 files changed, 1450 insertions(+), 1429 deletions(-) > > if we don't count the first patch, i.e., the new smart pointer, then > we get: > > 84 files changed, 1017 insertions(+), 1429 deletions(-) > > So while there's a lot of churn, there's a significant drop in number > of lines of code. > > Pedro Alves (3): > Introduce gdb::unique_ptr > ui_file_xstrdup -> std::string > 'struct parse_expression *' -> gdb::unique_ptr<expression> > > gdb/ada-lang.c | 83 +++------ > gdb/ada-lang.h | 2 +- > gdb/ada-valprint.c | 53 +++--- > gdb/ada-varobj.c | 130 ++++++-------- > gdb/arm-tdep.c | 6 +- > gdb/ax-gdb.c | 15 +- > gdb/break-catch-sig.c | 2 +- > gdb/break-catch-syscall.c | 2 +- > gdb/break-catch-throw.c | 26 +-- > gdb/breakpoint.c | 144 +++++++--------- > gdb/breakpoint.h | 8 +- > gdb/c-exp.y | 9 +- > gdb/c-lang.c | 9 +- > gdb/c-lang.h | 7 +- > gdb/c-typeprint.c | 5 +- > gdb/c-varobj.c | 142 ++++++++-------- > gdb/cli/cli-script.c | 130 +++++--------- > gdb/cli/cli-setshow.c | 7 +- > gdb/common/common-defs.h | 3 + > gdb/common/common-utils.c | 31 ++++ > gdb/common/common-utils.h | 6 + > gdb/common/gdb_unique_ptr.h | 363 ++++++++++++++++++++++++++++++++++++++++ > gdb/common/safe-bool.h | 67 ++++++++ > gdb/compile/compile-c-support.c | 6 +- > gdb/compile/compile.c | 70 ++++---- > gdb/cp-abi.c | 2 +- > gdb/cp-abi.h | 7 +- > gdb/cp-support.c | 60 +++---- > gdb/cp-support.h | 10 +- > gdb/dbxread.c | 22 +-- > gdb/dtrace-probe.c | 6 +- > gdb/dwarf2read.c | 25 ++- > gdb/eval.c | 43 ++--- > gdb/expression.h | 12 +- > gdb/gdbarch.c | 8 +- > gdb/gdbarch.sh | 8 +- > gdb/gdbcmd.h | 2 +- > gdb/gdbtypes.c | 12 +- > gdb/gnu-v3-abi.c | 55 ++---- > gdb/guile/guile.c | 18 +- > gdb/guile/scm-breakpoint.c | 6 +- > gdb/guile/scm-disasm.c | 6 +- > gdb/guile/scm-frame.c | 6 +- > gdb/guile/scm-type.c | 27 ++- > gdb/guile/scm-value.c | 18 +- > gdb/infcmd.c | 9 +- > gdb/infrun.c | 6 +- > gdb/language.c | 7 +- > gdb/language.h | 14 +- > gdb/linespec.c | 53 +++--- > gdb/location.c | 11 +- > gdb/location.h | 6 - > gdb/mi/mi-cmd-var.c | 70 +++----- > gdb/mi/mi-main.c | 41 ++--- > gdb/minsyms.c | 17 +- > gdb/objc-lang.c | 7 +- > gdb/parse.c | 50 +++--- > gdb/printcmd.c | 65 +++---- > gdb/python/py-arch.c | 10 +- > gdb/python/py-breakpoint.c | 8 +- > gdb/python/py-frame.c | 8 +- > gdb/python/py-type.c | 10 +- > gdb/python/py-unwind.c | 7 +- > gdb/python/py-value.c | 7 +- > gdb/python/py-varobj.c | 4 +- > gdb/python/python.c | 19 +-- > gdb/remote.c | 56 ++----- > gdb/rust-exp.y | 11 +- > gdb/rust-lang.c | 50 ++---- > gdb/stabsread.c | 21 ++- > gdb/stack.c | 6 +- > gdb/symtab.c | 61 +++---- > gdb/symtab.h | 19 ++- > gdb/top.c | 13 +- > gdb/tracepoint.c | 143 +++++----------- > gdb/tracepoint.h | 18 +- > gdb/typeprint.c | 21 +-- > gdb/ui-file.c | 24 ++- > gdb/ui-file.h | 9 +- > gdb/ui-out.c | 9 +- > gdb/utils.c | 5 +- > gdb/value.c | 8 +- > gdb/value.h | 2 +- > gdb/varobj-iter.h | 4 +- > gdb/varobj.c | 216 +++++++++++------------- > gdb/varobj.h | 66 ++++---- > gdb/xtensa-tdep.c | 9 +- > 87 files changed, 1450 insertions(+), 1429 deletions(-) > create mode 100644 gdb/common/gdb_unique_ptr.h > create mode 100644 gdb/common/safe-bool.h > ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 0/3] More cleanup elimination / gdb::unique_ptr 2016-10-10 16:58 ` [PATCH 0/3] More cleanup elimination / gdb::unique_ptr Pedro Alves @ 2016-10-16 7:05 ` Tom Tromey 2016-10-17 13:57 ` Pedro Alves 2016-10-20 13:46 ` Pedro Alves 1 sibling, 1 reply; 72+ messages in thread From: Tom Tromey @ 2016-10-16 7:05 UTC (permalink / raw) To: Pedro Alves; +Cc: gdb-patches >>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes: Pedro> I'm not sure whether patch #2 is just delayed, or whether it was Pedro> too big for the list (172K on disk). I found a buglet in patch #2. Namely, in rust-lang.c there are some assignments using concat that aren't converted to properly use std::string. This results in a memory leak. In particular look at rust_get_disr_info - I've appended a hunk from a patch of mine (untested), but note mine deletes the do_cleanups, which you don't want to do. Tom diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c index 5b81283..148e980 100644 --- a/gdb/rust-lang.c +++ b/gdb/rust-lang.c @@ -172,17 +171,15 @@ rust_get_disr_info (struct type *type, const gdb_byte *valaddr, if (value == 0) { ret.field_no = RUST_ENCODED_ENUM_HIDDEN; - ret.name = concat (TYPE_NAME (type), "::", token, (char *) NULL); + ret.name = std::string (TYPE_NAME (type)) + "::" + token; } else { ret.field_no = RUST_ENCODED_ENUM_REAL; - ret.name = concat (TYPE_NAME (type), "::", - rust_last_path_segment (TYPE_NAME (TYPE_FIELD_TYPE (type, 0))), - (char *) NULL); + ret.name = (std::string (TYPE_NAME (type)) + "::" + + rust_last_path_segment (TYPE_NAME (TYPE_FIELD_TYPE (type, 0)))); } - do_cleanups (cleanup); return ret; } ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 0/3] More cleanup elimination / gdb::unique_ptr 2016-10-16 7:05 ` Tom Tromey @ 2016-10-17 13:57 ` Pedro Alves 2016-10-17 14:07 ` Tom Tromey 0 siblings, 1 reply; 72+ messages in thread From: Pedro Alves @ 2016-10-17 13:57 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches On 10/16/2016 08:05 AM, Tom Tromey wrote: >>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes: > > Pedro> I'm not sure whether patch #2 is just delayed, or whether it was > Pedro> too big for the list (172K on disk). > > I found a buglet in patch #2. Namely, in rust-lang.c there are some > assignments using concat that aren't converted to properly use > std::string. This results in a memory leak. Good catch, thanks. > In particular look at rust_get_disr_info - I've appended a hunk from a > patch of mine (untested), but note mine deletes the do_cleanups, which > you don't want to do. I'd folded this into my patch (old patch #2 is now exploded into multiple smaller pieces), and the result is the patch below. But I'll be happy to drop my patch instead if you'd prefer. > but note mine deletes the do_cleanups, which you don't want to do. Looks like the last cleanup is this one: name = xstrdup (TYPE_FIELD_NAME (type, 0)); cleanup = make_cleanup (xfree, name); tail = name + strlen (RUST_ENUM_PREFIX); and, I can't figure out why we need to xstrdup at all here? The patch below is pushed in the branch, but, as I said above, I can happily drop it. From 5058928ec2f5f6fecd3a33d87d7f15ad631640b5 Mon Sep 17 00:00:00 2001 From: Pedro Alves <palves@redhat.com> Date: Mon, 17 Oct 2016 14:11:27 +0100 Subject: [PATCH] Use ui_file_as_string in gdb/rust-lang.c gdb/ChangeLog: yyyy-mm-yy Pedro Alves <palves@redhat.com> Tom Tromey <tom@tromey.com> * rust-lang.c (struct disr_info) <name>: Now a std::string. (rust_get_disr_info): Use ui_file_as_string and adjust to use std::string. (rust_val_print): Adjust to use std::string. --- gdb/rust-lang.c | 57 ++++++++++++++++++++------------------------------------- 1 file changed, 20 insertions(+), 37 deletions(-) diff --git a/gdb/rust-lang.c b/gdb/rust-lang.c index 82cd3f9..54a16cc 100644 --- a/gdb/rust-lang.c +++ b/gdb/rust-lang.c @@ -70,8 +70,8 @@ rust_crate_for_block (const struct block *block) struct disr_info { - /* Name of field. Must be freed by caller. */ - char *name; + /* Name of field. */ + std::string name; /* Field number in union. Negative on error. For an encoded enum, the "hidden" member will always be field 1, and the "real" member will always be field 0. */ @@ -172,14 +172,13 @@ rust_get_disr_info (struct type *type, const gdb_byte *valaddr, if (value == 0) { ret.field_no = RUST_ENCODED_ENUM_HIDDEN; - ret.name = concat (TYPE_NAME (type), "::", token, (char *) NULL); + ret.name = std::string (TYPE_NAME (type)) + "::" + token; } else { ret.field_no = RUST_ENCODED_ENUM_REAL; - ret.name = concat (TYPE_NAME (type), "::", - rust_last_path_segment (TYPE_NAME (TYPE_FIELD_TYPE (type, 0))), - (char *) NULL); + ret.name = (std::string (TYPE_NAME (type)) + "::" + + rust_last_path_segment (TYPE_NAME (TYPE_FIELD_TYPE (type, 0)))); } do_cleanups (cleanup); @@ -208,8 +207,8 @@ rust_get_disr_info (struct type *type, const gdb_byte *valaddr, address, temp_file, 0, val, &opts); - ret.name = ui_file_xstrdup (temp_file, NULL); - name_segment = rust_last_path_segment (ret.name); + ret.name = ui_file_as_string (temp_file); + name_segment = rust_last_path_segment (ret.name.c_str ()); if (name_segment != NULL) { for (i = 0; i < TYPE_NFIELDS (type); ++i) @@ -233,12 +232,11 @@ rust_get_disr_info (struct type *type, const gdb_byte *valaddr, } } - if (ret.field_no == -1 && ret.name != NULL) + if (ret.field_no == -1 && !ret.name.empty ()) { /* Somehow the discriminant wasn't found. */ - make_cleanup (xfree, ret.name); error (_("Could not find variant of %s with discriminant %s"), - TYPE_TAG_NAME (type), ret.name); + TYPE_TAG_NAME (type), ret.name.c_str ()); } do_cleanups (cleanup); @@ -553,19 +551,17 @@ rust_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, struct type *variant_type; struct disr_info disr; struct value_print_options opts; - struct cleanup *cleanup; opts = *options; opts.deref_ref = 0; disr = rust_get_disr_info (type, valaddr, embedded_offset, address, val); - cleanup = make_cleanup (xfree, disr.name); if (disr.is_encoded && disr.field_no == RUST_ENCODED_ENUM_HIDDEN) { - fprintf_filtered (stream, "%s", disr.name); - goto cleanup; + fprintf_filtered (stream, "%s", disr.name.c_str ()); + break; } first_field = 1; @@ -581,19 +577,19 @@ rust_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, { /* In case of a non-nullary variant, we output 'Foo(x,y,z)'. */ if (is_tuple) - fprintf_filtered (stream, "%s(", disr.name); + fprintf_filtered (stream, "%s(", disr.name.c_str ()); else { /* struct variant. */ - fprintf_filtered (stream, "%s{", disr.name); + fprintf_filtered (stream, "%s{", disr.name.c_str ()); } } else { /* In case of a nullary variant like 'None', just output the name. */ - fprintf_filtered (stream, "%s", disr.name); - goto cleanup; + fprintf_filtered (stream, "%s", disr.name.c_str ()); + break; } for (j = start; j < TYPE_NFIELDS (variant_type); j++) @@ -620,9 +616,6 @@ rust_val_print (struct type *type, const gdb_byte *valaddr, int embedded_offset, fputs_filtered (")", stream); else fputs_filtered ("}", stream); - - cleanup: - do_cleanups (cleanup); } break; @@ -1628,14 +1621,10 @@ rust_evaluate_subexp (struct type *expect_type, struct expression *exp, type = value_type (lhs); if (TYPE_CODE (type) == TYPE_CODE_UNION) { - struct cleanup *cleanup; - disr = rust_get_disr_info (type, value_contents (lhs), value_embedded_offset (lhs), value_address (lhs), lhs); - cleanup = make_cleanup (xfree, disr.name); - if (disr.is_encoded && disr.field_no == RUST_ENCODED_ENUM_HIDDEN) { variant_type = NULL; @@ -1654,17 +1643,16 @@ rust_evaluate_subexp (struct type *expect_type, struct expression *exp, error(_("Cannot access field %d of variant %s, \ there are only %d fields"), disr.is_encoded ? field_number : field_number - 1, - disr.name, + disr.name.c_str (), disr.is_encoded ? nfields : nfields - 1); if (!(disr.is_encoded ? rust_tuple_struct_type_p (variant_type) : rust_tuple_variant_type_p (variant_type))) - error(_("Variant %s is not a tuple variant"), disr.name); + error(_("Variant %s is not a tuple variant"), disr.name.c_str ()); result = value_primitive_field (lhs, 0, field_number, variant_type); - do_cleanups (cleanup); } else if (TYPE_CODE (type) == TYPE_CODE_STRUCT) { @@ -1706,7 +1694,6 @@ tuple structs, and tuple-like enum variants")); { int i, start; struct disr_info disr; - struct cleanup* cleanup; struct type* variant_type; char* field_name; @@ -1716,11 +1703,9 @@ tuple structs, and tuple-like enum variants")); value_embedded_offset (lhs), value_address (lhs), lhs); - cleanup = make_cleanup (xfree, disr.name); - if (disr.is_encoded && disr.field_no == RUST_ENCODED_ENUM_HIDDEN) error(_("Could not find field %s of struct variant %s"), - field_name, disr.name); + field_name, disr.name.c_str ()); variant_type = TYPE_FIELD_TYPE (type, disr.field_no); @@ -1728,7 +1713,7 @@ tuple structs, and tuple-like enum variants")); || rust_tuple_variant_type_p (variant_type)) error(_("Attempting to access named field %s of tuple variant %s, \ which has only anonymous fields"), - field_name, disr.name); + field_name, disr.name.c_str ()); start = disr.is_encoded ? 0 : 1; for (i = start; i < TYPE_NFIELDS (variant_type); i++) @@ -1743,9 +1728,7 @@ which has only anonymous fields"), if (i == TYPE_NFIELDS (variant_type)) /* We didn't find it. */ error(_("Could not find field %s of struct variant %s"), - field_name, disr.name); - - do_cleanups (cleanup); + field_name, disr.name.c_str ()); } else { -- 2.5.5 ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 0/3] More cleanup elimination / gdb::unique_ptr 2016-10-17 13:57 ` Pedro Alves @ 2016-10-17 14:07 ` Tom Tromey 2016-10-17 14:59 ` Pedro Alves 0 siblings, 1 reply; 72+ messages in thread From: Tom Tromey @ 2016-10-17 14:07 UTC (permalink / raw) To: Pedro Alves; +Cc: Tom Tromey, gdb-patches >>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes: Pedro> But I'll be happy to drop my patch instead if you'd prefer. No, please keep it. >> but note mine deletes the do_cleanups, which you don't want to do. Pedro> Looks like the last cleanup is this one: Pedro> name = xstrdup (TYPE_FIELD_NAME (type, 0)); Pedro> cleanup = make_cleanup (xfree, name); Pedro> tail = name + strlen (RUST_ENUM_PREFIX); Pedro> and, I can't figure out why we need to xstrdup at all here? The string is modified using strtok_r below. Tom ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 0/3] More cleanup elimination / gdb::unique_ptr 2016-10-17 14:07 ` Tom Tromey @ 2016-10-17 14:59 ` Pedro Alves 0 siblings, 0 replies; 72+ messages in thread From: Pedro Alves @ 2016-10-17 14:59 UTC (permalink / raw) To: Tom Tromey; +Cc: gdb-patches On 10/17/2016 03:05 PM, Tom Tromey wrote: >>>>>> "Pedro" == Pedro Alves <palves@redhat.com> writes: > > Pedro> But I'll be happy to drop my patch instead if you'd prefer. > > No, please keep it. OK. >>> but note mine deletes the do_cleanups, which you don't want to do. > > Pedro> Looks like the last cleanup is this one: > Pedro> name = xstrdup (TYPE_FIELD_NAME (type, 0)); > Pedro> cleanup = make_cleanup (xfree, name); > Pedro> tail = name + strlen (RUST_ENUM_PREFIX); > Pedro> and, I can't figure out why we need to xstrdup at all here? > > The string is modified using strtok_r below. Ah, indeed. Thanks, Pedro Alves ^ permalink raw reply [flat|nested] 72+ messages in thread
* Re: [PATCH 0/3] More cleanup elimination / gdb::unique_ptr 2016-10-10 16:58 ` [PATCH 0/3] More cleanup elimination / gdb::unique_ptr Pedro Alves 2016-10-16 7:05 ` Tom Tromey @ 2016-10-20 13:46 ` Pedro Alves 1 sibling, 0 replies; 72+ messages in thread From: Pedro Alves @ 2016-10-20 13:46 UTC (permalink / raw) To: gdb-patches On 10/10/2016 05:58 PM, Pedro Alves wrote: > I'm not sure whether patch #2 is just delayed, or whether it was too > big for the list (172K on disk). Meanwhile, I've force-pushed the > series to the For the record, the problem was that the patch triggered a false positive on sourceware's spam filter. That was also the reason the smaller version of this patch got delayed in v2: https://sourceware.org/ml/gdb-patches/2016-10/msg00603.html Thanks to Frank Ch. Eigler for sorting this out. -- Pedro Alves ^ permalink raw reply [flat|nested] 72+ messages in thread
end of thread, other threads:[~2016-10-20 13:46 UTC | newest] Thread overview: 72+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2016-10-10 16:46 [PATCH 0/3] More cleanup elimination / gdb::unique_ptr Pedro Alves 2016-10-10 16:46 ` [PATCH 1/3] Introduce gdb::unique_ptr Pedro Alves 2016-10-10 17:49 ` Simon Marchi 2016-10-10 18:03 ` Pedro Alves 2016-10-11 6:48 ` Metzger, Markus T 2016-10-11 10:23 ` Pedro Alves 2016-10-11 10:53 ` Andreas Schwab 2016-10-11 11:17 ` Metzger, Markus T 2016-10-11 11:43 ` Pedro Alves 2016-10-11 13:58 ` Yao Qi 2016-10-11 14:05 ` Trevor Saunders 2016-10-11 12:16 ` Joel Brobecker 2016-10-11 13:46 ` Pedro Alves 2016-10-11 14:47 ` Joel Brobecker 2016-10-11 15:17 ` Eli Zaretskii 2016-10-11 16:24 ` Pedro Alves 2016-10-11 16:58 ` Eli Zaretskii 2016-10-11 17:41 ` Pedro Alves 2016-10-11 18:37 ` Eli Zaretskii 2016-10-11 19:19 ` Pedro Alves 2016-10-11 20:47 ` Eli Zaretskii 2016-10-11 21:32 ` Pedro Alves 2016-10-12 6:34 ` Eli Zaretskii 2016-10-12 8:11 ` Metzger, Markus T 2016-10-12 9:31 ` Eli Zaretskii 2016-10-12 10:12 ` Pedro Alves 2016-10-12 11:05 ` Eli Zaretskii 2016-10-12 11:25 ` Pedro Alves 2016-10-12 11:45 ` Eli Zaretskii 2016-10-13 12:12 ` Pedro Alves 2016-10-12 10:28 ` Pedro Alves 2016-10-12 11:07 ` Eli Zaretskii 2016-10-12 11:19 ` Pedro Alves 2016-10-12 11:41 ` Eli Zaretskii 2016-10-12 11:55 ` Pedro Alves 2016-10-13 0:38 ` [PATCH] Enable C++11 starting with gcc 4.8 (was: Re: [PATCH 1/3] Introduce gdb::unique_ptr) Pedro Alves 2016-10-13 0:45 ` [PATCH 2/2] gdb: Enable C++11 if available Pedro Alves 2016-10-13 0:45 ` [PATCH 1/2] gdb: Import AX_CXX_COMPILE_STDCXX from the GNU Autoconf Archive Pedro Alves 2016-10-12 9:37 ` [PATCH 1/3] Introduce gdb::unique_ptr Pedro Alves 2016-10-12 10:51 ` Eli Zaretskii 2016-10-12 11:15 ` Pedro Alves 2016-10-12 11:40 ` Eli Zaretskii 2016-10-12 11:45 ` Jan Kratochvil 2016-10-12 11:56 ` Luis Machado 2016-10-12 12:03 ` Eli Zaretskii 2016-10-13 9:07 ` Jan Kratochvil 2016-10-13 10:07 ` Eli Zaretskii 2016-10-13 10:27 ` Pedro Alves 2016-10-13 13:22 ` Eli Zaretskii 2016-10-13 13:36 ` Pedro Alves 2016-10-13 13:59 ` Eli Zaretskii 2016-10-13 14:04 ` Pedro Alves 2016-10-13 15:06 ` Joel Brobecker 2016-10-13 10:46 ` Jan Kratochvil 2016-10-13 11:15 ` Pedro Alves 2016-10-13 13:28 ` Eli Zaretskii 2016-10-13 13:42 ` Pedro Alves 2016-10-13 14:07 ` Eli Zaretskii 2016-10-11 19:23 ` Simon Marchi 2016-10-11 20:54 ` Eli Zaretskii 2016-10-11 21:28 ` Simon Marchi 2016-10-12 6:23 ` Eli Zaretskii 2016-10-11 21:16 ` Jan Kratochvil 2016-10-11 17:15 ` Luis Machado 2016-10-11 18:21 ` Pedro Alves 2016-10-10 16:46 ` [PATCH 3/3] 'struct parse_expression *' -> gdb::unique_ptr<expression> Pedro Alves 2016-10-10 16:58 ` [PATCH 0/3] More cleanup elimination / gdb::unique_ptr Pedro Alves 2016-10-16 7:05 ` Tom Tromey 2016-10-17 13:57 ` Pedro Alves 2016-10-17 14:07 ` Tom Tromey 2016-10-17 14:59 ` Pedro Alves 2016-10-20 13:46 ` Pedro Alves
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox