This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Type-safe wrapper for enum flags


On 15-10-29 02:45 PM, Pedro Alves wrote:
> This patch fixes C++ build errors like this:
> 
> /home/pedro/gdb/mygit/cxx-convertion/src/gdb/linux-tdep.c:1126:35: error: invalid conversion from âintâ to âfilterflagsâ [-fpermissive]
>        | COREFILTER_HUGETLB_PRIVATE);
>                                    ^
> 
> This is a case of enums used as bit flags.  Unlike "regular" enums,
> these values are supposed to be or'ed together.  However, in C++, the
> type of "(ENUM1 | ENUM2)" is int, and you then can't assign an int to
> an enum variable without a cast.  That means that this:
> 
>   enum foo_flags flags = 0;
> 
>   if (...)
>     flags |= FOO_FLAG1;
>   if (...)
>     flags |= FOO_FLAG2;
> 
> ... would have to be written as:
> 
>   enum foo_flags flags = (enum foo_flags) 0;
> 
>   if (...)
>     flags = (enum foo_flags) (flags | FOO_FLAG1);
>   if (...)
>     flags = (enum foo_flags) (flags | FOO_FLAG2);
> 
> which is ... ugly.  Alternatively, we'd have to use an int for the
> variable's type, which isn't ideal either.
> 
> This patch instead adds an "enum flags" class.  "enum flags" are
> exactly the enums where the values are bits that are meant to be ORed
> together.
> 
> This allows writing code like the below, while with raw enums this
> would fail to compile without casts to enum type at the assignments to
> 'f':
> 
>   enum some_flag
>   {
>      flag_val1 = 1 << 1,
>      flag_val2 = 1 << 2,
>      flag_val3 = 1 << 3,
>      flag_val4 = 1 << 4,
>   };
>   DEF_ENUM_FLAGS_TYPE(enum some_flag, some_flags)
> 
>   some_flags f = flag_val1 | flag_val2;
>   f |= flag_val3;
> 
> It's also possible to assign literal zero to an enum flags variable
> (meaning, no flags), dispensing either adding an awkward explicit "no
> value" value to the enumeration or the cast to assignments from 0.
> For example:
> 
>   some_flags f = 0;
>   f |= flag_val3 | flag_val4;
> 
> Note that literal integers other than zero do fail to compile:
> 
>   some_flags f = 1; // error
> 
> C is still supported -- DEF_ENUM_FLAGS_TYPE is just a typedef in that
> case.
> 
> gdb/ChangeLog:
> 2015-10-29  Pedro Alves  <palves@redhat.com>
> 
> 	* btrace.h: Include common/enum_flags.h.
> 	(btrace_insn_flags): Define.
> 	(struct btrace_insn) <flags>: Change type.
> 	(btrace_function_flags): Define.
> 	(struct btrace_function) <flags>: Change type.
> 	(btrace_thread_flags): Define.
> 	(struct btrace_thread_info) <flags>: Change type.
> 	* c-exp.y (token_flags): Rename to ...
> 	(token_flag): ... this.
> 	(token_flags): Define.
> 	(struct token) <flags>: Change type.
> 	* common/enum_flags.h: New file.
> 	* compile/compile-c-types.c (convert_qualified): Change type of
> 	'quals' local.
> 	* compile/compile-internal.h: Include "common/enum_flags.h".
> 	(gcc_qualifiers_flags): Define.
> 	* completer.c (enum reg_completer_targets): Rename to ...
> 	(enum reg_completer_target): ... this.
> 	(reg_completer_targets): Define.
> 	(reg_or_group_completer_1): Change type of 'targets' parameter.
> 	* disasm.c (do_mixed_source_and_assembly_deprecated): Change type
> 	of 'psl_flags' local.
> 	(do_mixed_source_and_assembly): Change type of 'psl_flags' local.
> 	* infrun.c: Include "common/enum_flags.h".
> 	(enum step_over_what): Rename to ...
> 	(enum step_over_what_flag): ... this.
> 	(step_over_what): Change type.
> 	(start_step_over): Change type of 'step_what' local.
> 	(thread_still_needs_step_over): Now returns a step_over_what.
> 	Adjust.
> 	(keep_going_pass_signal): Change type of 'step_what' local.
> 	* linux-tdep.c: Include "common/enum_flags.h".
> 	(enum filterflags): Rename to ...
> 	(enum filter_flag): ... this.
> 	(filter_flags): Define.
> 	(dump_mapping_p): Change type of 'filterflags' parameter.
> 	(linux_find_memory_regions_full): Change type of 'filterflags'
> 	local.
> 	(linux_find_memory_regions_full): Pass the address of an unsigned
> 	int to sscanf instead of the address of an enum.
> 	* record-btrace.c (btrace_call_history): Replace 'flags' parameter
> 	with 'int_flags' parameter.  Adjust.
> 	(record_btrace_call_history, record_btrace_call_history_range)
> 	(record_btrace_call_history_from): Rename 'flags' parameter to
> 	'int_flags'.  Use record_print_flags.
> 	* record.h: Include "common/enum_flags.h".
> 	(record_print_flags): Define.
> 	* source.c: Include "common/enum_flags.h".
> 	(print_source_lines_base, print_source_lines): Change type of
> 	flags parameter.
> 	* symtab.h: Include "common/enum_flags.h".
> 	(enum print_source_lines_flags): Rename to ...
> 	(enum print_source_lines_flag): ... this.
> 	(print_source_lines_flags): Define.
> 	(print_source_lines): Change prototype.
> ---
>  gdb/btrace.h                   |  10 +-
>  gdb/c-exp.y                    |   5 +-
>  gdb/common/enum_flags.h        | 211 +++++++++++++++++++++++++++++++++++++++++
>  gdb/compile/compile-c-types.c  |   2 +-
>  gdb/compile/compile-internal.h |   4 +
>  gdb/completer.c                |   5 +-
>  gdb/disasm.c                   |   4 +-
>  gdb/infrun.c                   |  14 +--
>  gdb/linux-tdep.c               |  19 ++--
>  gdb/record-btrace.c            |  22 +++--
>  gdb/record.h                   |   2 +
>  gdb/source.c                   |   7 +-
>  gdb/symtab.h                   |   6 +-
>  13 files changed, 275 insertions(+), 36 deletions(-)
>  create mode 100644 gdb/common/enum_flags.h
> 
> diff --git a/gdb/btrace.h b/gdb/btrace.h
> index f844df8..e012c1e 100644
> --- a/gdb/btrace.h
> +++ b/gdb/btrace.h
> @@ -28,6 +28,7 @@
>  
>  #include "btrace-common.h"
>  #include "target/waitstatus.h" /* For enum target_stop_reason.  */
> +#include "common/enum_flags.h"
>  
>  #if defined (HAVE_LIBIPT)
>  #  include <intel-pt.h>
> @@ -58,6 +59,7 @@ enum btrace_insn_flag
>    /* The instruction has been executed speculatively.  */
>    BTRACE_INSN_FLAG_SPECULATIVE = (1 << 0)
>  };
> +DEF_ENUM_FLAGS_TYPE (enum btrace_insn_flag, btrace_insn_flags);
>  
>  /* A branch trace instruction.
>  
> @@ -74,7 +76,7 @@ struct btrace_insn
>    enum btrace_insn_class iclass;
>  
>    /* A bit vector of BTRACE_INSN_FLAGS.  */
> -  enum btrace_insn_flag flags;
> +  btrace_insn_flags flags;
>  };
>  
>  /* A vector of branch trace instructions.  */
> @@ -100,6 +102,7 @@ enum btrace_function_flag
>       if bfun_up_links_to_ret is clear.  */
>    BFUN_UP_LINKS_TO_TAILCALL = (1 << 1)
>  };
> +DEF_ENUM_FLAGS_TYPE (enum btrace_function_flag, btrace_function_flags);
>  
>  /* Decode errors for the BTS recording format.  */
>  enum btrace_bts_error
> @@ -181,7 +184,7 @@ struct btrace_function
>    int level;
>  
>    /* A bit-vector of btrace_function_flag.  */
> -  enum btrace_function_flag flags;
> +  btrace_function_flags flags;
>  };
>  
>  /* A branch trace instruction iterator.  */
> @@ -245,6 +248,7 @@ enum btrace_thread_flag
>    /* The thread is to be stopped.  */
>    BTHR_STOP = (1 << 4)
>  };
> +DEF_ENUM_FLAGS_TYPE (enum btrace_thread_flag, btrace_thread_flags);
>  
>  #if defined (HAVE_LIBIPT)
>  /* A packet.  */
> @@ -342,7 +346,7 @@ struct btrace_thread_info
>    unsigned int ngaps;
>  
>    /* A bit-vector of btrace_thread_flag.  */
> -  enum btrace_thread_flag flags;
> +  btrace_thread_flags flags;
>  
>    /* The instruction history iterator.  */
>    struct btrace_insn_history *insn_history;
> diff --git a/gdb/c-exp.y b/gdb/c-exp.y
> index d093491..26050cb 100644
> --- a/gdb/c-exp.y
> +++ b/gdb/c-exp.y
> @@ -2257,7 +2257,7 @@ parse_string_or_char (const char *tokptr, const char **outptr,
>  
>  /* This is used to associate some attributes with a token.  */
>  
> -enum token_flags
> +enum token_flag
>  {
>    /* If this bit is set, the token is C++-only.  */
>  
> @@ -2269,13 +2269,14 @@ enum token_flags
>  
>    FLAG_SHADOW = 2
>  };
> +DEF_ENUM_FLAGS_TYPE (enum token_flag, token_flags);
>  
>  struct token
>  {
>    char *oper;
>    int token;
>    enum exp_opcode opcode;
> -  enum token_flags flags;
> +  token_flags flags;
>  };
>  
>  static const struct token tokentab3[] =
> diff --git a/gdb/common/enum_flags.h b/gdb/common/enum_flags.h
> new file mode 100644
> index 0000000..030fd2f
> --- /dev/null
> +++ b/gdb/common/enum_flags.h
> @@ -0,0 +1,211 @@
> +/* Copyright (C) 2015 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 COMMON_ENUM_FLAGS_H
> +#define COMMON_ENUM_FLAGS_H
> +
> +/* Type-safe wrapper for enum flags.  enum flags are enums where the
> +   values are bits that are meant to be ORed together.
> +
> +   This allows writing code like the below, while with raw enums this
> +   would fail to compile without casts to enum type at the assignments
> +   to 'f':
> +
> +    enum some_flag
> +    {
> +       flag_val1 = 1 << 1,
> +       flag_val2 = 1 << 2,
> +       flag_val3 = 1 << 3,
> +       flag_val4 = 1 << 4,
> +    };
> +    DEF_ENUM_FLAGS_TYPE(enum some_flag, some_flags)
> +
> +    some_flags f = flag_val1 | flag_val2;
> +    f |= flag_val3;
> +
> +   It's also possible to assign literal zero to an enum flags variable
> +   (meaning, no flags), dispensing adding an awkward explicit "no
> +   value" value to the enumeration.  For example:
> +
> +    some_flags f = 0;
> +    f |= flag_val3 | flag_val4;
> +
> +   Note that literal integers other than zero fail to compile:
> +
> +    some_flags f = 1; // error
> +*/
> +
> +#ifdef __cplusplus
> +
> +/* Traits type used to prevent the global operator overloads from
> +   instantiating for non-flag enums.  */
> +template<typename T> struct enum_flags_type {};
> +
> +/* Use this to mark an enum as flags enum.  It defines FLAGS as
> +   enum_flags wrapper class for ENUM, and enables the global operator
> +   overloads for ENUM.  */
> +#define DEF_ENUM_FLAGS_TYPE(enum_type, flags_type)	\
> +  typedef enum_flags<enum_type> flags_type;		\
> +  template<>						\
> +  struct enum_flags_type<enum_type>			\
> +  {							\
> +    typedef enum_flags<enum_type> type;			\
> +  }
> +
> +/* Until we can rely on std::underlying type being universally
> +   available (C++11), roll our own for enums.  */
> +template<int size, bool sign> class integer_for_size { typedef void type; };
> +template<> struct integer_for_size<1, 0> { typedef uint8_t type; };
> +template<> struct integer_for_size<2, 0> { typedef uint16_t type; };
> +template<> struct integer_for_size<4, 0> { typedef uint32_t type; };
> +template<> struct integer_for_size<8, 0> { typedef uint64_t type; };
> +template<> struct integer_for_size<1, 1> { typedef int8_t type; };
> +template<> struct integer_for_size<2, 1> { typedef int16_t type; };
> +template<> struct integer_for_size<4, 1> { typedef int32_t type; };
> +template<> struct integer_for_size<8, 1> { typedef int64_t type; };
> +
> +template<typename T>
> +struct enum_underlying_type
> +{
> +  typedef typename
> +    integer_for_size<sizeof (T), static_cast<bool>(T (-1) < T (0))>::type
> +    type;
> +};
> +
> +template <typename E>
> +class enum_flags
> +{
> +public:
> +  typedef E enum_type;
> +  typedef typename enum_underlying_type<enum_type>::type underlying_type;
> +
> +private:
> +  /* Private type used to support initializing flag types with zero:
> +
> +       foo_flags f = 0;
> +
> +     but not other integers:
> +
> +       foo_flags f = 1;
> +
> +     The way this works is that we define an implicit constructor that
> +     takes a pointer to this private type.  Since nothing can
> +     instantiate an object of this type, the only possible pointer to
> +     pass to the constructor is the NULL pointer, or, zero.  */
> +  struct zero_type;
> +
> +  underlying_type
> +  underlying_value () const
> +  {
> +    return enum_value;
> +  }
> +
> +public:
> +  /* Allow default construction, just like raw enums.  */
> +  enum_flags ()
> +  {}
> +
> +  enum_flags (const enum_flags &other)
> +    : enum_value (other.enum_value)
> +  {}
> +
> +  enum_flags &operator= (const enum_flags &other)
> +  {
> +    enum_value = other.enum_value;
> +    return *this;
> +  }
> +
> +  /* If you get an error saying these two overloads are ambiguous,
> +     then you tried to mix values of different enum types.  */
> +  enum_flags (enum_type e)
> +    : enum_value (e)
> +  {}
> +  enum_flags (struct enum_flags::zero_type *zero)
> +    : enum_value ((enum_type) 0)
> +  {}
> +
> +  enum_flags &operator&= (enum_type e)
> +  {
> +    enum_value = (enum_type) (underlying_value () & e);
> +    return *this;
> +  }
> +  enum_flags &operator|= (enum_type e)
> +  {
> +    enum_value = (enum_type) (underlying_value () | e);
> +    return *this;
> +  }
> +  enum_flags &operator^= (enum_type e)
> +  {
> +    enum_value = (enum_type) (underlying_value () ^ e);
> +    return *this;
> +  }
> +
> +  operator enum_type () const
> +  {
> +    return enum_value;
> +  }
> +
> +  enum_flags operator& (enum_type e) const
> +  {
> +    return (enum_type) (underlying_value () & e);
> +  }
> +  enum_flags operator| (enum_type e) const
> +  {
> +    return (enum_type) (underlying_value () | e);
> +  }
> +  enum_flags operator^ (enum_type e) const
> +  {
> +    return (enum_type) (underlying_value () ^ e);
> +  }
> +
> +  enum_flags operator~ () const
> +  {
> +    return (enum_type) ~underlying_value ();
> +  }
> +
> +private:
> +  /* Stored as enum_type because GDB knows to print the bit flags
> +     neatly if the enum values look like bit flags.  */
> +  enum_type enum_value;
> +};
> +
> +/* Global operator overloads.  */
> +
> +template <typename enum_type>
> +typename enum_flags_type<enum_type>::type
> +operator| (enum_type e1, enum_type e2)
> +{
> +  return enum_flags<enum_type> (e1) | e2;
> +}
> +
> +template <typename enum_type>
> +typename enum_flags_type<enum_type>::type
> +operator~ (enum_type e)
> +{
> +  return ~enum_flags<enum_type> (e);
> +}
> +
> +#else /* __cplusplus */
> +
> +/* In C, the flags type is just a typedef for the enum type.  */
> +
> +#define DEF_ENUM_FLAGS_TYPE(enum_type, flags_type) \
> +  typedef enum_type flags_type
> +
> +#endif /* __cplusplus */
> +
> +#endif /* COMMON_ENUM_FLAGS_H */
> diff --git a/gdb/compile/compile-c-types.c b/gdb/compile/compile-c-types.c
> index ccc9167..8dcb122 100644
> --- a/gdb/compile/compile-c-types.c
> +++ b/gdb/compile/compile-c-types.c
> @@ -293,7 +293,7 @@ convert_qualified (struct compile_c_instance *context, struct type *type)
>  {
>    struct type *unqual = make_unqualified_type (type);
>    gcc_type unqual_converted;
> -  int quals = 0;
> +  gcc_qualifiers_flags quals = 0;
>  
>    unqual_converted = convert_type (context, unqual);
>  
> diff --git a/gdb/compile/compile-internal.h b/gdb/compile/compile-internal.h
> index b1a5a88..8ee6dee 100644
> --- a/gdb/compile/compile-internal.h
> +++ b/gdb/compile/compile-internal.h
> @@ -19,6 +19,10 @@
>  
>  #include "hashtab.h"
>  #include "gcc-c-interface.h"
> +#include "common/enum_flags.h"
> +
> +/* enum-flags wrapper.  */
> +DEF_ENUM_FLAGS_TYPE (enum gcc_qualifiers, gcc_qualifiers_flags);
>  
>  /* Debugging flag for the "compile" family of commands.  */
>  
> diff --git a/gdb/completer.c b/gdb/completer.c
> index 210a078..bafcb50 100644
> --- a/gdb/completer.c
> +++ b/gdb/completer.c
> @@ -1149,11 +1149,12 @@ signal_completer (struct cmd_list_element *ignore,
>  /* Bit-flags for selecting what the register and/or register-group
>     completer should complete on.  */
>  
> -enum reg_completer_targets
> +enum reg_completer_target
>    {
>      complete_register_names = 0x1,
>      complete_reggroup_names = 0x2
>    };
> +DEF_ENUM_FLAGS_TYPE (enum reg_completer_target, reg_completer_targets);
>  
>  /* Complete register names and/or reggroup names based on the value passed
>     in TARGETS.  At least one bit in TARGETS must be set.  */
> @@ -1161,7 +1162,7 @@ enum reg_completer_targets
>  static VEC (char_ptr) *
>  reg_or_group_completer_1 (struct cmd_list_element *ignore,
>  			  const char *text, const char *word,
> -			  enum reg_completer_targets targets)
> +			  reg_completer_targets targets)
>  {
>    VEC (char_ptr) *result = NULL;
>    size_t len = strlen (word);
> diff --git a/gdb/disasm.c b/gdb/disasm.c
> index c17574e..e274f3a 100644
> --- a/gdb/disasm.c
> +++ b/gdb/disasm.c
> @@ -290,7 +290,7 @@ do_mixed_source_and_assembly_deprecated
>    int out_of_order = 0;
>    int next_line = 0;
>    int num_displayed = 0;
> -  enum print_source_lines_flags psl_flags = 0;
> +  print_source_lines_flags psl_flags = 0;
>    struct cleanup *ui_out_chain;
>    struct cleanup *ui_out_tuple_chain = make_cleanup (null_cleanup, 0);
>    struct cleanup *ui_out_list_chain = make_cleanup (null_cleanup, 0);
> @@ -451,7 +451,7 @@ do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
>    int out_of_order = 0;
>    int next_line = 0;
>    int num_displayed = 0;
> -  enum print_source_lines_flags psl_flags = 0;
> +  print_source_lines_flags psl_flags = 0;
>    struct cleanup *cleanups;
>    struct cleanup *ui_out_chain;
>    struct cleanup *ui_out_tuple_chain;
> diff --git a/gdb/infrun.c b/gdb/infrun.c
> index 917f9be..29e78e8 100644
> --- a/gdb/infrun.c
> +++ b/gdb/infrun.c
> @@ -63,6 +63,7 @@
>  #include "solist.h"
>  #include "event-loop.h"
>  #include "thread-fsm.h"
> +#include "common/enum_flags.h"
>  
>  /* Prototypes for local functions */
>  
> @@ -1269,7 +1270,7 @@ struct thread_info *step_over_queue_head;
>  
>  /* Bit flags indicating what the thread needs to step over.  */
>  
> -enum step_over_what
> +enum step_over_what_flag
>    {
>      /* Step over a breakpoint.  */
>      STEP_OVER_BREAKPOINT = 1,
> @@ -1279,6 +1280,7 @@ enum step_over_what
>         expression.  */
>      STEP_OVER_WATCHPOINT = 2
>    };
> +DEF_ENUM_FLAGS_TYPE (enum step_over_what_flag, step_over_what);
>  
>  /* Info about an instruction that is being stepped over.  */
>  
> @@ -2011,7 +2013,7 @@ reset_ecs (struct execution_control_state *ecs, struct thread_info *tp)
>  static void keep_going_pass_signal (struct execution_control_state *ecs);
>  static void prepare_to_wait (struct execution_control_state *ecs);
>  static int keep_going_stepped_thread (struct thread_info *tp);
> -static int thread_still_needs_step_over (struct thread_info *tp);
> +static step_over_what thread_still_needs_step_over (struct thread_info *tp);
>  static void stop_all_threads (void);
>  
>  /* Are there any pending step-over requests?  If so, run all we can
> @@ -2031,7 +2033,7 @@ start_step_over (void)
>      {
>        struct execution_control_state ecss;
>        struct execution_control_state *ecs = &ecss;
> -      enum step_over_what step_what;
> +      step_over_what step_what;
>        int must_be_in_line;
>  
>        next = thread_step_over_chain_next (tp);
> @@ -2881,11 +2883,11 @@ thread_still_needs_step_over_bp (struct thread_info *tp)
>     to make progress when resumed.  Returns an bitwise or of enum
>     step_over_what bits, indicating what needs to be stepped over.  */
>  
> -static int
> +static step_over_what
>  thread_still_needs_step_over (struct thread_info *tp)
>  {
>    struct inferior *inf = find_inferior_ptid (tp->ptid);
> -  int what = 0;
> +  step_over_what what = 0;
>  
>    if (thread_still_needs_step_over_bp (tp))
>      what |= STEP_OVER_BREAKPOINT;
> @@ -7536,7 +7538,7 @@ keep_going_pass_signal (struct execution_control_state *ecs)
>        struct regcache *regcache = get_current_regcache ();
>        int remove_bp;
>        int remove_wps;
> -      enum step_over_what step_what;
> +      step_over_what step_what;
>  
>        /* Either the trap was not expected, but we are continuing
>  	 anyway (if we got a signal, the user asked it be passed to
> diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
> index 7c24eaa..9282dd4 100644
> --- a/gdb/linux-tdep.c
> +++ b/gdb/linux-tdep.c
> @@ -37,6 +37,7 @@
>  #include "infcall.h"
>  #include "gdbcmd.h"
>  #include "gdb_regex.h"
> +#include "common/enum_flags.h"
>  
>  #include <ctype.h>
>  
> @@ -46,7 +47,7 @@
>     Documentation/filesystems/proc.txt, inside the Linux kernel
>     tree.  */
>  
> -enum filterflags
> +enum filter_flag
>    {
>      COREFILTER_ANON_PRIVATE = 1 << 0,
>      COREFILTER_ANON_SHARED = 1 << 1,
> @@ -56,6 +57,7 @@ enum filterflags
>      COREFILTER_HUGETLB_PRIVATE = 1 << 5,
>      COREFILTER_HUGETLB_SHARED = 1 << 6,
>    };
> +DEF_ENUM_FLAGS_TYPE (enum filter_flag, filter_flags);
>  
>  /* This struct is used to map flags found in the "VmFlags:" field (in
>     the /proc/<PID>/smaps file).  */
> @@ -599,7 +601,7 @@ mapping_is_anonymous_p (const char *filename)
>       This should work OK enough, however.  */
>  
>  static int
> -dump_mapping_p (enum filterflags filterflags, const struct smaps_vmflags *v,
> +dump_mapping_p (filter_flags filterflags, const struct smaps_vmflags *v,
>  		int maybe_private_p, int mapping_anon_p, int mapping_file_p,
>  		const char *filename)
>  {
> @@ -1120,10 +1122,10 @@ linux_find_memory_regions_full (struct gdbarch *gdbarch,
>    /* Default dump behavior of coredump_filter (0x33), according to
>       Documentation/filesystems/proc.txt from the Linux kernel
>       tree.  */
> -  enum filterflags filterflags = (COREFILTER_ANON_PRIVATE
> -				  | COREFILTER_ANON_SHARED
> -				  | COREFILTER_ELF_HEADERS
> -				  | COREFILTER_HUGETLB_PRIVATE);
> +  filter_flags filterflags = (COREFILTER_ANON_PRIVATE
> +			      | COREFILTER_ANON_SHARED
> +			      | COREFILTER_ELF_HEADERS
> +			      | COREFILTER_HUGETLB_PRIVATE);
>  
>    /* We need to know the real target PID to access /proc.  */
>    if (current_inferior ()->fake_pid_p)
> @@ -1139,7 +1141,10 @@ linux_find_memory_regions_full (struct gdbarch *gdbarch,
>  							coredumpfilter_name);
>        if (coredumpfilterdata != NULL)
>  	{
> -	  sscanf (coredumpfilterdata, "%x", &filterflags);
> +	  unsigned int flags;
> +
> +	  sscanf (coredumpfilterdata, "%x", &flags);
> +	  filterflags = (enum filter_flag) flags;
>  	  xfree (coredumpfilterdata);
>  	}
>      }
> diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
> index 3f068e2..c842d86 100644
> --- a/gdb/record-btrace.c
> +++ b/gdb/record-btrace.c
> @@ -888,11 +888,12 @@ btrace_call_history (struct ui_out *uiout,
>  		     const struct btrace_thread_info *btinfo,
>  		     const struct btrace_call_iterator *begin,
>  		     const struct btrace_call_iterator *end,
> -		     enum record_print_flag flags)
> +		     int int_flags)
>  {
>    struct btrace_call_iterator it;
> +  record_print_flags flags = (enum record_print_flag) int_flags;
>  
> -  DEBUG ("ftrace (0x%x): [%u; %u)", flags, btrace_call_number (begin),
> +  DEBUG ("ftrace (0x%x): [%u; %u)", int_flags, btrace_call_number (begin),
>  	 btrace_call_number (end));
>  
>    for (it = *begin; btrace_call_cmp (&it, end) < 0; btrace_call_next (&it, 1))
> @@ -958,7 +959,7 @@ btrace_call_history (struct ui_out *uiout,
>  /* The to_call_history method of target record-btrace.  */
>  
>  static void
> -record_btrace_call_history (struct target_ops *self, int size, int flags)
> +record_btrace_call_history (struct target_ops *self, int size, int int_flags)
>  {
>    struct btrace_thread_info *btinfo;
>    struct btrace_call_history *history;
> @@ -966,6 +967,7 @@ record_btrace_call_history (struct target_ops *self, int size, int flags)
>    struct cleanup *uiout_cleanup;
>    struct ui_out *uiout;
>    unsigned int context, covered;
> +  record_print_flags flags = (enum record_print_flag) int_flags;
>  
>    uiout = current_uiout;
>    uiout_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout,
> @@ -980,7 +982,7 @@ record_btrace_call_history (struct target_ops *self, int size, int flags)
>      {
>        struct btrace_insn_iterator *replay;
>  
> -      DEBUG ("call-history (0x%x): %d", flags, size);
> +      DEBUG ("call-history (0x%x): %d", int_flags, size);
>  
>        /* If we're replaying, we start at the replay position.  Otherwise, we
>  	 start at the tail of the trace.  */
> @@ -1015,7 +1017,7 @@ record_btrace_call_history (struct target_ops *self, int size, int flags)
>        begin = history->begin;
>        end = history->end;
>  
> -      DEBUG ("call-history (0x%x): %d, prev: [%u; %u)", flags, size,
> +      DEBUG ("call-history (0x%x): %d, prev: [%u; %u)", int_flags, size,
>  	     btrace_call_number (&begin), btrace_call_number (&end));
>  
>        if (size < 0)
> @@ -1048,7 +1050,8 @@ record_btrace_call_history (struct target_ops *self, int size, int flags)
>  
>  static void
>  record_btrace_call_history_range (struct target_ops *self,
> -				  ULONGEST from, ULONGEST to, int flags)
> +				  ULONGEST from, ULONGEST to,
> +				  int int_flags)
>  {
>    struct btrace_thread_info *btinfo;
>    struct btrace_call_history *history;
> @@ -1057,6 +1060,7 @@ record_btrace_call_history_range (struct target_ops *self,
>    struct ui_out *uiout;
>    unsigned int low, high;
>    int found;
> +  record_print_flags flags = (enum record_print_flag) int_flags;
>  
>    uiout = current_uiout;
>    uiout_cleanup = make_cleanup_ui_out_tuple_begin_end (uiout,
> @@ -1064,7 +1068,7 @@ record_btrace_call_history_range (struct target_ops *self,
>    low = from;
>    high = to;
>  
> -  DEBUG ("call-history (0x%x): [%u; %u)", flags, low, high);
> +  DEBUG ("call-history (0x%x): [%u; %u)", int_flags, low, high);
>  
>    /* Check for wrap-arounds.  */
>    if (low != from || high != to)
> @@ -1101,9 +1105,11 @@ record_btrace_call_history_range (struct target_ops *self,
>  
>  static void
>  record_btrace_call_history_from (struct target_ops *self,
> -				 ULONGEST from, int size, int flags)
> +				 ULONGEST from, int size,
> +				 int int_flags)
>  {
>    ULONGEST begin, end, context;
> +  record_print_flags flags = (enum record_print_flag) int_flags;
>  
>    context = abs (size);
>    if (context == 0)
> diff --git a/gdb/record.h b/gdb/record.h
> index 101daae..bacde38 100644
> --- a/gdb/record.h
> +++ b/gdb/record.h
> @@ -21,6 +21,7 @@
>  #define _RECORD_H_
>  
>  #include "target/waitstatus.h" /* For enum target_stop_reason.  */
> +#include "common/enum_flags.h"
>  
>  struct cmd_list_element;
>  
> @@ -48,6 +49,7 @@ enum record_print_flag
>    /* Indent based on call stack depth (if applicable).  */
>    RECORD_PRINT_INDENT_CALLS = (1 << 2)
>  };
> +DEF_ENUM_FLAGS_TYPE (enum record_print_flag, record_print_flags);
>  
>  /* Determined whether the target is stopped at a software or hardware
>     breakpoint, based on PC and the breakpoint tables.  The breakpoint
> diff --git a/gdb/source.c b/gdb/source.c
> index 194b044..8687747 100644
> --- a/gdb/source.c
> +++ b/gdb/source.c
> @@ -42,6 +42,7 @@
>  #include "completer.h"
>  #include "ui-out.h"
>  #include "readline/readline.h"
> +#include "common/enum_flags.h"
>  
>  #define OPEN_MODE (O_RDONLY | O_BINARY)
>  #define FDOPEN_MODE FOPEN_RB
> @@ -1327,7 +1328,7 @@ identify_source_line (struct symtab *s, int line, int mid_statement,
>  
>  static void
>  print_source_lines_base (struct symtab *s, int line, int stopline,
> -			 enum print_source_lines_flags flags)
> +			 print_source_lines_flags flags)
>  {
>    int c;
>    int desc;
> @@ -1361,7 +1362,7 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
>    else
>      {
>        desc = last_source_error;
> -	  flags |= PRINT_SOURCE_LINES_NOERROR;
> +      flags |= PRINT_SOURCE_LINES_NOERROR;
>        noprint = 1;
>      }
>  
> @@ -1487,7 +1488,7 @@ print_source_lines_base (struct symtab *s, int line, int stopline,
>  
>  void
>  print_source_lines (struct symtab *s, int line, int stopline,
> -		    enum print_source_lines_flags flags)
> +		    print_source_lines_flags flags)
>  {
>    print_source_lines_base (s, line, stopline, flags);
>  }
> diff --git a/gdb/symtab.h b/gdb/symtab.h
> index 477befd..ffd8bdd 100644
> --- a/gdb/symtab.h
> +++ b/gdb/symtab.h
> @@ -23,6 +23,7 @@
>  #include "vec.h"
>  #include "gdb_vecs.h"
>  #include "gdbtypes.h"
> +#include "common/enum_flags.h"
>  
>  /* Opaque declarations.  */
>  struct ui_file;
> @@ -1470,7 +1471,7 @@ extern int identify_source_line (struct symtab *, int, int, CORE_ADDR);
>  
>  /* Flags passed as 4th argument to print_source_lines.  */
>  
> -enum print_source_lines_flags
> +enum print_source_lines_flag
>    {
>      /* Do not print an error message.  */
>      PRINT_SOURCE_LINES_NOERROR = (1 << 0),
> @@ -1478,9 +1479,10 @@ enum print_source_lines_flags
>      /* Print the filename in front of the source lines.  */
>      PRINT_SOURCE_LINES_FILENAME = (1 << 1)
>    };
> +DEF_ENUM_FLAGS_TYPE (enum print_source_lines_flag, print_source_lines_flags);
>  
>  extern void print_source_lines (struct symtab *, int, int,
> -				enum print_source_lines_flags);
> +				print_source_lines_flags);
>  
>  extern void forget_cached_source_info_for_objfile (struct objfile *);
>  extern void forget_cached_source_info (void);

Btw, this patch looks good to me, although I don't understand completely all the
C++ template magic.  At least the complexity is completely hidden, so it's very easy
to use, and the error messages I got when messing up where surprisingly easy to
understand for C++!


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]