+2015-11-17 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_print_lines): Change type of local
+ 'psl_flags'.
+ (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.
+
2015-11-17 Pedro Alves <palves@redhat.com>
* guile/scm-disasm.c (gdbscm_disasm_read_memory): Return -1 on
#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>
/* 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.
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. */
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
int level;
/* A bit-vector of btrace_function_flag. */
- enum btrace_function_flag flags;
+ btrace_function_flags flags;
};
/* A branch trace instruction iterator. */
/* 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. */
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;
/* 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. */
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[] =
--- /dev/null
+/* 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 m_enum_value;
+ }
+
+public:
+ /* Allow default construction, just like raw enums. */
+ enum_flags ()
+ {}
+
+ enum_flags (const enum_flags &other)
+ : m_enum_value (other.m_enum_value)
+ {}
+
+ enum_flags &operator= (const enum_flags &other)
+ {
+ m_enum_value = other.m_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)
+ : m_enum_value (e)
+ {}
+ enum_flags (struct enum_flags::zero_type *zero)
+ : m_enum_value ((enum_type) 0)
+ {}
+
+ enum_flags &operator&= (enum_type e)
+ {
+ m_enum_value = (enum_type) (underlying_value () & e);
+ return *this;
+ }
+ enum_flags &operator|= (enum_type e)
+ {
+ m_enum_value = (enum_type) (underlying_value () | e);
+ return *this;
+ }
+ enum_flags &operator^= (enum_type e)
+ {
+ m_enum_value = (enum_type) (underlying_value () ^ e);
+ return *this;
+ }
+
+ operator enum_type () const
+ {
+ return m_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 m_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 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 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 */
{
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);
#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. */
/* 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. */
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);
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);
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;
#include "solist.h"
#include "event-loop.h"
#include "thread-fsm.h"
+#include "common/enum-flags.h"
/* Prototypes for local functions */
/* 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,
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. */
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
{
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);
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;
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
#include "infcall.h"
#include "gdbcmd.h"
#include "gdb_regex.h"
+#include "common/enum-flags.h"
#include <ctype.h>
Documentation/filesystems/proc.txt, inside the Linux kernel
tree. */
-enum filterflags
+enum filter_flag
{
COREFILTER_ANON_PRIVATE = 1 << 0,
COREFILTER_ANON_SHARED = 1 << 1,
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). */
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)
{
/* 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)
coredumpfilter_name);
if (coredumpfilterdata != NULL)
{
- sscanf (coredumpfilterdata, "%x", &filterflags);
+ unsigned int flags;
+
+ sscanf (coredumpfilterdata, "%x", &flags);
+ filterflags = (enum filter_flag) flags;
xfree (coredumpfilterdata);
}
}
btrace_print_lines (struct btrace_line_range lines, struct ui_out *uiout,
struct cleanup **ui_item_chain, int flags)
{
- enum print_source_lines_flags psl_flags;
+ print_source_lines_flags psl_flags;
int line;
psl_flags = 0;
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))
/* 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;
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,
{
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. */
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)
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;
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,
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)
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)
#define _RECORD_H_
#include "target/waitstatus.h" /* For enum target_stop_reason. */
+#include "common/enum-flags.h"
struct cmd_list_element;
/* 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
#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
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;
else
{
desc = last_source_error;
- flags |= PRINT_SOURCE_LINES_NOERROR;
+ flags |= PRINT_SOURCE_LINES_NOERROR;
noprint = 1;
}
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);
}
#include "vec.h"
#include "gdb_vecs.h"
#include "gdbtypes.h"
+#include "common/enum-flags.h"
/* Opaque declarations. */
struct ui_file;
/* 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),
/* 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);