C++ compile support
This patch adds *basic* support for C++ to the compile feature. It does most simple type conversions, including everything that C compile does and your basic "with-classes" type of C++. I've written a new compile-support.exp support file which adds a new test facility for automating and simplifying "compile print" vs "compile code" testing. See testsuite/lib/compile-support.exp and CompileExpression for more on that. The tests use this facility extensively. This initial support has several glaring omissions: - No template support at all I have follow-on patches for this, but they add much complexity to this "basic" support. Consequently, they will be submitted separately. - Cannot print functions The code template needs tweaking, and I simply haven't gotten to it yet. - So-called "special function" support is not included Using constructors, destructors, operators, etc will not work. I have follow-on patches for that, but they require some work because of the recent churn in symbol searching. - There are several test suite references to "compile/1234" bugs. I will file bugs and update the test suite's bug references before pushing these patches. The test suite started as a copy of the original C-language support, but I have written tests to exercise the basic functionality of the plug-in. I've added a new option for outputting debug messages for C++ type-conversion ("debug compile-cplus-types"). gdb/ChangeLog: * Makefile.in (SUBDIR_GCC_COMPILE_SRCS): Add compile-cplus-symbols.c and compile-cplus-types.c. (HFILES_NO_SRCDIR): Add gcc-cp-plugin.h. * c-lang.c (cplus_language_defn): Set C++ compile functions. * c-lang.h (cplus_get_compile_context, cplus_compute_program): Declare. * compile/compile-c-support.c: Include compile-cplus.h. (load_libcompile): Templatize. (get_compile_context): "New" function. (c_get_compile_context): Use get_compile_context. (cplus_get_compile_context): New function. (cplus_push_user_expression, cplus_pop_user_expression) (cplus_add_code_header, cplus_add_input, cplus_compile_program) (cplus_compute_program): Define new structs/functions. * compile/compile-cplus-symmbols.c: New file. * compile/compile-cplus-types.c: New file. * compile/compile-cplus.h: New file. * compile/compile-internal.h (debug_compile_oracle, GCC_TYPE_NONE): Declare. * compile/compile-object-load.c (get_out_value_type): Use strncmp_iw when comparing symbol names. (compile_object_load): Add mst_bss and mst_data. * compile/compile.c (_initialize_compile): Remove -Wno-implicit-function-declaration from `compile_args'. * compile/gcc-cp-plugin.h: New file. * NEWS: Mention C++ compile support and new debug options. gdb/testsuite/ChangeLog: * gdb.compile/compile-cplus-anonymous.cc: New file. * gdb.compile/compile-cplus-anonymous.exp: New file. * gdb.compile/compile-cplus-array-decay.cc: New file. * gdb.compile/compile-cplus-array-decay.exp: New file. * gdb.compile/compile-cplus-inherit.cc: New file. * gdb.compile/compile-cplus-inherit.exp: New file. * gdb.compile/compile-cplus-member.cc: New file. * gdb.compile/compile-cplus-member.exp: New file. * gdb.compile/compile-cplus-method.cc: New file. * gdb.compile/compile-cplus-method.exp: New file. * gdb.compile/compile-cplus-mod.c: "New" file. * gdb.compile/compile-cplus-namespace.cc: New file. * gdb.compile/compile-cplus-namespace.exp: New file. * gdb.compile/compile-cplus-nested.cc: New file. * gdb.compile/compile-cplus-nested.exp: New file. * gdb.compile/compile-cplus-print.c: "New" file. * gdb.compile/compile-cplus-print.exp: "New" file. * gdb.compile/compile-cplus-virtual.cc: New file. * gdb.compile/compile-cplus-virtual.exp: New file. * gdb.compile/compile-cplus.c: "New" file. * gdb.compile/compile-cplus.exp: "New" file. * lib/compile-support.exp: New file. doc/ChangeLog: * gdb.texinfo (Compiling and injecting code in GDB): Document set/show "compile-oracle" and "compile-cplus-types" commands.
This commit is contained in:
parent
fcaad03cc0
commit
078a020797
38 changed files with 4449 additions and 30 deletions
|
@ -1,3 +1,32 @@
|
||||||
|
2018-08-29 Keith Seitz <keiths@redhat.com>
|
||||||
|
|
||||||
|
* Makefile.in (SUBDIR_GCC_COMPILE_SRCS): Add compile-cplus-symbols.c
|
||||||
|
and compile-cplus-types.c.
|
||||||
|
(HFILES_NO_SRCDIR): Add gcc-cp-plugin.h.
|
||||||
|
* c-lang.c (cplus_language_defn): Set C++ compile functions.
|
||||||
|
* c-lang.h (cplus_get_compile_context, cplus_compute_program):
|
||||||
|
Declare.
|
||||||
|
* compile/compile-c-support.c: Include compile-cplus.h.
|
||||||
|
(load_libcompile): Templatize.
|
||||||
|
(get_compile_context): "New" function.
|
||||||
|
(c_get_compile_context): Use get_compile_context.
|
||||||
|
(cplus_get_compile_context): New function.
|
||||||
|
(cplus_push_user_expression, cplus_pop_user_expression)
|
||||||
|
(cplus_add_code_header, cplus_add_input, cplus_compile_program)
|
||||||
|
(cplus_compute_program): Define new structs/functions.
|
||||||
|
* compile/compile-cplus-symmbols.c: New file.
|
||||||
|
* compile/compile-cplus-types.c: New file.
|
||||||
|
* compile/compile-cplus.h: New file.
|
||||||
|
* compile/compile-internal.h (debug_compile_oracle, GCC_TYPE_NONE):
|
||||||
|
Declare.
|
||||||
|
* compile/compile-object-load.c (get_out_value_type): Use
|
||||||
|
strncmp_iw when comparing symbol names.
|
||||||
|
(compile_object_load): Add mst_bss and mst_data.
|
||||||
|
* compile/compile.c (_initialize_compile): Remove
|
||||||
|
-Wno-implicit-function-declaration from `compile_args'.
|
||||||
|
* compile/gcc-cp-plugin.h: New file.
|
||||||
|
* NEWS: Mention C++ compile support and new debug options.
|
||||||
|
|
||||||
2018-08-29 Keith Seitz <keiths@redhat.com>
|
2018-08-29 Keith Seitz <keiths@redhat.com>
|
||||||
|
|
||||||
* linespec.c (collect_info::add_symbol): Make virtual.
|
* linespec.c (collect_info::add_symbol): Make virtual.
|
||||||
|
|
|
@ -317,6 +317,8 @@ SUBDIR_GCC_COMPILE_SRCS = \
|
||||||
compile/compile-c-support.c \
|
compile/compile-c-support.c \
|
||||||
compile/compile-c-symbols.c \
|
compile/compile-c-symbols.c \
|
||||||
compile/compile-c-types.c \
|
compile/compile-c-types.c \
|
||||||
|
compile/compile-cplus-symbols.c \
|
||||||
|
compile/compile-cplus-types.c \
|
||||||
compile/compile-loc2c.c \
|
compile/compile-loc2c.c \
|
||||||
compile/compile-object-load.c \
|
compile/compile-object-load.c \
|
||||||
compile/compile-object-run.c
|
compile/compile-object-run.c
|
||||||
|
@ -1464,10 +1466,12 @@ HFILES_NO_SRCDIR = \
|
||||||
common/xml-utils.h \
|
common/xml-utils.h \
|
||||||
compile/compile.h \
|
compile/compile.h \
|
||||||
compile/compile-c.h \
|
compile/compile-c.h \
|
||||||
|
compile/compile-cplus.h \
|
||||||
compile/compile-internal.h \
|
compile/compile-internal.h \
|
||||||
compile/compile-object-load.h \
|
compile/compile-object-load.h \
|
||||||
compile/compile-object-run.h \
|
compile/compile-object-run.h \
|
||||||
compile/gcc-c-plugin.h \
|
compile/gcc-c-plugin.h \
|
||||||
|
compile/gcc-cp-plugin.h \
|
||||||
config/nm-linux.h \
|
config/nm-linux.h \
|
||||||
config/nm-nto.h \
|
config/nm-nto.h \
|
||||||
config/djgpp/langinfo.h \
|
config/djgpp/langinfo.h \
|
||||||
|
|
14
gdb/NEWS
14
gdb/NEWS
|
@ -3,6 +3,14 @@
|
||||||
|
|
||||||
*** Changes since GDB 8.2
|
*** Changes since GDB 8.2
|
||||||
|
|
||||||
|
* GDB now has experimental support for the compilation and injection of
|
||||||
|
C++ source code into the inferior. This beta release does not include
|
||||||
|
support for several language features, such as templates, constructors,
|
||||||
|
and operators.
|
||||||
|
|
||||||
|
This feature requires GCC 7.1 or higher built with libcp1.so
|
||||||
|
(the C++ plug-in).
|
||||||
|
|
||||||
* GDB and GDBserver now support IPv6 connections. IPv6 addresses
|
* GDB and GDBserver now support IPv6 connections. IPv6 addresses
|
||||||
can be passed using the '[ADDRESS]:PORT' notation, or the regular
|
can be passed using the '[ADDRESS]:PORT' notation, or the regular
|
||||||
'ADDRESS:PORT' method.
|
'ADDRESS:PORT' method.
|
||||||
|
@ -15,6 +23,12 @@
|
||||||
|
|
||||||
* New commands
|
* New commands
|
||||||
|
|
||||||
|
set debug compile-cplus-types
|
||||||
|
show debug compile-cplus-types
|
||||||
|
Control the display of debug output about type conversion in the
|
||||||
|
C++ compile feature. Commands have no effect while compiliong
|
||||||
|
for other languages.
|
||||||
|
|
||||||
frame apply [all | COUNT | -COUNT | level LEVEL...] [FLAG]... COMMAND
|
frame apply [all | COUNT | -COUNT | level LEVEL...] [FLAG]... COMMAND
|
||||||
Apply a command to some frames.
|
Apply a command to some frames.
|
||||||
FLAG arguments allow to control what output to produce and how to handle
|
FLAG arguments allow to control what output to produce and how to handle
|
||||||
|
|
|
@ -1017,8 +1017,8 @@ extern const struct language_defn cplus_language_defn =
|
||||||
iterate_over_symbols,
|
iterate_over_symbols,
|
||||||
cp_search_name_hash,
|
cp_search_name_hash,
|
||||||
&cplus_varobj_ops,
|
&cplus_varobj_ops,
|
||||||
NULL,
|
cplus_get_compile_context,
|
||||||
NULL,
|
cplus_compute_program,
|
||||||
LANG_MAGIC
|
LANG_MAGIC
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
19
gdb/c-lang.h
19
gdb/c-lang.h
|
@ -160,6 +160,14 @@ extern int c_textual_element_type (struct type *, char);
|
||||||
|
|
||||||
extern compile_instance *c_get_compile_context (void);
|
extern compile_instance *c_get_compile_context (void);
|
||||||
|
|
||||||
|
/* Create a new instance of the C++ compiler and return it. The new
|
||||||
|
compiler is owned by the caller and must be freed using the destroy
|
||||||
|
method. This function never returns NULL, but rather throws an
|
||||||
|
exception on failure. This is suitable for use as the
|
||||||
|
la_get_compile_instance language method. */
|
||||||
|
|
||||||
|
extern compile_instance *cplus_get_compile_context ();
|
||||||
|
|
||||||
/* This takes the user-supplied text and returns a new bit of code to
|
/* This takes the user-supplied text and returns a new bit of code to
|
||||||
compile.
|
compile.
|
||||||
|
|
||||||
|
@ -172,4 +180,15 @@ extern std::string c_compute_program (compile_instance *inst,
|
||||||
const struct block *expr_block,
|
const struct block *expr_block,
|
||||||
CORE_ADDR expr_pc);
|
CORE_ADDR expr_pc);
|
||||||
|
|
||||||
|
/* This takes the user-supplied text and returns a new bit of code to compile.
|
||||||
|
|
||||||
|
This is used as the la_compute_program language method; see that
|
||||||
|
for a description of the arguments. */
|
||||||
|
|
||||||
|
extern std::string cplus_compute_program (compile_instance *inst,
|
||||||
|
const char *input,
|
||||||
|
struct gdbarch *gdbarch,
|
||||||
|
const struct block *expr_block,
|
||||||
|
CORE_ADDR expr_pc);
|
||||||
|
|
||||||
#endif /* !defined (C_LANG_H) */
|
#endif /* !defined (C_LANG_H) */
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* C language support for compilation.
|
/* C/C++ language support for compilation.
|
||||||
|
|
||||||
Copyright (C) 2014-2018 Free Software Foundation, Inc.
|
Copyright (C) 2014-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "compile-internal.h"
|
#include "compile-internal.h"
|
||||||
#include "compile-c.h"
|
#include "compile-c.h"
|
||||||
|
#include "compile-cplus.h"
|
||||||
#include "compile.h"
|
#include "compile.h"
|
||||||
#include "gdb-dlfcn.h"
|
#include "gdb-dlfcn.h"
|
||||||
#include "c-lang.h"
|
#include "c-lang.h"
|
||||||
|
@ -67,25 +68,22 @@ c_get_range_decl_name (const struct dynamic_prop *prop)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Helper function for c_get_compile_context. Open the GCC front-end
|
/* Load the plug-in library FE_LIBCC and return the initialization function
|
||||||
shared library and return the symbol specified by the current
|
FE_CONTEXT. */
|
||||||
GCC_C_FE_CONTEXT. */
|
|
||||||
|
|
||||||
static gcc_c_fe_context_function *
|
template <typename FUNCTYPE>
|
||||||
load_libcc (void)
|
FUNCTYPE *
|
||||||
|
load_libcompile (const char *fe_libcc, const char *fe_context)
|
||||||
{
|
{
|
||||||
gcc_c_fe_context_function *func;
|
FUNCTYPE *func;
|
||||||
|
|
||||||
/* gdb_dlopen will call error () on an error, so no need to check
|
/* gdb_dlopen will call error () on an error, so no need to check
|
||||||
value. */
|
value. */
|
||||||
gdb_dlhandle_up handle = gdb_dlopen (STRINGIFY (GCC_C_FE_LIBCC));
|
gdb_dlhandle_up handle = gdb_dlopen (fe_libcc);
|
||||||
func = (gcc_c_fe_context_function *) gdb_dlsym (handle,
|
func = (FUNCTYPE *) gdb_dlsym (handle, fe_context);
|
||||||
STRINGIFY (GCC_C_FE_CONTEXT));
|
|
||||||
|
|
||||||
if (func == NULL)
|
if (func == NULL)
|
||||||
error (_("could not find symbol %s in library %s"),
|
error (_("could not find symbol %s in library %s"), fe_context, fe_libcc);
|
||||||
STRINGIFY (GCC_C_FE_CONTEXT),
|
|
||||||
STRINGIFY (GCC_C_FE_LIBCC));
|
|
||||||
|
|
||||||
/* Leave the library open. */
|
/* Leave the library open. */
|
||||||
handle.release ();
|
handle.release ();
|
||||||
|
@ -93,28 +91,57 @@ load_libcc (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the compile instance associated with the current context.
|
/* Return the compile instance associated with the current context.
|
||||||
This function calls the symbol returned from the load_libcc
|
This function calls the symbol returned from the load_libcompile
|
||||||
function. This will provide the gcc_c_context. */
|
function. FE_LIBCC is the library to load. BASE_VERSION is the
|
||||||
|
base compile plug-in version we support. API_VERSION is the
|
||||||
|
API version supported. */
|
||||||
|
|
||||||
|
template <typename INSTTYPE, typename FUNCTYPE, typename CTXTYPE,
|
||||||
|
typename BASE_VERSION_TYPE, typename API_VERSION_TYPE>
|
||||||
compile_instance *
|
compile_instance *
|
||||||
c_get_compile_context (void)
|
get_compile_context (const char *fe_libcc, const char *fe_context,
|
||||||
|
BASE_VERSION_TYPE base_version,
|
||||||
|
API_VERSION_TYPE api_version)
|
||||||
{
|
{
|
||||||
static gcc_c_fe_context_function *func;
|
static FUNCTYPE *func;
|
||||||
|
static CTXTYPE *context;
|
||||||
struct gcc_c_context *context;
|
|
||||||
|
|
||||||
if (func == NULL)
|
if (func == NULL)
|
||||||
{
|
{
|
||||||
func = load_libcc ();
|
func = load_libcompile<FUNCTYPE> (fe_libcc, fe_context);
|
||||||
gdb_assert (func != NULL);
|
gdb_assert (func != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
context = (*func) (GCC_FE_VERSION_0, GCC_C_FE_VERSION_0);
|
context = (*func) (base_version, api_version);
|
||||||
if (context == NULL)
|
if (context == NULL)
|
||||||
error (_("The loaded version of GCC does not support the required version "
|
error (_("The loaded version of GCC does not support the required version "
|
||||||
"of the API."));
|
"of the API."));
|
||||||
|
|
||||||
return new compile_c_instance (context);
|
return new INSTTYPE (context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A C-language implementation of get_compile_context. */
|
||||||
|
|
||||||
|
compile_instance *
|
||||||
|
c_get_compile_context ()
|
||||||
|
{
|
||||||
|
return get_compile_context
|
||||||
|
<compile_c_instance, gcc_c_fe_context_function, gcc_c_context,
|
||||||
|
gcc_base_api_version, gcc_c_api_version>
|
||||||
|
(STRINGIFY (GCC_C_FE_LIBCC), STRINGIFY (GCC_C_FE_CONTEXT),
|
||||||
|
GCC_FE_VERSION_0, GCC_C_FE_VERSION_0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A C++-language implementation of get_compile_context. */
|
||||||
|
|
||||||
|
compile_instance *
|
||||||
|
cplus_get_compile_context ()
|
||||||
|
{
|
||||||
|
return get_compile_context
|
||||||
|
<compile_cplus_instance, gcc_cp_fe_context_function, gcc_cp_context,
|
||||||
|
gcc_base_api_version, gcc_cp_api_version>
|
||||||
|
(STRINGIFY (GCC_CP_FE_LIBCC), STRINGIFY (GCC_CP_FE_CONTEXT),
|
||||||
|
GCC_FE_VERSION_0, GCC_CP_FE_VERSION_0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -384,6 +411,113 @@ struct c_add_input
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* C++-language policy to emit a push user expression pragma into
|
||||||
|
BUF. */
|
||||||
|
|
||||||
|
struct cplus_push_user_expression
|
||||||
|
{
|
||||||
|
void push_user_expression (struct ui_file *buf)
|
||||||
|
{
|
||||||
|
fputs_unfiltered ("#pragma GCC push_user_expression\n", buf);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* C++-language policy to emit a pop user expression pragma into BUF. */
|
||||||
|
|
||||||
|
struct cplus_pop_user_expression
|
||||||
|
{
|
||||||
|
void pop_user_expression (struct ui_file *buf)
|
||||||
|
{
|
||||||
|
fputs_unfiltered ("#pragma GCC pop_user_expression\n", buf);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* C++-language policy to construct a code header for a block of code.
|
||||||
|
Takes a scope TYPE argument which selects the correct header to
|
||||||
|
insert into BUF. */
|
||||||
|
|
||||||
|
struct cplus_add_code_header
|
||||||
|
{
|
||||||
|
void add_code_header (enum compile_i_scope_types type, struct ui_file *buf)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case COMPILE_I_SIMPLE_SCOPE:
|
||||||
|
fputs_unfiltered ("void "
|
||||||
|
GCC_FE_WRAPPER_FUNCTION
|
||||||
|
" (struct "
|
||||||
|
COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG
|
||||||
|
" *"
|
||||||
|
COMPILE_I_SIMPLE_REGISTER_ARG_NAME
|
||||||
|
") {\n",
|
||||||
|
buf);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case COMPILE_I_PRINT_ADDRESS_SCOPE:
|
||||||
|
case COMPILE_I_PRINT_VALUE_SCOPE:
|
||||||
|
fputs_unfiltered (
|
||||||
|
"#include <cstring>\n"
|
||||||
|
"#include <bits/move.h>\n"
|
||||||
|
"void "
|
||||||
|
GCC_FE_WRAPPER_FUNCTION
|
||||||
|
" (struct "
|
||||||
|
COMPILE_I_SIMPLE_REGISTER_STRUCT_TAG
|
||||||
|
" *"
|
||||||
|
COMPILE_I_SIMPLE_REGISTER_ARG_NAME
|
||||||
|
", "
|
||||||
|
COMPILE_I_PRINT_OUT_ARG_TYPE
|
||||||
|
" "
|
||||||
|
COMPILE_I_PRINT_OUT_ARG
|
||||||
|
") {\n",
|
||||||
|
buf);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case COMPILE_I_RAW_SCOPE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
gdb_assert_not_reached (_("Unknown compiler scope reached."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* C++-language policy to emit the user code snippet INPUT into BUF based on
|
||||||
|
the scope TYPE. */
|
||||||
|
|
||||||
|
struct cplus_add_input
|
||||||
|
{
|
||||||
|
void add_input (enum compile_i_scope_types type, const char *input,
|
||||||
|
struct ui_file *buf)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case COMPILE_I_PRINT_VALUE_SCOPE:
|
||||||
|
case COMPILE_I_PRINT_ADDRESS_SCOPE:
|
||||||
|
fprintf_unfiltered
|
||||||
|
(buf,
|
||||||
|
/* "auto" strips ref- and cv- qualifiers, so we need to also strip
|
||||||
|
those from COMPILE_I_EXPR_PTR_TYPE. */
|
||||||
|
"auto " COMPILE_I_EXPR_VAL " = %s;\n"
|
||||||
|
"typedef "
|
||||||
|
"std::add_pointer<std::remove_cv<decltype (%s)>::type>::type "
|
||||||
|
" __gdb_expr_ptr;\n"
|
||||||
|
"__gdb_expr_ptr " COMPILE_I_EXPR_PTR_TYPE ";\n"
|
||||||
|
"std::memcpy (" COMPILE_I_PRINT_OUT_ARG ", %s ("
|
||||||
|
COMPILE_I_EXPR_VAL "),\n"
|
||||||
|
"\tsizeof (*" COMPILE_I_EXPR_PTR_TYPE "));\n"
|
||||||
|
,input, input,
|
||||||
|
(type == COMPILE_I_PRINT_ADDRESS_SCOPE
|
||||||
|
? "__builtin_addressof" : ""));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
fputs_unfiltered (input, buf);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fputs_unfiltered ("\n", buf);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/* A host class representing a compile program.
|
/* A host class representing a compile program.
|
||||||
|
|
||||||
CompileInstanceType is the type of the compile_instance for the
|
CompileInstanceType is the type of the compile_instance for the
|
||||||
|
@ -513,13 +647,18 @@ private:
|
||||||
struct gdbarch *m_arch;
|
struct gdbarch *m_arch;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Type used for C program computations. */
|
/* The types used for C and C++ program computations. */
|
||||||
|
|
||||||
typedef compile_program<compile_c_instance,
|
typedef compile_program<compile_c_instance,
|
||||||
c_push_user_expression, pop_user_expression_nop,
|
c_push_user_expression, pop_user_expression_nop,
|
||||||
c_add_code_header, c_add_code_footer,
|
c_add_code_header, c_add_code_footer,
|
||||||
c_add_input> c_compile_program;
|
c_add_input> c_compile_program;
|
||||||
|
|
||||||
|
typedef compile_program<compile_cplus_instance,
|
||||||
|
cplus_push_user_expression, cplus_pop_user_expression,
|
||||||
|
cplus_add_code_header, c_add_code_footer,
|
||||||
|
cplus_add_input> cplus_compile_program;
|
||||||
|
|
||||||
/* The la_compute_program method for C. */
|
/* The la_compute_program method for C. */
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
|
@ -534,3 +673,19 @@ c_compute_program (compile_instance *inst,
|
||||||
|
|
||||||
return program.compute (input, expr_block, expr_pc);
|
return program.compute (input, expr_block, expr_pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The la_compute_program method for C++. */
|
||||||
|
|
||||||
|
std::string
|
||||||
|
cplus_compute_program (compile_instance *inst,
|
||||||
|
const char *input,
|
||||||
|
struct gdbarch *gdbarch,
|
||||||
|
const struct block *expr_block,
|
||||||
|
CORE_ADDR expr_pc)
|
||||||
|
{
|
||||||
|
compile_cplus_instance *cplus_inst
|
||||||
|
= static_cast<compile_cplus_instance *> (inst);
|
||||||
|
cplus_compile_program program (cplus_inst, gdbarch);
|
||||||
|
|
||||||
|
return program.compute (input, expr_block, expr_pc);
|
||||||
|
}
|
||||||
|
|
493
gdb/compile/compile-cplus-symbols.c
Normal file
493
gdb/compile/compile-cplus-symbols.c
Normal file
|
@ -0,0 +1,493 @@
|
||||||
|
/* Convert symbols from GDB to GCC
|
||||||
|
|
||||||
|
Copyright (C) 2014-2018 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/>. */
|
||||||
|
|
||||||
|
|
||||||
|
#include "defs.h"
|
||||||
|
#include "compile-internal.h"
|
||||||
|
#include "compile-cplus.h"
|
||||||
|
#include "gdb_assert.h"
|
||||||
|
#include "symtab.h"
|
||||||
|
#include "parser-defs.h"
|
||||||
|
#include "block.h"
|
||||||
|
#include "objfiles.h"
|
||||||
|
#include "compile.h"
|
||||||
|
#include "value.h"
|
||||||
|
#include "exceptions.h"
|
||||||
|
#include "gdbtypes.h"
|
||||||
|
#include "dwarf2loc.h"
|
||||||
|
#include "cp-support.h"
|
||||||
|
#include "gdbcmd.h"
|
||||||
|
#include "compile-c.h"
|
||||||
|
|
||||||
|
/* Convert a given symbol, SYM, to the compiler's representation.
|
||||||
|
INSTANCE is the compiler instance. IS_GLOBAL is true if the
|
||||||
|
symbol came from the global scope. IS_LOCAL is true if the symbol
|
||||||
|
came from a local scope. (Note that the two are not strictly
|
||||||
|
inverses because the symbol might have come from the static
|
||||||
|
scope.) */
|
||||||
|
|
||||||
|
static void
|
||||||
|
convert_one_symbol (compile_cplus_instance *instance,
|
||||||
|
struct block_symbol sym, bool is_global, bool is_local)
|
||||||
|
{
|
||||||
|
/* Squash compiler warning. */
|
||||||
|
gcc_type sym_type = 0;
|
||||||
|
const char *filename = symbol_symtab (sym.symbol)->filename;
|
||||||
|
unsigned short line = SYMBOL_LINE (sym.symbol);
|
||||||
|
|
||||||
|
instance->error_symbol_once (sym.symbol);
|
||||||
|
|
||||||
|
if (SYMBOL_CLASS (sym.symbol) == LOC_LABEL)
|
||||||
|
sym_type = 0;
|
||||||
|
else
|
||||||
|
sym_type = instance->convert_type (SYMBOL_TYPE (sym.symbol));
|
||||||
|
|
||||||
|
if (SYMBOL_DOMAIN (sym.symbol) == STRUCT_DOMAIN)
|
||||||
|
{
|
||||||
|
/* Nothing to do. */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Squash compiler warning. */
|
||||||
|
gcc_cp_symbol_kind_flags kind = GCC_CP_FLAG_BASE;
|
||||||
|
CORE_ADDR addr = 0;
|
||||||
|
std::string name;
|
||||||
|
gdb::unique_xmalloc_ptr<char> symbol_name;
|
||||||
|
|
||||||
|
switch (SYMBOL_CLASS (sym.symbol))
|
||||||
|
{
|
||||||
|
case LOC_TYPEDEF:
|
||||||
|
if (TYPE_CODE (SYMBOL_TYPE (sym.symbol)) == TYPE_CODE_TYPEDEF)
|
||||||
|
kind = GCC_CP_SYMBOL_TYPEDEF;
|
||||||
|
else if (TYPE_CODE (SYMBOL_TYPE (sym.symbol)) == TYPE_CODE_NAMESPACE)
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LOC_LABEL:
|
||||||
|
kind = GCC_CP_SYMBOL_LABEL;
|
||||||
|
addr = SYMBOL_VALUE_ADDRESS (sym.symbol);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LOC_BLOCK:
|
||||||
|
{
|
||||||
|
kind = GCC_CP_SYMBOL_FUNCTION;
|
||||||
|
addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym.symbol));
|
||||||
|
if (is_global && TYPE_GNU_IFUNC (SYMBOL_TYPE (sym.symbol)))
|
||||||
|
addr = gnu_ifunc_resolve_addr (target_gdbarch (), addr);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LOC_CONST:
|
||||||
|
if (TYPE_CODE (SYMBOL_TYPE (sym.symbol)) == TYPE_CODE_ENUM)
|
||||||
|
{
|
||||||
|
/* Already handled by convert_enum. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
instance->plugin ().build_constant
|
||||||
|
(sym_type, SYMBOL_NATURAL_NAME (sym.symbol),
|
||||||
|
SYMBOL_VALUE (sym.symbol), filename, line);
|
||||||
|
return;
|
||||||
|
|
||||||
|
case LOC_CONST_BYTES:
|
||||||
|
error (_("Unsupported LOC_CONST_BYTES for symbol \"%s\"."),
|
||||||
|
SYMBOL_PRINT_NAME (sym.symbol));
|
||||||
|
|
||||||
|
case LOC_UNDEF:
|
||||||
|
internal_error (__FILE__, __LINE__, _("LOC_UNDEF found for \"%s\"."),
|
||||||
|
SYMBOL_PRINT_NAME (sym.symbol));
|
||||||
|
|
||||||
|
case LOC_COMMON_BLOCK:
|
||||||
|
error (_("Fortran common block is unsupported for compilation "
|
||||||
|
"evaluaton of symbol \"%s\"."),
|
||||||
|
SYMBOL_PRINT_NAME (sym.symbol));
|
||||||
|
|
||||||
|
case LOC_OPTIMIZED_OUT:
|
||||||
|
error (_("Symbol \"%s\" cannot be used for compilation evaluation "
|
||||||
|
"as it is optimized out."),
|
||||||
|
SYMBOL_PRINT_NAME (sym.symbol));
|
||||||
|
|
||||||
|
case LOC_COMPUTED:
|
||||||
|
if (is_local)
|
||||||
|
goto substitution;
|
||||||
|
/* Probably TLS here. */
|
||||||
|
warning (_("Symbol \"%s\" is thread-local and currently can only "
|
||||||
|
"be referenced from the current thread in "
|
||||||
|
"compiled code."),
|
||||||
|
SYMBOL_PRINT_NAME (sym.symbol));
|
||||||
|
/* FALLTHROUGH */
|
||||||
|
case LOC_UNRESOLVED:
|
||||||
|
/* 'symbol_name' cannot be used here as that one is used only for
|
||||||
|
local variables from compile_dwarf_expr_to_c.
|
||||||
|
Global variables can be accessed by GCC only by their address, not
|
||||||
|
by their name. */
|
||||||
|
{
|
||||||
|
struct value *val;
|
||||||
|
struct frame_info *frame = nullptr;
|
||||||
|
|
||||||
|
if (symbol_read_needs_frame (sym.symbol))
|
||||||
|
{
|
||||||
|
frame = get_selected_frame (nullptr);
|
||||||
|
if (frame == nullptr)
|
||||||
|
error (_("Symbol \"%s\" cannot be used because "
|
||||||
|
"there is no selected frame"),
|
||||||
|
SYMBOL_PRINT_NAME (sym.symbol));
|
||||||
|
}
|
||||||
|
|
||||||
|
val = read_var_value (sym.symbol, sym.block, frame);
|
||||||
|
if (VALUE_LVAL (val) != lval_memory)
|
||||||
|
error (_("Symbol \"%s\" cannot be used for compilation "
|
||||||
|
"evaluation as its address has not been found."),
|
||||||
|
SYMBOL_PRINT_NAME (sym.symbol));
|
||||||
|
|
||||||
|
kind = GCC_CP_SYMBOL_VARIABLE;
|
||||||
|
addr = value_address (val);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
case LOC_REGISTER:
|
||||||
|
case LOC_ARG:
|
||||||
|
case LOC_REF_ARG:
|
||||||
|
case LOC_REGPARM_ADDR:
|
||||||
|
case LOC_LOCAL:
|
||||||
|
substitution:
|
||||||
|
kind = GCC_CP_SYMBOL_VARIABLE;
|
||||||
|
symbol_name = c_symbol_substitution_name (sym.symbol);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LOC_STATIC:
|
||||||
|
kind = GCC_CP_SYMBOL_VARIABLE;
|
||||||
|
addr = SYMBOL_VALUE_ADDRESS (sym.symbol);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case LOC_FINAL_VALUE:
|
||||||
|
default:
|
||||||
|
gdb_assert_not_reached ("Unreachable case in convert_one_symbol.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Don't emit local variable decls for a raw expression. */
|
||||||
|
if (instance->scope () != COMPILE_I_RAW_SCOPE || symbol_name == nullptr)
|
||||||
|
{
|
||||||
|
compile_scope scope;
|
||||||
|
|
||||||
|
/* For non-local symbols, create/push a new scope so that the
|
||||||
|
symbol is properly scoped to the plug-in. */
|
||||||
|
if (!is_local)
|
||||||
|
{
|
||||||
|
scope
|
||||||
|
= instance->new_scope (SYMBOL_NATURAL_NAME (sym.symbol),
|
||||||
|
SYMBOL_TYPE (sym.symbol));
|
||||||
|
if (scope.nested_type () != GCC_TYPE_NONE)
|
||||||
|
{
|
||||||
|
/* We found a symbol for this type that was defined inside
|
||||||
|
some other symbol, e.g., a class tyepdef defined. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->enter_scope (scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the `raw' name of the symbol. */
|
||||||
|
if (name.empty () && SYMBOL_NATURAL_NAME (sym.symbol) != nullptr)
|
||||||
|
name = compile_cplus_instance::decl_name
|
||||||
|
(SYMBOL_NATURAL_NAME (sym.symbol)).get ();
|
||||||
|
|
||||||
|
/* Define the decl. */
|
||||||
|
instance->plugin ().build_decl
|
||||||
|
("variable", name.c_str (), kind, sym_type,
|
||||||
|
symbol_name.get (), addr, filename, line);
|
||||||
|
|
||||||
|
/* Pop scope for non-local symbols. */
|
||||||
|
if (!is_local)
|
||||||
|
instance->leave_scope ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert a full symbol to its gcc form. CONTEXT is the compiler to
|
||||||
|
use, IDENTIFIER is the name of the symbol, SYM is the symbol
|
||||||
|
itself, and DOMAIN is the domain which was searched. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
convert_symbol_sym (compile_cplus_instance *instance,
|
||||||
|
const char *identifier, struct block_symbol sym,
|
||||||
|
domain_enum domain)
|
||||||
|
{
|
||||||
|
/* If we found a symbol and it is not in the static or global
|
||||||
|
scope, then we should first convert any static or global scope
|
||||||
|
symbol of the same name. This lets this unusual case work:
|
||||||
|
|
||||||
|
int x; // Global.
|
||||||
|
int func(void)
|
||||||
|
{
|
||||||
|
int x;
|
||||||
|
// At this spot, evaluate "extern int x; x"
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
const struct block *static_block = block_static_block (sym.block);
|
||||||
|
/* STATIC_BLOCK is NULL if FOUND_BLOCK is the global block. */
|
||||||
|
bool is_local_symbol = (sym.block != static_block && static_block != nullptr);
|
||||||
|
if (is_local_symbol)
|
||||||
|
{
|
||||||
|
struct block_symbol global_sym;
|
||||||
|
|
||||||
|
global_sym = lookup_symbol (identifier, nullptr, domain, nullptr);
|
||||||
|
/* If the outer symbol is in the static block, we ignore it, as
|
||||||
|
it cannot be referenced. */
|
||||||
|
if (global_sym.symbol != nullptr
|
||||||
|
&& global_sym.block != block_static_block (global_sym.block))
|
||||||
|
{
|
||||||
|
if (compile_debug)
|
||||||
|
fprintf_unfiltered (gdb_stdlog,
|
||||||
|
"gcc_convert_symbol \"%s\": global symbol\n",
|
||||||
|
identifier);
|
||||||
|
convert_one_symbol (instance, global_sym, true, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (compile_debug)
|
||||||
|
fprintf_unfiltered (gdb_stdlog,
|
||||||
|
"gcc_convert_symbol \"%s\": local symbol\n",
|
||||||
|
identifier);
|
||||||
|
convert_one_symbol (instance, sym, false, is_local_symbol);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert a minimal symbol to its gcc form. CONTEXT is the compiler
|
||||||
|
to use and BMSYM is the minimal symbol to convert. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
convert_symbol_bmsym (compile_cplus_instance *instance,
|
||||||
|
struct bound_minimal_symbol bmsym)
|
||||||
|
{
|
||||||
|
struct minimal_symbol *msym = bmsym.minsym;
|
||||||
|
struct objfile *objfile = bmsym.objfile;
|
||||||
|
struct type *type;
|
||||||
|
gcc_cp_symbol_kind_flags kind;
|
||||||
|
gcc_type sym_type;
|
||||||
|
CORE_ADDR addr;
|
||||||
|
|
||||||
|
addr = MSYMBOL_VALUE_ADDRESS (objfile, msym);
|
||||||
|
|
||||||
|
/* Conversion copied from write_exp_msymbol. */
|
||||||
|
switch (MSYMBOL_TYPE (msym))
|
||||||
|
{
|
||||||
|
case mst_text:
|
||||||
|
case mst_file_text:
|
||||||
|
case mst_solib_trampoline:
|
||||||
|
type = objfile_type (objfile)->nodebug_text_symbol;
|
||||||
|
kind = GCC_CP_SYMBOL_FUNCTION;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case mst_text_gnu_ifunc:
|
||||||
|
/* nodebug_text_gnu_ifunc_symbol would cause:
|
||||||
|
function return type cannot be function */
|
||||||
|
type = objfile_type (objfile)->nodebug_text_symbol;
|
||||||
|
kind = GCC_CP_SYMBOL_FUNCTION;
|
||||||
|
addr = gnu_ifunc_resolve_addr (target_gdbarch (), addr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case mst_data:
|
||||||
|
case mst_file_data:
|
||||||
|
case mst_bss:
|
||||||
|
case mst_file_bss:
|
||||||
|
type = objfile_type (objfile)->nodebug_data_symbol;
|
||||||
|
kind = GCC_CP_SYMBOL_VARIABLE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case mst_slot_got_plt:
|
||||||
|
type = objfile_type (objfile)->nodebug_got_plt_symbol;
|
||||||
|
kind = GCC_CP_SYMBOL_FUNCTION;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
type = objfile_type (objfile)->nodebug_unknown_symbol;
|
||||||
|
kind = GCC_CP_SYMBOL_VARIABLE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
sym_type = instance->convert_type (type);
|
||||||
|
instance->plugin ().push_namespace ("");
|
||||||
|
instance->plugin ().build_decl
|
||||||
|
("minsym", MSYMBOL_NATURAL_NAME (msym), kind, sym_type, nullptr, addr,
|
||||||
|
nullptr, 0);
|
||||||
|
instance->plugin ().pop_binding_level ("");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See compile-cplus.h. */
|
||||||
|
|
||||||
|
void
|
||||||
|
gcc_cplus_convert_symbol (void *datum,
|
||||||
|
struct gcc_cp_context *gcc_context,
|
||||||
|
enum gcc_cp_oracle_request request ATTRIBUTE_UNUSED,
|
||||||
|
const char *identifier)
|
||||||
|
{
|
||||||
|
if (compile_debug)
|
||||||
|
fprintf_unfiltered (gdb_stdlog,
|
||||||
|
"got oracle request for \"%s\"\n", identifier);
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
compile_cplus_instance *instance = (compile_cplus_instance *) datum;
|
||||||
|
|
||||||
|
TRY
|
||||||
|
{
|
||||||
|
/* Symbol searching is a three part process unfortunately. */
|
||||||
|
|
||||||
|
/* First do a "standard" lookup, converting any found symbols.
|
||||||
|
This will find variables in the current scope. */
|
||||||
|
|
||||||
|
struct block_symbol sym
|
||||||
|
= lookup_symbol (identifier, instance->block (), VAR_DOMAIN, nullptr);
|
||||||
|
|
||||||
|
if (sym.symbol != nullptr)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
convert_symbol_sym (instance, identifier, sym, VAR_DOMAIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Then use linespec.c's multi-symbol search. This should find
|
||||||
|
all non-variable symbols for which we have debug info. */
|
||||||
|
|
||||||
|
symbol_searcher searcher;
|
||||||
|
searcher.find_all_symbols (identifier, current_language,
|
||||||
|
ALL_DOMAIN, nullptr, nullptr);
|
||||||
|
|
||||||
|
/* Convert any found symbols. */
|
||||||
|
for (const auto &it : searcher.matching_symbols ())
|
||||||
|
{
|
||||||
|
/* Don't convert the symbol found above, if any, twice! */
|
||||||
|
if (it.symbol != sym.symbol)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
convert_symbol_sym (instance, identifier, it,
|
||||||
|
SYMBOL_DOMAIN (it.symbol));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Finally, if no symbols have been found, fall back to minsyms. */
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
for (const auto &it : searcher.matching_msymbols ())
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
convert_symbol_bmsym (instance, it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CATCH (e, RETURN_MASK_ALL)
|
||||||
|
{
|
||||||
|
/* We can't allow exceptions to escape out of this callback. Safest
|
||||||
|
is to simply emit a gcc error. */
|
||||||
|
instance->plugin ().error (e.message);
|
||||||
|
}
|
||||||
|
END_CATCH
|
||||||
|
|
||||||
|
if (compile_debug && !found)
|
||||||
|
fprintf_unfiltered (gdb_stdlog,
|
||||||
|
"gcc_convert_symbol \"%s\": lookup_symbol failed\n",
|
||||||
|
identifier);
|
||||||
|
|
||||||
|
if (compile_debug)
|
||||||
|
{
|
||||||
|
if (found)
|
||||||
|
fprintf_unfiltered (gdb_stdlog, "found type for %s\n", identifier);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fprintf_unfiltered (gdb_stdlog, "did not find type for %s\n",
|
||||||
|
identifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See compile-cplus.h. */
|
||||||
|
|
||||||
|
gcc_address
|
||||||
|
gcc_cplus_symbol_address (void *datum, struct gcc_cp_context *gcc_context,
|
||||||
|
const char *identifier)
|
||||||
|
{
|
||||||
|
compile_cplus_instance *instance = (compile_cplus_instance *) datum;
|
||||||
|
gcc_address result = 0;
|
||||||
|
int found = 0;
|
||||||
|
|
||||||
|
if (compile_debug)
|
||||||
|
fprintf_unfiltered (gdb_stdlog,
|
||||||
|
"got oracle request for address of %s\n", identifier);
|
||||||
|
|
||||||
|
/* We can't allow exceptions to escape out of this callback. Safest
|
||||||
|
is to simply emit a gcc error. */
|
||||||
|
TRY
|
||||||
|
{
|
||||||
|
struct symbol *sym
|
||||||
|
= lookup_symbol (identifier, nullptr, VAR_DOMAIN, nullptr).symbol;
|
||||||
|
|
||||||
|
if (sym != nullptr && SYMBOL_CLASS (sym) == LOC_BLOCK)
|
||||||
|
{
|
||||||
|
if (compile_debug)
|
||||||
|
fprintf_unfiltered (gdb_stdlog,
|
||||||
|
"gcc_symbol_address \"%s\": full symbol\n",
|
||||||
|
identifier);
|
||||||
|
result = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
|
||||||
|
if (TYPE_GNU_IFUNC (SYMBOL_TYPE (sym)))
|
||||||
|
result = gnu_ifunc_resolve_addr (target_gdbarch (), result);
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct bound_minimal_symbol msym;
|
||||||
|
|
||||||
|
msym = lookup_bound_minimal_symbol (identifier);
|
||||||
|
if (msym.minsym != nullptr)
|
||||||
|
{
|
||||||
|
if (compile_debug)
|
||||||
|
fprintf_unfiltered (gdb_stdlog,
|
||||||
|
"gcc_symbol_address \"%s\": minimal "
|
||||||
|
"symbol\n",
|
||||||
|
identifier);
|
||||||
|
result = BMSYMBOL_VALUE_ADDRESS (msym);
|
||||||
|
if (MSYMBOL_TYPE (msym.minsym) == mst_text_gnu_ifunc)
|
||||||
|
result = gnu_ifunc_resolve_addr (target_gdbarch (), result);
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
CATCH (e, RETURN_MASK_ERROR)
|
||||||
|
{
|
||||||
|
instance->plugin ().error (e.message);
|
||||||
|
}
|
||||||
|
END_CATCH
|
||||||
|
|
||||||
|
if (compile_debug && !found)
|
||||||
|
fprintf_unfiltered (gdb_stdlog,
|
||||||
|
"gcc_symbol_address \"%s\": failed\n",
|
||||||
|
identifier);
|
||||||
|
|
||||||
|
if (compile_debug)
|
||||||
|
{
|
||||||
|
if (found)
|
||||||
|
fprintf_unfiltered (gdb_stdlog, "found address for %s!\n", identifier);
|
||||||
|
else
|
||||||
|
fprintf_unfiltered (gdb_stdlog,
|
||||||
|
"did not find address for %s\n", identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
1427
gdb/compile/compile-cplus-types.c
Normal file
1427
gdb/compile/compile-cplus-types.c
Normal file
File diff suppressed because it is too large
Load diff
205
gdb/compile/compile-cplus.h
Normal file
205
gdb/compile/compile-cplus.h
Normal file
|
@ -0,0 +1,205 @@
|
||||||
|
/* Header file for GDB compile C++ language support.
|
||||||
|
Copyright (C) 2016-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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 GDB_COMPILE_CPLUS_H
|
||||||
|
#define GDB_COMPILE_CPLUS_H
|
||||||
|
|
||||||
|
#include "common/enum-flags.h"
|
||||||
|
#include "gcc-cp-plugin.h"
|
||||||
|
|
||||||
|
struct type;
|
||||||
|
struct block;
|
||||||
|
|
||||||
|
/* enum-flags wrapper */
|
||||||
|
DEF_ENUM_FLAGS_TYPE (enum gcc_cp_qualifiers, gcc_cp_qualifiers_flags);
|
||||||
|
DEF_ENUM_FLAGS_TYPE (enum gcc_cp_ref_qualifiers, gcc_cp_ref_qualifiers_flags);
|
||||||
|
DEF_ENUM_FLAGS_TYPE (enum gcc_cp_symbol_kind, gcc_cp_symbol_kind_flags);
|
||||||
|
|
||||||
|
class compile_cplus_instance;
|
||||||
|
|
||||||
|
/* A single component of a type's scope. Type names are broken into
|
||||||
|
"components," a series of unqualified names comprising the type name,
|
||||||
|
e.g., "namespace1", "namespace2", "myclass". */
|
||||||
|
|
||||||
|
struct scope_component
|
||||||
|
{
|
||||||
|
/* The unqualified name of this scope. */
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
/* The block symbol for this type/scope. */
|
||||||
|
struct block_symbol bsymbol;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Comparison operators for scope_components. */
|
||||||
|
|
||||||
|
bool operator== (const scope_component &lhs, const scope_component &rhs);
|
||||||
|
bool operator!= (const scope_component &lhs, const scope_component &rhs);
|
||||||
|
|
||||||
|
|
||||||
|
/* A single compiler scope used to define a type.
|
||||||
|
|
||||||
|
A compile_scope is a list of scope_components, where all leading
|
||||||
|
scope_components are namespaces, followed by a single non-namespace
|
||||||
|
type component (the actual type we are converting). */
|
||||||
|
|
||||||
|
class compile_scope : private std::vector<scope_component>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
using std::vector<scope_component>::push_back;
|
||||||
|
using std::vector<scope_component>::pop_back;
|
||||||
|
using std::vector<scope_component>::back;
|
||||||
|
using std::vector<scope_component>::empty;
|
||||||
|
using std::vector<scope_component>::size;
|
||||||
|
using std::vector<scope_component>::begin;
|
||||||
|
using std::vector<scope_component>::end;
|
||||||
|
using std::vector<scope_component>::operator[];
|
||||||
|
|
||||||
|
compile_scope ()
|
||||||
|
: m_nested_type (GCC_TYPE_NONE), m_pushed (false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the gcc_type of the type if it is a nested definition.
|
||||||
|
Returns GCC_TYPE_NONE if this type was not nested. */
|
||||||
|
gcc_type nested_type ()
|
||||||
|
{
|
||||||
|
return m_nested_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/* compile_cplus_instance is a friend class so that it can set the
|
||||||
|
following private members when compile_scopes are created. */
|
||||||
|
friend compile_cplus_instance;
|
||||||
|
|
||||||
|
/* If the type was actually a nested type, this will hold that nested
|
||||||
|
type after the scope is pushed. */
|
||||||
|
gcc_type m_nested_type;
|
||||||
|
|
||||||
|
/* If true, this scope was pushed to the compiler and all namespaces
|
||||||
|
must be popped when leaving the scope. */
|
||||||
|
bool m_pushed;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Comparison operators for compile_scopes. */
|
||||||
|
|
||||||
|
bool operator== (const compile_scope &lhs, const compile_scope &rhs);
|
||||||
|
bool operator!= (const compile_scope &lhs, const compile_scope &rhs);
|
||||||
|
|
||||||
|
/* Convert TYPENAME into a vector of namespace and top-most/super
|
||||||
|
composite scopes.
|
||||||
|
|
||||||
|
For example, for the input "Namespace::classB::classInner", the
|
||||||
|
resultant vector will contain the tokens "Namespace" and
|
||||||
|
"classB". */
|
||||||
|
|
||||||
|
compile_scope type_name_to_scope (const char *type_name,
|
||||||
|
const struct block *block);
|
||||||
|
|
||||||
|
/* A callback suitable for use as the GCC C++ symbol oracle. */
|
||||||
|
|
||||||
|
extern gcc_cp_oracle_function gcc_cplus_convert_symbol;
|
||||||
|
|
||||||
|
/* A callback suitable for use as the GCC C++ address oracle. */
|
||||||
|
|
||||||
|
extern gcc_cp_symbol_address_function gcc_cplus_symbol_address;
|
||||||
|
|
||||||
|
/* A subclass of compile_instance that is specific to the C++ front
|
||||||
|
end. */
|
||||||
|
|
||||||
|
class compile_cplus_instance : public compile_instance
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit compile_cplus_instance (struct gcc_cp_context *gcc_cp)
|
||||||
|
: compile_instance (&gcc_cp->base, m_default_cflags),
|
||||||
|
m_plugin (gcc_cp)
|
||||||
|
{
|
||||||
|
m_plugin.set_callbacks (gcc_cplus_convert_symbol,
|
||||||
|
gcc_cplus_symbol_address,
|
||||||
|
gcc_cplus_enter_scope, gcc_cplus_leave_scope,
|
||||||
|
this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convert a gdb type, TYPE, to a GCC type.
|
||||||
|
|
||||||
|
If this type was defined in another type, NESTED_ACCESS should indicate
|
||||||
|
the accessibility of this type (or GCC_CP_ACCESS_NONE if not a nested
|
||||||
|
type). GCC_CP_ACCESS_NONE is the default nested access.
|
||||||
|
|
||||||
|
The new GCC type is returned. */
|
||||||
|
gcc_type convert_type
|
||||||
|
(struct type *type,
|
||||||
|
enum gcc_cp_symbol_kind nested_access = GCC_CP_ACCESS_NONE);
|
||||||
|
|
||||||
|
/* Return a handle for the GCC plug-in. */
|
||||||
|
gcc_cp_plugin &plugin () { return m_plugin; }
|
||||||
|
|
||||||
|
/* Factory method to create a new scope based on TYPE with name TYPE_NAME.
|
||||||
|
[TYPE_NAME could be TYPE_NAME or SYMBOL_NATURAL_NAME.]
|
||||||
|
|
||||||
|
If TYPE is a nested or local definition, nested_type () will return
|
||||||
|
the gcc_type of the conversion.
|
||||||
|
|
||||||
|
Otherwise, nested_type () is GCC_TYPE_NONE. */
|
||||||
|
compile_scope new_scope (const char *type_name, struct type *type);
|
||||||
|
|
||||||
|
/* Enter the given NEW_SCOPE. */
|
||||||
|
void enter_scope (compile_scope &scope);
|
||||||
|
|
||||||
|
/* Leave the current scope. */
|
||||||
|
void leave_scope ();
|
||||||
|
|
||||||
|
/* Add the qualifiers given by QUALS to BASE. */
|
||||||
|
gcc_type convert_qualified_base (gcc_type base,
|
||||||
|
gcc_cp_qualifiers_flags quals);
|
||||||
|
|
||||||
|
/* Convert TARGET into a pointer type. */
|
||||||
|
gcc_type convert_pointer_base (gcc_type target);
|
||||||
|
|
||||||
|
/* Convert BASE into a reference type. RQUALS describes the reference. */
|
||||||
|
gcc_type convert_reference_base (gcc_type base,
|
||||||
|
enum gcc_cp_ref_qualifiers rquals);
|
||||||
|
|
||||||
|
/* Return the declaration name of the symbol named NATURAL.
|
||||||
|
This returns a name with no function arguments or template parameters,
|
||||||
|
suitable for passing to the compiler plug-in. */
|
||||||
|
static gdb::unique_xmalloc_ptr<char> decl_name (const char *natural);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/* Callbacks suitable for use as the GCC C++ enter/leave scope requests. */
|
||||||
|
static gcc_cp_enter_leave_user_expr_scope_function gcc_cplus_enter_scope;
|
||||||
|
static gcc_cp_enter_leave_user_expr_scope_function gcc_cplus_leave_scope;
|
||||||
|
|
||||||
|
/* Default compiler flags for C++. */
|
||||||
|
static const char *m_default_cflags;
|
||||||
|
|
||||||
|
/* The GCC plug-in. */
|
||||||
|
gcc_cp_plugin m_plugin;
|
||||||
|
|
||||||
|
/* A list of scopes we are processing. */
|
||||||
|
std::vector<compile_scope> m_scopes;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Get the access flag for the NUM'th method of TYPE's FNI'th
|
||||||
|
fieldlist. */
|
||||||
|
|
||||||
|
enum gcc_cp_symbol_kind get_method_access_flag (const struct type *type,
|
||||||
|
int fni, int num);
|
||||||
|
|
||||||
|
#endif /* GDB_COMPILE_CPLUS_H */
|
|
@ -164,6 +164,10 @@ protected:
|
||||||
#define COMPILE_I_EXPR_VAL "__gdb_expr_val"
|
#define COMPILE_I_EXPR_VAL "__gdb_expr_val"
|
||||||
#define COMPILE_I_EXPR_PTR_TYPE "__gdb_expr_ptr_type"
|
#define COMPILE_I_EXPR_PTR_TYPE "__gdb_expr_ptr_type"
|
||||||
|
|
||||||
|
/* A "type" to indicate a NULL type. */
|
||||||
|
|
||||||
|
const gcc_type GCC_TYPE_NONE = (gcc_type) -1;
|
||||||
|
|
||||||
/* Call gdbarch_register_name (GDBARCH, REGNUM) and convert its result
|
/* Call gdbarch_register_name (GDBARCH, REGNUM) and convert its result
|
||||||
to a form suitable for the compiler source. The register names
|
to a form suitable for the compiler source. The register names
|
||||||
should not clash with inferior defined macros. */
|
should not clash with inferior defined macros. */
|
||||||
|
|
|
@ -459,7 +459,8 @@ get_out_value_type (struct symbol *func_sym, struct objfile *objfile,
|
||||||
if (function != NULL
|
if (function != NULL
|
||||||
&& (BLOCK_SUPERBLOCK (function_block)
|
&& (BLOCK_SUPERBLOCK (function_block)
|
||||||
== BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK))
|
== BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK))
|
||||||
&& (strcmp (SYMBOL_LINKAGE_NAME (function), GCC_FE_WRAPPER_FUNCTION)
|
&& (strcmp_iw (SYMBOL_LINKAGE_NAME (function),
|
||||||
|
GCC_FE_WRAPPER_FUNCTION)
|
||||||
== 0))
|
== 0))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -478,7 +479,7 @@ get_out_value_type (struct symbol *func_sym, struct objfile *objfile,
|
||||||
gdb_ptr_type = check_typedef (gdb_ptr_type);
|
gdb_ptr_type = check_typedef (gdb_ptr_type);
|
||||||
if (TYPE_CODE (gdb_ptr_type) != TYPE_CODE_PTR)
|
if (TYPE_CODE (gdb_ptr_type) != TYPE_CODE_PTR)
|
||||||
error (_("Type of \"%s\" is not a pointer"), COMPILE_I_EXPR_PTR_TYPE);
|
error (_("Type of \"%s\" is not a pointer"), COMPILE_I_EXPR_PTR_TYPE);
|
||||||
gdb_type_from_ptr = TYPE_TARGET_TYPE (gdb_ptr_type);
|
gdb_type_from_ptr = check_typedef (TYPE_TARGET_TYPE (gdb_ptr_type));
|
||||||
|
|
||||||
if (types_deeply_equal (gdb_type, gdb_type_from_ptr))
|
if (types_deeply_equal (gdb_type, gdb_type_from_ptr))
|
||||||
{
|
{
|
||||||
|
@ -741,6 +742,8 @@ compile_object_load (const compile_file_names &file_names,
|
||||||
? mst_unknown : MSYMBOL_TYPE (bmsym.minsym))
|
? mst_unknown : MSYMBOL_TYPE (bmsym.minsym))
|
||||||
{
|
{
|
||||||
case mst_text:
|
case mst_text:
|
||||||
|
case mst_bss:
|
||||||
|
case mst_data:
|
||||||
sym->value = BMSYMBOL_VALUE_ADDRESS (bmsym);
|
sym->value = BMSYMBOL_VALUE_ADDRESS (bmsym);
|
||||||
if (compile_debug)
|
if (compile_debug)
|
||||||
fprintf_unfiltered (gdb_stdlog,
|
fprintf_unfiltered (gdb_stdlog,
|
||||||
|
|
|
@ -995,7 +995,6 @@ String quoting is parsed like in shell, for example:\n\
|
||||||
" -fPIE"
|
" -fPIE"
|
||||||
/* We want warnings, except for some commonly happening for GDB commands. */
|
/* We want warnings, except for some commonly happening for GDB commands. */
|
||||||
" -Wall "
|
" -Wall "
|
||||||
" -Wno-implicit-function-declaration"
|
|
||||||
" -Wno-unused-but-set-variable"
|
" -Wno-unused-but-set-variable"
|
||||||
" -Wno-unused-variable"
|
" -Wno-unused-variable"
|
||||||
/* Override CU's possible -fstack-protector-strong. */
|
/* Override CU's possible -fstack-protector-strong. */
|
||||||
|
|
85
gdb/compile/gcc-cp-plugin.h
Normal file
85
gdb/compile/gcc-cp-plugin.h
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
/* GCC C++ plug-in wrapper for GDB.
|
||||||
|
|
||||||
|
Copyright (C) 2018 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/>. */
|
||||||
|
|
||||||
|
/* A class representing the GCC C++ plug-in. */
|
||||||
|
|
||||||
|
#include "gcc-cp-interface.h"
|
||||||
|
|
||||||
|
class gcc_cp_plugin
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit gcc_cp_plugin (struct gcc_cp_context *gcc_cp)
|
||||||
|
: m_context (gcc_cp)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the oracle callbacks to be used by the compiler plug-in. */
|
||||||
|
void set_callbacks (gcc_cp_oracle_function *binding_oracle,
|
||||||
|
gcc_cp_symbol_address_function *address_oracle,
|
||||||
|
gcc_cp_enter_leave_user_expr_scope_function *enter_scope,
|
||||||
|
gcc_cp_enter_leave_user_expr_scope_function *leave_scope,
|
||||||
|
void *datum)
|
||||||
|
{
|
||||||
|
m_context->cp_ops->set_callbacks (m_context, binding_oracle,
|
||||||
|
address_oracle, enter_scope, leave_scope,
|
||||||
|
datum);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Returns the interface version of the compiler plug-in. */
|
||||||
|
int version () const { return m_context->cp_ops->cp_version; }
|
||||||
|
|
||||||
|
#define GCC_METHOD0(R, N) R N () const;
|
||||||
|
#define GCC_METHOD1(R, N, A) R N (A) const;
|
||||||
|
#define GCC_METHOD2(R, N, A, B) R N (A, B) const;
|
||||||
|
#define GCC_METHOD3(R, N, A, B, C) R N (A, B, C) const;
|
||||||
|
#define GCC_METHOD4(R, N, A, B, C, D) R N (A, B, C, D) const;
|
||||||
|
#define GCC_METHOD5(R, N, A, B, C, D, E) R N (A, B, C, D, E) const;
|
||||||
|
#define GCC_METHOD7(R, N, A, B, C, D, E, F, G) R N (A, B, C, D, E, F, G) const;
|
||||||
|
|
||||||
|
#include "gcc-cp-fe.def"
|
||||||
|
|
||||||
|
#undef GCC_METHOD0
|
||||||
|
#undef GCC_METHOD1
|
||||||
|
#undef GCC_METHOD2
|
||||||
|
#undef GCC_METHOD3
|
||||||
|
#undef GCC_METHOD4
|
||||||
|
#undef GCC_METHOD5
|
||||||
|
#undef GCC_METHOD7
|
||||||
|
|
||||||
|
/* Special overloads of plug-in methods with added debugging information. */
|
||||||
|
|
||||||
|
gcc_expr build_decl (const char *debug_decltype, const char *name,
|
||||||
|
enum gcc_cp_symbol_kind sym_kind, gcc_type sym_type,
|
||||||
|
const char *substitution_name, gcc_address address,
|
||||||
|
const char *filename, unsigned int line_number);
|
||||||
|
|
||||||
|
gcc_type start_class_type (const char *debug_name, gcc_decl typedecl,
|
||||||
|
const struct gcc_vbase_array *base_classes,
|
||||||
|
const char *filename, unsigned int line_number);
|
||||||
|
|
||||||
|
int finish_class_type (const char *debug_name, unsigned long size_in_bytes);
|
||||||
|
|
||||||
|
int pop_binding_level (const char *debug_name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
/* The GCC C++ context. */
|
||||||
|
struct gcc_cp_context *m_context;
|
||||||
|
};
|
|
@ -1,3 +1,8 @@
|
||||||
|
2018-08-29 Keith Seitz <keiths@redhat.com>
|
||||||
|
|
||||||
|
* gdb.texinfo (Compiling and injecting code in GDB): Document
|
||||||
|
set/show "compile-oracle" and "compile-cplus-types" commands.
|
||||||
|
|
||||||
2018-08-22 Jan Vrany <jan.vrany@fit.cvut.cz>
|
2018-08-22 Jan Vrany <jan.vrany@fit.cvut.cz>
|
||||||
|
|
||||||
* gdb.texinfo (The -stack-list-frames Command): Update description
|
* gdb.texinfo (The -stack-list-frames Command): Update description
|
||||||
|
|
|
@ -18689,6 +18689,16 @@ injecting the code. The default is off.
|
||||||
@item show debug compile
|
@item show debug compile
|
||||||
Displays the current state of displaying @value{GDBN} process of
|
Displays the current state of displaying @value{GDBN} process of
|
||||||
compiling and injecting the code.
|
compiling and injecting the code.
|
||||||
|
|
||||||
|
@anchor{set debug compile-cplus-types}
|
||||||
|
@item set debug compile-cplus-types
|
||||||
|
@cindex compile C@t{++} type conversion
|
||||||
|
Turns on or off the display of C@t{++} type conversion debugging information.
|
||||||
|
The default is off.
|
||||||
|
|
||||||
|
@item show debug compile-cplus-types
|
||||||
|
Displays the current state of displaying debugging information for
|
||||||
|
C@t{++} type conversion.
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
@subsection Compilation options for the @code{compile} command
|
@subsection Compilation options for the @code{compile} command
|
||||||
|
|
|
@ -1,3 +1,28 @@
|
||||||
|
2018-08-29 Keith Seitz <keiths@redhat.com>
|
||||||
|
|
||||||
|
* gdb.compile/compile-cplus-anonymous.cc: New file.
|
||||||
|
* gdb.compile/compile-cplus-anonymous.exp: New file.
|
||||||
|
* gdb.compile/compile-cplus-array-decay.cc: New file.
|
||||||
|
* gdb.compile/compile-cplus-array-decay.exp: New file.
|
||||||
|
* gdb.compile/compile-cplus-inherit.cc: New file.
|
||||||
|
* gdb.compile/compile-cplus-inherit.exp: New file.
|
||||||
|
* gdb.compile/compile-cplus-member.cc: New file.
|
||||||
|
* gdb.compile/compile-cplus-member.exp: New file.
|
||||||
|
* gdb.compile/compile-cplus-method.cc: New file.
|
||||||
|
* gdb.compile/compile-cplus-method.exp: New file.
|
||||||
|
* gdb.compile/compile-cplus-mod.c: "New" file.
|
||||||
|
* gdb.compile/compile-cplus-namespace.cc: New file.
|
||||||
|
* gdb.compile/compile-cplus-namespace.exp: New file.
|
||||||
|
* gdb.compile/compile-cplus-nested.cc: New file.
|
||||||
|
* gdb.compile/compile-cplus-nested.exp: New file.
|
||||||
|
* gdb.compile/compile-cplus-print.c: "New" file.
|
||||||
|
* gdb.compile/compile-cplus-print.exp: "New" file.
|
||||||
|
* gdb.compile/compile-cplus-virtual.cc: New file.
|
||||||
|
* gdb.compile/compile-cplus-virtual.exp: New file.
|
||||||
|
* gdb.compile/compile-cplus.c: "New" file.
|
||||||
|
* gdb.compile/compile-cplus.exp: "New" file.
|
||||||
|
* lib/compile-support.exp: New file.
|
||||||
|
|
||||||
2018-08-16 Gary Benson <gbenson@redhat.com>
|
2018-08-16 Gary Benson <gbenson@redhat.com>
|
||||||
|
|
||||||
PR gdb/13000:
|
PR gdb/13000:
|
||||||
|
|
76
gdb/testsuite/gdb.compile/compile-cplus-anonymous.cc
Normal file
76
gdb/testsuite/gdb.compile/compile-cplus-anonymous.cc
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
/* Copyright 2015-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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/>. */
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
static enum {ABC = 1, DEF, GHI, JKL} anon_e = GHI;
|
||||||
|
static union
|
||||||
|
{
|
||||||
|
char aa;
|
||||||
|
int bb;
|
||||||
|
float ff;
|
||||||
|
double dd;
|
||||||
|
void *pp;
|
||||||
|
} anon_u = { 'a' };
|
||||||
|
|
||||||
|
static struct
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
int len;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
unsigned MAGIC;
|
||||||
|
};
|
||||||
|
union
|
||||||
|
{
|
||||||
|
int ua;
|
||||||
|
char *ub;
|
||||||
|
};
|
||||||
|
} anon_s = {"abracadabra", 11, 0xdead, 0xbeef};
|
||||||
|
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
A () : e (AA)
|
||||||
|
{
|
||||||
|
this->u.b = 0;
|
||||||
|
this->s.ptr = "hello";
|
||||||
|
this->s.len = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum {AA = 10, BB, CC, DD} e;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
char a;
|
||||||
|
int b;
|
||||||
|
float f;
|
||||||
|
double d;
|
||||||
|
void *p;
|
||||||
|
} u;
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
char *ptr;
|
||||||
|
int len;
|
||||||
|
} s;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
A a;
|
||||||
|
int var = 1234;
|
||||||
|
|
||||||
|
return a.u.b + a.s.len + static_cast<int> (a.e)
|
||||||
|
+ static_cast<int> (anon_e) + anon_u.bb + anon_s.len; // break here
|
||||||
|
}
|
64
gdb/testsuite/gdb.compile/compile-cplus-anonymous.exp
Normal file
64
gdb/testsuite/gdb.compile/compile-cplus-anonymous.exp
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
# Copyright 2015-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
# Anonymous type conversion tests for GDB's C++ compile feature.
|
||||||
|
|
||||||
|
load_lib compile-support.exp
|
||||||
|
|
||||||
|
standard_testfile .cc
|
||||||
|
|
||||||
|
if {[skip_cplus_tests]} {
|
||||||
|
untested "skipping C++ tests"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[prepare_for_testing $testfile $testfile $srcfile \
|
||||||
|
{debug nowarnings c++}]} {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if {![runto_main]} {
|
||||||
|
untested "could not run to main"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[skip_compile_feature_tests]} {
|
||||||
|
untested \
|
||||||
|
"compile command not supported (could not find libcc1 shared library?)"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_breakpoint [gdb_get_line_number "break here" $srcfile]
|
||||||
|
gdb_continue_to_breakpoint "testing location"
|
||||||
|
|
||||||
|
# Reminder, "var" is an integer; all these types get converted to `int'.
|
||||||
|
CompileExpression::new "var"
|
||||||
|
CompileExpression::test "anon_e" {(3|GHI)}
|
||||||
|
CompileExpression::test "anon_u.aa" {97( 'a')?}
|
||||||
|
CompileExpression::test "a.u.b" 0
|
||||||
|
CompileExpression::test "a.s.len" 5
|
||||||
|
CompileExpression::test "a.e" {(10|A::AA)}
|
||||||
|
CompileExpression::test "(*a.s.ptr != 'h')" (0|false)
|
||||||
|
CompileExpression::test "A::BB" {(11|A::BB)}
|
||||||
|
CompileExpression::test "ABC" {(1|ABC)}
|
||||||
|
CompileExpression::test "DEF" {(2|DEF)}
|
||||||
|
CompileExpression::test "GHI" {(3|GHI)}
|
||||||
|
CompileExpression::test "JKL" {(4|JKL)}
|
||||||
|
|
||||||
|
set k "compile/23588 *-*-*"
|
||||||
|
CompileExpression::test "anon_s.len" 11 -kfail $k
|
||||||
|
CompileExpression::test "anon_s.MAGIC" "57005" -kfail $k
|
||||||
|
CompileExpression::test "anon_s.ua" "48879" -kfail $k
|
||||||
|
CompileExpression::test "(*anon_s.ptr == 'a')" (1|true) -kfail $k
|
31
gdb/testsuite/gdb.compile/compile-cplus-array-decay.cc
Normal file
31
gdb/testsuite/gdb.compile/compile-cplus-array-decay.cc
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
/* Copyright 2017-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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/>. */
|
||||||
|
|
||||||
|
static const char *g_string_initializer = "hello";
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
int integers[10];
|
||||||
|
const char *strings[10];
|
||||||
|
|
||||||
|
for (auto &i : integers)
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
for (auto &i : strings)
|
||||||
|
i = g_string_initializer;
|
||||||
|
|
||||||
|
return 0; // break here
|
||||||
|
}
|
50
gdb/testsuite/gdb.compile/compile-cplus-array-decay.exp
Normal file
50
gdb/testsuite/gdb.compile/compile-cplus-array-decay.exp
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
# Copyright 2017-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
# Test whether GDB's C++ compile feature is decaying arrays into pointers.
|
||||||
|
|
||||||
|
load_lib compile-support.exp
|
||||||
|
|
||||||
|
standard_testfile .cc
|
||||||
|
|
||||||
|
if {[skip_cplus_tests]} {
|
||||||
|
untested "skipping C++ tests"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[prepare_for_testing $testfile $testfile $srcfile \
|
||||||
|
{debug nowarnings c++}]} {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if {![runto_main]} {
|
||||||
|
untested "could not run to main"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[skip_compile_feature_tests]} {
|
||||||
|
untested \
|
||||||
|
"compile command not supported (could not find libcc1 shared library?)"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_breakpoint [gdb_get_line_number "break here" $srcfile]
|
||||||
|
gdb_continue_to_breakpoint "testing location"
|
||||||
|
|
||||||
|
gdb_test "compile print integers" " = \\{0, 0, 0, 0, 0, 0, 0, 0, 0, 0\\}"
|
||||||
|
|
||||||
|
gdb_test "compile print strings" " = \\{$hex \"hello\", $hex \"hello\",\
|
||||||
|
$hex \"hello\", $hex \"hello\", $hex \"hello\", $hex \"hello\",\
|
||||||
|
$hex \"hello\", $hex \"hello\", $hex \"hello\", $hex \"hello\"\\}"
|
58
gdb/testsuite/gdb.compile/compile-cplus-inherit.cc
Normal file
58
gdb/testsuite/gdb.compile/compile-cplus-inherit.cc
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/* Copyright 2015-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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/>. */
|
||||||
|
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
A () : a_ (1) {}
|
||||||
|
int do_it (int amount) { return a_ + amount; }
|
||||||
|
|
||||||
|
int a_;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct B
|
||||||
|
{
|
||||||
|
B () : b_ (2) {}
|
||||||
|
int do_it (int amount) { return b_ - amount; }
|
||||||
|
|
||||||
|
int b_;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct C
|
||||||
|
{
|
||||||
|
C () : c_ (3) {}
|
||||||
|
int do_it (int amount) { return c_ * amount; }
|
||||||
|
|
||||||
|
int c_;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct D : public A, B, C
|
||||||
|
{
|
||||||
|
D () : d_ (4) {}
|
||||||
|
|
||||||
|
int d_;
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
D d;
|
||||||
|
int var = 1234;
|
||||||
|
|
||||||
|
var = d.A::do_it (1)
|
||||||
|
+ d.B::do_it (2)
|
||||||
|
+ d.C::do_it (3); // break here
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
53
gdb/testsuite/gdb.compile/compile-cplus-inherit.exp
Normal file
53
gdb/testsuite/gdb.compile/compile-cplus-inherit.exp
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
# Copyright 2015-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
# Inheritance tests for GDB's C++ compile feature.
|
||||||
|
|
||||||
|
load_lib compile-support.exp
|
||||||
|
|
||||||
|
standard_testfile .cc
|
||||||
|
|
||||||
|
if {[skip_cplus_tests]} {
|
||||||
|
untested "skipping C++ tests"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[prepare_for_testing $testfile $testfile $srcfile \
|
||||||
|
{debug nowarnings c++}]} {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if {![runto_main]} {
|
||||||
|
untested "could not run to main"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[skip_compile_feature_tests]} {
|
||||||
|
untested \
|
||||||
|
"compile command not supported (could not find libcc1 shared library?)"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_breakpoint [gdb_get_line_number "break here" $srcfile]
|
||||||
|
gdb_continue_to_breakpoint "testing location"
|
||||||
|
|
||||||
|
CompileExpression::new "var"
|
||||||
|
CompileExpression::test "d.a_" 1
|
||||||
|
CompileExpression::test "d.b_" 2
|
||||||
|
CompileExpression::test "d.c_" 3
|
||||||
|
CompileExpression::test "d.d_" 4
|
||||||
|
CompileExpression::test "d.A::do_it (1)" 2
|
||||||
|
CompileExpression::test "d.B::do_it (1)" 1
|
||||||
|
CompileExpression::test "d.C::do_it (1)" 3
|
83
gdb/testsuite/gdb.compile/compile-cplus-member.cc
Normal file
83
gdb/testsuite/gdb.compile/compile-cplus-member.cc
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
/* Copyright 2015-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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/>. */
|
||||||
|
|
||||||
|
class A;
|
||||||
|
static int get_values (const A& a);
|
||||||
|
|
||||||
|
enum myenum {E_A = 10, E_B, E_C, E_D, E_E};
|
||||||
|
|
||||||
|
namespace N {
|
||||||
|
typedef enum {NA = 20, NB, NC, ND} ANON_NE;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
typedef enum {AA = 40, AB, AC, AD} ANON_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
ANON_E g_e = AC;
|
||||||
|
|
||||||
|
class A
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef int ATYPE;
|
||||||
|
|
||||||
|
A () : public_ (1), protected_ (N::NB), private_ (3) {}
|
||||||
|
ATYPE public_;
|
||||||
|
static const myenum s_public_;
|
||||||
|
friend ATYPE get_values (const A&);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
N::ANON_NE protected_;
|
||||||
|
static N::ANON_NE s_protected_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ATYPE private_;
|
||||||
|
static myenum s_private_;
|
||||||
|
};
|
||||||
|
|
||||||
|
const myenum A::s_public_ = E_A;
|
||||||
|
N::ANON_NE A::s_protected_ = N::NA;
|
||||||
|
myenum A::s_private_ = E_C;
|
||||||
|
|
||||||
|
static A::ATYPE
|
||||||
|
get_values (const A& a)
|
||||||
|
{
|
||||||
|
A::ATYPE val;
|
||||||
|
|
||||||
|
val = a.public_ + a.private_; // 1 + 3
|
||||||
|
if (a.protected_ == N::NB) // + 21
|
||||||
|
val += 21;
|
||||||
|
if (a.s_public_ == E_A) // +10
|
||||||
|
val += 10;
|
||||||
|
if (a.s_protected_ == N::NA) // +20
|
||||||
|
val += 20;
|
||||||
|
if (a.s_private_ == E_C) // +30
|
||||||
|
val += 30;
|
||||||
|
if (g_e == AC) // +40
|
||||||
|
val += 40;
|
||||||
|
return val; // = 125
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef int A::*PMI;
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
A a;
|
||||||
|
int var = 1234;
|
||||||
|
PMI pmi = &A::public_;
|
||||||
|
|
||||||
|
return a.*pmi + get_values (a); // break here
|
||||||
|
}
|
76
gdb/testsuite/gdb.compile/compile-cplus-member.exp
Normal file
76
gdb/testsuite/gdb.compile/compile-cplus-member.exp
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
# Copyright 2015-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
# Member tests for GDB's C++ compile feature.
|
||||||
|
|
||||||
|
load_lib compile-support.exp
|
||||||
|
|
||||||
|
standard_testfile .cc
|
||||||
|
|
||||||
|
if {[skip_cplus_tests]} {
|
||||||
|
untested "skipping C++ tests"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[prepare_for_testing $testfile $testfile $srcfile \
|
||||||
|
{debug nowarnings c++}]} {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if {![runto_main]} {
|
||||||
|
untested "could not run to main"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[skip_compile_feature_tests]} {
|
||||||
|
untested \
|
||||||
|
"compile command not supported (could not find libcc1 shared library?)"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_breakpoint [gdb_get_line_number "break here" $srcfile]
|
||||||
|
gdb_continue_to_breakpoint "testing location"
|
||||||
|
|
||||||
|
CompileExpression::new "var"
|
||||||
|
CompileExpression::test "a.public_" 1
|
||||||
|
CompileExpression::test "a.protected_" {(21|N::NB)}
|
||||||
|
CompileExpression::test "a.private_" 3
|
||||||
|
CompileExpression::test "A::s_public_" {(10|E_A)}
|
||||||
|
CompileExpression::test "A::s_protected_" {(20|N::NA)}
|
||||||
|
CompileExpression::test "A::s_private_" {(12|E_C)}
|
||||||
|
CompileExpression::test "A::ATYPE i = 10; var = i;" 10 -explicit
|
||||||
|
CompileExpression::test "get_values (a)" 125
|
||||||
|
CompileExpression::test "myenum me = E_B; var = me;" 11 -explicit
|
||||||
|
CompileExpression::test "A::s_protected_ = N::NB; var = A::s_protected_;" \
|
||||||
|
21 -explicit
|
||||||
|
CompileExpression::test "A::s_private_ = E_B; var = A::s_private_;" 11 -explicit
|
||||||
|
CompileExpression::test "N::ANON_NE ae = N::ND; var = ae;" 23 -explicit
|
||||||
|
CompileExpression::test {a.*pmi} 1
|
||||||
|
CompileExpression::test {a.public_ = 2; var = a.*pmi; a.public_ = 1} 2 -explicit
|
||||||
|
CompileExpression::test "g_e" {(42|AC)}
|
||||||
|
|
||||||
|
# Test some compilation failures
|
||||||
|
set failed {\r\nCompilation failed\.}
|
||||||
|
gdb_test "compile code a.s_public_ = E_B" \
|
||||||
|
".*assignment of read-only variable 'A::s_public_'$failed"
|
||||||
|
|
||||||
|
gdb_test "compile code get_values ()" \
|
||||||
|
".*too few arguments to function.*$failed"
|
||||||
|
|
||||||
|
gdb_test "compile code ATYPE i;" \
|
||||||
|
".*.ATYPE. was not declared in this scope$failed"
|
||||||
|
|
||||||
|
gdb_test "compile code N::ANON_NE nse = E_A" \
|
||||||
|
".*cannot convert.*$failed"
|
91
gdb/testsuite/gdb.compile/compile-cplus-method.cc
Normal file
91
gdb/testsuite/gdb.compile/compile-cplus-method.cc
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
/* Copyright 2015-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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/>. */
|
||||||
|
|
||||||
|
class A;
|
||||||
|
static int get_value (const A* a);
|
||||||
|
|
||||||
|
class A
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef int ATYPE;
|
||||||
|
|
||||||
|
A () : a_ (21) {}
|
||||||
|
ATYPE get_var () { return a_; }
|
||||||
|
ATYPE get_var (unsigned long a) { return 100; }
|
||||||
|
ATYPE get_var (ATYPE a) { return 101; }
|
||||||
|
ATYPE get_var (float a) { return 102; }
|
||||||
|
ATYPE get_var (void *a) { return 103;}
|
||||||
|
ATYPE get_var (A& lr) { return 104; }
|
||||||
|
ATYPE get_var (A const& lr) { return 105; }
|
||||||
|
|
||||||
|
ATYPE get_var1 (int n) { return a_ << n; }
|
||||||
|
ATYPE get_var2 (int incr, unsigned n) { return (a_ + incr) << n; }
|
||||||
|
|
||||||
|
static ATYPE get_1 (int a) { return a + 1; }
|
||||||
|
static ATYPE get_2 (int a, int b) { return a + b + 2; }
|
||||||
|
|
||||||
|
friend ATYPE get_value (const A*);
|
||||||
|
|
||||||
|
private:
|
||||||
|
ATYPE a_;
|
||||||
|
};
|
||||||
|
|
||||||
|
static A::ATYPE
|
||||||
|
get_value (A::ATYPE a)
|
||||||
|
{
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
static A::ATYPE
|
||||||
|
get_value (const A* a)
|
||||||
|
{
|
||||||
|
return a->a_;
|
||||||
|
}
|
||||||
|
|
||||||
|
static A::ATYPE
|
||||||
|
get_value ()
|
||||||
|
{
|
||||||
|
return 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef int (A::*PMF) (A::ATYPE);
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
A *a = new A ();
|
||||||
|
int var = 1234;
|
||||||
|
float f = 1.23;
|
||||||
|
unsigned long ul = 0xdeadbeef;
|
||||||
|
A const* ac = a;
|
||||||
|
|
||||||
|
PMF pmf = &A::get_var;
|
||||||
|
PMF *pmf_p = &pmf;
|
||||||
|
|
||||||
|
var -= a->get_var (); // break here
|
||||||
|
var -= a->get_var (1);
|
||||||
|
var -= a->get_var (ul);
|
||||||
|
var -= a->get_var (f);
|
||||||
|
var -= a->get_var (a);
|
||||||
|
var -= a->get_var (*a);
|
||||||
|
var -= a->get_var (*ac);
|
||||||
|
var -= a->get_var1 (1);
|
||||||
|
var -= a->get_var2 (1, 2);
|
||||||
|
var += (a->*pmf) (1);
|
||||||
|
var -= (a->**pmf_p) (1);
|
||||||
|
|
||||||
|
return var - A::get_1 (1) + A::get_2 (1, 2) + get_value ()
|
||||||
|
+ get_value (get_value ()) + get_value (a);
|
||||||
|
}
|
67
gdb/testsuite/gdb.compile/compile-cplus-method.exp
Normal file
67
gdb/testsuite/gdb.compile/compile-cplus-method.exp
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
# Copyright 2015-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
# Method tests for GDB's C++ compile feature.
|
||||||
|
|
||||||
|
load_lib compile-support.exp
|
||||||
|
|
||||||
|
standard_testfile .cc
|
||||||
|
|
||||||
|
if {[skip_cplus_tests]} {
|
||||||
|
untested "skipping C++ tests"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[prepare_for_testing $testfile $testfile $srcfile \
|
||||||
|
{debug nowarnings c++}]} {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if {![runto_main]} {
|
||||||
|
untested "could not run to main"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[skip_compile_feature_tests]} {
|
||||||
|
untested \
|
||||||
|
"compile command not supported (could not find libcc1 shared library?)"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_breakpoint [gdb_get_line_number "break here" $srcfile]
|
||||||
|
gdb_continue_to_breakpoint "testing location"
|
||||||
|
|
||||||
|
CompileExpression::new "var"
|
||||||
|
CompileExpression::test "a->get_var ()" 21
|
||||||
|
CompileExpression::test "a->get_var (static_cast<unsigned long> (1))" 100
|
||||||
|
CompileExpression::test "a->get_var (static_cast<int> (1))" 101
|
||||||
|
CompileExpression::test "a->get_var (static_cast<float> (1))" 102
|
||||||
|
CompileExpression::test "a->get_var (static_cast<void *> (a))" 103
|
||||||
|
CompileExpression::test "a->get_var (*a)" 104
|
||||||
|
CompileExpression::test "a->get_var (*ac)" 105
|
||||||
|
CompileExpression::test "a->get_var1 (1)" 42
|
||||||
|
CompileExpression::test "a->get_var2 (1, 2)" 88
|
||||||
|
CompileExpression::test "A::get_1 (1)" 2
|
||||||
|
CompileExpression::test "A::get_2 (1, 2)" 5
|
||||||
|
CompileExpression::test "A::get_1 (a->get_var ())" 22
|
||||||
|
CompileExpression::test "a->get_var1 (a->get_var () - 16)" 672
|
||||||
|
CompileExpression::test "a->get_var2 (a->get_var (), A::get_1 (2))" 336
|
||||||
|
CompileExpression::test "get_value ()" 200
|
||||||
|
CompileExpression::test "get_value (a)" 21
|
||||||
|
CompileExpression::test "get_value (get_value ())" 200
|
||||||
|
CompileExpression::test {(a->*pmf) (1)} 101
|
||||||
|
CompileExpression::test \
|
||||||
|
{pmf = &A::get_var1; var = (a->*pmf) (2); pmf = &A::get_var} 84 -explicit
|
||||||
|
CompileExpression::test {(a->**pmf_p) (1)} 101
|
28
gdb/testsuite/gdb.compile/compile-cplus-mod.c
Normal file
28
gdb/testsuite/gdb.compile/compile-cplus-mod.c
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
/* This testcase is part of GDB, the GNU debugger.
|
||||||
|
|
||||||
|
Copyright 2014-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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/>. */
|
||||||
|
|
||||||
|
extern "C" void
|
||||||
|
_gdb_expr ()
|
||||||
|
{
|
||||||
|
// Make 'globalvar' lookup working.
|
||||||
|
#pragma GCC push_user_expression
|
||||||
|
|
||||||
|
globalvar = 3;
|
||||||
|
globalvar += 4;
|
||||||
|
|
||||||
|
#pragma GCC pop_user_expression
|
||||||
|
}
|
52
gdb/testsuite/gdb.compile/compile-cplus-namespace.cc
Normal file
52
gdb/testsuite/gdb.compile/compile-cplus-namespace.cc
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/* Copyright 2015-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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/>. */
|
||||||
|
|
||||||
|
namespace N1
|
||||||
|
{
|
||||||
|
namespace N2
|
||||||
|
{
|
||||||
|
namespace N3
|
||||||
|
{
|
||||||
|
namespace N4
|
||||||
|
{
|
||||||
|
static int n4static = 400;
|
||||||
|
|
||||||
|
struct S4
|
||||||
|
{
|
||||||
|
static int s4static;
|
||||||
|
int s4int_;
|
||||||
|
S4 () : s4int_ (4) {};
|
||||||
|
~S4 () { --s4static; }
|
||||||
|
|
||||||
|
int get_var () { return s4int_; }
|
||||||
|
static int get_svar () { return s4static; }
|
||||||
|
};
|
||||||
|
int S4::s4static = 40;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
using namespace N1::N2::N3::N4;
|
||||||
|
|
||||||
|
S4 s4;
|
||||||
|
int var = 1234;
|
||||||
|
|
||||||
|
var += s4.s4int_; /* break here */
|
||||||
|
return S4::get_svar () - 10 * s4.get_var ();
|
||||||
|
}
|
51
gdb/testsuite/gdb.compile/compile-cplus-namespace.exp
Normal file
51
gdb/testsuite/gdb.compile/compile-cplus-namespace.exp
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
# Copyright 2015-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
# Namespace tests for GDB's C++ compile feature.
|
||||||
|
|
||||||
|
load_lib compile-support.exp
|
||||||
|
|
||||||
|
standard_testfile .cc
|
||||||
|
|
||||||
|
if {[skip_cplus_tests]} {
|
||||||
|
untested "skipping C++ tests"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[prepare_for_testing $testfile $testfile $srcfile \
|
||||||
|
{debug nowarnings c++}]} {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if {![runto_main]} {
|
||||||
|
untested "could not run to main"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[skip_compile_feature_tests]} {
|
||||||
|
untested \
|
||||||
|
"compile command not supported (could not find libcc1 shared library?)"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_breakpoint [gdb_get_line_number "break here" $srcfile]
|
||||||
|
gdb_continue_to_breakpoint "testing location"
|
||||||
|
|
||||||
|
CompileExpression::new "var"
|
||||||
|
CompileExpression::test "N1::N2::N3::N4::n4static" 400
|
||||||
|
CompileExpression::test "N1::N2::N3::N4::S4::s4static" 40
|
||||||
|
CompileExpression::test "s4.s4int_" 4
|
||||||
|
CompileExpression::test "N1::N2::N3::N4::S4::get_svar ()" 40
|
||||||
|
CompileExpression::test "s4.get_var ()" 4
|
58
gdb/testsuite/gdb.compile/compile-cplus-nested.cc
Normal file
58
gdb/testsuite/gdb.compile/compile-cplus-nested.cc
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/* Copyright 2015-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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/>. */
|
||||||
|
|
||||||
|
class A
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
A () : a_ (1) {}
|
||||||
|
int get ();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int a_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
/* It is important to not /not/ use the nested class definition in A.
|
||||||
|
This exercises a different path through the code. */
|
||||||
|
struct Inner1
|
||||||
|
{
|
||||||
|
int a_;
|
||||||
|
Inner1 () : a_ (2) {}
|
||||||
|
|
||||||
|
struct Inner2
|
||||||
|
{
|
||||||
|
int a_;
|
||||||
|
Inner2 () : a_ (3) {}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
A::get ()
|
||||||
|
{
|
||||||
|
A::Inner1 i1;
|
||||||
|
A::Inner1::Inner2 i2;
|
||||||
|
|
||||||
|
return i1.a_ + i2.a_; // break here
|
||||||
|
}
|
||||||
|
|
||||||
|
int var = 1234;
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
A a;
|
||||||
|
|
||||||
|
return a.get ();
|
||||||
|
}
|
53
gdb/testsuite/gdb.compile/compile-cplus-nested.exp
Normal file
53
gdb/testsuite/gdb.compile/compile-cplus-nested.exp
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
# Copyright 2015-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
# Nested type tests for GDB's C++ compile feature.
|
||||||
|
|
||||||
|
load_lib compile-support.exp
|
||||||
|
|
||||||
|
standard_testfile .cc
|
||||||
|
|
||||||
|
if {[skip_cplus_tests]} {
|
||||||
|
untested "skipping C++ tests"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[prepare_for_testing $testfile $testfile $srcfile \
|
||||||
|
{debug nowarnings c++}]} {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if {![runto_main]} {
|
||||||
|
untested "could not run to main"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[skip_compile_feature_tests]} {
|
||||||
|
untested \
|
||||||
|
"compile command not supported (could not find libcc1 shared library?)"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_breakpoint [gdb_get_line_number "break here" $srcfile]
|
||||||
|
gdb_continue_to_breakpoint "testing location"
|
||||||
|
|
||||||
|
CompileExpression::new "var"
|
||||||
|
CompileExpression::test "i1.a_" 2
|
||||||
|
CompileExpression::test "i2.a_" 3
|
||||||
|
CompileExpression::test "A::Inner1 *i1p = &i1; var = i1p->a_;" 2 -explicit
|
||||||
|
CompileExpression::test "A::Inner1::Inner2 *i2p = &i2; var = i2p->a_;" 3 \
|
||||||
|
-explicit
|
||||||
|
CompileExpression::test "A::Inner1 &r1 = i1; var = r1.a_;" 2 -explicit
|
||||||
|
CompileExpression::test "A::Inner1::Inner2 &r2 = i2; var = r2.a_;" 3 -explicit
|
32
gdb/testsuite/gdb.compile/compile-cplus-print.c
Normal file
32
gdb/testsuite/gdb.compile/compile-cplus-print.c
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/* This testcase is part of GDB, the GNU debugger.
|
||||||
|
|
||||||
|
Copyright 2015-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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/>. */
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int varint = 10;
|
||||||
|
int vararray[] = { 1, 2, 3, 4, 5 };
|
||||||
|
int *vararrayp = vararray;
|
||||||
|
struct object
|
||||||
|
{
|
||||||
|
int field;
|
||||||
|
} varobject = { 1 };
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
79
gdb/testsuite/gdb.compile/compile-cplus-print.exp
Normal file
79
gdb/testsuite/gdb.compile/compile-cplus-print.exp
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
# Copyright 2015-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
load_lib compile-support.exp
|
||||||
|
|
||||||
|
standard_testfile
|
||||||
|
|
||||||
|
get_compiler_info
|
||||||
|
set options {}
|
||||||
|
if [test_compiler_info gcc*] {
|
||||||
|
lappend options additional_flags=-g3
|
||||||
|
lappend options additional_flags=-std=gnu++11
|
||||||
|
lappend options c++
|
||||||
|
}
|
||||||
|
|
||||||
|
set srcfilesoptions [list ${srcfile} ${options}]
|
||||||
|
|
||||||
|
if { [eval build_executable_from_specs ${testfile}.exp $testfile {$options} ${srcfilesoptions}] } {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
clean_restart ${testfile}
|
||||||
|
|
||||||
|
if {[skip_compile_feature_tests]} {
|
||||||
|
untested "compile command not supported (could not find libcc1 shared library?)"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_test_no_output "set language c++" \
|
||||||
|
"Set language to C++"
|
||||||
|
|
||||||
|
if ![runto_main] {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_test "compile print varint" " = 10"
|
||||||
|
gdb_test "compile print vararray" " = \\{1, 2, 3, 4, 5\\}"
|
||||||
|
|
||||||
|
setup_kfail compile/23586 *-*-*
|
||||||
|
gdb_test "compile print main" " = \\{int \\(void\\)\\} 0x\[0-9a-f\]+"
|
||||||
|
|
||||||
|
setup_kfail compile/23587 *-*-*
|
||||||
|
set test "compile print *vararray@3"
|
||||||
|
gdb_test_multiple $test $test {
|
||||||
|
-re " = \\{1, 2, 3\\}\r\n$gdb_prompt $" {
|
||||||
|
pass $test
|
||||||
|
}
|
||||||
|
-re "warning: .*All references to this method will be undefined\.\r\n" {
|
||||||
|
exp_continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setup_kfail compile/23587 *-*-*
|
||||||
|
set test "compile print *vararrayp@3"
|
||||||
|
gdb_test_multiple $test $test {
|
||||||
|
-re " = \\{1, 2, 3\\}\r\n$gdb_prompt $" {
|
||||||
|
pass $test
|
||||||
|
}
|
||||||
|
-re "warning: .*All references to this method will be undefined\.\r\n" {
|
||||||
|
exp_continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_test "compile print/x 256" " = 0x100"
|
||||||
|
gdb_test {print $} " = 256"
|
||||||
|
|
||||||
|
gdb_test "compile print varobject" { = {field = 1}}
|
54
gdb/testsuite/gdb.compile/compile-cplus-virtual.cc
Normal file
54
gdb/testsuite/gdb.compile/compile-cplus-virtual.cc
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
/* Copyright 2015-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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/>. */
|
||||||
|
|
||||||
|
struct A
|
||||||
|
{
|
||||||
|
virtual int doit () { return 1; }
|
||||||
|
virtual int doit3 () { return -3; }
|
||||||
|
virtual int doit2 () = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct B : virtual A
|
||||||
|
{
|
||||||
|
int doit () { return 2; }
|
||||||
|
int doit2 () { return 22; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct C : virtual A
|
||||||
|
{
|
||||||
|
int doit () { return 3; }
|
||||||
|
int doit2 () { return 33; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct D : B, C
|
||||||
|
{
|
||||||
|
int doit () { return 4; }
|
||||||
|
int doit2 () { return 44; }
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
int var = 1234;
|
||||||
|
B b;
|
||||||
|
C c;
|
||||||
|
D d;
|
||||||
|
A *ap = &d;
|
||||||
|
|
||||||
|
var = (b.doit () + c.doit () + d.doit () + d.doit3 ()
|
||||||
|
+ ap->doit () + ap->doit2 ()); // break here
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
71
gdb/testsuite/gdb.compile/compile-cplus-virtual.exp
Normal file
71
gdb/testsuite/gdb.compile/compile-cplus-virtual.exp
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
# Copyright 2015-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
# Virtual method/inheritance tests for GDB's C++ compile feature.
|
||||||
|
|
||||||
|
load_lib compile-support.exp
|
||||||
|
|
||||||
|
standard_testfile .cc
|
||||||
|
|
||||||
|
if {[skip_cplus_tests]} {
|
||||||
|
untested "skipping C++ tests"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[prepare_for_testing $testfile $testfile $srcfile \
|
||||||
|
{debug nowarnings c++}]} {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if {![runto_main]} {
|
||||||
|
untested "could not run to main"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[skip_compile_feature_tests]} {
|
||||||
|
untested \
|
||||||
|
"compile command not supported (could not find libcc1 shared library?)"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_breakpoint [gdb_get_line_number "break here" $srcfile]
|
||||||
|
gdb_continue_to_breakpoint "testing location"
|
||||||
|
|
||||||
|
CompileExpression::new "var"
|
||||||
|
CompileExpression::test "b.doit ()" 2
|
||||||
|
CompileExpression::test "c.doit ()" 3
|
||||||
|
CompileExpression::test "d.doit ()" 4
|
||||||
|
CompileExpression::test "ap->doit ()" 4
|
||||||
|
CompileExpression::test "b.doit2 ()" 22
|
||||||
|
CompileExpression::test "c.doit2 ()" 33
|
||||||
|
CompileExpression::test "d.doit2 ()" 44
|
||||||
|
CompileExpression::test "ap->doit2 ()" 44
|
||||||
|
CompileExpression::test "b.doit3 ()" -3
|
||||||
|
CompileExpression::test "c.doit3 ()" -3
|
||||||
|
CompileExpression::test "d.doit3 ()" -3
|
||||||
|
|
||||||
|
# These two tests are "disabled". They represent new/future features.
|
||||||
|
# CompileExpression::test \
|
||||||
|
[concat "struct ABC {int doit2() { return 3333; }} abc;" \
|
||||||
|
"var = abc.doit2()"] \
|
||||||
|
3333 -explicit
|
||||||
|
# CompileExpression::test \
|
||||||
|
[concat "struct ABC : A {int doit2() { return 4444; }} abc;" \
|
||||||
|
"var = abc.doit2()"] \
|
||||||
|
4444 -explicit
|
||||||
|
|
||||||
|
# Test some error conditions
|
||||||
|
gdb_test "compile code A a;" \
|
||||||
|
".*cannot declare variable .a. to be of abstract type.*Compilation failed."
|
241
gdb/testsuite/gdb.compile/compile-cplus.c
Normal file
241
gdb/testsuite/gdb.compile/compile-cplus.c
Normal file
|
@ -0,0 +1,241 @@
|
||||||
|
/* This testcase is part of GDB, the GNU debugger.
|
||||||
|
|
||||||
|
Copyright 2014-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
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/>. */
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#define SOME_MACRO 23
|
||||||
|
#define ARG_MACRO(X, Y) ((X) + (Y) - 1)
|
||||||
|
|
||||||
|
|
||||||
|
enum enum_type {
|
||||||
|
ONE = 1,
|
||||||
|
TWO = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef int v4 __attribute__ ((vector_size (16)));
|
||||||
|
|
||||||
|
union union_type;
|
||||||
|
|
||||||
|
struct struct_type {
|
||||||
|
char charfield;
|
||||||
|
unsigned char ucharfield;
|
||||||
|
short shortfield;
|
||||||
|
unsigned short ushortfield;
|
||||||
|
int intfield;
|
||||||
|
unsigned int uintfield;
|
||||||
|
unsigned int bitfield : 3;
|
||||||
|
long longfield;
|
||||||
|
unsigned long ulongfield;
|
||||||
|
enum enum_type enumfield;
|
||||||
|
float floatfield;
|
||||||
|
double doublefield;
|
||||||
|
const union union_type *ptrfield;
|
||||||
|
struct struct_type *selffield;
|
||||||
|
int arrayfield[5];
|
||||||
|
_Complex double complexfield;
|
||||||
|
_Bool boolfield;
|
||||||
|
v4 vectorfield;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef int inttypedef;
|
||||||
|
|
||||||
|
union union_type {
|
||||||
|
int intfield;
|
||||||
|
inttypedef typedeffield;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* volatile provides some coverage of the conversion code. */
|
||||||
|
volatile struct struct_type struct_object;
|
||||||
|
|
||||||
|
union union_type union_object;
|
||||||
|
|
||||||
|
|
||||||
|
enum ulonger_enum_type {
|
||||||
|
REALLY_MINUS_1 = -1UL,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ulonger_enum_type ulonger;
|
||||||
|
|
||||||
|
enum longer_enum_type {
|
||||||
|
MINUS_1 = -1,
|
||||||
|
FORCE_TO_LONG = 1L << ((8 * sizeof (long)) - 2)
|
||||||
|
};
|
||||||
|
|
||||||
|
enum longer_enum_type longer;
|
||||||
|
|
||||||
|
int globalvar = 10;
|
||||||
|
|
||||||
|
static void
|
||||||
|
func_static (int addend)
|
||||||
|
{
|
||||||
|
globalvar += addend;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
func_global (int subtrahend)
|
||||||
|
{
|
||||||
|
globalvar -= subtrahend;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
no_args_or_locals ()
|
||||||
|
{
|
||||||
|
/* no_args_or_locals breakpoint */
|
||||||
|
}
|
||||||
|
|
||||||
|
int *intptr;
|
||||||
|
int globalshadow = 10;
|
||||||
|
static int staticshadow = 20;
|
||||||
|
int externed = 7;
|
||||||
|
|
||||||
|
class Base
|
||||||
|
{
|
||||||
|
virtual int pure_virt () = 0;
|
||||||
|
public:
|
||||||
|
int return_value () {return a;}
|
||||||
|
private:
|
||||||
|
int a = 1;
|
||||||
|
int b = 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Base2
|
||||||
|
{
|
||||||
|
virtual int non_pure () {return 84;}
|
||||||
|
public:
|
||||||
|
int return_value () {return b;}
|
||||||
|
private:
|
||||||
|
int a = 3;
|
||||||
|
int b = 4;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Base3
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int return_value () {return b;}
|
||||||
|
private:
|
||||||
|
int b = 5;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Multiple : public Base, public Base2
|
||||||
|
{
|
||||||
|
int pure_virt ()
|
||||||
|
{
|
||||||
|
int a = Base::return_value ();
|
||||||
|
return a + 42;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//struct foo { foo(); virtual ~foo(); }; struct bar : virtual foo { bar(); ~bar(); }; struct baz : bar {}; bar::bar() {} bar::~bar() {} bar t; baz u;
|
||||||
|
struct VirtualOnly
|
||||||
|
{
|
||||||
|
VirtualOnly();
|
||||||
|
virtual ~VirtualOnly()=0;
|
||||||
|
};
|
||||||
|
|
||||||
|
VirtualOnly::VirtualOnly ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VirtualOnly::~VirtualOnly ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
struct VirtualBase : virtual VirtualOnly
|
||||||
|
{
|
||||||
|
int z = 22;
|
||||||
|
VirtualBase ();
|
||||||
|
~VirtualBase ();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VirtualBase2 : VirtualBase {};
|
||||||
|
|
||||||
|
VirtualBase::VirtualBase ()
|
||||||
|
{
|
||||||
|
z = 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
VirtualBase::~VirtualBase ()
|
||||||
|
{
|
||||||
|
z = 22;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Foo
|
||||||
|
{
|
||||||
|
int var;
|
||||||
|
static const int public_static_var = 12;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int private_var = 0;
|
||||||
|
int private_method ();
|
||||||
|
|
||||||
|
public:
|
||||||
|
int public_var = 0;
|
||||||
|
int public_method ();
|
||||||
|
void set_private_var (int);
|
||||||
|
};
|
||||||
|
|
||||||
|
void Foo::set_private_var (int i)
|
||||||
|
{
|
||||||
|
private_var = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Foo::private_method ()
|
||||||
|
{
|
||||||
|
return private_var;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Foo::public_method ()
|
||||||
|
{
|
||||||
|
return public_var;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main ()
|
||||||
|
{
|
||||||
|
int localvar = 50;
|
||||||
|
int shadowed = 51;
|
||||||
|
int bound = 3;
|
||||||
|
int unresolved = 10;
|
||||||
|
int globalshadow = 100;
|
||||||
|
int staticshadow = 200;
|
||||||
|
int externed = 9;
|
||||||
|
int f = 0;
|
||||||
|
int var = 0;
|
||||||
|
Foo foovar;
|
||||||
|
Multiple *multivar = new Multiple;
|
||||||
|
VirtualBase vbase;
|
||||||
|
VirtualBase2 vbase2;
|
||||||
|
static int static_local = 77000;
|
||||||
|
|
||||||
|
foovar.public_var = 42;
|
||||||
|
foovar.set_private_var (42);
|
||||||
|
multivar->Base2::return_value();
|
||||||
|
{
|
||||||
|
int another_local = 7;
|
||||||
|
int shadowed = 52;
|
||||||
|
extern int unresolved;
|
||||||
|
extern int externed;
|
||||||
|
|
||||||
|
int vla[bound];
|
||||||
|
|
||||||
|
func_static (0); /* break-here */
|
||||||
|
no_args_or_locals ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
347
gdb/testsuite/gdb.compile/compile-cplus.exp
Normal file
347
gdb/testsuite/gdb.compile/compile-cplus.exp
Normal file
|
@ -0,0 +1,347 @@
|
||||||
|
# Copyright 2014-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
load_lib compile-support.exp
|
||||||
|
|
||||||
|
standard_testfile .c compile-shlib.c compile-constvar.S compile-nodebug.c
|
||||||
|
|
||||||
|
get_compiler_info
|
||||||
|
set options {}
|
||||||
|
if [test_compiler_info gcc*] {
|
||||||
|
lappend options additional_flags=-g3
|
||||||
|
lappend options additional_flags=-std=gnu++11
|
||||||
|
lappend options c++
|
||||||
|
}
|
||||||
|
|
||||||
|
if { ![istarget x86_64-*-* ] || ![is_lp64_target] } {
|
||||||
|
verbose "Skipping x86_64 LOC_CONST test."
|
||||||
|
set srcfile3 ""
|
||||||
|
}
|
||||||
|
|
||||||
|
set srcfilesoptions [list ${srcfile} ${options}]
|
||||||
|
if { $srcfile3 != "" } {
|
||||||
|
lappend srcfilesoptions $srcfile3 ${options}
|
||||||
|
}
|
||||||
|
lappend srcfilesoptions $srcfile4 "nodebug c++"
|
||||||
|
if { [eval build_executable_from_specs ${testfile}.exp $testfile {$options} ${srcfilesoptions}] } {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
clean_restart ${testfile}
|
||||||
|
|
||||||
|
#
|
||||||
|
# FIXME: Right now, for C++ we just duplicate the C tests, but force
|
||||||
|
# the language to C++
|
||||||
|
#
|
||||||
|
gdb_test_no_output "set language c++" \
|
||||||
|
"Set language to C++"
|
||||||
|
|
||||||
|
if ![runto_main] {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[skip_compile_feature_tests]} {
|
||||||
|
untested "compile command not supported (could not find libcc1 shared library?)"
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test delimiter for code, and arguments.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
gdb_test_no_output "compile code globalvar = SOME_MACRO;" \
|
||||||
|
"set variable from macro"
|
||||||
|
gdb_test "p globalvar" " = 23" "expect 23"
|
||||||
|
|
||||||
|
gdb_test_no_output "compile code globalvar = ARG_MACRO(0, 0);" \
|
||||||
|
"set variable from function-like macro"
|
||||||
|
gdb_test "p globalvar" " = -1" "expect -1"
|
||||||
|
|
||||||
|
gdb_test_no_output "compile code globalvar = 42;" "set variable"
|
||||||
|
gdb_test "p globalvar" " = 42" "expect 42"
|
||||||
|
|
||||||
|
gdb_test_no_output "compile code globalvar *= 2;" "modify variable"
|
||||||
|
gdb_test "p globalvar" " = 84" "expect 84"
|
||||||
|
|
||||||
|
gdb_test_no_output "compile file -r ${srcdir}/${subdir}/${testfile}-mod.c" \
|
||||||
|
"use external source file"
|
||||||
|
gdb_test "p globalvar" " = 7" "expect 7"
|
||||||
|
|
||||||
|
gdb_test_no_output "compile code func_static (2);" "call static function"
|
||||||
|
gdb_test "p globalvar" " = 9" "expect 9"
|
||||||
|
gdb_test_no_output "compile code func_global (1);" "call global function"
|
||||||
|
gdb_test "p globalvar" " = 8" "expect 8"
|
||||||
|
|
||||||
|
gdb_test_no_output \
|
||||||
|
"compile code globalvar = (sizeof (ulonger) == sizeof (long))" \
|
||||||
|
"compute size of ulonger"
|
||||||
|
gdb_test "p globalvar" " = 1" "check size of ulonger"
|
||||||
|
gdb_test_no_output \
|
||||||
|
"compile code globalvar = (sizeof (longer) == sizeof (long))" \
|
||||||
|
"compute size of longer"
|
||||||
|
gdb_test "p globalvar" " = 1" "check size of longer"
|
||||||
|
gdb_test_no_output "compile code globalvar = MINUS_1"
|
||||||
|
gdb_test "p globalvar" " = -1" "check MINUS_1"
|
||||||
|
|
||||||
|
gdb_test_no_output "compile code globalvar = static_local"
|
||||||
|
gdb_test "p globalvar" " = 77000" "check static_local"
|
||||||
|
|
||||||
|
gdb_test_no_output \
|
||||||
|
"compile code static int staticvar = 5; intptr = &staticvar" \
|
||||||
|
"do not keep jit in memory"
|
||||||
|
gdb_test "p *intptr" "Cannot access memory at address 0x\[0-9a-f\]+" \
|
||||||
|
"expect 5"
|
||||||
|
|
||||||
|
gdb_test "compile code func_doesnotexist ();" "error: \'func_doesnotexist\' was not declared in this scope.*"
|
||||||
|
|
||||||
|
gdb_test "compile code *(volatile int *) 0 = 0;" \
|
||||||
|
"The program being debugged was signaled while in a function called from GDB\\.\r\nGDB remains in the frame where the signal was received\\.\r\n.*" \
|
||||||
|
"compile code segfault first"
|
||||||
|
gdb_test "bt" \
|
||||||
|
"\r\n#0 \[^\r\n\]* in _gdb_expr \[^\r\n\]*\r\n#1 <function called from gdb>\r\n.*"
|
||||||
|
|
||||||
|
set test "p/x \$pc"
|
||||||
|
set infcall_pc 0
|
||||||
|
gdb_test_multiple $test $test {
|
||||||
|
-re " = (0x\[0-9a-f\]+)\r\n$gdb_prompt $" {
|
||||||
|
set infcall_pc $expect_out(1,string)
|
||||||
|
pass $test
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_test "info sym $infcall_pc" "\r\n_gdb_expr.*" "info sym found"
|
||||||
|
gdb_test "return" "\r\n#0 main .*" "return" \
|
||||||
|
"Make _gdb_expr\\(__gdb_regs\\*\\) return now\\? \\(y or n\\) " "y"
|
||||||
|
gdb_test "info sym $infcall_pc" "\r\nNo symbol matches .*" "info sym not found"
|
||||||
|
|
||||||
|
gdb_test_no_output "set unwindonsignal on"
|
||||||
|
gdb_test "compile code *(volatile int *) 0 = 0;" \
|
||||||
|
"The program being debugged was signaled while in a function called from GDB\\.\r\nGDB has restored the context to what it was before the call\\.\r\n.*" \
|
||||||
|
"compile code segfault second"
|
||||||
|
|
||||||
|
gdb_breakpoint [gdb_get_line_number "break-here"]
|
||||||
|
gdb_continue_to_breakpoint "break-here" ".* break-here .*"
|
||||||
|
|
||||||
|
# C++ Specific tests.
|
||||||
|
## Public methods and members
|
||||||
|
|
||||||
|
gdb_test "print foovar.public_var" "42" \
|
||||||
|
"Test compile code foovar.public_var = 42 setting."
|
||||||
|
gdb_test_no_output "compile code foovar.public_var = 43;" \
|
||||||
|
"set foobar.public_var to 43"
|
||||||
|
gdb_test "print foovar.public_var" "43" \
|
||||||
|
"Test compile code foovar.public_var = 43 setting."
|
||||||
|
gdb_test "print foovar.public_method ()" "43" \
|
||||||
|
"Test compile code foovar.public_method = 43 setting."
|
||||||
|
|
||||||
|
## Private methods and members
|
||||||
|
gdb_test_no_output "compile code foovar.set_private_var (84);" \
|
||||||
|
"Call class function to set private_var"
|
||||||
|
gdb_test "print foovar.private_var" "84" \
|
||||||
|
"Test compile code foovar.set_private_var = 84 setting."
|
||||||
|
gdb_test_no_output "compile code foovar.private_var = 85" \
|
||||||
|
"Directly set a private member in GDB compile5"
|
||||||
|
gdb_test "print foovar.private_var" "85" \
|
||||||
|
"Test compile code foovar.set_private_var = 85 setting."
|
||||||
|
|
||||||
|
## Simple inheritance
|
||||||
|
CompileExpression::new "var"
|
||||||
|
CompileExpression::test "class Baz: public Foo {public: int z = 12;}; Baz bazvar; bazvar.z = 24; var = bazvar.z" 24 -explicit
|
||||||
|
## Multiple inheritance
|
||||||
|
CompileExpression::test "class MI: public Base, public Base2 {int pure_virt () {return 42;}}; MI MIVar; var = MIVar.pure_virt();" 42 -explicit
|
||||||
|
CompileExpression::test "class MI: public Base, public Base2 {int pure_virt () {return Base::return_value() + 42;}}; MI MIVar; var = MIVar.pure_virt();" 43 -explicit
|
||||||
|
CompileExpression::test "class Base3 {public: int z = 99;}; class MI: public Base, public Base3 {int pure_virt () {return Base3::z + 42;}}; MI MIVar; var = MIVar.pure_virt();" 141 -explicit
|
||||||
|
|
||||||
|
gdb_test "p localvar" " = 50" "expect localvar 50"
|
||||||
|
|
||||||
|
gdb_test_no_output "compile code localvar = 12;" "set localvar"
|
||||||
|
gdb_test "p localvar" " = 12" "expect 12"
|
||||||
|
|
||||||
|
gdb_test_no_output "compile code localvar *= 2;" "modify localvar"
|
||||||
|
gdb_test "p localvar" " = 24" "expect 24"
|
||||||
|
|
||||||
|
gdb_test_no_output "compile code localvar = shadowed" \
|
||||||
|
"test shadowing"
|
||||||
|
gdb_test "p localvar" " = 52" "expect 52"
|
||||||
|
|
||||||
|
gdb_test_no_output "compile code localvar = externed"
|
||||||
|
gdb_test "p localvar" " = 7" "test extern in inner scope"
|
||||||
|
|
||||||
|
gdb_test_no_output "compile code vla\[2\] = 7"
|
||||||
|
gdb_test "p vla\[2\]" " = 7"
|
||||||
|
gdb_test_no_output \
|
||||||
|
"compile code localvar = (sizeof (vla) == bound * sizeof (vla\[0\]))"
|
||||||
|
gdb_test "p localvar" " = 1"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test setting fields and also many different types.
|
||||||
|
#
|
||||||
|
|
||||||
|
gdb_test_no_output "compile code struct_object.selffield = (struct_type*)&struct_object"
|
||||||
|
gdb_test "print struct_object.selffield == &struct_object" " = true"
|
||||||
|
|
||||||
|
gdb_test_no_output "compile code struct_object.charfield = 1"
|
||||||
|
gdb_test "print struct_object.charfield" " = 1 '\\\\001'"
|
||||||
|
gdb_test_no_output "compile code struct_object.ucharfield = 1"
|
||||||
|
gdb_test "print struct_object.ucharfield" " = 1 '\\\\001'"
|
||||||
|
|
||||||
|
foreach {field value} {
|
||||||
|
shortfield -5
|
||||||
|
ushortfield 5
|
||||||
|
intfield -7
|
||||||
|
uintfield 7
|
||||||
|
bitfield 2
|
||||||
|
longfield -9
|
||||||
|
ulongfield 9
|
||||||
|
enumfield ONE
|
||||||
|
floatfield 1
|
||||||
|
doublefield 2
|
||||||
|
} {
|
||||||
|
gdb_test_no_output "compile code struct_object.$field = $value"
|
||||||
|
gdb_test "print struct_object.$field" " = $value"
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_test_no_output "compile code struct_object.arrayfield\[2\] = 7"
|
||||||
|
gdb_test "print struct_object.arrayfield" \
|
||||||
|
" = \\{0, 0, 7, 0, 0\\}"
|
||||||
|
|
||||||
|
gdb_test_no_output "compile code struct_object.complexfield = 7 + 5i"
|
||||||
|
gdb_test "print struct_object.complexfield" " = 7 \\+ 5 \\* I"
|
||||||
|
|
||||||
|
gdb_test_no_output "compile code struct_object.boolfield = 1"
|
||||||
|
gdb_test "print struct_object.boolfield" " = true"
|
||||||
|
|
||||||
|
gdb_test_no_output "compile code struct_object.vectorfield\[2\] = 7"
|
||||||
|
gdb_test "print struct_object.vectorfield" \
|
||||||
|
" = \\{0, 0, 7, 0\\}"
|
||||||
|
|
||||||
|
gdb_test_no_output "compile code union_object.typedeffield = 7"
|
||||||
|
gdb_test "print union_object.typedeffield" " = 7"
|
||||||
|
gdb_test "print union_object.intfield" " = 7"
|
||||||
|
|
||||||
|
|
||||||
|
# LOC_UNRESOLVED tests.
|
||||||
|
|
||||||
|
gdb_test "print unresolved" " = 20"
|
||||||
|
gdb_test "compile code globalvar = unresolved;"
|
||||||
|
gdb_test "print globalvar" " = 20" "print unresolved value"
|
||||||
|
|
||||||
|
# Test shadowing with global and static variables.
|
||||||
|
|
||||||
|
gdb_test_no_output "compile code globalshadow += 1;"
|
||||||
|
gdb_test "print globalshadow" " = 101"
|
||||||
|
gdb_test_no_output "compile code extern int globalshadow; globalshadow += 5;"
|
||||||
|
gdb_test "print 'compile-cplus.c'::globalshadow" " = 15"
|
||||||
|
gdb_test "print globalshadow" " = 101" "print globalshadow second time"
|
||||||
|
gdb_test_no_output "compile code staticshadow += 2;"
|
||||||
|
gdb_test "print staticshadow" " = 202"
|
||||||
|
# "extern int staticshadow;" cannot access static variable.
|
||||||
|
|
||||||
|
# Raw code cannot refer to locals.
|
||||||
|
# As it references global variable we need the #pragma.
|
||||||
|
# For #pragma we need multiline input.
|
||||||
|
gdb_test_multiple "compile code -r" "compile code -r multiline 1" { -re "\r\n>$" {} }
|
||||||
|
gdb_test_multiple "void _gdb_expr(void) {" "compile code -r multiline 2" { -re "\r\n>$" {} }
|
||||||
|
gdb_test_multiple "#pragma GCC push_user_expression" "compile code -r multiline 3" { -re "\r\n>$" {} }
|
||||||
|
gdb_test_multiple " globalshadow = 77000;" "compile code -r multiline 4" { -re "\r\n>$" {} }
|
||||||
|
gdb_test_multiple "#pragma GCC pop_user_expression" "compile code -r multiline 5" { -re "\r\n>$" {} }
|
||||||
|
gdb_test_multiple "}" "compile code -r multiline 6" { -re "\r\n>$" {} }
|
||||||
|
gdb_test_no_output "end" "compile code -r multiline 7"
|
||||||
|
gdb_test "print 'compile-cplus.c'::globalshadow" " = 77000" \
|
||||||
|
"check globalshadow with -r"
|
||||||
|
|
||||||
|
# Test GOT vs. resolving jit function pointers.
|
||||||
|
|
||||||
|
gdb_test_no_output "compile -raw -- extern \"C\" void abort(); int func(){return 21;} void _gdb_expr(){int (*funcp)()=func; if (funcp()!=21) abort();}" \
|
||||||
|
"pointer to jit function"
|
||||||
|
|
||||||
|
#
|
||||||
|
# Test the case where the registers structure would not normally have
|
||||||
|
# any fields.
|
||||||
|
#
|
||||||
|
|
||||||
|
gdb_breakpoint [gdb_get_line_number "no_args_or_locals breakpoint"]
|
||||||
|
gdb_continue_to_breakpoint "no_args_or_locals"
|
||||||
|
|
||||||
|
gdb_test_no_output "compile code globalvar = 77;" "set variable to 77"
|
||||||
|
gdb_test "p globalvar" " = 77" "expect 77"
|
||||||
|
|
||||||
|
|
||||||
|
# Test reference to minimal_symbol, not (full) symbol.
|
||||||
|
|
||||||
|
setup_kfail compile/23585 *-*-*
|
||||||
|
gdb_test_no_output "compile code globalvar = func_nodebug (75);" \
|
||||||
|
"call func_nodebug"
|
||||||
|
|
||||||
|
setup_kfail compile/23585 *-*-*
|
||||||
|
gdb_test "p globalvar" " = -75" "expect -75"
|
||||||
|
|
||||||
|
setup_kfail compile/23585 *-*-*
|
||||||
|
gdb_test_no_output \
|
||||||
|
"compile code int (*funcp) (int) = (int(*)(int))func_nodebug; globalvar = funcp (76);" \
|
||||||
|
"call func_nodebug indirectly"
|
||||||
|
setup_kfail compile/23585 *-*-*
|
||||||
|
gdb_test "p globalvar" " = -76" "expect -76"
|
||||||
|
|
||||||
|
|
||||||
|
# Test compiled module memory protection.
|
||||||
|
|
||||||
|
gdb_test_no_output "set debug compile on"
|
||||||
|
gdb_test "compile code static const int readonly = 1; *(int *) &readonly = 2;" \
|
||||||
|
"The program being debugged was signaled while in a function called from GDB\\.\r\nGDB has restored the context to what it was before the call\\.\r\n.*"
|
||||||
|
gdb_test_no_output "set debug compile off"
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Some simple coverage tests.
|
||||||
|
#
|
||||||
|
|
||||||
|
gdb_test "show debug compile" "Compile debugging is .*"
|
||||||
|
gdb_test "show compile-args" \
|
||||||
|
"Compile command command-line arguments are .*"
|
||||||
|
gdb_test "compile code -z" "Unknown argument.*"
|
||||||
|
|
||||||
|
gdb_test "set lang rust" \
|
||||||
|
"Warning: the current language does not match this frame."
|
||||||
|
gdb_test "compile code globalvar" "No compiler support for language rust\."
|
||||||
|
gdb_test_no_output "set lang auto"
|
||||||
|
|
||||||
|
gdb_test_no_output "compile code union union_type newdecl_u"
|
||||||
|
gdb_test_no_output "compile code struct struct_type newdecl_s"
|
||||||
|
gdb_test_no_output "compile code inttypedef newdecl_i"
|
||||||
|
|
||||||
|
gdb_test "compile file" \
|
||||||
|
"You must provide a filename for this command.*" \
|
||||||
|
"Test compile file without a filename"
|
||||||
|
gdb_test "compile file -r" \
|
||||||
|
"You must provide a filename with the raw option set.*" \
|
||||||
|
"Test compile file and raw option without a filename"
|
||||||
|
gdb_test "compile file -z" \
|
||||||
|
"Unknown argument.*" \
|
||||||
|
"Test compile file with unknown argument"
|
||||||
|
|
||||||
|
|
||||||
|
# LOC_CONST tests.
|
||||||
|
|
||||||
|
if { $srcfile3 != "" } {
|
||||||
|
gdb_test "p constvar" " = 3"
|
||||||
|
gdb_test "info addr constvar" {Symbol "constvar" is constant\.}
|
||||||
|
|
||||||
|
gdb_test_no_output "compile code globalvar = constvar;"
|
||||||
|
gdb_test "print globalvar" " = 3" "print constvar value"
|
||||||
|
} else {
|
||||||
|
untested "print constvar value"
|
||||||
|
}
|
227
gdb/testsuite/lib/compile-support.exp
Normal file
227
gdb/testsuite/lib/compile-support.exp
Normal file
|
@ -0,0 +1,227 @@
|
||||||
|
# Copyright 2015-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# 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/>.
|
||||||
|
|
||||||
|
# Generic/oft used support routines for testing GDB's compile feature.
|
||||||
|
|
||||||
|
# Return 1 if we should skip tests of the "compile" feature.
|
||||||
|
# This must be invoked after the inferior has been started.
|
||||||
|
|
||||||
|
proc skip_compile_feature_tests {} {
|
||||||
|
global gdb_prompt
|
||||||
|
|
||||||
|
set result 0
|
||||||
|
gdb_test_multiple "compile code -- ;" "check for working compile command" {
|
||||||
|
"Could not load libcc1.*\r\n$gdb_prompt $" {
|
||||||
|
set result 1
|
||||||
|
}
|
||||||
|
-re "Command not supported on this host\\..*\r\n$gdb_prompt $" {
|
||||||
|
set result 1
|
||||||
|
}
|
||||||
|
-re "\r\n$gdb_prompt $" {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $result
|
||||||
|
}
|
||||||
|
|
||||||
|
# This namespace provides some convenience functions for running
|
||||||
|
# "compile code" and "compile print" tests.
|
||||||
|
#
|
||||||
|
# Exported functions are defined inline below.
|
||||||
|
#
|
||||||
|
# General usage:
|
||||||
|
#
|
||||||
|
# Start a new session, noting that the variable "var" will be used for
|
||||||
|
# "compile code" expressions. This variable /must/ exist in the stopped
|
||||||
|
# location.
|
||||||
|
#
|
||||||
|
# CompileExpression::new "var"
|
||||||
|
#
|
||||||
|
# Test the implicit expression "foo;" with result/value 3.
|
||||||
|
# CompileExpression::test "foo" 3
|
||||||
|
# ---> Runs the following tests (name of tests ignored for illustration)
|
||||||
|
# gdb_test_no_output "compile code var = foo"
|
||||||
|
# gdb_test "p var" "= 3"
|
||||||
|
# gdb_test "compile print foo;" "= 3"
|
||||||
|
#
|
||||||
|
# Test the explicit expression "a = function (3); var = a;" with the result 21.
|
||||||
|
# CompileExpression::test "a = function (3); var = a;" 21 -explicit
|
||||||
|
# ---> Runs the following tests (name of tests ignored for illustration)
|
||||||
|
# gdb_test_no_output "compile code a = function (3); var = a;"
|
||||||
|
# gdb_test "p var" "= 21"
|
||||||
|
#
|
||||||
|
# Additional option flags may be passed to test to control the behavior
|
||||||
|
# of the test harness:
|
||||||
|
#
|
||||||
|
# Pass -explicit to specify that the test uses an explicit expression,
|
||||||
|
# one which sets the value of the variable (see above). Only the code test
|
||||||
|
# will be run.
|
||||||
|
#
|
||||||
|
# Pass -value and/or -print to indicate that the value and/or print steps
|
||||||
|
# will optionally fail. Specify "xfail" or "kfail" to indicate how
|
||||||
|
# particular step will fail. These may be followed by any accepted DejaGNU
|
||||||
|
# parameters such as architecture and bug#. [See examples below.]
|
||||||
|
#
|
||||||
|
# To specify that the compile (and consequently print and value tests) is
|
||||||
|
# expected to kfail/xfail, use -kfail or -xfail with any appropriate
|
||||||
|
# DejaGNU parameters. Both options override -print and -value.
|
||||||
|
# [-xfail is given precedence over -kfail should both be given.]
|
||||||
|
#
|
||||||
|
# -value is used when a "code" test is run, specifying that the "compile
|
||||||
|
# code" and "print VAR" steps will fail in the prescribed manner.
|
||||||
|
# [If the print step generates a PASS, the test is considered invalidly
|
||||||
|
# written. VAR's value should /always/ be invalidated before a test is
|
||||||
|
# run.]
|
||||||
|
#
|
||||||
|
# -print is used to specify that an expression will fail in the prescribed
|
||||||
|
# manner when "print" test is executed.
|
||||||
|
#
|
||||||
|
# Pass "-name NAME" to set an optional test name. If not specified,
|
||||||
|
# the harness will use test names such as "compile code EXPR" and
|
||||||
|
# "result of compile code EXPR".
|
||||||
|
#
|
||||||
|
# Pass "-noprint" or "-nocode" to suppress print or code tests, respectively,
|
||||||
|
# This is useful when the expression being tested modifies the object
|
||||||
|
# being tested, e.g., "a++".
|
||||||
|
#
|
||||||
|
# These options must be passed LAST to CompileExpression::test.
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
#
|
||||||
|
# Both "code" and "print" tests are expected to xfail:
|
||||||
|
# CompileExpression add_imp "foo" 3 -compile {xfail *-*-*} -print {xfail *-*-*}
|
||||||
|
#
|
||||||
|
# The "print $VARIABLE" portion of the "code" test is expected to kfail
|
||||||
|
# (the actual "compile code" GDB command will succeed), but the "print"
|
||||||
|
# test should pass:
|
||||||
|
# CompileExpression add_imp "foo" 3 -value {kfail *-*-* gdb/1234}
|
||||||
|
|
||||||
|
namespace eval ::CompileExpression {
|
||||||
|
|
||||||
|
# The variable name to check testing results. This variable
|
||||||
|
# must be in scope when tests are run.
|
||||||
|
variable varName_ {}
|
||||||
|
|
||||||
|
# Start a new expression list. VARNAME is the name of the variable
|
||||||
|
# that will be printed to check if the result of the test was
|
||||||
|
# successful.
|
||||||
|
proc new {varname} {
|
||||||
|
variable varName_
|
||||||
|
|
||||||
|
set varName_ $varname
|
||||||
|
}
|
||||||
|
|
||||||
|
# Test an expression.
|
||||||
|
#
|
||||||
|
# See the preamble for a list of valid optional arguments.
|
||||||
|
#
|
||||||
|
# Implicit expressions will be sent to GDB in the form
|
||||||
|
# "$varName = $EXP". "p $varName" will be used to decide the pass
|
||||||
|
# or fail status of the test.
|
||||||
|
#
|
||||||
|
# Explicit expressions will be sent to GDB as-is and tested using only
|
||||||
|
# "compile code". The expression should set the value of the variable
|
||||||
|
# $varName, which is then printed to determine whether the test passed
|
||||||
|
# or failed.
|
||||||
|
#
|
||||||
|
# Unlike explicit expressions, implicit expressions are tested with both
|
||||||
|
# "compile print" and "compile code".
|
||||||
|
|
||||||
|
proc test {exp result args} {
|
||||||
|
parse_args {{value {"" ""}} {print {"" ""}} {name ""}
|
||||||
|
{noprint} {nocode} {explicit} {xfail {"" ""}} {kfail {"" ""}}}
|
||||||
|
|
||||||
|
if {[lindex $xfail 0] != ""} {
|
||||||
|
set l "xfail $xfail"
|
||||||
|
} elseif {[lindex $kfail 0] != ""} {
|
||||||
|
set l "kfail $kfail"
|
||||||
|
} else {
|
||||||
|
set l ""
|
||||||
|
set compile {"" ""}
|
||||||
|
}
|
||||||
|
if {$l != ""} {
|
||||||
|
set compile $l
|
||||||
|
set print $l
|
||||||
|
set value $l
|
||||||
|
}
|
||||||
|
|
||||||
|
if {!$nocode} {
|
||||||
|
do_test_ code $exp $result $explicit $name \
|
||||||
|
[list $compile $value $print]
|
||||||
|
}
|
||||||
|
if {!$noprint} {
|
||||||
|
do_test_ print $exp $result $explicit $name \
|
||||||
|
[list $compile $value $print]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Run a compile test for CMD ("print" or "code").
|
||||||
|
|
||||||
|
proc do_test_ {cmd exp result is_explicit tst fail_list} {
|
||||||
|
variable varName_
|
||||||
|
|
||||||
|
if {![string match $cmd "code"]
|
||||||
|
&& ![string match $cmd "print"]} {
|
||||||
|
error "invalid command, $cmd; should be \"print\" or \"compile\""
|
||||||
|
}
|
||||||
|
|
||||||
|
# Get expected result of test. Will be "" if test is
|
||||||
|
# expected to PASS.
|
||||||
|
lassign $fail_list fail_compile fail_value fail_print
|
||||||
|
|
||||||
|
# Set a test name if one hasn't been provided.
|
||||||
|
if {$tst == ""} {
|
||||||
|
set tst "compile $cmd $exp"
|
||||||
|
}
|
||||||
|
|
||||||
|
if {[string match $cmd "print"]} {
|
||||||
|
if {!$is_explicit} {
|
||||||
|
eval setup_failures_ $fail_print
|
||||||
|
gdb_test "compile print $exp" $result $tst
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if {$is_explicit} {
|
||||||
|
set command "compile code $exp"
|
||||||
|
} else {
|
||||||
|
set command "compile code $varName_ = $exp"
|
||||||
|
}
|
||||||
|
eval setup_failures_ $fail_compile
|
||||||
|
gdb_test_no_output $command $tst
|
||||||
|
eval setup_failures_ $fail_value
|
||||||
|
gdb_test "p $varName_" "= $result" "result of $tst"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# A convenience proc used to set up xfail and kfail tests.
|
||||||
|
# HOW is either xfail or kfail (case is ignored). ARGS is any
|
||||||
|
# optional architecture, bug number, or other string to pass to
|
||||||
|
# respective DejaGNU setup_$how routines.
|
||||||
|
|
||||||
|
proc setup_failures_ {how args} {
|
||||||
|
switch -nocase $how {
|
||||||
|
xfail {
|
||||||
|
eval setup_xfail $args
|
||||||
|
}
|
||||||
|
|
||||||
|
kfail {
|
||||||
|
eval setup_kfail $args
|
||||||
|
}
|
||||||
|
|
||||||
|
default {
|
||||||
|
# Do nothing. Either the test is expected to PASS
|
||||||
|
# or we have an unhandled failure mode.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue