Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [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

* [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

* [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

* 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 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 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 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 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: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 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: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

* 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 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: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 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 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 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 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: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 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  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: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  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  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: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 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 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: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: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: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 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: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 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: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

* 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

* [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 1/2] gdb: Import AX_CXX_COMPILE_STDCXX from the GNU Autoconf Archive Pedro Alves
  2016-10-13  0:45                                     ` [PATCH 2/2] gdb: Enable C++11 if available 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                                     ` [PATCH 1/2] gdb: Import AX_CXX_COMPILE_STDCXX from the GNU Autoconf Archive 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

... 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                                     ` Pedro Alves
  2016-10-13  0:45                                     ` [PATCH 2/2] gdb: Enable C++11 if available 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 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: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-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-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 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: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: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: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 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-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 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 1/2] gdb: Import AX_CXX_COMPILE_STDCXX from the GNU Autoconf Archive Pedro Alves
2016-10-13  0:45                                     ` [PATCH 2/2] gdb: Enable C++11 if available 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