summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Seitz <keiths@redhat.com>2017-02-17 13:50:40 -0800
committerKeith Seitz <keiths@redhat.com>2017-02-21 13:33:46 -0800
commitb34c45412cdc3b13c2d8b0aa0ab78e3574ba5bbc (patch)
tree3a9a23943616657be7bae0406688055c05aa8f36
parent882b3a06fd27ecbbe562d137a0eac62034f00651 (diff)
downloadbinutils-gdb-users/keiths/c++compile-submit.tar.gz
Compile C++ feature.users/keiths/c++compile-submit
-rw-r--r--gdb/Makefile.in8
-rw-r--r--gdb/c-lang.c4
-rw-r--r--gdb/c-lang.h19
-rw-r--r--gdb/compile/compile-c-support.c144
-rw-r--r--gdb/compile/compile-cplus-support.c33
-rw-r--r--gdb/compile/compile-cplus-symbols.c705
-rw-r--r--gdb/compile/compile-cplus-templates.c1448
-rw-r--r--gdb/compile/compile-cplus-templates.h319
-rw-r--r--gdb/compile/compile-cplus-types.c2273
-rw-r--r--gdb/compile/compile-cplus.h399
-rw-r--r--gdb/compile/compile-internal.h4
-rw-r--r--gdb/compile/compile-object-load.c4
-rw-r--r--gdb/compile/compile.c1
-rw-r--r--gdb/testsuite/gdb.compile/compile-cplus-mod.c28
-rw-r--r--gdb/testsuite/gdb.compile/compile-cplus-print.c32
-rw-r--r--gdb/testsuite/gdb.compile/compile-cplus-print.exp75
-rw-r--r--gdb/testsuite/gdb.compile/compile-cplus.c241
-rw-r--r--gdb/testsuite/gdb.compile/compile-cplus.exp341
-rw-r--r--gdb/testsuite/gdb.compile/cp-namespace-template.cc138
-rw-r--r--gdb/testsuite/gdb.compile/cp-namespace-template.exp67
-rw-r--r--gdb/testsuite/gdb.compile/cp-simple-anonymous.cc65
-rw-r--r--gdb/testsuite/gdb.compile/cp-simple-anonymous.exp55
-rw-r--r--gdb/testsuite/gdb.compile/cp-simple-inherit.cc58
-rw-r--r--gdb/testsuite/gdb.compile/cp-simple-inherit.exp52
-rw-r--r--gdb/testsuite/gdb.compile/cp-simple-member.cc83
-rw-r--r--gdb/testsuite/gdb.compile/cp-simple-member.exp76
-rw-r--r--gdb/testsuite/gdb.compile/cp-simple-method.cc91
-rw-r--r--gdb/testsuite/gdb.compile/cp-simple-method.exp66
-rw-r--r--gdb/testsuite/gdb.compile/cp-simple-nested.cc58
-rw-r--r--gdb/testsuite/gdb.compile/cp-simple-nested.exp52
-rw-r--r--gdb/testsuite/gdb.compile/cp-simple-ns.cc37
-rw-r--r--gdb/testsuite/gdb.compile/cp-simple-ns.exp48
-rw-r--r--gdb/testsuite/gdb.compile/cp-simple-template.cc180
-rw-r--r--gdb/testsuite/gdb.compile/cp-simple-template.exp79
-rw-r--r--gdb/testsuite/gdb.compile/cp-simple-virtual.cc65
-rw-r--r--gdb/testsuite/gdb.compile/cp-simple-virtual.exp72
-rw-r--r--gdb/testsuite/gdb.compile/cp-special-function.cc661
-rw-r--r--gdb/testsuite/gdb.compile/cp-special-function.exp260
-rw-r--r--gdb/testsuite/lib/compile-support.exp208
-rw-r--r--include/gcc-cp-fe.def1050
-rw-r--r--include/gcc-cp-interface.h496
41 files changed, 10089 insertions, 6 deletions
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 43253d3dc15..3686fb60fe6 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -354,6 +354,10 @@ SUBDIR_GCC_COMPILE_OBS = \
compile-c-support.o \
compile-c-symbols.o \
compile-c-types.o \
+ compile-cplus-support.o \
+ compile-cplus-symbols.o \
+ compile-cplus-templates.o \
+ compile-cplus-types.o \
compile-loc2c.o \
compile-object-load.o \
compile-object-run.o
@@ -363,6 +367,10 @@ SUBDIR_GCC_COMPILE_SRCS = \
compile/compile-c-support.c \
compile/compile-c-symbols.c \
compile/compile-c-types.c \
+ compile/compile-cplus-support.c \
+ compile/compile-cplus-symbols.c \
+ compile/compile-cplus-templates.c \
+ compile/compile-cplus-types.c \
compile/compile-loc2c.c \
compile/compile-object-load.c \
compile/compile-object-load.h \
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index a61540d272f..1d69338f5aa 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -1068,8 +1068,8 @@ const struct language_defn cplus_language_defn =
iterate_over_symbols,
cplus_compute_string_hash,
&cplus_varobj_ops,
- NULL,
- NULL,
+ cplus_get_compile_context,
+ cplus_compute_program,
LANG_MAGIC
};
diff --git a/gdb/c-lang.h b/gdb/c-lang.h
index 58a81b01fce..6fdcaa4f90b 100644
--- a/gdb/c-lang.h
+++ b/gdb/c-lang.h
@@ -152,6 +152,14 @@ extern int c_textual_element_type (struct type *, char);
extern compile::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::compile_instance *cplus_get_compile_context (void);
+
/* This takes the user-supplied text and returns a new bit of code to
compile.
@@ -164,4 +172,15 @@ extern std::string c_compute_program (compile::compile_instance *inst,
const struct block *expr_block,
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::compile_instance *inst,
+ const char *input,
+ struct gdbarch *gdbarch,
+ const struct block *expr_block,
+ CORE_ADDR expr_pc);
+
#endif /* !defined (C_LANG_H) */
diff --git a/gdb/compile/compile-c-support.c b/gdb/compile/compile-c-support.c
index ead2bddf210..02421f054d5 100644
--- a/gdb/compile/compile-c-support.c
+++ b/gdb/compile/compile-c-support.c
@@ -1,4 +1,4 @@
-/* C language support for compilation.
+/* C/C++ language support for compilation.
Copyright (C) 2014-2017 Free Software Foundation, Inc.
@@ -20,6 +20,7 @@
#include "defs.h"
#include "compile-internal.h"
#include "compile-c.h"
+#include "compile-cplus.h"
#include "compile.h"
#include "gdb-dlfcn.h"
#include "c-lang.h"
@@ -130,6 +131,20 @@ c_get_compile_context (void)
GCC_FE_VERSION_0, GCC_C_FE_VERSION_0);
}
+/* A C++-language implementation of get_compile_context. */
+
+compile::compile_instance *
+cplus_get_compile_context (void)
+{
+ using namespace compile;
+
+ 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);
+}
+
/* Write one macro definition. */
@@ -392,6 +407,108 @@ 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_ADDRESS_SCOPE:
+ case COMPILE_I_PRINT_VALUE_SCOPE:
+ fprintf_unfiltered
+ (buf,
+ "auto " COMPILE_I_EXPR_VAL " = %s;\n"
+ "decltype ( %s ) *" COMPILE_I_EXPR_PTR_TYPE ";\n"
+ "std::memcpy (" COMPILE_I_PRINT_OUT_ARG ", %s ("
+ COMPILE_I_EXPR_VAL "),\n"
+ "sizeof (decltype(%s)));\n"
+ ,input, input,
+ (type == COMPILE_I_PRINT_ADDRESS_SCOPE
+ ? "std::__addressof" : ""), input);
+ break;
+
+ default:
+ fputs_unfiltered (input, buf);
+ break;
+ }
+ fputs_unfiltered ("\n", buf);
+ }
+};
+
/* A host class representing a compile program.
CompileInstanceType is the type of the compile_instance for the
@@ -531,13 +648,18 @@ private:
struct gdbarch *m_arch;
};
-/* Type used for C program computations. */
+/* The types used for C and C++ program computations. */
typedef compile_program<compile::compile_c_instance, c_push_user_expression,
pop_user_expression_nop, c_add_code_header,
c_add_code_footer,
c_add_input> c_compile_program;
+typedef compile_program<compile::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. */
std::string
@@ -554,3 +676,21 @@ c_compute_program (compile::compile_instance *inst,
return program.compute (input, expr_block, expr_pc);
}
+
+/* The la_compute_program method for C++. */
+
+std::string
+cplus_compute_program (compile::compile_instance *inst,
+ const char *input,
+ struct gdbarch *gdbarch,
+ const struct block *expr_block,
+ CORE_ADDR expr_pc)
+{
+ using namespace compile;
+
+ 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);
+}
diff --git a/gdb/compile/compile-cplus-support.c b/gdb/compile/compile-cplus-support.c
new file mode 100644
index 00000000000..063476da6d9
--- /dev/null
+++ b/gdb/compile/compile-cplus-support.c
@@ -0,0 +1,33 @@
+/* C language support for compilation.
+
+ Copyright (C) 2015, 2016 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "gcc-cp-interface.h"
+
+void
+gcc_cplus_enter_scope (void *datum, struct gcc_cp_context *gcc_context)
+{
+ /* FIXME: enter the scope in which the user expression is supposed
+ to be parsed. -lxo */
+}
+
+void
+gcc_cplus_leave_scope (void *datum, struct gcc_cp_context *gcc_context)
+{
+ /* FIXME: leave the scopes entered by gcc_cplus_enter_scope. -lxo */
+}
diff --git a/gdb/compile/compile-cplus-symbols.c b/gdb/compile/compile-cplus-symbols.c
new file mode 100644
index 00000000000..cbd4cdaa14e
--- /dev/null
+++ b/gdb/compile/compile-cplus-symbols.c
@@ -0,0 +1,705 @@
+/* Convert symbols from GDB to GCC
+
+ Copyright (C) 2014-2017 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" /* !!keiths FIXME for c_get_range_decl_name */
+
+
+
+using namespace compile;
+
+/* See description in compile-internal.h. */
+
+int debug_compile_oracle = 0;
+
+/* Convert a given symbol, SYM, to the compiler's representation.
+ CONTEXT 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 if (!SYMBOL_IS_CPLUS_TEMPLATE_FUNCTION (sym.symbol))
+ 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;
+ char *symbol_name = NULL;
+
+ /* Add a null cleanup for templates. !!keiths: remove! */
+ struct cleanup *back_to
+ = make_cleanup (free_current_contents, &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)
+ {
+ do_cleanups (back_to);
+ return;
+ }
+ break;
+
+ case LOC_LABEL:
+ kind = GCC_CP_SYMBOL_LABEL;
+ addr = SYMBOL_VALUE_ADDRESS (sym.symbol);
+ break;
+
+ case LOC_BLOCK:
+ {
+ bool ignore;
+ char *special_name;
+ const char *func_name;
+
+ 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);
+
+ special_name = NULL;
+ func_name = maybe_canonicalize_special_function
+ (SYMBOL_LINKAGE_NAME (sym.symbol), NULL,
+ SYMBOL_TYPE (sym.symbol), &special_name, &ignore);
+ if (special_name != NULL)
+ {
+ kind |= GCC_CP_FLAG_SPECIAL_FUNCTION;
+ name = special_name;
+ xfree (special_name);
+ }
+ else if (func_name != SYMBOL_NATURAL_NAME (sym.symbol))
+ {
+ kind |= GCC_CP_FLAG_SPECIAL_FUNCTION;
+ name = func_name;
+ }
+ else if (ignore)
+ {
+ /* !!keiths: I don't think we can get here, can we? */
+ gdb_assert_not_reached ("told to ignore method!");
+ }
+ }
+ break;
+
+ case LOC_CONST:
+ if (TYPE_CODE (SYMBOL_TYPE (sym.symbol)) == TYPE_CODE_ENUM)
+ {
+ /* Already handled by convert_enum. */
+ do_cleanups (back_to);
+ return;
+ }
+ instance->build_constant (sym_type, SYMBOL_NATURAL_NAME (sym.symbol),
+ SYMBOL_VALUE (sym.symbol), filename, line);
+ do_cleanups (back_to);
+ 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 = NULL;
+
+ if (symbol_read_needs_frame (sym.symbol))
+ {
+ frame = get_selected_frame (NULL);
+ if (frame == NULL)
+ 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 == NULL)
+ {
+ 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.
+ Don't return anything in that case because that really
+ confuses users. */
+ do_cleanups (back_to);
+ return;
+ }
+
+ instance->enter_scope (scope);
+ }
+
+ /* Get the `raw' name of the symbol. */
+ if (name.empty () && SYMBOL_NATURAL_NAME (sym.symbol) != NULL)
+ {
+ char *str = cp_func_name (SYMBOL_NATURAL_NAME (sym.symbol));
+
+ name = str;
+ xfree (str);
+ }
+
+ /* Define the decl. */
+ if (SYMBOL_IS_CPLUS_TEMPLATE_FUNCTION (sym.symbol))
+ {
+ struct template_symbol *tsymbol
+ = (struct template_symbol *) sym.symbol;
+
+ instance->build_function_template_specialization (tsymbol, addr,
+ filename, line);
+ }
+ else
+ {
+ instance->build_decl ("variable", name.c_str (), kind, sym_type,
+ symbol_name, addr, filename, line);
+ }
+
+ /* Pop scope for non-local symbols. */
+ if (!is_local)
+ instance->leave_scope ();
+ }
+
+ /* Free any allocated memory. */
+ do_cleanups (back_to);
+ }
+}
+
+/* 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 != NULL);
+ if (is_local_symbol)
+ {
+ struct block_symbol global_sym;
+
+ global_sym = lookup_symbol (identifier, NULL, domain, NULL);
+ /* If the outer symbol is in the static block, we ignore it, as
+ it cannot be referenced. */
+ if (global_sym.symbol != NULL
+ && global_sym.block != block_static_block (global_sym.block))
+ {
+ if (compile_debug)
+ fprintf_unfiltered (gdb_stdout,
+ "gcc_convert_symbol \"%s\": global symbol\n",
+ identifier);
+ convert_one_symbol (instance, global_sym, true, false);
+ }
+ }
+
+ if (compile_debug)
+ fprintf_unfiltered (gdb_stdout,
+ "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->push_namespace ("");
+ /* FIXME: push (and, after the call, pop) any other namespaces, if
+ any, and drop the above when defining a class member. drop any
+ namespace and class names from before the symbol name, and any
+ function signatures from after it. -lxo */
+ /* !!keiths: I don't see how we could do this. We have NO debug
+ information for the symbol. While we have access to the demangled
+ name, we still don't know what A::B::C::D::E::F means without debug
+ info, no? */
+ instance->build_decl ("minsym", MSYMBOL_NATURAL_NAME (msym), kind, sym_type,
+ NULL, addr, NULL, 0);
+ instance->pop_binding_level ("");
+}
+
+/* Do a regular expression search of the symbol table for any symbol
+ named NAME in the given DOMAIN. Warning: This is INCREDIBLY slow. */
+
+static int
+regexp_search_symbols (compile_cplus_instance *instance,
+ const char *name, domain_enum domain)
+{
+ char *regexp;
+ enum search_domain search_domain;
+ struct symbol_search *symbols, *p;
+ struct cleanup *cleanup;
+ int found = 0;
+
+ switch (domain)
+ {
+ case STRUCT_DOMAIN:
+ search_domain = TYPES_DOMAIN;
+ break;
+ case VAR_DOMAIN:
+ /* !!keiths: We really don't want to search functions. The search
+ will return all kinds of stuff that we don't really want, such as
+ every operator+ defined in every class. */
+ return 0;
+ /* !!keiths; fscked up. We need to search through functions
+ when GCC_CP_ORACLE_SYMBOL (= VAR_DOMAIN). */
+ /* !!keiths; I hope we don't have to search even more domains! */
+ search_domain = FUNCTIONS_DOMAIN;
+ break;
+ default:
+ /* This will cause search_symbols to assert. */
+ search_domain = ALL_DOMAIN;
+ break;
+ }
+
+ symbols = NULL;
+ cleanup = make_cleanup_free_search_symbols (&symbols);
+
+ regexp = xstrprintf ("\\(\\(::\\)\\|^\\)%s\\($\\|<\\)", name);
+ make_cleanup (xfree, regexp);
+ search_symbols (regexp, search_domain, 0, NULL, &symbols);
+
+ for (p = symbols; p != NULL; p = p->next)
+ {
+ if (p->symbol != NULL)
+ {
+ struct block_symbol sym;
+
+ sym.symbol = p->symbol;
+ sym.block = SYMBOL_BLOCK_VALUE (p->symbol);
+ convert_symbol_sym (instance, name, sym, domain);
+ found = 1;
+ }
+ /* !!keiths: Ignore minsyms? */
+ }
+
+ do_cleanups (cleanup);
+ return found;
+}
+
+/* See compile-cplus.h. */
+
+void
+gcc_cplus_convert_symbol (void *datum,
+ struct gcc_cp_context *gcc_context,
+ enum gcc_cp_oracle_request request,
+ const char *identifier)
+{
+ compile_cplus_instance *instance
+ = (compile_cplus_instance *) datum;
+ int found = 0;
+ struct search_multiple_result search_result;
+ struct cleanup *cleanups;
+ /* !!keiths create htab for template definitions */
+
+ switch (request)
+ {
+ case GCC_CP_ORACLE_IDENTIFIER:
+ /* FIXME: This used to be separate SYMBOL and TAG. Check for
+ simplification opportunities below. -lxo */
+ break;
+ default:
+ gdb_assert_not_reached ("Unrecognized oracle request.");
+ }
+
+ /* We can't allow exceptions to escape out of this callback. Safest
+ is to simply emit a gcc error. */
+ if (debug_compile_oracle)
+ {
+ printf ("got oracle request for \"%s\"\n", identifier);
+ }
+
+ memset (&search_result, 0, sizeof (search_result));
+ cleanups = make_cleanup (search_multiple_result_cleanup, &search_result);
+ TRY
+ {
+ int ix;
+
+ /* !!keiths: Symbol lookup is out of control. Here's the current
+ process, screaming for a custom symbol table search:
+
+ 1. If looking up a symbol in VAR_DOMAIN (basically anything but
+ a type), use linespec.c's (new) multi-symbol search. This will
+ allow overloads of functions (not methods) to be converted.
+
+ 2. If a symbol is not found, do a "standard" lookup. This will
+ find variables in the current scope.
+
+ 3. If a symbol is still not found, try a regexp search. This
+ allows namespace-y stuff to work (cp-simple-ns.exp). This is currently
+ only used for STRUCT_DOMAIN lookups.
+
+ 4. Finally, if all else fails, fall back to minsyms. */
+
+ if (1)
+ {
+ search_result = search_symbols_multiple (identifier,
+ current_language,
+ VAR_DOMAIN, NULL, NULL);
+ if (!VEC_empty (block_symbol_d, search_result.symbols))
+ {
+ struct block_symbol *elt;
+
+ /* Define any template generics from the found symbols. */
+ define_templates (instance, search_result.symbols);
+
+ /* Convert each found symbol. */
+ for (ix = 0;
+ VEC_iterate (block_symbol_d, search_result.symbols, ix, elt);
+ ++ix)
+ {
+ convert_symbol_sym (instance, identifier, *elt, VAR_DOMAIN);
+ }
+ found = 1;
+ }
+ }
+
+ if (!found)
+ {
+ struct block_symbol sym
+ = lookup_symbol (identifier, instance->block (), VAR_DOMAIN, NULL);
+
+ if (sym.symbol != NULL)
+ {
+ convert_symbol_sym (instance, identifier, sym, VAR_DOMAIN);
+ found = 1;
+ }
+ }
+
+ if (1)
+ {
+ struct block_symbol sym
+ = lookup_symbol (identifier, instance->block (), STRUCT_DOMAIN,
+ NULL);
+
+ if (sym.symbol != NULL)
+ {
+ convert_symbol_sym (instance, identifier, sym, STRUCT_DOMAIN);
+ found = 1;
+ }
+ }
+
+ if (!found)
+ {
+ /* Try a regexp search of the program's symbols. */
+ found = regexp_search_symbols (instance, identifier, VAR_DOMAIN)
+ + regexp_search_symbols (instance, identifier, STRUCT_DOMAIN);
+
+ /* One last attempt: fall back to minsyms. */
+ if (!found && !VEC_empty (bound_minimal_symbol_d,
+ search_result.minimal_symbols))
+ {
+ struct bound_minimal_symbol *elt;
+
+ for (ix = 0;
+ VEC_iterate (bound_minimal_symbol_d,
+ search_result.minimal_symbols, ix, elt);
+ ++ix)
+ {
+ convert_symbol_bmsym (instance, *elt);
+ }
+ found = 1;
+ }
+ }
+ }
+ CATCH (e, RETURN_MASK_ALL)
+ {
+ instance->error (e.message);
+ }
+ END_CATCH
+
+ if (compile_debug && !found)
+ fprintf_unfiltered (gdb_stdout,
+ "gcc_convert_symbol \"%s\": lookup_symbol failed\n",
+ identifier);
+
+ if (debug_compile_oracle)
+ {
+ if (found)
+ printf_unfiltered ("found type for %s!\n", identifier);
+ else
+ printf_unfiltered ("did not find type for %s\n", identifier);
+ }
+
+ do_cleanups (cleanups);
+ 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 (debug_compile_oracle)
+ printf_unfiltered ("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;
+
+ /* FIXME: We used to only need global functions here, but we may
+ now be asked for other symbols. IDENTIFIER is a mangled
+ name. -lxo */
+ sym = lookup_symbol (identifier, NULL, VAR_DOMAIN, NULL).symbol;
+ if (sym != NULL && SYMBOL_CLASS (sym) == LOC_BLOCK)
+ {
+ if (compile_debug)
+ fprintf_unfiltered (gdb_stdout,
+ "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 != NULL)
+ {
+ if (compile_debug)
+ fprintf_unfiltered (gdb_stdout,
+ "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->error (e.message);
+ }
+ END_CATCH
+
+ if (compile_debug && !found)
+ fprintf_unfiltered (gdb_stdout,
+ "gcc_symbol_address \"%s\": failed\n",
+ identifier);
+
+ if (debug_compile_oracle)
+ {
+ if (found)
+ printf_unfiltered ("found address for %s!\n", identifier);
+ else
+ printf_unfiltered ("did not find address for %s\n", identifier);
+ }
+
+ return result;
+}
+
+
+
+void _initialize_compile_cplus_symbols (void);
+
+void
+_initialize_compile_cplus_symbols (void)
+{
+ add_setshow_boolean_cmd ("compile-oracle", no_class,
+ &debug_compile_oracle, _("\
+Set debugging of compiler plug-in oracle requests."), _("\
+Show debugging of compiler plug-in oracle requests."), _("\
+When enabled debugging messages are printed for compiler plug-in\n\
+oracle requests."),
+ NULL,
+ NULL,
+ &setdebuglist,
+ &showdebuglist);
+}
diff --git a/gdb/compile/compile-cplus-templates.c b/gdb/compile/compile-cplus-templates.c
new file mode 100644
index 00000000000..4b2bf46baae
--- /dev/null
+++ b/gdb/compile/compile-cplus-templates.c
@@ -0,0 +1,1448 @@
+/* Template support for compile.
+
+ Copyright (C) 2016, 2017 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 "cp-support.h"
+#include "demangle.h"
+#include "typeprint.h"
+#include "c-lang.h"
+#include "gdbcmd.h"
+
+#include <algorithm>
+
+using namespace compile;
+
+/* Modifiers for abstract template parameters when used in template function
+ declarations, including CV and ref qualifiers and pointer and reference
+ type modifiers, e.g., const T*. */
+
+enum template_parameter_type_modifier
+{
+ /*/ The abstract parameter type is not qualified at all. */
+ PARAMETER_NONE,
+
+ /* The abstract parameter type was declared `const', const T. */
+ PARAMETER_CONST,
+
+ /* The abstract parameter type was declared `volatile', volatile T. */
+ PARAMETER_VOLATILE,
+
+ /* The abstract parameter type was declared `restrict', restrict T. */
+ PARAMETER_RESTRICT,
+
+ /* The abstract parameter type was declared as a pointer, T*. */
+ PARAMETER_POINTER,
+
+ /* The abstract parameter type was declared as a reference, T&. */
+ PARAMETER_LVALUE_REFERENCE,
+
+ /* The abstract parameter type was declared as rvalue reference,
+ T&&. */
+ PARAMETER_RVALUE_REFERENCE
+};
+typedef enum template_parameter_type_modifier template_parameter_modifier;
+
+/* Forward declarations. */
+
+static void print_template_parameter_list
+ (const struct template_argument_info *arg_info, struct ui_file *stream);
+
+static void print_template_type (const struct demangle_component *comp,
+ const struct template_symbol *tsymbol,
+ struct ui_file *stream);
+
+static void print_conversion_node (const struct demangle_component *comp,
+ const struct template_symbol *tsymbol,
+ struct ui_file *stream);
+
+static void print_function_template_arglist
+ (const struct demangle_component *comp,
+ const struct template_symbol *tsymbol, struct ui_file *stream);
+
+/* See description in compile-cplus-templates.h. */
+
+function_template_defn::function_template_defn
+ (std::string generic, std::unique_ptr<demangle_parse_info> info,
+ const struct template_symbol *tsymbol, struct type *parent_type,
+ int fidx, int midx)
+ : template_defn (compile::decl_name (tsymbol->search_name), generic,
+ tsymbol->template_arguments->n_arguments),
+ m_tsymbol (tsymbol), m_parent_type (parent_type),
+ m_fidx (fidx), m_midx (midx),
+ m_demangle_info (std::move (info))
+{
+}
+
+/* Return a string representing the template declaration for TSYMBOL.
+ All template symbols deriving from the same source declaration should
+ yield the same string representation.
+
+ This string representation is of the generic form
+ RETURN_TYPE QUALIFIED_NAME <parameter list>(argument list), with
+ generic template parameters instead of any instanced type.
+
+ For example, both "void foo<int> (int)" and "void foo<A> (A)" will
+ return "T foo<typename T>(T)". */
+
+static std::string
+function_template_decl (const struct template_symbol *tsymbol,
+ const struct demangle_parse_info *info)
+{
+ gdb_assert (info != NULL);
+
+ string_file stream;
+ struct demangle_component *ret_comp = info->tree;
+
+ if (ret_comp != NULL)
+ {
+ if (ret_comp->type == DEMANGLE_COMPONENT_TYPED_NAME)
+ ret_comp = d_right (ret_comp);
+
+ /* Print out the return type to the stream (if there is one). */
+ if (d_left (ret_comp) != NULL)
+ {
+ if (tsymbol->template_return_index == -1)
+ {
+ struct type *return_type
+ = TYPE_TARGET_TYPE (SYMBOL_TYPE (&tsymbol->base));
+
+ c_print_type (return_type, "", &stream, -1, 0,
+ &type_print_raw_options);
+ }
+ else
+ print_template_type (d_left (ret_comp), tsymbol, &stream);
+ stream.putc (' ');
+ }
+
+ /* Print the name of the template. */
+ if (tsymbol->conversion_operator_index != -1)
+ print_conversion_node (info->tree, tsymbol, &stream);
+ else
+ {
+ stream.puts (tsymbol->search_name);
+ if (tsymbol->search_name[strlen (tsymbol->search_name) - 1] == '<')
+ stream.putc (' ');
+ }
+
+ /* Print out template (generic) arguments. */
+ stream.putc ('<');
+ print_template_parameter_list (tsymbol->template_arguments, &stream);
+ stream.putc ('>');
+
+ /* Print out function arguments. */
+ stream.putc ('(');
+ print_function_template_arglist (ret_comp, tsymbol, &stream);
+ stream.putc (')');
+ }
+
+ return std::move (stream.string ());
+}
+
+/* Compute the generic used by the given function template
+ definition. */
+
+static std::string
+compute_function_template_generic (struct template_symbol *tsymbol,
+ const demangle_parse_info *info)
+{
+ gdb_assert (info->tree != NULL);
+
+ /* Ensure template arguments have been decoded. */
+ cp_decode_template_type_indices (tsymbol, info);
+
+ /* Output the template generic. */
+ return function_template_decl (tsymbol, info);
+}
+
+/* See description in compile-cplus.h. */
+
+void
+compile_cplus_instance::maybe_define_new_function_template
+ (const struct symbol *sym, struct type *parent_type, int f_idx,
+ int m_idx)
+
+{
+ if (sym != NULL && SYMBOL_IS_CPLUS_TEMPLATE_FUNCTION (sym))
+ {
+ struct template_symbol *tsym = (struct template_symbol *) sym;
+
+ if (tsym->linkage_name == NULL)
+ return;
+
+ std::unique_ptr<demangle_parse_info> info
+ = cp_mangled_name_to_comp (tsym->linkage_name, DMGL_ANSI | DMGL_PARAMS);
+
+ std::string generic
+ = compute_function_template_generic (tsym, info.get ());
+ function_template_defn_map_t::iterator pos
+ = m_function_template_defns->find (generic);
+
+ function_template_defn *defn;
+
+ if (pos == m_function_template_defns->end ())
+ {
+ /* Create the new template definition and insert it into
+ the cache. */
+ defn = new function_template_defn (generic, std::move (info), tsym,
+ parent_type, f_idx, m_idx);
+ m_function_template_defns->insert (std::make_pair (generic, defn));
+ }
+ else
+ {
+ /* Or use the existing definition. */
+ defn = pos->second.get ();
+ }
+
+ /* Loop over the template arguments, noting any default values. */
+ for (unsigned int i = 0; i < tsym->template_arguments->n_arguments; ++i)
+ {
+ if (defn->default_argument (i) == NULL
+ && tsym->template_arguments->default_arguments[i] != NULL)
+ {
+ struct symbol *def
+ = tsym->template_arguments->default_arguments[i];
+ defn->set_default_argument (i, def);
+
+ /* We don't want to define them here because it could start
+ emitting template definitions before we're even done
+ collecting the default values. [Easy to demonstrate if the
+ default value is a class.] */
+ }
+ }
+ }
+}
+
+/* See description in compile-cplus-templates.h. */
+
+void
+compile::define_templates (compile_cplus_instance *instance,
+ VEC (block_symbol_d) *symbols)
+{
+ int i;
+ struct block_symbol *elt;
+
+ /* We need to do this in two passes. On the first pass, we collect
+ the list of "unique" template definitions we need (using the template
+ hashing function) and we collect the list of default values for the
+ template (which can only be done after we have a list of all templates).
+ On the second pass, we iterate over the list of templates we need to
+ define, enumerating those definitions (with default values) to the
+ compiler plug-in. */
+
+ for (i = 0; VEC_iterate (block_symbol_d, symbols, i, elt); ++i)
+ instance->maybe_define_new_function_template (elt->symbol, NULL, -1, -1);
+
+ /* From here on out, we MUST have all types declared or defined,
+ otherwise GCC will give us "definition of TYPE in template parameter
+ list." */
+ /* Create any new template definitions we encountered. */
+ instance->emit_function_template_decls ();
+ instance->emit_class_template_decls ();
+}
+
+/* See description in compile-cplus-templates.h. */
+
+function_template_defn *
+compile_cplus_instance::find_function_template_defn
+ (struct template_symbol *tsym)
+{
+ if (tsym->linkage_name == NULL)
+ return NULL;
+
+ std::unique_ptr<demangle_parse_info> info
+ = cp_mangled_name_to_comp (tsym->linkage_name, DMGL_ANSI | DMGL_PARAMS);
+
+ std::string generic = compute_function_template_generic (tsym, info.get ());
+ function_template_defn_map_t::iterator pos
+ = m_function_template_defns->find (generic);
+
+ if (pos != m_function_template_defns->end ())
+ return pos->second.get ();
+
+ return NULL;
+}
+
+/* Compute the generic used by the given function template
+ definition. */
+
+static std::string
+compute_class_template_generic (std::string name, struct type *type)
+{
+ string_file stream;
+
+ /* Format: class|struct|union namespaces::NAME<parameters> */
+ if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
+ {
+ if (TYPE_DECLARED_CLASS (type))
+ stream.puts ("class ");
+ else
+ stream.puts ("struct ");
+ }
+ else
+ {
+ gdb_assert (TYPE_CODE (type) == TYPE_CODE_UNION);
+ stream.puts ("union ");
+ }
+
+ /* Print all namespaces. Note that we do not push the last
+ scope_component -- that's the actual type we are defining. */
+
+ compile::compile_scope scope = type_name_to_scope (TYPE_NAME (type), NULL);
+ std::for_each (scope.begin (), scope.end () - 1, [&] (const auto &comp)
+ {
+ gdb_assert (TYPE_CODE (SYMBOL_TYPE (comp.bsymbol.symbol))
+ == TYPE_CODE_NAMESPACE);
+
+ if (comp.name != CP_ANONYMOUS_NAMESPACE_STR)
+ stream.printf ("%s::", comp.name.c_str ());
+ });
+
+ stream.printf ("%s<", name.c_str ());
+ print_template_parameter_list (TYPE_TEMPLATE_ARGUMENT_INFO (type), &stream);
+ stream.putc ('>');
+
+ return std::move (stream.string ());
+}
+
+/* See description in compile-cplus-templates.h. */
+
+class_template_defn *
+compile_cplus_instance::find_class_template_defn (struct type *type)
+{
+ /* There are no template definitions associated with anonymous types or
+ types without template arguments. */
+ if (TYPE_NAME (type) == NULL || TYPE_TEMPLATE_ARGUMENT_INFO (type) == NULL)
+ return NULL;
+
+ char *name = decl_name (TYPE_NAME (type));
+ struct cleanup *back_to = make_cleanup (xfree, name);
+
+ std::string generic (compute_class_template_generic (name, type));
+ class_template_defn_map_t::iterator pos
+ = m_class_template_defns->find (generic);
+ if (pos != m_class_template_defns->end ())
+ {
+ /* A template generic for this was already defined. */
+ do_cleanups (back_to);
+ return pos->second.get ();
+ }
+
+ /* No generic for this template was found. */
+ do_cleanups (back_to);
+ return NULL;
+}
+
+/* A class providing printing for a single parameter type modifier. */
+
+class one_template_type_modifier_printer
+{
+public:
+ /* Construct a new printer which outputs to STREAM. */
+ explicit one_template_type_modifier_printer (struct ui_file *stream)
+ : m_stream (stream)
+ {
+ }
+
+ /* Unary function to output the modifier. */
+ void operator() (template_parameter_modifier modifier)
+ {
+ switch (modifier)
+ {
+ case PARAMETER_NONE:
+ break;
+
+ case PARAMETER_CONST:
+ fputs_unfiltered (" const", m_stream);
+ break;
+
+ case PARAMETER_VOLATILE:
+ fputs_unfiltered (" volatile", m_stream);
+ break;
+
+ case PARAMETER_RESTRICT:
+ fputs_unfiltered (" restrict", m_stream);
+ break;
+
+ case PARAMETER_POINTER:
+ fputs_unfiltered ("*", m_stream);
+ break;
+
+ case PARAMETER_LVALUE_REFERENCE:
+ fputc_unfiltered ('&', m_stream);
+ break;
+
+ case PARAMETER_RVALUE_REFERENCE:
+ fputs_unfiltered ("&&", m_stream);
+
+ default:
+ gdb_assert_not_reached ("unknown template parameter modifier");
+ }
+ }
+
+private:
+ /* The stream to which to print the modifier. */
+ struct ui_file *m_stream;
+};
+
+/* Print the type modifiers MODIFIERS to STREAM. */
+
+static void
+print_template_type_modifiers
+ (const std::vector<template_parameter_modifier> &modifiers,
+ struct ui_file *stream)
+{
+ one_template_type_modifier_printer printer (stream);
+
+ for (auto &item : modifiers)
+ printer (item);
+}
+
+/* Get the abstract template type described by COMP, returning any
+ type modifiers in MODIFIERS. */
+
+static const struct demangle_component *
+get_template_type (const struct demangle_component *comp,
+ std::vector <template_parameter_modifier> &modifiers)
+{
+ bool done = 0;
+
+ /* This is probably a little too simplistic... */
+ while (!done)
+ {
+ switch (comp->type)
+ {
+ case DEMANGLE_COMPONENT_POINTER:
+ modifiers.insert (modifiers.begin (), PARAMETER_POINTER);
+ comp = d_left (comp);
+ break;
+
+ case DEMANGLE_COMPONENT_REFERENCE:
+ modifiers.insert (modifiers.begin (), PARAMETER_LVALUE_REFERENCE);
+ comp = d_left (comp);
+ break;
+
+ case DEMANGLE_COMPONENT_CONST:
+ modifiers.insert (modifiers.begin (), PARAMETER_CONST);
+ comp = d_left (comp);
+ break;
+
+ case DEMANGLE_COMPONENT_RESTRICT:
+ modifiers.insert (modifiers.begin (), PARAMETER_RESTRICT);
+ comp = d_left (comp);
+ break;
+
+ case DEMANGLE_COMPONENT_VOLATILE:
+ modifiers.insert (modifiers.begin (), PARAMETER_VOLATILE);
+ comp = d_left (comp);
+ break;
+
+ case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
+ default:
+ done = true;
+ break;
+ }
+ }
+
+ return comp;
+}
+
+/* Print the generic parameter type given by COMP from the template symbol
+ TSYMBOL to STREAM. This function prints the generic template parameter
+ type, not the instanced type, e.g., "const T&". */
+
+static void
+print_template_type (const struct demangle_component *comp,
+ const struct template_symbol *tsymbol,
+ struct ui_file *stream)
+{
+ /* Get the template parameter and modifiers. */
+ std::vector<template_parameter_modifier> modifiers;
+ comp = get_template_type (comp, modifiers);
+
+ /* This had better be a template parameter! */
+ gdb_assert (comp->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM);
+
+ /* Using the parameter's index, get the parameter's symbol and print it
+ with modifiers. */
+ long idx = comp->u.s_number.number;
+ struct symbol *sym = tsymbol->template_arguments->arguments[idx];
+
+ fputs_unfiltered (SYMBOL_NATURAL_NAME (sym), stream);
+ print_template_type_modifiers (modifiers, stream);
+}
+
+/* Print the template parameter list of a type/symbol to STREAM. */
+
+static void
+print_template_parameter_list (const struct template_argument_info *arg_info,
+ struct ui_file *stream)
+{
+ for (int i = 0; i < arg_info->n_arguments; ++i)
+ {
+ if (i != 0)
+ fputs_unfiltered (", ", stream);
+
+ switch (arg_info->argument_kinds[i])
+ {
+ case type_parameter:
+ fprintf_unfiltered (stream, "typename %s",
+ SYMBOL_NATURAL_NAME (arg_info->arguments[i]));
+ break;
+
+ case value_parameter:
+ c_print_type (SYMBOL_TYPE (arg_info->arguments[i]), "", stream, -1, 0,
+ &type_print_raw_options);
+ fprintf_unfiltered (stream, " %s",
+ SYMBOL_NATURAL_NAME (arg_info->arguments[i]));
+ break;
+
+ case template_parameter:
+ break;
+
+ case variadic_parameter:
+ break;
+
+ default:
+ gdb_assert_not_reached ("unexpected template parameter kind");
+ }
+ }
+}
+
+/* Print out the generic template function argument list of the template
+ symbol TSYMBOL to STREAM. COMP represents the FUNCTION_TYPE of the
+ demangle tree for TSYMBOL. */
+
+static void
+print_function_template_arglist (const struct demangle_component *comp,
+ const struct template_symbol *tsymbol,
+ struct ui_file *stream)
+{
+ int i, artificials;
+ struct type *ttype = SYMBOL_TYPE (&tsymbol->base);
+
+ for (i = 0, artificials = 0; i < TYPE_NFIELDS (ttype); ++i)
+ {
+ int tidx;
+
+ if (TYPE_FIELD_ARTIFICIAL (ttype, i))
+ {
+ ++artificials;
+ continue;
+ }
+
+ if ((i - artificials) > 0)
+ fputs_unfiltered (", ", stream);
+
+ tidx = tsymbol->template_argument_indices[i - artificials];
+ if (tidx == -1)
+ {
+ /* A concrete type was used to define this argument. */
+ c_print_type (TYPE_FIELD_TYPE (ttype, i), "", stream, -1, 0,
+ &type_print_raw_options);
+ continue;
+ }
+
+ /* The type of this argument was specified by a template parameter,
+ possibly with added CV and ref qualifiers. */
+
+ /* Get the next ARGLIST node and print it. */
+ comp = d_right (comp);
+ gdb_assert (comp != NULL);
+ gdb_assert (comp->type == DEMANGLE_COMPONENT_ARGLIST);
+ print_template_type (d_left (comp), tsymbol, stream);
+ }
+}
+
+/* Print the conversion operator in COMP for the template symbol TSYMBOL
+ to STREAM. */
+
+static void
+print_conversion_node (const struct demangle_component *comp,
+ const struct template_symbol *tsymbol,
+ struct ui_file *stream)
+{
+ while (1)
+ {
+ switch (comp->type)
+ {
+ case DEMANGLE_COMPONENT_TYPED_NAME:
+ case DEMANGLE_COMPONENT_TEMPLATE:
+ comp = d_left (comp);
+ break;
+
+ case DEMANGLE_COMPONENT_QUAL_NAME:
+ {
+ /* Print out the qualified name. */
+ struct cleanup *back_to;
+ char *ret = cp_comp_to_string (d_left (comp), 10);
+
+ back_to = make_cleanup (xfree, ret);
+ fprintf_unfiltered (stream, "%s::", ret);
+ do_cleanups (back_to);
+
+ /* Follow the rest of the name. */
+ comp = d_right (comp);
+ }
+ break;
+
+ case DEMANGLE_COMPONENT_CONVERSION:
+ fputs_unfiltered ("operator ", stream);
+ print_template_type (d_left (comp), tsymbol, stream);
+ return;
+
+ default:
+ return;
+ }
+ }
+}
+
+/* See description in compile-cplus-templates.h. */
+
+void
+compile_cplus_instance::maybe_define_new_class_template
+ (struct type *type, const char *decl_name)
+{
+ if (TYPE_N_TEMPLATE_ARGUMENTS (type) == 0 || decl_name == NULL)
+ return;
+
+ std::string generic (compute_class_template_generic (decl_name, type));
+ class_template_defn_map_t::iterator pos
+ = m_class_template_defns->find (generic);
+
+ class_template_defn *defn = NULL;
+
+ if (pos == m_class_template_defns->end ())
+ {
+ /* Insert the new template definition into the cache. */
+ defn = new class_template_defn (decl_name, generic, type);
+ m_class_template_defns->insert (std::make_pair (generic, defn));
+ }
+ else
+ {
+ /* If there is an existing definition, use that definition. */
+ defn = pos->second.get ();
+ }
+
+ /* Loop over the template arguments, noting any default values. */
+ for (unsigned int i = 0; i < TYPE_N_TEMPLATE_ARGUMENTS (type); ++i)
+ {
+ if (defn->default_argument (i) == NULL
+ && TYPE_TEMPLATE_DEFAULT_ARGUMENT (type, i) != NULL)
+ {
+ defn->set_default_argument (i,
+ TYPE_TEMPLATE_DEFAULT_ARGUMENT (type, i));
+
+ /* We don't want to define them here because it could start
+ emitting template definitions before we're even done
+ collecting the default values. [Easy to demonstrate if the
+ default value is a class.] */
+ }
+ }
+}
+
+/* See description in compile-cplus-templates.h. */
+
+void
+compile::scan_type_for_function_templates (compile_cplus_instance *instance,
+ struct type *type)
+{
+ for (int i = 0; i < TYPE_NFN_FIELDS (type); ++i)
+ {
+ struct fn_field *methods = TYPE_FN_FIELDLIST1 (type, i);
+
+ for (int j = 0; j < TYPE_FN_FIELDLIST_LENGTH (type, i); ++j)
+ {
+ struct block_symbol sym
+ = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (methods, j),
+ instance->block (), VAR_DOMAIN, NULL);
+
+ instance->maybe_define_new_function_template (sym.symbol, type, i, j);
+ }
+ }
+}
+
+/* Helper function to define and return the `value' of TYPE of the template
+ parameter ARG in compile INSTANCE. */
+
+static gcc_expr
+get_template_argument_value (compile_cplus_instance *instance,
+ gcc_type type, struct symbol *arg)
+{
+ gcc_expr value = 0;
+
+ switch (SYMBOL_CLASS (arg))
+ {
+ /* !!keiths: More (incomplete) fun. */
+ case LOC_CONST:
+ value = instance->build_literal_expr (type, SYMBOL_VALUE (arg));
+ break;
+
+ case LOC_COMPUTED:
+ {
+ struct value *val;
+ struct frame_info *frame = NULL;
+
+ /* !!keiths: I don't think this can happen, but I've been
+ wrong before. */
+ if (symbol_read_needs_frame (arg))
+ {
+ frame = get_selected_frame (NULL);
+ gdb_assert (frame != NULL);
+ }
+ val = read_var_value (arg, instance->block (), frame);
+
+ /* !!keiths: This is a hack, but I don't want to write
+ yet another linkage name translation function. At least
+ not just yet. */
+ value = instance->build_literal_expr (type, value_address (val));
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached
+ ("unhandled template value argument symbol class");
+ }
+
+ return value;
+}
+
+/* Enumerate the template parameters of the generic form of the template
+ definition DEFN into DEST. */
+
+static void
+define_template_parameters_generic
+ (compile_cplus_instance *instance, template_defn *defn,
+ const struct template_argument_info *arg_info,
+ const char *filename, int line)
+{
+ for (int i = 0; i < arg_info->n_arguments; ++i)
+ {
+ const char *id = SYMBOL_NATURAL_NAME (arg_info->arguments[i]);
+
+ switch (arg_info->argument_kinds[i])
+ {
+ case type_parameter:
+ {
+ /* GDB doesn't support variadic templates yet. */
+ int is_pack = 0;
+ gcc_type default_type = 0;
+
+ if (defn->default_argument (i) != NULL)
+ {
+ struct type *type = SYMBOL_TYPE (defn->default_argument (i));
+
+ /* This type must previously have been converted,
+ or GCC will error with "definition of TYPE inside
+ template parameter list." */
+ default_type = instance->convert_type (type);
+ }
+
+ gcc_type abstract_type
+ = instance->build_type_template_parameter (id, is_pack,
+ default_type, filename, line);
+ defn->set_parameter_abstract_type (i, abstract_type);
+ }
+ break;
+
+ case value_parameter:
+ {
+ gcc_expr default_value = 0;
+ struct type *ptype = SYMBOL_TYPE (arg_info->arguments[i]);
+
+ /* Get the argument's type. This type must also have been
+ previously defined (or declared) to prevent errors. */
+ gcc_type abstract_type = instance->convert_type (ptype);
+ defn->set_parameter_abstract_type (i, abstract_type);
+
+ if (defn->default_argument (i) != NULL)
+ {
+ default_value
+ = get_template_argument_value (instance, abstract_type,
+ defn->default_argument (i));
+ }
+
+ instance->build_value_template_parameter (abstract_type, id,
+ default_value,
+ filename, line);
+ }
+ break;
+
+ case template_parameter:
+ /* GDB doesn't support template-template parameters. */
+ break;
+
+ case variadic_parameter:
+ /* GDB doesn't support variadic templates. */
+ break;
+
+ default:
+ gdb_assert_not_reached ("unexpected template parameter kind");
+ }
+ }
+}
+
+/* Populate the `kinds' member of DEST from ARG_INFO. */
+
+static void
+enumerate_template_parameter_kinds
+ (compile_cplus_instance *instance, struct gcc_cp_template_args *dest,
+ const struct template_argument_info *arg_info)
+{
+ for (int i = 0; i < arg_info->n_arguments; ++i)
+ {
+ switch (arg_info->argument_kinds[i])
+ {
+ case type_parameter:
+ dest->kinds[i] = GCC_CP_TPARG_CLASS;
+ break;
+ case value_parameter:
+ dest->kinds[i] = GCC_CP_TPARG_VALUE;
+ break;
+ case template_parameter:
+ dest->kinds[i] = GCC_CP_TPARG_TEMPL;
+ break;
+ case variadic_parameter:
+ dest->kinds[i] = GCC_CP_TPARG_PACK;
+ break;
+ default:
+ gdb_assert_not_reached ("unexpected template parameter kind");
+ }
+ }
+}
+
+/* See description in compile-cplus-templates.h. */
+
+void
+compile_cplus_instance::enumerate_template_arguments
+ (struct gcc_cp_template_args *dest, const template_defn *defn,
+ const struct template_argument_info *arg_info)
+{
+ /* Fill in the parameter kinds. */
+ enumerate_template_parameter_kinds (this, dest, arg_info);
+
+ /* Loop over the arguments, converting parameter types, values, etc
+ into DEST. */
+ for (int i = 0; i < arg_info->n_arguments; ++i)
+ {
+ switch (arg_info->argument_kinds[i])
+ {
+ case type_parameter:
+ {
+ gcc_type type
+ = convert_type (SYMBOL_TYPE (arg_info->arguments[i]));
+
+ dest->elements[i].type = type;
+ }
+ break;
+
+ case value_parameter:
+ {
+ gcc_type type = defn->parameter_abstract_type (i);
+
+ dest->elements[i].value
+ = get_template_argument_value (this, type,
+ arg_info->arguments[i]);
+ }
+ break;
+
+ case template_parameter:
+ break;
+
+ case variadic_parameter:
+ break;
+
+ default:
+ gdb_assert_not_reached ("unexpected template parameter kind");
+ }
+ }
+}
+
+/* Define the type for all default template parameters for the template
+ arguments given by ARGUMENTS. */
+
+static void
+define_default_template_parameter_types
+ (compile_cplus_instance *instance, template_defn *defn,
+ const struct template_argument_info *arg_info)
+{
+ for (int i = 0; i < arg_info->n_arguments; ++i)
+ {
+ if (defn->default_argument (i) != NULL)
+ {
+ switch (arg_info->argument_kinds[i])
+ {
+ case type_parameter:
+ case value_parameter:
+ instance->convert_type (SYMBOL_TYPE (defn->default_argument (i)));
+ break;
+
+ case template_parameter:
+ case variadic_parameter:
+ default:
+ gdb_assert (_("unexpected template parameter kind"));
+ }
+ }
+ }
+}
+
+/* A class to add type modifiers to a given compiler type. */
+
+class template_parameter_type_modifier_adder
+{
+public:
+ template_parameter_type_modifier_adder
+ (compile_cplus_instance *instance, gcc_type the_type)
+ : m_instance (instance), m_flags (0), m_type (the_type)
+ {
+ }
+
+ void operator() (template_parameter_modifier modifier)
+ {
+ switch (modifier)
+ {
+ case PARAMETER_NONE:
+ break;
+
+ case PARAMETER_CONST:
+ m_flags |= GCC_CP_QUALIFIER_CONST;
+ break;
+
+ case PARAMETER_VOLATILE:
+ m_flags |= GCC_CP_QUALIFIER_VOLATILE;
+ break;
+
+ case PARAMETER_RESTRICT:
+ m_flags |= GCC_CP_QUALIFIER_RESTRICT;
+ break;
+
+ case PARAMETER_POINTER:
+ m_type = convert_qualified_base (m_instance, m_type, m_flags);
+ m_type = convert_pointer_base (m_instance, m_type);
+ m_flags = (enum gcc_cp_qualifiers) 0;
+ break;
+
+ case PARAMETER_LVALUE_REFERENCE:
+ m_type = convert_qualified_base (m_instance, m_type, m_flags);
+ m_type = convert_pointer_base (m_instance, m_type);
+ m_flags = (enum gcc_cp_qualifiers) 0;
+ break;
+
+ case PARAMETER_RVALUE_REFERENCE:
+ m_type = convert_qualified_base (m_instance, m_type, m_flags);
+ m_type = convert_reference_base (m_instance, m_type);
+ m_flags = (enum gcc_cp_qualifiers) 0;
+ break;
+
+ default:
+ gdb_assert_not_reached ("unknown template parameter modifier");
+ }
+ }
+
+ /* Returns the modified type. */
+
+ gcc_type type () const
+ {
+ return m_type;
+ }
+
+private:
+ /* The compiler instance into which to define the new type(s). */
+ compile_cplus_instance *m_instance;
+
+ /* The qualifier flags. */
+ gcc_cp_qualifiers_flags m_flags;
+
+ /* The type we are modifying. */
+ gcc_type m_type;
+};
+
+/* Add the modifiers given by MODIFIERS to TYPE. */
+
+static gcc_type
+add_template_type_modifiers
+ (compile_cplus_instance *instance, gcc_type type,
+ const std::vector<template_parameter_modifier> &modifiers)
+{
+ template_parameter_type_modifier_adder adder (instance, type);
+
+ for (auto &item : modifiers)
+ adder (item);
+ return adder.type ();
+}
+
+/* Add the type modifiers described in COMP to BASE_TYPE. */
+
+static gcc_type
+add_type_modifiers (compile_cplus_instance *instance,
+ gcc_type base_type,
+ const struct demangle_component *comp)
+{
+ std::vector<template_parameter_modifier> modifiers;
+
+ get_template_type (comp, modifiers);
+
+ gcc_type result
+ = add_template_type_modifiers (instance, base_type, modifiers);
+
+ return result;
+}
+
+/* A struct to define (to the plug-in) and fill-in the
+ function template definition based on the template instance in SLOT.
+ CALL_DATA should be the compiler instance to use. */
+
+class function_template_definer
+{
+ public:
+
+ function_template_definer (compile_cplus_instance *instance)
+ : m_instance (instance)
+ {
+ }
+
+ void operator() (function_template_defn *defn)
+ {
+ if (defn->defined ())
+ {
+ /* This template has already been defined. Keep looking for more
+ undefined templates. */
+ return;
+ }
+
+ /* Ensure this is one-time operation. */
+ defn->set_defined (true);
+
+ struct fn_field *method_field;
+ struct type *method_type;
+ const struct template_symbol *tsym = defn->template_symbol ();
+ if (defn->parent_type () != NULL
+ && defn->fidx () != -1 && defn->midx () != -1)
+ {
+ struct fn_field *methods
+ = TYPE_FN_FIELDLIST1 (defn->parent_type (), defn->fidx ());
+
+ method_field = &methods[defn->midx ()];
+ method_type = method_field->type;
+ }
+ else
+ {
+ method_field = NULL;
+ method_type = SYMBOL_TYPE (&tsym->base);
+ }
+
+ bool ignore;
+ char *special_name = NULL;
+ const char *id = defn->decl_name ();
+ gdb_assert (!strchr (id, ':'));
+ const char *name = maybe_canonicalize_special_function (id,
+ method_field,
+ method_type,
+ &special_name,
+ &ignore);
+
+ /* Ignore any "ignore" -- we need the template defined even if
+ this specific instance shouldn't emit a template. */
+ struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
+
+ if (special_name != NULL)
+ {
+ make_cleanup (xfree, special_name);
+ name = special_name;
+ }
+
+ gcc_cp_symbol_kind_flags sym_kind = GCC_CP_SYMBOL_FUNCTION;
+
+ if (name != id)
+ sym_kind |= GCC_CP_FLAG_SPECIAL_FUNCTION;
+
+ /* Define any default value types. */
+ define_default_template_parameter_types (m_instance, defn,
+ tsym->template_arguments);
+
+ /* Assess the processing context. */
+ gcc_type result;
+ compile_scope scope
+ = m_instance->new_scope (SYMBOL_NATURAL_NAME (&tsym->base),
+ SYMBOL_TYPE (&tsym->base));
+
+ if (scope.nested_type () != GCC_TYPE_NONE)
+ {
+ do_cleanups (back_to);
+ /* new_scope returned the type of the actual template instance from
+ which we're constructing the template definition. It is already
+ defined. */
+ return;
+ }
+
+ /* Start the new template declaration. */
+ m_instance->enter_scope (scope);
+ m_instance->start_template_decl (defn->generic ().c_str ());
+
+ /* Get the parameters' generic kinds and types. */
+ define_template_parameters_generic (m_instance, defn,
+ tsym->template_arguments,
+ symbol_symtab (&tsym->base)->filename,
+ SYMBOL_LINE (&tsym->base));
+
+ /* Find the function node describing this template function. */
+ gdb_assert (defn->demangle_info ()->tree->type
+ == DEMANGLE_COMPONENT_TYPED_NAME);
+ struct demangle_component *comp = d_right (defn->demangle_info ()->tree);
+
+ gdb_assert (comp->type == DEMANGLE_COMPONENT_FUNCTION_TYPE);
+
+ /* The return type is either a concrete type (TYPE_TARGET_TYPE)
+ or a template parameter. */
+ gcc_type return_type;
+
+ if (tsym->template_return_index != -1)
+ {
+ gcc_type param_type
+ = defn->parameter_abstract_type (tsym->template_return_index);
+
+ return_type
+ = add_type_modifiers (m_instance, param_type, d_left (comp));
+ }
+ else if (tsym->conversion_operator_index != -1)
+ {
+ bool done = false;
+ gcc_type param_type
+ = defn->parameter_abstract_type (tsym->conversion_operator_index);
+
+ /* Conversion operators do not have a return type or arguments,
+ so we need to use the CONVERSION node in the left/name sub-tree
+ of the demangle tree. */
+
+ comp = d_left (defn->demangle_info ()->tree);
+ while (!done)
+ {
+ switch (comp->type)
+ {
+ case DEMANGLE_COMPONENT_TEMPLATE:
+ comp = d_left (comp);
+ break;
+
+ case DEMANGLE_COMPONENT_QUAL_NAME:
+ comp = d_right (comp);
+ break;
+
+ case DEMANGLE_COMPONENT_CONVERSION:
+ default:
+ done = true;
+ break;
+ }
+ }
+
+ /* We had better have found a CONVERSION node if
+ tsym->conversion_operator_index was set! */
+ gdb_assert (comp->type == DEMANGLE_COMPONENT_CONVERSION);
+ return_type = add_type_modifiers (m_instance, param_type,
+ d_left (comp));
+ }
+ else
+ {
+ struct type *temp = TYPE_TARGET_TYPE (SYMBOL_TYPE (&tsym->base));
+
+ return_type = m_instance->convert_type (temp);
+ }
+
+ /* Get the parameters' definitions, and put them into ARRAY. */
+ struct type *templ_type = SYMBOL_TYPE (&tsym->base);
+ int is_varargs = is_varargs_p (templ_type);
+ struct gcc_type_array array;
+
+ array.n_elements = TYPE_NFIELDS (templ_type);
+ array.elements = XNEWVEC (gcc_type, TYPE_NFIELDS (templ_type));
+ make_cleanup (xfree, array.elements);
+
+ int artificials = 0;
+
+ /* d_right (info->tree) is FUNCTION_TYPE (assert above). */
+ comp = d_right (d_right (defn->demangle_info ()->tree));
+ gdb_assert (comp != NULL && comp->type == DEMANGLE_COMPONENT_ARGLIST);
+
+ for (int i = 0; i < TYPE_NFIELDS (templ_type); ++i)
+ {
+ if (TYPE_FIELD_ARTIFICIAL (templ_type, i))
+ {
+ --array.n_elements;
+ ++artificials;
+ }
+ else
+ {
+ int tidx = tsym->template_argument_indices[i - artificials];
+ struct type *arg_type = TYPE_FIELD_TYPE (templ_type, i);
+
+ if (tidx == -1)
+ {
+ /* The parameter's type is a concrete type. */
+ array.elements[i - artificials]
+ = m_instance->convert_type (arg_type);
+ }
+ else
+ {
+ /* The parameter's type is a template parameter. */
+ gcc_type result = defn->parameter_abstract_type (tidx);
+
+ array.elements[i - artificials]
+ = add_type_modifiers (m_instance, result, d_left (comp));
+ }
+
+ /* Move to the next ARGLIST node. */
+ comp = d_right (comp);
+ }
+ }
+
+ gcc_type func_type = m_instance->build_function_type (return_type, &array,
+ is_varargs);
+
+ /* If we have a method, create its type and set additional symbol flags
+ for the compiler. */
+ if (defn->parent_type () != NULL
+ && defn->fidx () != -1 && defn->midx () != -1)
+ {
+ gcc_type class_type;
+ struct fn_field *methods
+ = TYPE_FN_FIELDLIST1 (defn->parent_type (), defn->fidx ());
+
+ /* Get the defining class's type. This should already be in the
+ cache. */
+ class_type = m_instance->convert_type (defn->parent_type ());
+
+ /* Add any virtuality flags. */
+ if (TYPE_FN_FIELD_VIRTUAL_P (methods, defn->midx ()))
+ {
+ sym_kind |= GCC_CP_FLAG_VIRTUAL_FUNCTION;
+
+ /* Unfortunate to have to do a symbol lookup, but this is the only
+ way to know if we have a pure virtual method. */
+ struct block_symbol sym
+ = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (methods, defn->midx ()),
+ m_instance->block (), VAR_DOMAIN, NULL);
+ if (sym.symbol == NULL)
+ {
+ /* !!keiths: The pure virtual hack. See
+ ccp_convert_struct_or_union_methods for more. */
+ sym_kind |= GCC_CP_FLAG_PURE_VIRTUAL_FUNCTION;
+ }
+ }
+
+ /* Add access flags. */
+ sym_kind |= get_method_access_flag (defn->parent_type (),
+ defn->fidx (), defn->midx ());
+
+ /* Create the method type. */
+ if (!TYPE_FN_FIELD_STATIC_P (methods, defn->midx ()))
+ {
+ gcc_cp_qualifiers_flags quals;
+ gcc_cp_ref_qualifiers_flags rquals;
+
+ quals = (enum gcc_cp_qualifiers) 0; /* !!keiths FIXME */
+ rquals = GCC_CP_REF_QUAL_NONE; /* !!keiths FIXME */
+ func_type
+ = m_instance->build_method_type (class_type, func_type, quals,
+ rquals);
+ }
+ }
+
+ /* Finally, define the new generic template declaration. */
+ gcc_decl decl
+ = m_instance->build_decl ("function template", name, sym_kind,
+ func_type, 0, 0,
+ symbol_symtab (&(tsym->base))->filename,
+ SYMBOL_LINE (&(tsym->base)));
+ defn->set_decl (decl);
+
+ m_instance->leave_scope ();
+ do_cleanups (back_to);
+ }
+
+ private:
+
+ /* The compiler instance to use. */
+ compile_cplus_instance *m_instance;
+};
+
+/* See description in compile-cplus-templates.h. */
+
+void
+compile_cplus_instance::emit_function_template_decls ()
+{
+ function_template_definer definer (this);
+
+ for (auto &item : *m_function_template_defns)
+ definer (item.second.get ());
+}
+
+/* A class to define and fill-in class template definitions. */
+
+class class_template_definer
+{
+ public:
+
+ class_template_definer (compile_cplus_instance *instance)
+ : m_instance (instance)
+ {
+ }
+
+ void operator() (class_template_defn *defn)
+ {
+ if (defn->defined ())
+ {
+ /* This template has already been defined. Keep looking for more
+ undefined templates. */
+ return;
+ }
+
+ /* Make sure this is only done once! */
+ defn->set_defined (true);
+
+ /* Define any default value types. */
+ const struct template_argument_info *arg_info
+ = TYPE_TEMPLATE_ARGUMENT_INFO (defn->type ());
+
+ define_default_template_parameter_types (m_instance, defn, arg_info);
+
+ /* Create/push new scope. */
+ compile_scope scope
+ = m_instance->new_scope (TYPE_NAME (defn->type ()), defn->type ());
+
+ if (scope.nested_type () != GCC_TYPE_NONE)
+ {
+ /* new_processing_context returned the type of the actual template
+ instance from which we're constructing the template definition.
+ It is already defined. */
+ return;
+ }
+ m_instance->enter_scope (scope);
+
+ /* Start a new template list for this template. */
+ m_instance->start_template_decl (defn->generic ().c_str ());
+
+ /* Get the parameters' generic kinds and types. */
+ define_template_parameters_generic (m_instance, defn, arg_info,
+ /* filename */ NULL, /*
+ !!keiths FIXME */
+ /* line */ 0
+ /* !!keiths FIXME */
+ );
+
+
+ /* Define the new generic template declaration. */
+ if (TYPE_CODE (defn->type ()) == TYPE_CODE_STRUCT)
+ {
+ gcc_decl decl
+ = m_instance->build_decl ("class template", defn->decl_name (),
+ GCC_CP_SYMBOL_CLASS /* | nested_access? */
+ | (TYPE_DECLARED_CLASS (defn->type ())
+ ? GCC_CP_FLAG_CLASS_NOFLAG
+ : GCC_CP_FLAG_CLASS_IS_STRUCT),
+ 0, NULL, 0, /*filename*/ NULL, /*line*/ 0);
+
+ defn->set_decl (decl);
+ }
+ else
+ {
+ gdb_assert (TYPE_CODE (defn->type ()) == TYPE_CODE_UNION);
+ gcc_decl decl
+ = m_instance->build_decl ("union template", defn->decl_name (),
+ GCC_CP_SYMBOL_UNION /* | nested_access? */,
+ 0, NULL, 0, /*fileanme*/NULL, /*line*/0);
+
+ defn->set_decl (decl);
+ }
+
+ m_instance->leave_scope ();
+ }
+
+ private:
+
+ /* The compiler instance to use. */
+ compile_cplus_instance *m_instance;
+};
+
+/* See description in compile-cplus-templates.h. */
+
+void
+compile_cplus_instance::emit_class_template_decls ()
+{
+ class_template_definer definer (this);
+
+ for (auto &item : *m_class_template_defns)
+ definer (item.second.get ());
+}
+
+/* A command to test function_template_decl. */
+
+static void
+print_template_defn_command (char *arg, int from_tty)
+{
+
+ char *demangled_name
+ = gdb_demangle (arg, DMGL_ANSI | DMGL_PARAMS | DMGL_RET_DROP);
+
+ if (demangled_name == NULL)
+ {
+ fprintf_filtered (gdb_stderr, _("could not demangle \"%s\"\n"), arg);
+ return;
+ }
+
+ struct cleanup *back_to = make_cleanup (xfree, demangled_name);
+ struct block_symbol symbol
+ = lookup_symbol (demangled_name, NULL, VAR_DOMAIN, NULL);
+
+ if (symbol.symbol == NULL)
+ {
+ fprintf_filtered (gdb_stderr, _("could not find symbol for \"%s\"\n"),
+ arg);
+ do_cleanups (back_to);
+ return;
+ }
+
+ if (!SYMBOL_IS_CPLUS_TEMPLATE_FUNCTION (symbol.symbol))
+ {
+ fprintf_filtered (gdb_stderr, _("symbol \"%s\" does not represent a"
+ " template function\n"), arg);
+ do_cleanups (back_to);
+ return;
+ }
+
+ struct template_symbol *tsymbol = (struct template_symbol *) symbol.symbol;
+
+ cp_decode_template_type_indices (tsymbol, NULL);
+
+ std::unique_ptr<demangle_parse_info> info
+ = cp_mangled_name_to_comp (arg, DMGL_ANSI | DMGL_PARAMS);
+ std::string str = function_template_decl (tsymbol, info.get ());
+
+ fprintf_filtered (gdb_stdout, "%s\n", str.c_str ());
+ do_cleanups (back_to);
+}
+
+void _initialize_compile_cplus_templates ();
+
+void
+_initialize_compile_cplus_templates ()
+{
+ add_cmd ("tdef", class_maintenance, print_template_defn_command,
+ _("Print the template generic for the given linkage name."),
+ &maint_cplus_cmd_list);
+}
diff --git a/gdb/compile/compile-cplus-templates.h b/gdb/compile/compile-cplus-templates.h
new file mode 100644
index 00000000000..56290b49331
--- /dev/null
+++ b/gdb/compile/compile-cplus-templates.h
@@ -0,0 +1,319 @@
+/* Template support for compile.
+
+ Copyright (C) 2016, 2017 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef COMPILE_CPLUS_TEMPLATES_H
+#define COMPILE_CPLUS_TEMPLATES_H
+#include "gdbtypes.h"
+#include "cp-support.h"
+
+#include <string>
+#include <vector>
+#include <unordered_map>
+#include <memory>
+
+struct symbol;
+struct gcc_cp_template_args;
+struct template_symbol;
+
+namespace compile
+{
+ class function_template_defn;
+ class class_template_defn;
+ class compile_cplus_instance;
+
+ /* Types used for tracking template definitions. */
+ typedef std::unique_ptr<function_template_defn> function_template_defn_up;
+ typedef std::unique_ptr<class_template_defn> class_template_defn_up;
+ typedef std::pair<std::string, function_template_defn_up>
+ function_template_map_item_t;
+ typedef std::unordered_map<std::string, function_template_defn_up>
+ function_template_defn_map_t;
+ typedef std::pair<std::string, class_template_defn_up>
+ class_template_map_item_t;
+ typedef std::unordered_map<std::string, class_template_defn_up>
+ class_template_defn_map_t;
+
+ /* A base class holding data common to all template definitions. */
+
+ class template_defn
+ {
+ public:
+
+ /* Return the declaration name of this definition. */
+
+ const char *
+ decl_name () const
+ {
+ return m_decl_name.c_str ();
+ }
+
+ /* Return the compiler plug-in's decl for this definition. */
+
+ gcc_decl
+ decl () const
+ {
+ return m_decl;
+ }
+
+ /* Set the compiler plug-in's decl for this definition. */
+
+ void
+ set_decl (gcc_decl decl)
+ {
+ m_decl = decl;
+ }
+
+ /* Return the generic string for this template definition. */
+
+ const std::string
+ generic (void) const
+ {
+ return m_generic;
+ }
+
+ /* Return the compiler plug-in's abstract type for the IDX'th
+ template parameter. */
+
+ gcc_type
+ parameter_abstract_type (unsigned int idx) const
+ {
+ return m_abstract_types[idx];
+ }
+
+ /* Set the IDX'th template parameter's abstract type. */
+
+ void
+ set_parameter_abstract_type (unsigned int idx, gcc_type type)
+ {
+ m_abstract_types[idx] = type;
+ }
+
+ /* Has this template already been defined in the compiler plug-in? */
+
+ bool
+ defined (void) const
+ {
+ return m_defined;
+ }
+
+ /* Mark this definition as defined in the compiler plug-in. */
+
+ void
+ set_defined (bool val)
+ {
+ m_defined = val;
+ }
+
+ /* Return the ARG_NUM'th template parameter's default value
+ or NULL if none was set (or known). */
+
+ struct symbol *
+ default_argument (unsigned int arg_num) const
+ {
+ return m_default_arguments[arg_num];
+ }
+
+ /* Record the value of the ARG_NUM'th template parameter. */
+
+ void
+ set_default_argument (unsigned int arg_num, struct symbol *value)
+ {
+ m_default_arguments[arg_num] = value;
+ }
+
+ protected:
+
+ /* Protected constructor so that no one instantiates this
+ type directly.
+
+ DECL_NAME is the declaration name of this template, i.e., it's
+ name with no template parameters. GENERIC is the computed generic
+ template definition. N_PARAMETERS specifies how many template
+ parameters this template has. */
+
+ template_defn (std::string decl_name, std::string generic,
+ unsigned int n_parameters)
+ : m_decl_name (decl_name), m_generic (generic),
+ m_abstract_types (n_parameters), m_decl (0),
+ m_default_arguments (n_parameters), m_defined (false)
+ {
+ }
+
+ private:
+
+ /* The declaration name of the template, excluding any
+ parameters. */
+ std::string m_decl_name;
+
+ /* A string representation of the generic template definition. */
+ std::string m_generic;
+
+ /* The abstract template parameter types. */
+ std::vector<gcc_type> m_abstract_types;
+
+ /* The decl associated with this template definition. */
+ gcc_decl m_decl;
+
+ /* A list of default values for the parameters of this template. */
+ std::vector<struct symbol *> m_default_arguments;
+
+ /* Has this template already been defined? This is a necessary evil
+ since we have to traverse over all hash table entries. */
+ bool m_defined;
+ };
+
+ /* A function template definition. */
+
+ class function_template_defn
+ : public template_defn
+ {
+ public:
+
+ /* Construct a new function template definition with the generic
+ string representation GENERIC and demangle INFO, based on the
+ concrete instance given by template symbol TSYMBOL.
+
+ If this definition is a method template, PARENT_TYPE is the type
+ of the closing class and FIDX and MIDX are the fieldlist and
+ method indices, respectively, which describe this method.
+
+ If this definition is not a method template, PARENT_TYPE is NULL
+ and FIDX/MIDX are both -1. */
+
+ function_template_defn (std::string generic,
+ std::unique_ptr<demangle_parse_info> info,
+ const struct template_symbol *tsymbol,
+ struct type *parent_type, int fidx, int midx);
+
+ /* Return the demangle information for this template. */
+
+ const demangle_parse_info *demangle_info (void) const
+ {
+ return m_demangle_info.get ();
+ }
+
+ /* Return the concrete instance used to define this template. */
+
+ const struct template_symbol *template_symbol (void) const
+ {
+ return m_tsymbol;
+ }
+
+ /* For method templates, return the type of the enclosing parent type,
+ or NULL for non-method templates. */
+
+ struct type *parent_type (void) const
+ {
+ return m_parent_type;
+ }
+
+ /* For method templates, return the field list index in PARENT_TYPE
+ which describes this method. Return -1 otherwise. */
+
+ int fidx (void) const
+ {
+ return m_fidx;
+ }
+
+ /* For method templates, return the index of this method into the
+ field list (given by fidx()). Return -1 otherwise. */
+
+ int midx (void) const
+ {
+ return m_midx;
+ }
+
+ private:
+
+ /* The template symbol used to create this template definition.
+ NOTE: Any given template_defn could be associated with any number
+ of template instances in the program.
+
+ This field is not const since we will be lazily computing template
+ parameter indices for the function's argument and return types. */
+
+ const struct template_symbol *m_tsymbol;
+
+ /* The parent type or NULL if this does not represent a method. */
+
+ struct type *m_parent_type;
+
+ /* The fieldlist and method indices for the method or -1 if this template
+ definition does not represent a method. */
+
+ int m_fidx;
+ int m_midx;
+
+ /* Demangle tree for the template defining this generic. */
+ std::unique_ptr<demangle_parse_info> m_demangle_info;
+ };
+
+ /* A class template definition. */
+
+ class class_template_defn
+ : public template_defn
+ {
+ public:
+
+ /* A unary function to delete map items. */
+
+ static void destroy (class_template_map_item_t p);
+
+ /* Construct a new class template definition with the generic
+ string representation GENERIC based on the concrete instance
+ TYPE. */
+
+ class_template_defn (std::string decl_name, std::string generic,
+ struct type *type)
+ : template_defn (decl_name, generic, TYPE_N_TEMPLATE_ARGUMENTS (type)),
+ m_type (type)
+ {
+ }
+
+ /* Return concrete instance that this template definition was
+ based on. */
+
+ struct type *type (void) const
+ {
+ return m_type;
+ }
+
+ private:
+
+ /* The type used to create this template definition.
+ NOTE: Any given template_defn could be associated with any number
+ of template instances in the program. */
+ struct type *m_type;
+ };
+
+ /* Loop over SYMBOLS, defining any generic template definitions for
+ any template symbols in the list. */
+
+ void define_templates (compile_cplus_instance *instance,
+ VEC (block_symbol_d) *symbols);
+
+
+ /* Scan TYPE for any new function templates.
+ Does not actually emit definitions for any new templates until
+ emit_function_template_decls is called. */
+
+ void scan_type_for_function_templates (compile_cplus_instance *instance,
+ struct type *type);
+};
+#endif /* COMPILE_CPLUS_TEMPLATES_H */
diff --git a/gdb/compile/compile-cplus-types.c b/gdb/compile/compile-cplus-types.c
new file mode 100644
index 00000000000..52655246199
--- /dev/null
+++ b/gdb/compile/compile-cplus-types.c
@@ -0,0 +1,2273 @@
+/* Convert types from GDB to GCC
+
+ Copyright (C) 2014-2017 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 "gdbtypes.h"
+#include "compile-internal.h"
+#include "compile-cplus.h"
+#include "gdb_assert.h"
+#include "symtab.h"
+#include "source.h"
+#include "cp-support.h"
+#include "cp-abi.h"
+#include "symtab.h"
+#include "objfiles.h"
+#include "block.h"
+#include "gdbcmd.h"
+#include "c-lang.h"
+#include "compile-c.h" /* Included for c_get_range_decl_name
+ et al. */
+
+#include <algorithm>
+
+using namespace compile;
+
+/* Define to enable debugging for ctor/dtor definitions during
+ type conversion. */
+
+#define DEBUG_XTOR 0
+
+/* A "type" to indicate that convert_type should not attempt to
+ cache its resultant type. This is used, for example, when defining
+ namespaces for the oracle. */
+
+#define DONT_CACHE_TYPE ((gcc_type) 0)
+
+/* Flag to enable internal debugging. */
+
+static int debug_compile_cplus_types = 0;
+
+/* Flag to enable internal scope switching debugging. */
+
+static int debug_compile_cplus_scopes = 0;
+
+/* Forward declarations. */
+
+static gcc_type ccp_convert_func (compile_cplus_instance *instance,
+ struct type *type, int strip_artificial);
+
+/* See description in compile-cplus.h. */
+
+char *
+compile::decl_name (const char *natural)
+{
+ char *name = NULL;
+
+ if (natural != NULL)
+ {
+ char *stripped;
+
+ /* !!keiths: FIXME: Write a new parser func to do this? */
+ name = cp_func_name (natural);
+ if (name == NULL)
+ {
+ stripped = cp_strip_template_parameters (natural);
+ if (stripped != NULL)
+ return stripped;
+
+ name = xstrdup (natural);
+ }
+ else
+ {
+ stripped = cp_strip_template_parameters (name);
+ if (stripped != NULL)
+ {
+ xfree (name);
+ return stripped;
+ }
+ }
+ }
+
+ return name;
+}
+
+/* See description in compile-cplus.h. */
+
+int
+compile::is_varargs_p (const struct type *type)
+{
+ /* !!keiths: This doesn't always work, unfortunately. When we have a
+ pure virtual method, TYPE_PROTOTYPED == 0.
+ But this *may* be needed for several gdb.compile tests. Or at least
+ indicate other unresolved bugs in this file or elsewhere in gdb. */
+ return TYPE_VARARGS (type) /*|| !TYPE_PROTOTYPED (type)*/;
+}
+
+/* Get the access flag for the NUM'th field of TYPE. */
+
+static enum gcc_cp_symbol_kind
+get_field_access_flag (const struct type *type, int num)
+{
+ if (TYPE_FIELD_PROTECTED (type, num))
+ return GCC_CP_ACCESS_PROTECTED;
+ else if (TYPE_FIELD_PRIVATE (type, num))
+ return GCC_CP_ACCESS_PRIVATE;
+
+ /* GDB assumes everything else is public. */
+ return GCC_CP_ACCESS_PUBLIC;
+}
+
+/* Get the access flag for the NUM'th method of TYPE's FNI'th
+ fieldlist. */
+
+enum gcc_cp_symbol_kind
+compile::get_method_access_flag (const struct type *type, int fni, int num)
+{
+ const struct fn_field *methods;
+
+ gdb_assert (TYPE_CODE (type) == TYPE_CODE_STRUCT);
+
+ /* If this type was not declared a class, everything is public. */
+ if (!TYPE_DECLARED_CLASS (type))
+ return GCC_CP_ACCESS_PUBLIC;
+
+ /* Otherwise, read accessibility from the fn_field. */
+ methods = TYPE_FN_FIELDLIST1 (type, fni);
+ if (TYPE_FN_FIELD_PUBLIC (methods, num))
+ return GCC_CP_ACCESS_PUBLIC;
+ else if (TYPE_FN_FIELD_PROTECTED (methods, num))
+ return GCC_CP_ACCESS_PROTECTED;
+ else if (TYPE_FN_FIELD_PRIVATE (methods, num))
+ return GCC_CP_ACCESS_PRIVATE;
+
+ gdb_assert_not_reached ("unhandled method access specifier");
+}
+
+/* A useful debugging function to output the scope SCOPE
+ to stdout. */
+
+static void __attribute__ ((used))
+debug_print_scope (const compile_scope &scope)
+{
+ int i;
+
+ for (const auto &comp: scope)
+ {
+ std::string symbol = (comp.bsymbol.symbol != NULL
+ ? SYMBOL_NATURAL_NAME (comp.bsymbol.symbol)
+ : "<none>");
+
+ printf ("\tname = %s, symbol = %s\n", comp.name.c_str (),
+ symbol.c_str ());
+ }
+}
+
+/* Utility function to convert CODE into a string. */
+
+static const char *
+type_code_to_string (enum type_code code)
+{
+ const char * const s[] =
+ {"BISTRING (deprecated)", "UNDEF (not used)",
+ "PTR", "ARRAY", "STRUCT", "UNION", "ENUM",
+ "FLAGS", "FUNC", "INT", "FLT", "VOID",
+ "SET", "RANGE", "STRING", "ERROR", "METHOD",
+ "METHODPTR", "MEMBERPTR", "REF", "CHAR", "BOOL",
+ "COMPLEX", "TYPEDEF", "NAMESPACE", "DECFLOAT", "MODULE",
+ "INTERNAL_FUNCTION", "XMETHOD"};
+
+ return s[code + 1];
+}
+
+/* See description in compile-cplus.h. */
+
+compile_scope
+compile::type_name_to_scope (const char *type_name, const struct block *block)
+{
+ compile_scope scope;
+
+ if (type_name == NULL)
+ {
+ /* An anonymous type. We cannot really do much here. We simply cannot
+ look up anonymous types easily/at all. */
+ return scope;
+ }
+
+ const char *p = type_name;
+ std::string lookup_name;
+
+ while (1)
+ {
+ /* Create a string token of the first component of TYPE_NAME. */
+ int len = cp_find_first_component (p);
+ std::string s (p, len);
+
+ /* Advance past the last token. */
+ p += len;
+
+ /* Look up the symbol and decide when to stop. */
+ if (!lookup_name.empty ())
+ lookup_name += "::";
+ lookup_name += s;
+
+ /* Look up the resulting name. */
+ struct block_symbol bsymbol
+ = lookup_symbol (lookup_name.c_str (), block, VAR_DOMAIN, NULL);
+
+ if (bsymbol.symbol != NULL)
+ {
+ scope_component comp = {s, bsymbol};
+
+ scope.push_back (comp);
+
+ if (TYPE_CODE (SYMBOL_TYPE (bsymbol.symbol)) != TYPE_CODE_NAMESPACE)
+ {
+ /* We're done. */
+ break;
+ }
+ }
+
+ if (*p == ':')
+ {
+ ++p;
+ if (*p == ':')
+ ++p;
+ else
+ {
+ /* This shouldn't happen since we are not attempting to
+ loop over user input. This name is generated by GDB
+ from debug info. */
+ internal_error (__FILE__, __LINE__,
+ _("malformed TYPE_NAME during parsing"));
+ }
+ }
+ if (p[0] == '\0')
+ break;
+ }
+
+ return scope;
+}
+
+/* Compare two scope_components for equality. These are equal if the names
+ of the two components' are the same. */
+
+bool
+compile::operator== (const scope_component &lhs, const scope_component &rhs)
+{
+ return lhs.name == rhs.name;
+}
+
+/* Compare two scope_components for inequality. These are not equal if
+ the two components' names are not equal. */
+
+bool
+compile::operator!= (const scope_component &lhs, const scope_component &rhs)
+{
+ return lhs.name != rhs.name;
+}
+
+/* Compare two compile_scopes for equality. These are equal if they are both
+ contain the same number of components and each component is equal. */
+
+bool
+compile::operator== (const compile_scope &lhs, const compile_scope &rhs)
+{
+ if (lhs.size () != rhs.size ())
+ return false;
+
+ for (int i = 0; i < lhs.size (); ++i)
+ {
+ if (lhs[i] != rhs[i])
+ return false;
+ }
+
+ return true;
+}
+
+/* Compare two compile_scopes for inequality. These are inequal if they
+ contain unequal number of elements or if any of the components are not
+ the same. */
+
+bool
+compile::operator!= (const compile_scope &lhs, const compile_scope &rhs)
+{
+ if (lhs.size () != rhs.size ())
+ return true;
+
+ for (int i = 0; i < lhs.size (); ++i)
+ {
+ if (lhs[i] != rhs[i])
+ return true;
+ }
+
+ return false;
+}
+
+/* See description in compile-cplus.h. */
+
+void
+compile_cplus_instance::enter_scope (compile_scope &new_scope)
+{
+ bool must_push = m_scopes.empty () || m_scopes.back () != new_scope;
+
+ new_scope.m_pushed = must_push;
+
+ /* Save the new scope. */
+ m_scopes.push_back (new_scope);
+
+ if (must_push)
+ {
+ if (debug_compile_cplus_scopes)
+ printf_unfiltered ("entering new scope %p\n", new_scope);
+
+ /* Push the global namespace. */
+ push_namespace ("");
+
+ /* Push all other namespaces. Note that we do not push the last
+ scope_component -- that's the actual type we are converting. */
+ std::for_each
+ (new_scope.begin (), new_scope.end () - 1, [this] (const auto &comp)
+ {
+ gdb_assert (TYPE_CODE (SYMBOL_TYPE (comp.bsymbol.symbol))
+ == TYPE_CODE_NAMESPACE);
+
+ const char *ns = (comp.name == CP_ANONYMOUS_NAMESPACE_STR ? NULL
+ : comp.name.c_str ());
+
+ this->push_namespace (ns);
+ });
+ }
+ else
+ {
+ if (debug_compile_cplus_scopes)
+ {
+ printf_unfiltered
+ ("staying in current scope -- scopes are identical\n");
+ }
+ }
+}
+
+/* See description in compile-cplus.h. */
+
+void
+compile_cplus_instance::leave_scope ()
+{
+ /* Get the current scope and remove it from the internal list of
+ scopes. */
+ compile_scope current = m_scopes.back ();
+
+ m_scopes.pop_back ();
+
+ if (current.m_pushed)
+ {
+ if (debug_compile_cplus_scopes)
+ printf_unfiltered ("leaving scope %p\n", current);
+
+ /* Pop namespaces. Do not push the last scope_component -- that's
+ the type we are converting, not a namespace. */
+ std::for_each
+ (current.begin (),current.end () - 1, [this] (const auto &comp) {
+ gdb_assert (TYPE_CODE (SYMBOL_TYPE (comp.bsymbol.symbol))
+ == TYPE_CODE_NAMESPACE);
+ this->pop_binding_level (comp.name.c_str ());
+ });
+
+ /* Pop global namespace. */
+ pop_binding_level ("");
+ }
+ else
+ {
+ if (debug_compile_cplus_scopes)
+ printf_unfiltered ("identical scopes -- not leaving scope\n");
+ }
+}
+
+/*See description in compile-cplus.h. */
+
+compile_scope
+compile_cplus_instance::new_scope (const char *type_name, struct type *type)
+{
+ /* Break the type name into components. If TYPE was defined in some
+ superclass, we do not process TYPE but process the enclosing type
+ instead. */
+ compile_scope scope = type_name_to_scope (type_name, block ());
+
+ if (!scope.empty ())
+ {
+ /* Get the name of the last component, which should be the
+ unqualified name of the type to process. */
+ scope_component &comp = scope.back ();
+
+ if (!types_equal (type, SYMBOL_TYPE (comp.bsymbol.symbol))
+ && (m_scopes.empty ()
+ || (m_scopes.back ().back ().bsymbol.symbol
+ != comp.bsymbol.symbol)))
+ {
+ /* The type is defined inside another class(es). Convert that
+ type instead of defining this type. */
+ convert_type (SYMBOL_TYPE (comp.bsymbol.symbol));
+
+ /* If the original type (passed in to us) is defined in a nested
+ class, the previous call will give us that type's gcc_type.
+ Upper layers are expecting to get the original type's
+ gcc_type! */
+ type_map_t::iterator pos = m_type_map.find (type);
+
+ gdb_assert (pos != m_type_map.end ());
+ scope.m_nested_type = pos->second;
+ return scope;
+ }
+ }
+ else
+ {
+ if (TYPE_NAME (type) == NULL)
+ {
+ /* Anonymous type */
+
+ /* We don't have a qualified name for this to look up, but
+ we need a scope. We have to assume, then, that it is the same
+ as the current scope, if any. */
+ if (!m_scopes.empty ())
+ {
+ scope = m_scopes.back ();
+ scope.m_pushed = false;
+ }
+ else
+ scope.push_back (scope_component ());
+ }
+ else
+ {
+ scope_component comp;
+
+ comp.bsymbol
+ = lookup_symbol (TYPE_NAME (type), block (), VAR_DOMAIN, NULL);
+
+ char *name = cp_func_name (TYPE_NAME (type));
+
+ comp.name = name;
+ xfree (name);
+ scope.push_back (comp);
+ }
+ }
+
+ /* Ensure least one component in the scope. */
+ gdb_assert (scope.size () > 0);
+ return scope;
+}
+
+/* !!keiths: not RVALUE REFERENCES! */
+
+gcc_type
+compile::convert_reference_base (compile_cplus_instance *instance,
+ gcc_type base)
+{
+ return instance->build_reference_type (base, GCC_CP_REF_QUAL_LVALUE);
+}
+
+/* Convert a reference type to its gcc representation. */
+
+static gcc_type
+ccp_convert_reference (compile_cplus_instance *instance,
+ struct type *type)
+{
+ gcc_type target = instance->convert_type (TYPE_TARGET_TYPE (type));
+
+ /* !!keiths: GDB does not currently do anything with rvalue references.
+ [Except set the type code to TYPE_CODE_ERROR! */
+ return convert_reference_base (instance, target);
+}
+
+/* See description in compile-cplus.h. */
+
+gcc_type
+compile::convert_pointer_base (compile_cplus_instance *instance,
+ gcc_type target)
+{
+ return instance->build_pointer_type (target);
+}
+
+/* Convert a pointer type to its gcc representation. */
+
+static gcc_type
+ccp_convert_pointer (compile_cplus_instance *instance,
+ struct type *type)
+{
+ gcc_type target = instance->convert_type (TYPE_TARGET_TYPE (type));
+
+ return convert_pointer_base (instance, target);
+}
+
+/* Convert an array type to its gcc representation. */
+
+static gcc_type
+ccp_convert_array (compile_cplus_instance *instance, struct type *type)
+{
+ struct type *range = TYPE_INDEX_TYPE (type);
+ gcc_type element_type = instance->convert_type (TYPE_TARGET_TYPE (type));
+
+ if (TYPE_LOW_BOUND_KIND (range) != PROP_CONST)
+ {
+ const char *s = _("array type with non-constant"
+ " lower bound is not supported");
+
+ return instance->error (s);
+ }
+
+ if (TYPE_LOW_BOUND (range) != 0)
+ {
+ const char *s = _("cannot convert array type with "
+ "non-zero lower bound to C");
+
+ return instance->error (s);
+ }
+
+ if (TYPE_HIGH_BOUND_KIND (range) == PROP_LOCEXPR
+ || TYPE_HIGH_BOUND_KIND (range) == PROP_LOCLIST)
+ {
+ gcc_type result;
+ char *upper_bound;
+
+ if (TYPE_VECTOR (type))
+ {
+ const char *s = _("variably-sized vector type is not supported");
+
+ return instance->error (s);
+ }
+
+ upper_bound = c_get_range_decl_name (&TYPE_RANGE_DATA (range)->high);
+ result = instance->build_vla_array_type (element_type, upper_bound);
+ xfree (upper_bound);
+ return result;
+ }
+ else
+ {
+ LONGEST low_bound, high_bound, count;
+
+ if (get_array_bounds (type, &low_bound, &high_bound) == 0)
+ count = -1;
+ else
+ {
+ gdb_assert (low_bound == 0); /* Ensured above. */
+ count = high_bound + 1;
+ }
+
+ if (TYPE_VECTOR (type))
+ return instance->build_vector_type (element_type, count);
+
+ return instance->build_array_type (element_type, count);
+ }
+}
+
+/* Convert a typedef of TYPE. If not GCC_CP_ACCESS_NONE, NESTED_ACCESS
+ will define the accessibility of the typedef definition in its
+ containing class. */
+
+static gcc_type
+ccp_convert_typedef (compile_cplus_instance *instance,
+ struct type *type, enum gcc_cp_symbol_kind nested_access)
+{
+ compile_scope scope = instance->new_scope (TYPE_NAME (type), type);
+
+ if (scope.nested_type () != GCC_TYPE_NONE)
+ return scope.nested_type ();
+
+ char *name = NULL;
+ struct cleanup *cleanups = make_cleanup (free_current_contents, &name);
+
+ if (TYPE_NAME (type) != NULL)
+ name = cp_func_name (TYPE_NAME (type));
+
+ /* Make sure the scope for this type has been pushed. */
+ instance->enter_scope (scope);
+
+ /* Convert the typedef's real type. */
+ gcc_type typedef_type = instance->convert_type (check_typedef (type));
+
+ instance->build_decl ("typedef", name,
+ GCC_CP_SYMBOL_TYPEDEF | nested_access,
+ typedef_type,
+ 0, 0,
+ /* !!keiths: Wow. More of this! */
+ NULL, 0);
+
+ /* Completed this scope. */
+ instance->leave_scope ();
+ do_cleanups (cleanups);
+ return typedef_type;
+}
+
+/* Convert types defined in TYPE. */
+
+static void
+ccp_convert_type_defns (compile_cplus_instance *instance, struct type *type)
+{
+ int i;
+ enum gcc_cp_symbol_kind accessibility;
+
+ /* Convert typedefs. */
+ for (i = 0; i < TYPE_TYPEDEF_FIELD_COUNT (type); ++i)
+ {
+ if (TYPE_TYPEDEF_FIELD_PUBLIC (type, i))
+ accessibility = GCC_CP_ACCESS_PUBLIC;
+ else if (TYPE_TYPEDEF_FIELD_PROTECTED (type, i))
+ accessibility = GCC_CP_ACCESS_PROTECTED;
+ else if (TYPE_TYPEDEF_FIELD_PRIVATE (type, i))
+ accessibility = GCC_CP_ACCESS_PRIVATE;
+ else
+ gdb_assert_not_reached ("unknown accessibility");
+ instance->convert_type (TYPE_TYPEDEF_FIELD_TYPE (type, i), accessibility);
+ }
+
+ /* Convert nested types. */
+ for (i = 0; i < TYPE_NESTED_TYPES_COUNT (type); ++i)
+ {
+ if (TYPE_NESTED_TYPES_FIELD_PUBLIC (type, i))
+ accessibility = GCC_CP_ACCESS_PUBLIC;
+ else if (TYPE_NESTED_TYPES_FIELD_PROTECTED (type, i))
+ accessibility = GCC_CP_ACCESS_PROTECTED;
+ else if (TYPE_NESTED_TYPES_FIELD_PRIVATE (type, i))
+ accessibility = GCC_CP_ACCESS_PRIVATE;
+ else
+ gdb_assert_not_reached ("unknown accessibility");
+ instance->convert_type (TYPE_NESTED_TYPES_FIELD_TYPE (type, i),
+ accessibility);
+ }
+}
+
+/* Convert data members defined in TYPE, which should be struct/class/union
+ with gcc_type COMP_TYPE. */
+
+static void
+ccp_convert_struct_or_union_members (compile_cplus_instance *instance,
+ struct type *type, gcc_type comp_type)
+{
+ int i;
+
+ for (i = TYPE_N_BASECLASSES (type); i < TYPE_NFIELDS (type); ++i)
+ {
+ CORE_ADDR physaddr;
+ gcc_type field_type;
+ const char *field_name = TYPE_FIELD_NAME (type, i);
+
+ if (TYPE_FIELD_IGNORE (type, i)
+ || TYPE_FIELD_ARTIFICIAL (type, i))
+ continue;
+
+ field_type
+ = instance->convert_type (TYPE_FIELD_TYPE (type, i));
+
+ if (field_is_static (&TYPE_FIELD (type, i)))
+ {
+ switch (TYPE_FIELD_LOC_KIND (type, i))
+ {
+ case FIELD_LOC_KIND_PHYSADDR:
+ {
+ physaddr = TYPE_FIELD_STATIC_PHYSADDR (type, i);
+
+ instance->build_decl ("field physaddr", field_name,
+ (GCC_CP_SYMBOL_VARIABLE
+ | get_field_access_flag (type, i)),
+ field_type, NULL, physaddr,
+ NULL, 0);
+ }
+ break;
+
+ case FIELD_LOC_KIND_PHYSNAME:
+ {
+ const char *physname = TYPE_FIELD_STATIC_PHYSNAME (type, i);
+ struct block_symbol sym
+ = lookup_symbol (physname, instance->block (), VAR_DOMAIN,
+ NULL);
+ const char *filename;
+ unsigned int line;
+
+ if (sym.symbol == NULL)
+ {
+ /* We didn't actually find the symbol. There's little
+ we can do but ignore this member. */
+ continue;
+ }
+ filename = symbol_symtab (sym.symbol)->filename;
+ line = SYMBOL_LINE (sym.symbol);
+ physaddr = SYMBOL_VALUE_ADDRESS (sym.symbol);
+ instance->build_decl ("field physname", field_name,
+ (GCC_CP_SYMBOL_VARIABLE
+ | get_field_access_flag (type, i)),
+ field_type, NULL, physaddr,
+ filename, line);
+ }
+ break;
+
+ default:
+ gdb_assert_not_reached
+ ("unexpected static field location kind");
+ }
+ }
+ else
+ {
+ unsigned long bitsize = TYPE_FIELD_BITSIZE (type, i);
+ enum gcc_cp_symbol_kind field_flags = GCC_CP_SYMBOL_FIELD
+ | get_field_access_flag (type, i)
+ /* FIXME:
+ | (field-is-mutable-p (type, i)
+ ? GCC_CP_FLAG_FIELD_MUTABLE
+ : GCC_CP_FLAG_FIELD_NOFLAG)
+ -lxo */
+ ;
+
+ if (bitsize == 0)
+ bitsize = 8 * TYPE_LENGTH (TYPE_FIELD_TYPE (type, i));
+
+ /* FIXME: We have to save the returned decl somewhere, so
+ that we can refer to it in expressions, in context for
+ lambdas, etc. */
+ instance->build_field (field_name, field_type, field_flags,
+ bitsize, TYPE_FIELD_BITPOS (type, i));
+ }
+ }
+}
+
+/* Convert a method type to its gcc representation. */
+
+static gcc_type
+ccp_convert_method (compile_cplus_instance *instance,
+ struct type *parent_type, struct type *method_type)
+{
+ gcc_type result, func_type, class_type;
+ gcc_cp_qualifiers_flags quals;
+ gcc_cp_ref_qualifiers_flags rquals;
+
+ /* Get the actual (proto)type of the method, as a function. */
+ func_type = ccp_convert_func (instance, method_type, 1);
+
+ class_type = instance->convert_type (parent_type);
+ quals = (enum gcc_cp_qualifiers) 0;
+ if (TYPE_CONST (method_type))
+ quals |= GCC_CP_QUALIFIER_CONST;
+ if (TYPE_VOLATILE (method_type))
+ quals |= GCC_CP_QUALIFIER_VOLATILE;
+ if (TYPE_RESTRICT (method_type))
+ quals |= GCC_CP_QUALIFIER_RESTRICT;
+ rquals = GCC_CP_REF_QUAL_NONE;
+ /* !!keiths FIXME */
+ result = instance->build_method_type (class_type, func_type, quals, rquals);
+ return result;
+}
+
+/* Convert a member or method pointer represented by TYPE. */
+
+static gcc_type
+ccp_convert_memberptr (compile_cplus_instance *instance, struct type *type)
+{
+ struct type *containing_class = TYPE_SELF_TYPE (type);
+
+ if (containing_class == NULL)
+ return GCC_TYPE_NONE;
+
+ gcc_type class_type = instance->convert_type (containing_class);
+ gcc_type member_type = instance->convert_type (TYPE_TARGET_TYPE (type));
+
+ return instance->build_pointer_to_member_type (class_type, member_type);
+}
+
+#define OPHASH1(A) ((uint32_t) A << 16)
+#define OPHASH2(A,B) OPHASH1(A) | (uint32_t) B << 8
+#define OPHASH3(A,B,C) OPHASH2(A,B) | (uint32_t) C
+
+/* Compute a one, two, or three letter hash for the operator given by
+ OP. Returns the computed hash or zero for (some) conversion operators. */
+
+static uint32_t
+operator_hash (const char *op)
+{
+ const char *p = op;
+ uint32_t hash = 0;
+ int len = 0;
+
+ while (p[0] != '\0' && (p[0] != '(' || p[1] == ')'))
+ {
+ ++len;
+ ++p;
+ }
+
+ switch (len)
+ {
+ case 1:
+ hash = OPHASH1(op[0]);
+ break;
+ case 2:
+ hash = OPHASH2(op[0], op[1]);
+ break;
+ case 3:
+ /* This will also hash "operator int", but the plug-in does not
+ recognize OPHASH3('i', 'n', 't'), so we still end up in the code
+ to do a conversion operator in the caller. */
+ hash = OPHASH3(op[0], op[1], op[2]);
+ break;
+ default:
+ break;
+ }
+
+ return hash;
+}
+
+/* Returns non-zero iff TYPE represents a binary method. */
+
+static int
+is_binary_method (const struct type *type)
+{
+ int i, len;
+
+ for (i = 0, len = 0; i < TYPE_NFIELDS (type); ++i)
+ {
+ if (!TYPE_FIELD_ARTIFICIAL (type, i))
+ ++len;
+ }
+
+ return len > 1;
+}
+
+/* See compile-cplus.h. */
+
+const char *
+compile::maybe_canonicalize_special_function
+ (const char *field_name, const struct fn_field *method_field,
+ const struct type *method_type, char **outname, bool *ignore)
+{
+ /* We assume that no method is to be ignored. */
+ *ignore = false;
+
+ /* We only consider ctors and dtors if METHOD_FIELD is non-NULL. */
+ if (method_field != NULL)
+ {
+ if (method_field->is_constructor)
+ {
+#if DEBUG_XTOR
+ printf ("*** CONSTRUCTOR %s: ", field_name);
+#endif
+#if CAUSES_ICE
+ switch (method_field->cdtor_type.ctor_kind)
+ {
+ case complete_object_ctor:
+#if DEBUG_XTOR
+ printf ("complete_object_ctor (C1)\n");
+#endif
+ return "C1";
+
+ case base_object_ctor:
+#if DEBUG_XTOR
+ printf ("base_object_ctor (C2)\n");
+#endif
+ return "C2";
+
+ case complete_object_allocating_ctor:
+ *ignore = true;
+#if DEBUG_XTOR
+ printf ("complete_object_allocating_ctor -- ignored\n");
+#endif
+ return field_name; /* C? */
+
+ case unified_ctor:
+#if DEBUG_XTOR
+ printf ("unified_ctor (C4) -- ignored\n");
+#endif
+ *ignore = true;
+ return field_name; /* C4 */
+
+ case object_ctor_group:
+#if DEBUG_XTOR
+ printf ("object_ctor_group -- ignored\n");
+#endif
+ *ignore = true;
+ return field_name; /* C? */
+
+ case not_ctor:
+#if DEBUG_XTOR
+ printf ("unknown_ctr -- ignored\n");
+#endif
+ *ignore = true;
+ return field_name; /* unknown */
+
+ default:
+ gdb_assert_not_reached ("unknown constructor kind");
+ }
+#else
+#if DEBUG_XTOR
+ printf ("DISABLED -- ignored\n");
+#endif
+ *ignore = true;
+#endif /* CAUSES_ICE */
+ }
+ else if (method_field->is_destructor)
+ {
+#if DEBUG_XTOR
+ printf ("*** DESTRUCTOR %s: ", field_name);
+#endif
+ switch (method_field->cdtor_type.dtor_kind)
+ {
+ case deleting_dtor:
+#if DEBUG_XTOR
+ printf ("deleting_dtor (D0)\n");
+#endif
+ return "D0";
+
+ case complete_object_dtor:
+#if DEBUG_XTOR
+ printf ("complete_object_dtor (D1)\n");
+#endif
+ return "D1";
+
+ case base_object_dtor:
+#if DEBUG_XTOR
+ printf ("base_object_dtor (D2)\n");
+#endif
+ return "D2";
+
+ case unified_dtor:
+#if DEBUG_XTOR
+ printf ("unified_dtor (D4) -- ignored\n");
+#endif
+ *ignore = true;
+ return field_name; /* D4 */
+
+ case object_dtor_group:
+#if DEBUG_XTOR
+ printf ("object_dtor_group (D?) -- ignored\n");
+#endif
+ *ignore = true;
+ return field_name; /* D? */
+
+ case not_dtor:
+#if DEBUG_XTOR
+ printf ("not_dtor -- ignored\n");
+#endif
+ *ignore = true;
+ return field_name; /* unknown */
+
+ default:
+ gdb_assert_not_reached ("unknown destructor kind");
+ }
+ }
+ }
+
+ if (!is_operator_name (field_name))
+ return field_name;
+
+ /* Skip over "operator". */
+ field_name += sizeof ("operator") - 1;
+
+ if (strncmp (field_name, "new", sizeof ("new") - 1) == 0)
+ {
+ field_name += 3;
+ if (*field_name == '\0')
+ return "nw";
+ else if (*field_name == '[')
+ return "na";
+ }
+ else if (strncmp (field_name, "delete", sizeof ("delete") - 1) == 0)
+ {
+ if (*field_name == '\0')
+ return "dl";
+ else if (*field_name == '[')
+ return "da";
+ }
+ else if (field_name[0] == '\"' && field_name[1] == '\"')
+ {
+ const char *end;
+ size_t len;
+
+ /* Skip over \"\" -- the plug-in doesn't want it. */
+ field_name += 2;
+
+ /* Skip any whitespace that may have been introduced during
+ canonicalization. */
+ field_name = skip_spaces_const (field_name);
+
+ /* Find the opening '(', if any. */
+ end = strchr (field_name, '(');
+ if (end == NULL)
+ end = field_name + strlen (field_name);
+
+ /* Size of buffer: 'li', 'i', sizeof operator name, '\0' */
+ len = 2 + end - field_name + 1;
+ *outname = (char *) xmalloc (len);
+ strcpy (*outname, "li");
+ strncat (*outname, field_name, end - field_name);
+ (*outname)[len-1] = '\0';
+ return "li";
+ }
+
+ switch (operator_hash (field_name))
+ {
+ case OPHASH1 ('+'):
+ if (is_binary_method (method_type))
+ return "pl";
+ else
+ return "ps";
+ break;
+
+ case OPHASH1 ('-'):
+ if (is_binary_method (method_type))
+ return "mi";
+ else
+ return "ng";
+ break;
+ case OPHASH1 ('&'):
+ if (is_binary_method (method_type))
+ return "an";
+ else
+ return "ad";
+ break;
+
+ case OPHASH1 ('*'):
+ if (is_binary_method (method_type))
+ return "ml";
+ else
+ return "de";
+ break;
+
+ case OPHASH1 ('~'):
+ return "co";
+ case OPHASH1 ('/'):
+ return "dv";
+ case OPHASH1 ('%'):
+ return "rm";
+ case OPHASH1 ('|'):
+ return "or";
+ case OPHASH1 ('^'):
+ return "eo";
+ case OPHASH1 ('='):
+ return "aS";
+ case OPHASH2 ('+', '='):
+ return "pL";
+ case OPHASH2 ('-', '='):
+ return "mI";
+ case OPHASH2 ('*', '='):
+ return "mL";
+ case OPHASH2 ('/', '='):
+ return "dV";
+ case OPHASH2 ('%', '='):
+ return "rM";
+ case OPHASH2 ('&', '='):
+ return "aN";
+ case OPHASH2 ('|', '='):
+ return "oR";
+ case OPHASH2 ('^', '='):
+ return "eO";
+ case OPHASH2 ('<', '<'):
+ return "ls";
+ case OPHASH2 ('>', '>'):
+ return "rs";
+ case OPHASH3 ('<', '<', '='):
+ return "lS";
+ case OPHASH3 ('>', '>', '='):
+ return "rS";
+ case OPHASH2 ('=', '='):
+ return "eq";
+ case OPHASH2 ('!', '='):
+ return "ne";
+ case OPHASH1 ('<'):
+ return "lt";
+ case OPHASH1 ('>'):
+ return "gt";
+ case OPHASH2 ('<', '='):
+ return "le";
+ case OPHASH2 ('>', '='):
+ return "ge";
+ case OPHASH1 ('!'):
+ return "nt";
+ case OPHASH2 ('&', '&'):
+ return "aa";
+ case OPHASH2 ('|', '|'):
+ return "oo";
+ case OPHASH2 ('+', '+'):
+ return "pp";
+ case OPHASH2 ('-', '-'):
+ return "mm";
+ case OPHASH1 (','):
+ return "cm";
+ case OPHASH3 ('-', '>', '*'):
+ return "pm";
+ case OPHASH2 ('-', '>'):
+ return "pt";
+ case OPHASH2 ('(', ')'):
+ return "cl";
+ case OPHASH2 ('[', ']'):
+ return "ix";
+ case OPHASH1 ('?'):
+ return "qu";
+
+ default:
+ /* Conversion operators: Full name is not needed. */
+ return "cv";
+ }
+}
+
+/* Convert all methods defined in TYPE, which should be a class/struct/union
+ with gcc_type CLASS_TYPE. */
+
+static void
+ccp_convert_struct_or_union_methods (compile_cplus_instance *instance,
+ struct type *type, gcc_type class_type)
+{
+ int i;
+
+ /* First things first: If this class had any template methods, emit them so
+ that the compiler knows about them. */
+ instance->emit_function_template_decls ();
+
+
+ /* Now define the actual methods/template specializations. */
+ for (i = 0; i < TYPE_NFN_FIELDS (type); ++i)
+ {
+ int j;
+ struct fn_field *methods = TYPE_FN_FIELDLIST1 (type, i);
+ char *overloaded_name
+ = decl_name (TYPE_FN_FIELDLIST_NAME (type, i));
+ struct cleanup *outer = make_cleanup (xfree, overloaded_name);
+
+ /* Loop through the fieldlist, adding decls to the compiler's
+ representation of the class. */
+ for (j = 0; j < TYPE_FN_FIELDLIST_LENGTH (type, i); ++j)
+ {
+ CORE_ADDR address;
+ gcc_type method_type;
+ struct block_symbol sym;
+ const char *filename;
+ unsigned int line;
+ const char *kind;
+ gcc_cp_symbol_kind_flags sym_kind = GCC_CP_SYMBOL_FUNCTION;
+ const char *name;
+ char *special_name;
+ struct cleanup *back_to;
+ bool ignore;
+ struct template_symbol *tsym = NULL;
+
+ /* Skip artificial methods. */
+ if (TYPE_FN_FIELD_ARTIFICIAL (methods, j))
+ continue;
+
+ special_name = NULL;
+ name = maybe_canonicalize_special_function (overloaded_name,
+ &methods[j],
+ methods[j].type,
+ &special_name,
+ &ignore);
+ if (ignore)
+ continue;
+
+ back_to = make_cleanup (null_cleanup, NULL);
+
+ if (special_name != NULL)
+ {
+ make_cleanup (xfree, special_name);
+ name = special_name;
+ }
+
+ if (name != overloaded_name)
+ {
+ sym_kind |= GCC_CP_FLAG_SPECIAL_FUNCTION;
+ }
+ sym = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (methods, j),
+ instance->block (), VAR_DOMAIN, NULL);
+
+ if (sym.symbol == NULL)
+ {
+ if (TYPE_FN_FIELD_VIRTUAL_P (methods, j))
+ {
+ /* This is beyond hacky, and is really only a workaround for
+ detecting pure virtual methods. */
+ method_type
+ = ccp_convert_method (instance, type,
+ TYPE_FN_FIELD_TYPE (methods, j));
+
+ instance->build_decl ("pure virtual method", name,
+ (sym_kind
+ | get_method_access_flag (type, i, j)
+ | GCC_CP_FLAG_VIRTUAL_FUNCTION
+ | GCC_CP_FLAG_PURE_VIRTUAL_FUNCTION),
+ method_type, NULL, 0,
+ NULL /* FIXME: filename */,
+ 0 /* FIXME: line number */);
+ do_cleanups (back_to);
+ continue;
+ }
+
+ /* This can happen if we have a DW_AT_declaration DIE
+ for the method, but no "definition"-type DIE (with
+ DW_AT_specification referencing the decl DIE), i.e.,
+ the compiler has probably optimized the method away.
+
+ In this case, all we can hope to do is issue a warning
+ to the user letting him know. If the user has not actually
+ requested using this method, things should still work. */
+ warning (_("Method %s appears to be optimized out.\n"
+ "All references to this method will be undefined."),
+ TYPE_FN_FIELD_PHYSNAME (methods, j));
+ do_cleanups (back_to);
+ continue;
+ }
+
+ filename = symbol_symtab (sym.symbol)->filename;
+ line = SYMBOL_LINE (sym.symbol);
+ address = BLOCK_START (SYMBOL_BLOCK_VALUE (sym.symbol));
+
+ /* Short-circuit for method templates. */
+ if (SYMBOL_IS_CPLUS_TEMPLATE_FUNCTION (sym.symbol))
+ {
+ struct template_symbol *tsymbol
+ = (struct template_symbol *) sym.symbol;
+
+ instance->build_function_template_specialization (tsymbol,
+ address,
+ filename, line);
+ do_cleanups (back_to);
+ continue;
+ }
+
+ if (TYPE_FN_FIELD_STATIC_P (methods, j))
+ {
+ kind = "static method";
+ method_type = ccp_convert_func (instance,
+ TYPE_FN_FIELD_TYPE (methods, j),
+ 1);
+ }
+ else
+ {
+ kind = "method";
+ method_type
+ = ccp_convert_method (instance, type,
+ TYPE_FN_FIELD_TYPE (methods, j));
+ }
+
+ if (TYPE_FN_FIELD_VIRTUAL_P (methods, j))
+ sym_kind |= GCC_CP_FLAG_VIRTUAL_FUNCTION;
+
+ /* FIXME: for cdtors, we must call build_decl with a zero
+ address, if we haven't created the base declaration
+ yet, and then define_cdtor_clone with the address of
+ each clone. When we leave the address out, GCC uses
+ the address oracle. -lxo */
+ if ((sym_kind & GCC_CP_FLAG_SPECIAL_FUNCTION)
+ && (name[0] == 'C' || name[0] == 'D'))
+ {
+ address = 0;
+ /* FIXME: We should declare only one cdtor for each
+ clone set with "C" or "D" as the name, with address
+ zero, then define each address with
+ define_cdtor_clone. Until this is implemented,
+ declare only one of these, and let the address oracle
+ take care of the addresses. -lxo */
+ if (name[1] != '2' && name[1] != '4')
+ {
+ do_cleanups (back_to);
+ continue;
+ }
+ }
+
+ instance->build_decl (kind, name,
+ sym_kind | get_method_access_flag (type, i, j),
+ method_type, NULL, address, filename, line);
+ do_cleanups (back_to);
+ }
+
+ do_cleanups (outer);
+ }
+}
+
+/* Convert a struct or union type to its gcc representation. If this type
+ was defined in another type, NESTED_ACCESS should indicate the
+ accessibility of this type. */
+
+static gcc_type
+ccp_convert_struct_or_union (compile_cplus_instance *instance,
+ struct type *type,
+ enum gcc_cp_symbol_kind nested_access)
+{
+ const char *filename = NULL; /* !!keiths: FIXME */
+ unsigned short line = 0;
+ char *name = NULL;
+ struct cleanup *back_to = make_cleanup (free_current_contents, &name);
+
+ /* Get the decl name of this type. */
+ if (TYPE_NAME (type) != NULL)
+ name = decl_name (TYPE_NAME (type));
+
+ /* First things first: If this type has any templates in it, make sure
+ that we collect default arguments and get those types defined BEFORE
+ this type is defined. */
+ scan_type_for_function_templates (instance, type);
+
+ /* If this is a new template class, make sure the generic has been seen
+ and defined. */
+ instance->maybe_define_new_class_template (type, name);
+ instance->emit_class_template_decls ();
+
+ /* Create a new scope for TYPE. */
+ compile_scope scope = instance->new_scope (TYPE_NAME (type), type);
+
+ if (scope.nested_type () != GCC_TYPE_NONE)
+ {
+ /* The type requested was actually defined inside another type,
+ such as a nested class definition. Return that type. */
+ return scope.nested_type ();
+ }
+
+ /* Push all scopes. */
+ instance->enter_scope (scope);
+
+ /* First we create the resulting type and enter it into our hash
+ table. This lets recursive types work. */
+
+ gcc_decl resuld; /* FIXME: yeah, it's a terrible pun. Please make
+ it go once we separate declaration from
+ definition (see below). -lxo */
+ if (TYPE_N_TEMPLATE_ARGUMENTS (type))
+ {
+ resuld = instance->build_class_template_specialization (type,
+ filename, line);
+ }
+ else if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
+ {
+ const char *what = TYPE_DECLARED_CLASS (type) ? "struct" : "class";
+
+ resuld = instance->build_decl (what, name,
+ GCC_CP_SYMBOL_CLASS | nested_access
+ | (TYPE_DECLARED_CLASS (type)
+ ? GCC_CP_FLAG_CLASS_NOFLAG
+ : GCC_CP_FLAG_CLASS_IS_STRUCT),
+ 0, NULL, 0, filename, line);
+ }
+ else
+ {
+ gdb_assert (TYPE_CODE (type) == TYPE_CODE_UNION);
+ resuld = instance->build_decl ("union", name,
+ GCC_CP_SYMBOL_UNION | nested_access,
+ 0, NULL, 0, filename, line);
+ }
+
+ /* FIXME: we should be able to pop the scope at this point, rather
+ than at the end, and we ought to delay the rest of this function
+ to the point in which we need the class or union to be a complete
+ type, otherwise some well-formed C++ types cannot be represented.
+ -lxo */
+
+ gcc_type result;
+ if (TYPE_CODE (type) == TYPE_CODE_STRUCT)
+ {
+ struct gcc_vbase_array bases;
+ int num_baseclasses = TYPE_N_BASECLASSES (type);
+
+ memset (&bases, 0, sizeof (bases));
+
+ if (num_baseclasses > 0)
+ {
+ bases.elements = XNEWVEC (gcc_type, num_baseclasses);
+ bases.flags = XNEWVEC (enum gcc_cp_symbol_kind, num_baseclasses);
+ bases.n_elements = num_baseclasses;
+ for (int i = 0; i < num_baseclasses; ++i)
+ {
+ struct type *base_type = TYPE_BASECLASS (type, i);
+
+ bases.flags[i] = GCC_CP_SYMBOL_BASECLASS
+ | get_field_access_flag (type, i)
+ | (BASETYPE_VIA_VIRTUAL (type, i)
+ ? GCC_CP_FLAG_BASECLASS_VIRTUAL
+ : GCC_CP_FLAG_BASECLASS_NOFLAG);
+ bases.elements[i] = instance->convert_type (base_type);
+ }
+ }
+
+ result = instance->start_class_type (name, resuld, &bases,
+ filename, line);
+ xfree (bases.flags);
+ xfree (bases.elements);
+ }
+ else
+ {
+ gdb_assert (TYPE_CODE (type) == TYPE_CODE_UNION);
+ result
+ = instance->start_class_type (name, resuld, NULL, filename, line);
+ }
+
+ instance->insert_type (type, result);
+
+ /* Add definitions. */
+ ccp_convert_type_defns (instance, type);
+
+ /* Add methods. */
+ ccp_convert_struct_or_union_methods (instance, type, result);
+
+ /* Add members. */
+ ccp_convert_struct_or_union_members (instance, type, result);
+
+ /* All finished. */
+ instance->finish_class_type (name, TYPE_LENGTH (type));
+
+ /* Pop all scopes. */
+ instance->leave_scope ();
+ do_cleanups (back_to);
+ return result;
+}
+
+/* Convert an enum type to its gcc representation. If this type
+ was defined in another type, NESTED_ACCESS should indicate the
+ accessibility of this type.*/
+
+static gcc_type
+ccp_convert_enum (compile_cplus_instance *instance, struct type *type,
+ enum gcc_cp_symbol_kind nested_access)
+{
+ int i;
+ gcc_type int_type;
+ const char *filename = NULL;
+ unsigned short line = 0;
+ /* !!keiths: This does not appear to work. GCC complains about
+ being unable to convert enum values from '(MyEnum)0' to 'int'. */
+ int scoped_enum_p = /*TYPE_DECLARED_CLASS (type) ? TRUE :*/ FALSE;
+
+ /* Create a new scope for this type. */
+ compile_scope scope = instance->new_scope (TYPE_NAME (type), type);
+
+ if (scope.nested_type () != GCC_TYPE_NONE)
+ {
+ /* The type requested was actually defined inside another type,
+ such as a nested class definition. Return that type. */
+ return scope.nested_type ();
+ }
+
+ char *name = NULL;
+ struct cleanup *cleanups = make_cleanup (free_current_contents, &name);
+
+ if (TYPE_NAME (type) != NULL)
+ name = cp_func_name (TYPE_NAME (type));
+
+ /* Push all scopes. */
+ instance->enter_scope (scope);
+
+ int_type = instance->get_int_type (TYPE_UNSIGNED (type),
+ TYPE_LENGTH (type), NULL);
+ gcc_type result
+ = instance->start_enum_type (name, int_type,
+ GCC_CP_SYMBOL_ENUM | nested_access
+ | (scoped_enum_p
+ ? GCC_CP_FLAG_ENUM_SCOPED
+ : GCC_CP_FLAG_ENUM_NOFLAG),
+ filename, line);
+ for (i = 0; i < TYPE_NFIELDS (type); ++i)
+ {
+ char *fname = cp_func_name (TYPE_FIELD_NAME (type, i));
+
+ if (TYPE_FIELD_LOC_KIND (type, i) != FIELD_LOC_KIND_ENUMVAL
+ || fname == NULL)
+ {
+ xfree (fname);
+ continue;
+ }
+
+ instance->build_enum_constant (result, fname,
+ TYPE_FIELD_ENUMVAL (type, i));
+ xfree (fname);
+ }
+
+ instance->finish_enum_type (result);
+
+ /* Pop all scopes. */
+ instance->leave_scope ();
+ do_cleanups (cleanups);
+ return result;
+}
+
+/* Convert a function type to its gcc representation. This function does
+ not deal with function templates. */
+
+static gcc_type
+ccp_convert_func (compile_cplus_instance *instance, struct type *type,
+ int strip_artificial)
+{
+ int i, artificials;
+ gcc_type result, return_type;
+ struct gcc_type_array array;
+ int is_varargs = is_varargs_p (type);
+
+ /* This approach means we can't make self-referential function
+ types. Those are impossible in C, though. */
+ return_type = instance->convert_type (TYPE_TARGET_TYPE (type));
+
+ array.n_elements = TYPE_NFIELDS (type);
+ array.elements = XNEWVEC (gcc_type, TYPE_NFIELDS (type));
+ artificials = 0;
+ for (i = 0; i < TYPE_NFIELDS (type); ++i)
+ {
+ if (strip_artificial && TYPE_FIELD_ARTIFICIAL (type, i))
+ {
+ --array.n_elements;
+ ++artificials;
+ }
+ else
+ {
+ array.elements[i - artificials]
+ = instance->convert_type (TYPE_FIELD_TYPE (type, i));
+ }
+ }
+
+ /* FIXME: add default args, exception specs and, once support is
+ added, attributes. -lxo */
+
+ /* We omit setting the argument types to `void' to be a little flexible
+ with some minsyms like printf (compile-cplus.exp has examples). */
+ result = instance->build_function_type (return_type, &array, is_varargs);
+ xfree (array.elements);
+
+ return result;
+}
+
+/* Convert an integer type to its gcc representation. */
+
+static gcc_type
+ccp_convert_int (compile_cplus_instance *instance, struct type *type)
+{
+ if (TYPE_NOSIGN (type))
+ {
+ gdb_assert (TYPE_LENGTH (type) == 1);
+ return instance->get_char_type ();
+ }
+
+ return instance->get_int_type (TYPE_UNSIGNED (type), TYPE_LENGTH (type),
+ TYPE_NAME (type));
+}
+
+/* Convert a floating-point type to its gcc representation. */
+
+static gcc_type
+ccp_convert_float (compile_cplus_instance *instance, struct type *type)
+{
+ return instance->get_float_type (TYPE_LENGTH (type), TYPE_NAME (type));
+}
+
+/* Convert the 'void' type to its gcc representation. */
+
+static gcc_type
+ccp_convert_void (compile_cplus_instance *instance, struct type *type)
+{
+ return instance->get_void_type ();
+}
+
+/* Convert a boolean type to its gcc representation. */
+
+static gcc_type
+ccp_convert_bool (compile_cplus_instance *instance, struct type *type)
+{
+ return instance->get_bool_type ();
+}
+
+/* See description in compile-cplus.h. */
+
+gcc_type
+compile::convert_qualified_base (compile_cplus_instance *instance,
+ gcc_type base,
+ gcc_cp_qualifiers_flags quals)
+{
+ gcc_type result = base;
+
+ if (quals != 0)
+ result = instance->build_qualified_type (base, quals);
+
+ return result;
+}
+
+/* Convert a qualified type to its gcc representation. */
+
+static gcc_type
+ccp_convert_qualified (compile_cplus_instance *instance,
+ struct type *type)
+{
+ struct type *unqual = make_unqualified_type (type);
+ gcc_type unqual_converted;
+ gcc_cp_qualifiers_flags quals = (enum gcc_cp_qualifiers) 0;
+ gcc_type result;
+
+ unqual_converted = instance->convert_type (unqual);
+
+ if (TYPE_CONST (type))
+ quals |= GCC_CP_QUALIFIER_CONST;
+ if (TYPE_VOLATILE (type))
+ quals |= GCC_CP_QUALIFIER_VOLATILE;
+ if (TYPE_RESTRICT (type))
+ quals |= GCC_CP_QUALIFIER_RESTRICT;
+
+ return convert_qualified_base (instance, unqual_converted, quals);
+}
+
+/* Convert a complex type to its gcc representation. */
+
+static gcc_type
+ccp_convert_complex (compile_cplus_instance *instance,
+ struct type *type)
+{
+ gcc_type base = instance->convert_type (TYPE_TARGET_TYPE (type));
+
+ return instance->build_complex_type (base);
+}
+
+/* Convert a namespace of TYPE. */
+
+static gcc_type
+ccp_convert_namespace (compile_cplus_instance *instance,
+ struct type *type)
+{
+ compile_scope scope = instance->new_scope (TYPE_NAME (type), type);
+
+
+ char *name = NULL;
+ struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
+ if (TYPE_NAME (type) != NULL)
+ {
+ name = cp_func_name (TYPE_NAME (type));
+ make_cleanup (xfree, name);
+ }
+ else
+ name = "";
+
+ /* Push scope. */
+ instance->enter_scope (scope);
+
+ /* Convert this namespace. */
+ instance->push_namespace (name);
+ instance->pop_binding_level (name);
+
+ /* Pop scope. */
+ instance->leave_scope ();
+ do_cleanups (cleanups);
+
+ /* Namespaces are non-cacheable types. */
+ return DONT_CACHE_TYPE;
+}
+
+/* A helper function which knows how to convert most types from their
+ gdb representation to the corresponding gcc form. This examines
+ the TYPE and dispatches to the appropriate conversion function. It
+ returns the gcc type.
+
+ If the type was defined in another type, NESTED_ACCESS should indicate the
+ accessibility of this type. */
+
+static gcc_type
+convert_type_cplus_basic (compile_cplus_instance *instance,
+ struct type *type,
+ enum gcc_cp_symbol_kind nested_access)
+{
+ /* Reference types seem to always have a const qualifier, but we
+ don't want that to be propagated to the GCC type, because GCC
+ doesn't like the reference types themselves to be qualified. */
+ if (TYPE_CODE (type) == TYPE_CODE_REF)
+ return ccp_convert_reference (instance, type);
+
+ /* If we are converting a qualified type, first convert the
+ unqualified type and then apply the qualifiers. */
+ if ((TYPE_INSTANCE_FLAGS (type) & (TYPE_INSTANCE_FLAG_CONST
+ | TYPE_INSTANCE_FLAG_VOLATILE
+ | TYPE_INSTANCE_FLAG_RESTRICT)) != 0)
+ return ccp_convert_qualified (instance, type);
+
+ switch (TYPE_CODE (type))
+ {
+#if 0
+ case TYPE_CODE_REF:
+ return ccp_convert_reference (instance, type);
+#endif
+
+ case TYPE_CODE_PTR:
+ return ccp_convert_pointer (instance, type);
+
+ case TYPE_CODE_ARRAY:
+ return ccp_convert_array (instance, type);
+
+ case TYPE_CODE_STRUCT:
+ case TYPE_CODE_UNION:
+ return ccp_convert_struct_or_union (instance, type, nested_access);
+
+ case TYPE_CODE_ENUM:
+ return ccp_convert_enum (instance, type, nested_access);
+
+ case TYPE_CODE_FUNC:
+ return ccp_convert_func (instance, type, 0);
+
+ case TYPE_CODE_METHOD:
+ return ccp_convert_method (instance, TYPE_SELF_TYPE (type), type);
+
+ case TYPE_CODE_MEMBERPTR:
+ case TYPE_CODE_METHODPTR:
+ return ccp_convert_memberptr (instance, type);
+ break;
+
+ case TYPE_CODE_INT:
+ return ccp_convert_int (instance, type);
+
+ case TYPE_CODE_FLT:
+ return ccp_convert_float (instance, type);
+
+ case TYPE_CODE_VOID:
+ return ccp_convert_void (instance, type);
+
+ case TYPE_CODE_BOOL:
+ return ccp_convert_bool (instance, type);
+
+ case TYPE_CODE_COMPLEX:
+ return ccp_convert_complex (instance, type);
+
+ case TYPE_CODE_NAMESPACE:
+ return ccp_convert_namespace (instance, type);
+
+ case TYPE_CODE_TYPEDEF:
+ return ccp_convert_typedef (instance, type, nested_access);
+ }
+
+ {
+ char *s = xstrprintf (_("unhandled TYPE_CODE_%s"),
+ type_code_to_string (TYPE_CODE (type)));
+
+ return instance->error (s);
+ xfree (s);
+ }
+}
+
+gcc_type
+compile_cplus_instance::convert_type (struct type *type,
+ enum gcc_cp_symbol_kind nested_access)
+{
+ type_map_t::iterator pos = m_type_map.find (type);
+ if (pos != m_type_map.end ())
+ return pos->second;
+
+ gcc_type result = convert_type_cplus_basic (this, type, nested_access);
+ if (result != DONT_CACHE_TYPE)
+ insert_type (type, result);
+ return result;
+}
+
+
+
+/* Default compile flags for C++. */
+
+const char *compile_cplus_instance::m_default_cflags = "-std=gnu++11";
+
+/* See compile-cplus.h. */
+
+compile_cplus_instance::compile_cplus_instance (struct gcc_cp_context *gcc_fe)
+ : compile_instance (&gcc_fe->base, m_default_cflags),
+ m_context (gcc_fe),
+ m_function_template_defns (new function_template_defn_map_t ()),
+ m_class_template_defns (new class_template_defn_map_t ())
+{
+ gcc_fe->cp_ops->set_callbacks (gcc_fe, gcc_cplus_convert_symbol,
+ gcc_cplus_symbol_address,
+ gcc_cplus_enter_scope,
+ gcc_cplus_leave_scope,
+ this);
+}
+
+/* Plug-in forwards. */
+
+/* A result printer for plug-in calls that return a boolean result. */
+
+static void
+ccp_output_result (int result)
+{
+ printf_unfiltered ("%s\n", result ? "true" : "false");
+}
+
+/* A result printer for plug-in calls that return a gcc_type or
+ gcc_decl. */
+
+static void
+ccp_output_result (gcc_type result)
+{
+ printf_unfiltered ("%lld\n", result);
+}
+
+#define STR(x) #x
+#define STRINGIFY(x) STR(x)
+
+#define DECLARE_FORWARD(OP,...) \
+ auto forward = [&] (const char *fmt, ...) \
+ { \
+ if (debug_compile_cplus_types) \
+ { \
+ std::string format (STRINGIFY (OP)); \
+ \
+ format += " "; \
+ format += fmt; \
+ format += ": "; \
+ \
+ va_list args; \
+ \
+ va_start (args, fmt); \
+ vprintf_unfiltered (format.c_str (), args); \
+ va_end (args); \
+ } \
+ \
+ auto result = m_context->cp_ops->OP (m_context, ##__VA_ARGS__); \
+ \
+ if (debug_compile_cplus_types) \
+ ccp_output_result (result); \
+ \
+ return result; \
+ };
+
+/* See description in gcc-cp-fe.def. */
+
+bool
+compile_cplus_instance::build_constant (gcc_type type, const char *name,
+ unsigned long value,
+ const char *filename,
+ unsigned int line_number)
+{
+ DECLARE_FORWARD (build_constant, type, name, value, filename, line_number);
+
+ return forward ("\"%s\"", name);
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_decl
+compile_cplus_instance::build_function_template_specialization
+ (struct template_symbol *concrete, gcc_address address,
+ const char *filename, unsigned int line_number)
+{
+ function_template_defn *defn
+ = find_function_template_defn (concrete);
+
+ /* A generic should already have been defined at this point. */
+ gdb_assert (defn != NULL);
+
+ struct gcc_cp_template_args targs;
+
+ targs.n_elements = concrete->template_arguments->n_arguments;
+ targs.kinds = XNEWVEC (char, targs.n_elements);
+
+ struct cleanup *back_to = make_cleanup (xfree, targs.kinds);
+
+ targs.elements = XNEWVEC (gcc_cp_template_arg, targs.n_elements);
+ make_cleanup (xfree, targs.elements);
+ enumerate_template_arguments (&targs, defn, concrete->template_arguments);
+
+ DECLARE_FORWARD (build_function_template_specialization, defn->decl (),
+ &targs, address, filename, line_number);
+
+ gcc_decl result = forward ("%s", SYMBOL_NATURAL_NAME (&concrete->base));
+ do_cleanups (back_to);
+ return result;
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_decl
+compile_cplus_instance::build_class_template_specialization
+ (struct type *concrete, const char *filename, unsigned int line_number)
+{
+ class_template_defn *defn
+ = find_class_template_defn (concrete);
+
+ /* A generic should have already been defined at this point. */
+ gdb_assert (defn != NULL);
+
+ struct gcc_cp_template_args targs;
+
+ targs.n_elements = TYPE_N_TEMPLATE_ARGUMENTS (concrete);
+ targs.kinds = XNEWVEC (char, targs.n_elements);
+
+ struct cleanup *back_to = make_cleanup (xfree, targs.kinds);
+
+ targs.elements = XNEWVEC (gcc_cp_template_arg, targs.n_elements);
+ make_cleanup (xfree, targs.elements);
+ enumerate_template_arguments (&targs, defn,
+ TYPE_TEMPLATE_ARGUMENT_INFO (concrete));
+
+ DECLARE_FORWARD (build_class_template_specialization, defn->decl (), &targs,
+ filename, line_number);
+
+ gcc_decl result
+ = forward ("%s for template decl %lld\n", TYPE_NAME (concrete),
+ defn->decl ());
+ do_cleanups (back_to);
+ return result;
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_decl
+compile_cplus_instance::build_decl (const char *decl_type,
+ 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)
+{
+ DECLARE_FORWARD (build_decl, name, sym_kind, sym_type,
+ substitution_name, address, filename, line_number);
+
+ return forward ("%s %s %d %s", decl_type, name, (int) sym_kind,
+ substitution_name);
+}
+
+/* See description in gcc-cp-fe.def. */
+
+bool
+compile_cplus_instance::push_namespace (const char *name)
+{
+ DECLARE_FORWARD (push_namespace, name);
+
+ return forward ("\"%s\"", name);
+}
+
+/* See description in gcc-cp-fe.def. */
+
+bool
+compile_cplus_instance::pop_binding_level (const char *opt_name)
+{
+ DECLARE_FORWARD (pop_binding_level);
+
+ return forward ("\"%s\"", opt_name);
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_type
+compile_cplus_instance::error (const char *message)
+{
+ DECLARE_FORWARD (error, message);
+
+ return forward ("%s", message);
+}
+
+/* See description in gcc-cp-fe.def. */
+
+
+gcc_type
+compile_cplus_instance::build_reference_type (gcc_type base_type,
+ enum gcc_cp_ref_qualifiers rquals)
+{
+ DECLARE_FORWARD (build_reference_type, base_type, rquals);
+
+ return forward ("");
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_type
+compile_cplus_instance::build_pointer_type (gcc_type base_type)
+{
+ DECLARE_FORWARD (build_pointer_type, base_type);
+
+ return forward ("");
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_type
+compile_cplus_instance::build_vla_array_type (gcc_type element_type,
+ const char *upper_bound_name)
+{
+ DECLARE_FORWARD (build_vla_array_type, element_type, upper_bound_name);
+
+ return forward ("");
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_type
+compile_cplus_instance::build_vector_type (gcc_type element_type,
+ int num_elements)
+{
+ DECLARE_FORWARD (build_vector_type, element_type, num_elements);
+
+ return forward ("");
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_type
+compile_cplus_instance::build_array_type (gcc_type element_type,
+ int num_elements)
+{
+ DECLARE_FORWARD (build_array_type, element_type, num_elements);
+
+ return forward ("");
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_decl
+compile_cplus_instance::build_field (const char *field_name,
+ gcc_type field_type,
+ enum gcc_cp_symbol_kind field_flags,
+ unsigned long bitsize,
+ unsigned long bitpos)
+{
+ DECLARE_FORWARD (build_field, field_name, field_type, field_flags,
+ bitsize, bitpos);
+
+ return forward ("%s %lld", field_name, field_type);
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_type
+compile_cplus_instance::build_method_type (gcc_type class_type,
+ gcc_type func_type,
+ enum gcc_cp_qualifiers quals,
+ enum gcc_cp_ref_qualifiers rquals)
+{
+ DECLARE_FORWARD (build_method_type, class_type, func_type, quals, rquals);
+
+ return forward ("");
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_type
+compile_cplus_instance::start_class_type
+ (const char *name, gcc_decl typedecl,
+ const struct gcc_vbase_array *base_classes,
+ const char *filename, unsigned int line_number)
+{
+ DECLARE_FORWARD (start_class_type, typedecl, base_classes,
+ filename, line_number);
+
+ return forward ("%s", name);
+}
+
+/* See description in gcc-cp-fe.def. */
+
+bool
+compile_cplus_instance::finish_class_type (const char *name,
+ unsigned long size_in_bytes)
+{
+ DECLARE_FORWARD (finish_class_type, size_in_bytes);
+
+ return forward ("%s (%ld)", name, size_in_bytes);
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_type
+compile_cplus_instance::get_int_type (bool is_unsigned,
+ unsigned long size_in_bytes,
+ const char *builtin_name)
+{
+ DECLARE_FORWARD (get_int_type, is_unsigned, size_in_bytes, builtin_name);
+
+ return forward ("%d %ld %s", is_unsigned, size_in_bytes, builtin_name);
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_type
+compile_cplus_instance::start_enum_type (const char *name,
+ gcc_type underlying_int_type,
+ enum gcc_cp_symbol_kind flags,
+ const char *filename,
+ unsigned int line_number)
+{
+ DECLARE_FORWARD (start_enum_type, name, underlying_int_type,
+ flags, filename, line_number);
+
+ return forward ("%s", name);
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_decl
+compile_cplus_instance::build_enum_constant (gcc_type enum_type,
+ const char *name,
+ unsigned long value)
+{
+ DECLARE_FORWARD (build_enum_constant, enum_type, name, value);
+
+ return forward ("%s = %ld", name, value);
+}
+
+/* See description in gcc-cp-fe.def. */
+
+bool
+compile_cplus_instance::finish_enum_type (gcc_type enum_type)
+{
+ DECLARE_FORWARD (finish_enum_type, enum_type);
+
+ return forward ("");
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_type
+compile_cplus_instance::build_function_type
+ (gcc_type return_type, const struct gcc_type_array *argument_types,
+ bool is_varargs)
+{
+ DECLARE_FORWARD (build_function_type, return_type, argument_types,
+ is_varargs);
+
+ return forward ("%lld %d", return_type, is_varargs);
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_type
+compile_cplus_instance::get_char_type ()
+{
+ DECLARE_FORWARD (get_char_type);
+
+ return forward ("");
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_type
+compile_cplus_instance::get_float_type (unsigned long size_in_bytes,
+ const char *builtin_name)
+{
+ DECLARE_FORWARD (get_float_type, size_in_bytes, builtin_name);
+
+ return forward ("%ld %s", size_in_bytes, builtin_name);
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_type
+compile_cplus_instance::get_void_type ()
+{
+ DECLARE_FORWARD (get_void_type);
+
+ return forward ("");
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_type
+compile_cplus_instance::get_bool_type ()
+{
+ DECLARE_FORWARD (get_bool_type);
+
+ return forward ("");
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_type
+compile_cplus_instance::build_qualified_type (gcc_type unqualified_type,
+ enum gcc_cp_qualifiers qualifiers)
+{
+ DECLARE_FORWARD (build_qualified_type, unqualified_type, qualifiers);
+
+ return forward ("");
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_type
+compile_cplus_instance::build_complex_type (gcc_type element_type)
+{
+ DECLARE_FORWARD (build_complex_type, element_type);
+
+ return forward ("%lld", element_type);
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_expr
+compile_cplus_instance::build_literal_expr (gcc_type type, unsigned long value)
+{
+ DECLARE_FORWARD (build_literal_expr, type, value);
+
+ return forward ("%lld %ld", type, value);
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_type
+compile_cplus_instance::build_type_template_parameter (const char *id,
+ bool pack_p,
+ gcc_type default_type,
+ const char *filename,
+ unsigned int line_number)
+{
+ DECLARE_FORWARD (build_type_template_parameter, id, pack_p,
+ default_type, filename, line_number);
+
+ return forward ("%s %d %lld %s %d", id, pack_p, default_type,
+ filename, line_number);
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_decl
+compile_cplus_instance::build_value_template_parameter
+ (gcc_type type, const char *id, gcc_expr default_value,
+ const char *filename, unsigned int line_number)
+{
+ DECLARE_FORWARD (build_value_template_parameter, type, id,
+ default_value, filename, line_number);
+
+ return forward ("%lld %s %lld %s %d", type, id, default_value,
+ filename, line_number);
+}
+
+/* See description in gcc-cp-fe.def. */
+
+bool
+compile_cplus_instance::start_template_decl (const char *generic)
+{
+ DECLARE_FORWARD (start_template_decl);
+
+ return forward ("for generic %s\n", generic);
+}
+
+/* See description in gcc-cp-fe.def. */
+
+gcc_type
+compile_cplus_instance::build_pointer_to_member_type (gcc_type class_type,
+ gcc_type member_type)
+{
+ DECLARE_FORWARD (build_pointer_to_member_type, class_type, member_type);
+
+ return forward ("%lld %lld", class_type, member_type);
+}
+
+#undef DECLARE_FORWARD
+
+void _initialize_compile_cplus_types (void);
+
+void
+_initialize_compile_cplus_types (void)
+{
+ add_setshow_boolean_cmd ("compile-cplus-types", no_class,
+ &debug_compile_cplus_types, _("\
+Set debugging of C++ compile type conversion."), _("\
+Show debugging of C++ compile type conversion."), _("\
+When enabled debugging messages are printed during C++ type conversion for\n\
+the compile commands."),
+ NULL,
+ NULL,
+ &setdebuglist,
+ &showdebuglist);
+
+ add_setshow_boolean_cmd ("compile-cplus-scopes", no_class,
+ &debug_compile_cplus_scopes, _("\
+Set debugging of C++ compile scopes."), _("\
+Show debugging of C++ compile scopes."), _("\
+When enabled debugging messages are printed about definition scopes during\n\
+C++ type conversion for the compile commands."),
+ NULL,
+ NULL,
+ &setdebuglist,
+ &showdebuglist);
+}
diff --git a/gdb/compile/compile-cplus.h b/gdb/compile/compile-cplus.h
new file mode 100644
index 00000000000..2ab31fe1634
--- /dev/null
+++ b/gdb/compile/compile-cplus.h
@@ -0,0 +1,399 @@
+/* Header file for GDB compile C++ language support.
+ Copyright (C) 2016, 2017 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 "gcc-cp-interface.h"
+#include "common/enum-flags.h"
+#include "compile-cplus-templates.h"
+
+#include <string>
+#include <memory>
+
+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);
+
+namespace compile
+{
+ 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 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_fe);
+
+ /* If SYM is a template symbol whose generic we have not yet declared,
+ add it to INSTANCE's list of template definitions and scan for default
+ values. */
+
+ void maybe_define_new_function_template (const struct symbol *sym,
+ struct type *parent_type,
+ int f_idx, int m_idx);
+
+ /* If TYPE (with declaration name DECL_NAME) represents a concrete instance
+ of a new class template, note the new template definition. */
+
+ void maybe_define_new_class_template (struct type *type,
+ const char *decl_name);
+
+ /* Find the generic template definition for TSYM or NULL if none was
+ found. */
+
+ function_template_defn *find_function_template_defn
+ (struct template_symbol *tsym);
+
+ /* Search for an existing class template definition based on TYPE.
+ Returns NULL if no template based on TYPE is known. */
+
+ class_template_defn *find_class_template_defn (struct type *type);
+
+ /* Emit any new function template definitions to the compiler
+ plug-in. */
+
+ void emit_function_template_decls ();
+
+ /* Emit any new class template definitions to the compiler
+ plug-in. */
+
+ void emit_class_template_decls ();
+
+ /* 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);
+
+ /* 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 ();
+
+ /* Plug-in forwards */
+
+ gcc_type get_bool_type ();
+
+ gcc_decl build_enum_constant (gcc_type enum_type, const char *name,
+ unsigned long value);
+
+ gcc_type build_array_type (gcc_type element_type, int num_elements);
+
+ bool build_constant (gcc_type type, const char *name, unsigned long value,
+ const char *filename, unsigned int line_number);
+
+ gcc_type build_complex_type (gcc_type element_type);
+
+ gcc_type build_function_type (gcc_type return_type,
+ const struct gcc_type_array *argument_types,
+ bool is_varargs);
+
+ gcc_type build_method_type (gcc_type class_type, gcc_type func_type,
+ enum gcc_cp_qualifiers quals,
+ enum gcc_cp_ref_qualifiers rquals);
+
+ gcc_type build_qualified_type (gcc_type unqualified_type,
+ enum gcc_cp_qualifiers qualifiers);
+
+ gcc_type build_pointer_to_member_type (gcc_type class_type,
+ gcc_type member_type);
+
+ gcc_type build_pointer_type (gcc_type base_type);
+
+ gcc_type build_reference_type (gcc_type base_type,
+ enum gcc_cp_ref_qualifiers rquals);
+
+ gcc_type build_vla_array_type (gcc_type element_type,
+ const char *upper_bound_name);
+
+ gcc_type build_vector_type (gcc_type element_type, int num_elements);
+
+ gcc_type get_char_type ();
+
+ gcc_type error (const char *message);
+
+ bool finish_enum_type (gcc_type enum_type);
+
+ /* NAME is for debugging only. */
+
+ bool finish_class_type (const char *name, unsigned long size_in_bytes);
+
+ gcc_type get_float_type (unsigned long size_in_bytes,
+ const char *builtin_name);
+
+ gcc_type get_int_type (bool is_unsigned, unsigned long size_in_bytes,
+ const char *builtin_name);
+
+ gcc_expr build_literal_expr (gcc_type type, unsigned long value);
+
+ /* DECL_DESC is for debugging only. */
+
+ gcc_decl build_decl (const char *decl_desc, 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_decl build_field (const char *field_name, gcc_type field_type,
+ enum gcc_cp_symbol_kind field_flags,
+ unsigned long bitsize, unsigned long bitpos);
+
+ gcc_type build_type_template_parameter (const char *id, bool pack_p,
+ gcc_type default_type,
+ const char *filename,
+ unsigned int line_number);
+
+ gcc_decl build_value_template_parameter (gcc_type type, const char *id,
+ gcc_expr default_value,
+ const char *filename,
+ unsigned int line_number);
+
+ /* NAME is for debugging only. */
+
+ bool pop_binding_level (const char *name);
+
+ bool push_namespace (const char *name);
+
+ gcc_decl build_class_template_specialization (struct type *concrete,
+ const char *filename,
+ unsigned int line_number);
+
+ gcc_decl build_function_template_specialization
+ (struct template_symbol *concrete, gcc_address address,
+ const char *filename, unsigned int line_number);
+
+ /* NAME is for debugging only. */
+
+ gcc_type start_class_type (const char *name, gcc_decl typedecl,
+ const struct gcc_vbase_array *base_classes,
+ const char *filename,
+ unsigned int line_number);
+
+ gcc_type start_enum_type (const char *name,
+ gcc_type underlying_int_type,
+ enum gcc_cp_symbol_kind flags,
+ const char *filename,
+ unsigned int line_number);
+
+ /* GENERIC is for debugging only. */
+
+ bool start_template_decl (const char *generic);
+
+ gcc_type get_void_type ();
+
+
+ private:
+
+ /* Default compiler flags for C++. */
+ static const char *m_default_cflags;
+
+ /* Enumerate the template arguments of template DEFN into DEST. */
+
+ void enumerate_template_arguments
+ (struct gcc_cp_template_args *dest, const template_defn *defn,
+ const struct template_argument_info *arg_info);
+
+ /* The C++ compile plug-in context. */
+ struct gcc_cp_context *m_context;
+
+ /* A cache of function template definitions. */
+ std::unique_ptr<function_template_defn_map_t> m_function_template_defns;
+
+ /* A cache of class template definitions. */
+ std::unique_ptr<class_template_defn_map_t> m_class_template_defns;
+
+ /* A list of scopes we are processing. */
+ std::vector<compile_scope> m_scopes;
+ };
+
+ /* Return the declaration name of the natural name NATURAL.
+ This returns a name with no function arguments or template parameters.
+ The result must be freed by the caller. */
+
+ char *decl_name (const char *natural);
+
+ /* Add the qualifiers given by QUALS to BASE. */
+
+ gcc_type convert_qualified_base (compile_cplus_instance *instance,
+ gcc_type base,
+ gcc_cp_qualifiers_flags quals);
+
+ /* Convert TARGET into a pointer type in the given compiler
+ INSTANCE. */
+
+ gcc_type convert_pointer_base (compile_cplus_instance *instance,
+ gcc_type target);
+
+ /* Convert BASE into a reference type in the given compile
+ INSTANCE. */
+
+ gcc_type convert_reference_base (compile_cplus_instance *instance,
+ gcc_type base);
+
+ /* Returns non-zero if the given TYPE represents a varargs function,
+ zero otherwise. */
+
+ int is_varargs_p (const struct type *type);
+
+ /* 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);
+
+/* Maybe canonicalize FIELD_NAME with function field METHOD_FIELD (may
+ be NULL for non-constructors) and METHOD_TYPE (may not be NULL).
+
+ If the field is not represented by one of the plug-in's "special functions,"
+ (operators, ctors, dtors), return FIELD_NAME.
+
+ Otherwise return the unique plug-in identifier for the function.
+
+ If memory was allocated for the name (required by some function types),
+ it *OUTNAME will be set and should be used over the return value. It
+ must subsequently be freed by the caller.
+
+ If the given method should be ignored (not defined to the plug-in),
+ IGNORE will be true. */
+
+ const char *maybe_canonicalize_special_function
+ (const char *field_name, const struct fn_field *method_field,
+ const struct type *method_type, char **outname, bool *ignore);
+};
+
+/* 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;
+
+/* Callbacks suitable for use as the GCC C++ enter/leave scope requests. */
+
+extern gcc_cp_enter_leave_user_expr_scope_function gcc_cplus_enter_scope;
+extern gcc_cp_enter_leave_user_expr_scope_function gcc_cplus_leave_scope;
+
+#endif /* GDB_COMPILE_CPLUS_H */
diff --git a/gdb/compile/compile-internal.h b/gdb/compile/compile-internal.h
index 292282e6550..71522827c68 100644
--- a/gdb/compile/compile-internal.h
+++ b/gdb/compile/compile-internal.h
@@ -27,6 +27,10 @@
extern int compile_debug;
+/* Flag to enable internal debugging for oracle requests. */
+
+extern int debug_compile_oracle;
+
struct block;
namespace compile
diff --git a/gdb/compile/compile-object-load.c b/gdb/compile/compile-object-load.c
index 473e664abad..8dbc7547afa 100644
--- a/gdb/compile/compile-object-load.c
+++ b/gdb/compile/compile-object-load.c
@@ -460,7 +460,7 @@ get_out_value_type (struct symbol *func_sym, struct objfile *objfile,
if (function != NULL
&& (BLOCK_SUPERBLOCK (function_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))
break;
}
@@ -742,6 +742,8 @@ compile_object_load (const compile_file_names &file_names,
? mst_unknown : MSYMBOL_TYPE (bmsym.minsym))
{
case mst_text:
+ case mst_bss:
+ case mst_data:
sym->value = BMSYMBOL_VALUE_ADDRESS (bmsym);
if (compile_debug)
fprintf_unfiltered (gdb_stdlog,
diff --git a/gdb/compile/compile.c b/gdb/compile/compile.c
index b9a3d3419f9..a0a5d73de87 100644
--- a/gdb/compile/compile.c
+++ b/gdb/compile/compile.c
@@ -917,7 +917,6 @@ String quoting is parsed like in shell, for example:\n\
" -fPIE"
/* We want warnings, except for some commonly happening for GDB commands. */
" -Wall "
- " -Wno-implicit-function-declaration"
" -Wno-unused-but-set-variable"
" -Wno-unused-variable"
/* Override CU's possible -fstack-protector-strong. */
diff --git a/gdb/testsuite/gdb.compile/compile-cplus-mod.c b/gdb/testsuite/gdb.compile/compile-cplus-mod.c
new file mode 100644
index 00000000000..8b7c75576a5
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/compile-cplus-mod.c
@@ -0,0 +1,28 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2014-2015 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 (void)
+{
+ // Make 'globalvar' lookup working.
+#pragma GCC push_user_expression
+
+ globalvar = 3;
+ globalvar += 4;
+
+#pragma GCC pop_user_expression
+}
diff --git a/gdb/testsuite/gdb.compile/compile-cplus-print.c b/gdb/testsuite/gdb.compile/compile-cplus-print.c
new file mode 100644
index 00000000000..2635d16796f
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/compile-cplus-print.c
@@ -0,0 +1,32 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2015-2016 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 (void)
+{
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.compile/compile-cplus-print.exp b/gdb/testsuite/gdb.compile/compile-cplus-print.exp
new file mode 100644
index 00000000000..cb453a4e184
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/compile-cplus-print.exp
@@ -0,0 +1,75 @@
+# Copyright 2015-2016 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\\}"
+gdb_test "compile print main" " = \\{int \\(void\\)\\} 0x\[0-9a-f\]+"
+
+set test "compile print *vararray@3"
+gdb_test_multiple $test $test {
+ -re " = \\{1, 2, 3\\}\r\n$gdb_prompt $" {
+ pass $test
+ }
+ -re ": error: stray '@' in program\r\n.*\r\n$gdb_prompt $" {
+ kfail compile/18489 "$test"
+ }
+}
+
+set test "compile print *vararrayp@3"
+gdb_test_multiple $test $test {
+ -re " = \\{1, 2, 3\\}\r\n$gdb_prompt $" {
+ pass $test
+ }
+ -re ": error: stray '@' in program\r\n.*\r\n$gdb_prompt $" {
+ kfail compile/18489 "$test"
+ }
+}
+
+gdb_test "compile print/x 256" " = 0x100"
+gdb_test {print $} " = 256"
+
+gdb_test "compile print varobject" { = {field = 1}}
diff --git a/gdb/testsuite/gdb.compile/compile-cplus.c b/gdb/testsuite/gdb.compile/compile-cplus.c
new file mode 100644
index 00000000000..3ba46ce947d
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/compile-cplus.c
@@ -0,0 +1,241 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2014-2017 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 (void)
+{
+ /* 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 (void);
+ ~VirtualBase (void);
+};
+
+struct VirtualBase2 : VirtualBase {};
+
+VirtualBase::VirtualBase (void)
+{
+ z = 24;
+}
+
+VirtualBase::~VirtualBase (void)
+{
+ z = 22;
+}
+
+class Foo
+{
+ int var;
+ static const int public_static_var = 12;
+
+ private:
+ int private_var = 0;
+ int private_method (void);
+
+ public:
+ int public_var = 0;
+ int public_method (void);
+ void set_private_var (int);
+};
+
+void Foo::set_private_var (int i)
+{
+ private_var = i;
+}
+
+int Foo::private_method (void)
+{
+ return private_var;
+}
+
+int Foo::public_method (void)
+{
+ return public_var;
+}
+
+int
+main (void)
+{
+ 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;
+}
diff --git a/gdb/testsuite/gdb.compile/compile-cplus.exp b/gdb/testsuite/gdb.compile/compile-cplus.exp
new file mode 100644
index 00000000000..04849ba3947
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/compile-cplus.exp
@@ -0,0 +1,341 @@
+# Copyright 2014-2017 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.
+
+gdb_test_no_output "compile code globalvar = func_nodebug (75);" \
+ "call func_nodebug"
+gdb_test "p globalvar" " = -75" "expect -75"
+gdb_test_no_output \
+ "compile code int (*funcp) (int) = (int(*)(int))func_nodebug; globalvar = funcp (76);" \
+ "call func_nodebug indirectly"
+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 "compile code globalvar = constvar;"
+ gdb_test "print globalvar" " = 3" "print constvar value"
+} else {
+ untested "print constvar value"
+}
diff --git a/gdb/testsuite/gdb.compile/cp-namespace-template.cc b/gdb/testsuite/gdb.compile/cp-namespace-template.cc
new file mode 100644
index 00000000000..18bbab4d666
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/cp-namespace-template.cc
@@ -0,0 +1,138 @@
+/* Copyright 2016-2017 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
+ {
+ template <typename T, int V>
+ T mytemplate (int a)
+ {
+ return static_cast<T> (a) + V;
+ }
+
+ template <typename T, int V>
+ T mytemplate (void)
+ {
+ return -V;
+ }
+
+ template <int V = 100>
+ int mytemplate (void)
+ {
+ return V;
+ }
+
+ struct A
+ {
+ A (int val) : value (val) { }
+ operator int () const { return value; }
+
+ template <typename T = A>
+ T tempmethod (void)
+ {
+ return value;
+ }
+
+ template <typename T = A, int V = -1>
+ static T stempmethod (void)
+ {
+ return V;
+ }
+
+ template <typename T = A, int V = -2>
+ static T stempmethod (T arg)
+ {
+ return arg + V;
+ }
+
+ int value;
+ };
+
+ template<>
+ int
+ A::tempmethod (void)
+ {
+ return -value;
+ }
+
+ // A handful of operator templates
+ struct O
+ {
+ O (int v) : v_ (v) { }
+
+ template <typename T>
+ operator T (void) { return -v_; }
+
+ template <typename T>
+ O operator+ (T val)
+ {
+ return v_ + val;
+ }
+
+ int v_;
+ };
+
+ // A simple class template
+ template <typename T1 = O, typename T2 = int, int V = 3>
+ class classt
+ {
+ public:
+ classt (T1 v) : val1_ (v), val2_ (107) { }
+ T1 get1 (void) const { return val1_; }
+ T2 get2 (void) const { return val2_; }
+ int get3 (void) const { return V; }
+
+ private:
+ T1 val1_;
+ T2 val2_;
+ };
+ };
+};
+
+int
+main (void)
+{
+ using namespace N1::N2;
+
+ A a (20);
+ O o (30);
+ int var = 0xdeadbeef;
+ int i = 1;
+ const int j = 1;
+ int* pi = &i;
+ int const* const cpci = &j;
+ int *const cpi = &i;
+
+ int o_val = o + 30;
+
+ classt<> cddd (o);
+ classt<int> cdd (100);
+ classt<int, char> cd (101);
+ classt<int, char, 12> c (102);
+ int cvals = cddd.get1 () + cddd.get2 () + cddd.get3 ();
+ cvals += cdd.get1 () + cdd.get2 () + cdd.get3 ();
+ cvals += cd.get1 () + cd.get2 () + cd.get3 ();
+ cvals += c.get1 () + c.get2 () + c.get3 ();
+
+ return mytemplate<int, 1> (0)
+ + mytemplate<int, 1> ()
+ + mytemplate<0> ()
+ + mytemplate ()
+ + a.tempmethod ()
+ + a.tempmethod<int> ()
+ + A::stempmethod ()
+ + A::stempmethod (0); // break here
+}
diff --git a/gdb/testsuite/gdb.compile/cp-namespace-template.exp b/gdb/testsuite/gdb.compile/cp-namespace-template.exp
new file mode 100644
index 00000000000..19eabe97595
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/cp-namespace-template.exp
@@ -0,0 +1,67 @@
+# Copyright 2016-2017 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-qualified template tests.
+
+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]} {
+ 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::mytemplate<int, 1> ()" -1
+CompileExpression::test "N1::N2::mytemplate<int, 1> (1)" 2
+CompileExpression::test "N1::N2::mytemplate<0> ()" 0
+CompileExpression::test "N1::N2::mytemplate ()" 100
+CompileExpression::test "a.tempmethod ()" {(20|{value = 20})} \
+ -print {xfail *-*-* gcc/debug/49348} \
+ -value {xfail *-*-* gcc/debug/49348}
+CompileExpression::test "a.tempmethod<N1::N2::A> ()" {(20|{value = 20})}
+CompileExpression::test "a.tempmethod<int> ()" -20
+CompileExpression::test "o + 3" {(-33|{v_ = 33})}
+CompileExpression::test "cddd.get1 ()" {(-30|{v_ = 30})}
+CompileExpression::test "cddd.get2 ()" 107
+CompileExpression::test "cddd.get3 ()" 3
+CompileExpression::test "cdd.get1 ()" 100
+CompileExpression::test "cdd.get2 ()" 107
+CompileExpression::test "cdd.get3 ()" 3
+CompileExpression::test "cd.get1 ()" 101
+CompileExpression::test "cd.get2 ()" {107( 'k')?}
+CompileExpression::test "cd.get3 ()" 3
+CompileExpression::test "c.get1 ()" 102
+CompileExpression::test "c.get2 ()" {107( 'k')?}
+CompileExpression::test "c.get3 ()" 12
diff --git a/gdb/testsuite/gdb.compile/cp-simple-anonymous.cc b/gdb/testsuite/gdb.compile/cp-simple-anonymous.cc
new file mode 100644
index 00000000000..19b9fc85b7b
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/cp-simple-anonymous.cc
@@ -0,0 +1,65 @@
+/* Copyright 2015 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 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;
+} anon_s = {"abracadabra", 11};
+
+struct A
+{
+ A (void) : 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 (void)
+{
+ 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
+}
diff --git a/gdb/testsuite/gdb.compile/cp-simple-anonymous.exp b/gdb/testsuite/gdb.compile/cp-simple-anonymous.exp
new file mode 100644
index 00000000000..094c07be0c8
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/cp-simple-anonymous.exp
@@ -0,0 +1,55 @@
+# Copyright 2015-2016 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/>.
+
+# (Very) simple method tests.
+
+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]} {
+ 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 "anon_s.len" 11
+CompileExpression::test "a.u.b" 0
+CompileExpression::test "a.s.len" 5
+CompileExpression::test "a.e" {(10|A::AA)}
+CompileExpression::test "(*anon_s.ptr == 'a')" (1|true)
+CompileExpression::test "(*a.s.ptr != 'h')" (0|false)
+CompileExpression::test "A::BB" {(11|A::BB)}
diff --git a/gdb/testsuite/gdb.compile/cp-simple-inherit.cc b/gdb/testsuite/gdb.compile/cp-simple-inherit.cc
new file mode 100644
index 00000000000..3e445dffc34
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/cp-simple-inherit.cc
@@ -0,0 +1,58 @@
+/* Copyright 2015 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 (void)
+{
+ 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;
+}
diff --git a/gdb/testsuite/gdb.compile/cp-simple-inherit.exp b/gdb/testsuite/gdb.compile/cp-simple-inherit.exp
new file mode 100644
index 00000000000..64c89064269
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/cp-simple-inherit.exp
@@ -0,0 +1,52 @@
+# Copyright 2015, 2016, 2017 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/>.
+
+# (Very) simple inheritance tests.
+
+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]} {
+ 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
diff --git a/gdb/testsuite/gdb.compile/cp-simple-member.cc b/gdb/testsuite/gdb.compile/cp-simple-member.cc
new file mode 100644
index 00000000000..9278088468c
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/cp-simple-member.cc
@@ -0,0 +1,83 @@
+/* Copyright 2015 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};
+
+#if WE_DONT_LIKE_THIS
+// Yet? GCC outputs DW_AT_linkage_name="<anon>"
+// This *really* messes things up.
+namespace {
+ typedef enum {AA = 20, AB, AC, AD} ANON_E;
+}
+#endif
+
+namespace N {
+ typedef enum {AA = 20, AB, AC, AD} ANON_E;
+}
+
+class A
+{
+public:
+ typedef int ATYPE;
+
+ A(void) : public_ (1), protected_ (N::AB), private_ (3) {}
+ ATYPE public_;
+ static const myenum s_public_;
+ friend ATYPE get_values (const A&);
+
+protected:
+ N::ANON_E protected_;
+ static N::ANON_E s_protected_;
+
+private:
+ ATYPE private_;
+ static myenum s_private_;
+};
+
+const myenum A::s_public_ = E_A;
+N::ANON_E A::s_protected_ = N::AA;
+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::AB) // + 21
+ val += 21;
+ if (a.s_public_ == E_A) // +10
+ val += 10;
+ if (a.s_protected_ == N::AA) // +20
+ val += 20;
+ if (a.s_private_ == E_C) // +30
+ val += 30;
+ return val; // = 85
+}
+
+typedef int A::*PMI;
+
+int
+main (void)
+{
+ A a;
+ int var = 1234;
+ PMI pmi = &A::public_;
+
+ return a.*pmi + get_values (a); // break here
+}
diff --git a/gdb/testsuite/gdb.compile/cp-simple-member.exp b/gdb/testsuite/gdb.compile/cp-simple-member.exp
new file mode 100644
index 00000000000..c9320d7c2f2
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/cp-simple-member.exp
@@ -0,0 +1,76 @@
+# Copyright 2015-2016 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/>.
+
+# (Very) simple method tests.
+
+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]} {
+ 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::AB)}
+CompileExpression::test "a.private_" 3
+CompileExpression::test "A::s_public_" {(10|E_A)}
+CompileExpression::test "A::s_protected_" {(20|N::AA)}
+CompileExpression::test "A::s_private_" {(12|E_C)}
+CompileExpression::test "A::ATYPE i = 10; var = i;" 10 -explicit
+CompileExpression::test "get_values (a)" 85
+CompileExpression::test "myenum me = E_B; var = me;" 11 -explicit
+CompileExpression::test "A::s_protected_ = N::AB; var = A::s_protected_;" \
+ 21 -explicit
+CompileExpression::test "A::s_private_ = E_B; var = A::s_private_;" 11 -explicit
+CompileExpression::test "N::ANON_E ae = N::AD; var = ae;" 23 -explicit
+CompileExpression::test {a.*pmi} 1
+CompileExpression::test {a.public_ = 2; var = a.*pmi; a.public_ = 1} 2 -explicit
+
+# Test some compilation failures
+set failed {\r\nCompilation failed\.}
+# !!keiths: This should actually really work...
+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"
+
+# !!keiths; The "to ..." part depends on how we name anonymous types.
+gdb_test "compile code N::ANON_E nse = E_A" \
+ ".*cannot convert .myenum. to .N::anonymous enum.*$failed"
diff --git a/gdb/testsuite/gdb.compile/cp-simple-method.cc b/gdb/testsuite/gdb.compile/cp-simple-method.cc
new file mode 100644
index 00000000000..c3c99696df6
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/cp-simple-method.cc
@@ -0,0 +1,91 @@
+/* Copyright 2015, 2016 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 (void) : a_ (21) {}
+ ATYPE get_var (void) { 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 (void)
+{
+ return 200;
+}
+
+typedef int (A::*PMF) (A::ATYPE);
+
+int
+main (void)
+{
+ 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);
+}
diff --git a/gdb/testsuite/gdb.compile/cp-simple-method.exp b/gdb/testsuite/gdb.compile/cp-simple-method.exp
new file mode 100644
index 00000000000..ebb1273b6ce
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/cp-simple-method.exp
@@ -0,0 +1,66 @@
+# Copyright 2015-2017 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/>.
+
+# (Very) simple method tests.
+
+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]} {
+ 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
diff --git a/gdb/testsuite/gdb.compile/cp-simple-nested.cc b/gdb/testsuite/gdb.compile/cp-simple-nested.cc
new file mode 100644
index 00000000000..50db34f1494
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/cp-simple-nested.cc
@@ -0,0 +1,58 @@
+/* Copyright 2015-2016 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 (void) : a_ (1) {}
+ int get (void);
+
+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 (void) : a_ (2) {}
+
+ struct Inner2
+ {
+ int a_;
+ Inner2 (void) : a_ (3) {}
+ };
+ };
+};
+
+int
+A::get (void)
+{
+ A::Inner1 i1;
+ A::Inner1::Inner2 i2;
+
+ return i1.a_ + i2.a_; // break here
+}
+
+int var = 1234;
+
+int
+main (void)
+{
+ A a;
+
+ return a.get ();
+}
diff --git a/gdb/testsuite/gdb.compile/cp-simple-nested.exp b/gdb/testsuite/gdb.compile/cp-simple-nested.exp
new file mode 100644
index 00000000000..be3619740f4
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/cp-simple-nested.exp
@@ -0,0 +1,52 @@
+# Copyright 2015-2016 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/>.
+
+# (Very) simple virtual method/inheritance tests.
+
+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]} {
+ 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
diff --git a/gdb/testsuite/gdb.compile/cp-simple-ns.cc b/gdb/testsuite/gdb.compile/cp-simple-ns.cc
new file mode 100644
index 00000000000..56923edba14
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/cp-simple-ns.cc
@@ -0,0 +1,37 @@
+namespace N1
+{
+ namespace N2
+ {
+ namespace N3
+ {
+ namespace N4
+ {
+ static int n4static = 400;
+
+ struct S4
+ {
+ static int s4static;
+ int s4int_;
+ S4 (void) : s4int_ (4) {};
+ ~S4 (void) { --s4static; }
+
+ int get_var (void) { return s4int_; }
+ static int get_svar (void) { return s4static; }
+ };
+ int S4::s4static = 40;
+ }
+ }
+ }
+}
+
+int
+main (void)
+{
+ using namespace N1::N2::N3::N4;
+
+ S4 s;
+ int var = 1234;
+
+ var += s.s4int_; /* break here */
+ return S4::get_svar () - 10 * s.get_var ();
+}
diff --git a/gdb/testsuite/gdb.compile/cp-simple-ns.exp b/gdb/testsuite/gdb.compile/cp-simple-ns.exp
new file mode 100644
index 00000000000..5d51a3d3d61
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/cp-simple-ns.exp
@@ -0,0 +1,48 @@
+# Copyright 2015, 2016, 2017 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 .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]} {
+ 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 "s.s4int_" 4
+CompileExpression::test "N1::N2::N3::N4::S4::get_svar ()" 40
+CompileExpression::test "s.get_var ()" 4
diff --git a/gdb/testsuite/gdb.compile/cp-simple-template.cc b/gdb/testsuite/gdb.compile/cp-simple-template.cc
new file mode 100644
index 00000000000..ec46694757b
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/cp-simple-template.cc
@@ -0,0 +1,180 @@
+/* Copyright 2016 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/>. */
+
+// NOTE: We cannot currently use namespaces until namespace-qualified
+// symbol lookups are fixed in gdb
+
+template <typename T, int V>
+T mytemplate (int a)
+{
+ return static_cast<T> (a) + V;
+}
+
+template <typename T, int V>
+T mytemplate (void)
+{
+ return -V;
+}
+
+template <int V = 100>
+int mytemplate (void)
+{
+ return V;
+}
+
+struct A
+{
+ A (int val) : value (val) { }
+ operator int () const { return value; }
+
+ template <typename T = A>
+ T tempmethod (void)
+ {
+ return value;
+ }
+
+ template <typename T = A, int V = -1>
+ static T stempmethod (void)
+ {
+ return V;
+ }
+
+ template <typename T = A, int V = -2>
+ static T stempmethod (T arg)
+ {
+ return arg + V;
+ }
+
+ int value;
+};
+
+template<>
+int
+A::tempmethod (void)
+{
+ return -value;
+}
+
+template <typename T>
+T deduct (T a)
+{
+ return a;
+}
+
+extern char const g_str[] = "hello";
+
+template <typename T>
+int mod_test (T a) { return 1; }
+
+template <typename T>
+int mod_test (T* const a) { return 2; }
+
+template <typename T>
+int mod_test (T const* const a) { return 3; }
+
+#if 0
+/* This chaining of defaults has no good representation in the debug info.
+ For each instance where T2 defaulted to T1, we will have as many
+ default values in the debug info for T2, one for each such instance. */
+template <typename T1 = int, typename T2 = T1, typename T3 = T2,
+ int V1 = 10, int V2 = 20, const char* V3 = g_str>
+T1 defaultvals (void)
+{
+ return static_cast<T1> (V1);
+}
+#else
+template <typename T = A, int V = 10, const char* S = g_str>
+T defaultvals (void)
+{
+ return static_cast<T> (V);
+}
+#endif
+
+// A handful of operator templates
+struct O
+{
+ O (int v) : v_ (v) { }
+
+ template <typename T>
+ operator T (void) { return -v_; }
+
+ template <typename T>
+ O operator+ (T val)
+ {
+ return v_ + val;
+ }
+
+ int v_;
+};
+
+template <typename T>
+const T** ret_test (void) { return 0; }
+
+template <typename T>
+T const* const* ret2_test (void) { return 0; }
+
+// Some simple class templates
+template <typename T1 = O, typename T2 = int, int V = 3>
+class classt
+{
+public:
+ classt (T1 v) : val1_ (v), val2_ (107) { }
+ T1 get1 (void) const { return val1_; }
+ T2 get2 (void) const { return val2_; }
+ int get3 (void) const { return V; }
+
+private:
+ T1 val1_;
+ T2 val2_;
+};
+
+int
+main (void)
+{
+ A a (20);
+ O o (30);
+ int var = 0xdeadbeef;
+ int i = 1;
+ const int j = 1;
+ int* pi = &i;
+ int const* const cpci = &j;
+ int *const cpi = &i;
+
+ int o_val = o + 30;
+ int mod_value = mod_test (i) + mod_test (cpci) + mod_test (cpi);
+ const char** cp = ret_test<char> ();
+ char const* const* ccp = ret2_test<char> ();
+
+ classt<> cddd (o);
+ classt<int> cdd (100);
+ classt<int, char> cd (101);
+ classt<int, char, 12> c (102);
+ int cvals = cddd.get1 () + cddd.get2 () + cddd.get3 ();
+ cvals += cdd.get1 () + cdd.get2 () + cdd.get3 ();
+ cvals += cd.get1 () + cd.get2 () + cd.get3 ();
+ cvals += c.get1 () + c.get2 () + c.get3 ();
+
+ return mytemplate<int, 1> (0)
+ + mytemplate<int, 1> ()
+ + mytemplate<0> ()
+ + mytemplate ()
+ + a.tempmethod ()
+ + a.tempmethod<int> ()
+ + A::stempmethod ()
+ + A::stempmethod (0)
+ + defaultvals ()
+ + defaultvals<int, 20> ()
+ + deduct (0); // break here
+}
diff --git a/gdb/testsuite/gdb.compile/cp-simple-template.exp b/gdb/testsuite/gdb.compile/cp-simple-template.exp
new file mode 100644
index 00000000000..7261eed332a
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/cp-simple-template.exp
@@ -0,0 +1,79 @@
+# Copyright 2016 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/>.
+
+# (Very) simple template tests.
+
+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]} {
+ 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 "mytemplate<int, 1> ()" -1
+CompileExpression::test "mytemplate<int, 1> (1)" 2
+CompileExpression::test "mytemplate<0> ()" 0
+CompileExpression::test "mytemplate ()" 100
+CompileExpression::test "a.tempmethod ()" {(20|{value = 20})} \
+ -print {xfail *-*-* gcc/debug/49348} \
+ -value {xfail *-*-* gcc/debug/49348}
+CompileExpression::test "a.tempmethod<A> ()" {(20|{value = 20})}
+CompileExpression::test "a.tempmethod<int> ()" -20
+CompileExpression::test "defaultvals ()" {(10|{value = 10})}
+CompileExpression::test "defaultvals<int, 20> ()" 20
+CompileExpression::test "deduct (1234)" 1234
+CompileExpression::test "o + 3" {(-33|{v_ = 33})}
+CompileExpression::test "mod_test (i)" 1
+CompileExpression::test "mod_test (cpi)" 2
+CompileExpression::test "mod_test (cpci)" 3
+CompileExpression::test "cddd.get1 ()" {(-30|{v_ = 30})}
+CompileExpression::test "cddd.get2 ()" 107
+CompileExpression::test "cddd.get3 ()" 3
+CompileExpression::test "cdd.get1 ()" 100
+CompileExpression::test "cdd.get2 ()" 107
+CompileExpression::test "cdd.get3 ()" 3
+CompileExpression::test "cd.get1 ()" 101
+CompileExpression::test "cd.get2 ()" {107( 'k')?}
+CompileExpression::test "cd.get3 ()" 3
+CompileExpression::test "c.get1 ()" 102
+CompileExpression::test "c.get2 ()" {107( 'k')?}
+CompileExpression::test "c.get3 ()" 12
+
+# Some explicit tests that don't fit neatly into CompileExpression (yet)
+gdb_test "compile print ret_test<char>()" \
+ [string_to_regexp {= (const char **) 0x0}]
+gdb_test "compile print ret2_test<char>()" \
+ [string_to_regexp {= (const char * const *) 0x0}]
diff --git a/gdb/testsuite/gdb.compile/cp-simple-virtual.cc b/gdb/testsuite/gdb.compile/cp-simple-virtual.cc
new file mode 100644
index 00000000000..f778d70a9b3
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/cp-simple-virtual.cc
@@ -0,0 +1,65 @@
+/* Copyright 2015 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 (void) { return 1; }
+ virtual int doit3 (void) { return -3; }
+ virtual int doit2 (void) = 0;
+};
+
+struct B : virtual A
+{
+ int doit (void) { return 2; }
+ int doit2 (void) { return 22; }
+};
+
+struct C : virtual A
+{
+ int doit (void) { return 3; }
+ int doit2 (void) { return 33; }
+};
+
+struct D : B, C
+{
+ int doit (void) { return 4; }
+ int doit2 (void) { return 44; }
+};
+
+int
+main (void)
+{
+ int var = 1234;
+ B b;
+ C c;
+ D d;
+ A *ap = &d;
+
+ struct Foo
+ {
+ int doit (void) { return 1111; }
+ } foo;
+
+ struct Bar : A
+ {
+ int doit2 (void) { return 2222; }
+ } bar;
+
+ var = (b.doit () + c.doit () + d.doit () + d.doit3 ()
+ + ap->doit () + ap->doit2 () + foo.doit ()
+ + bar.doit2 ()); // break here
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.compile/cp-simple-virtual.exp b/gdb/testsuite/gdb.compile/cp-simple-virtual.exp
new file mode 100644
index 00000000000..44bb3dd7250
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/cp-simple-virtual.exp
@@ -0,0 +1,72 @@
+# Copyright 2015, 2016 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/>.
+
+# (Very) simple virtual method/inheritance tests.
+
+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]} {
+ 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
+CompileExpression::test "foo.doit ()" 1111
+CompileExpression::test "bar.doit2 ()" 2222
+
+# These two tests are "disabled". They represent new/future features.
+# CompileExpression::test \
+ [concat "struct ABC {int doit2(void) { return 3333; }} abc;" \
+ "var = abc.doit2()"] \
+ 3333 -explicit
+# CompileExpression::test \
+ [concat "struct ABC : A {int doit2(void) { 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."
diff --git a/gdb/testsuite/gdb.compile/cp-special-function.cc b/gdb/testsuite/gdb.compile/cp-special-function.cc
new file mode 100644
index 00000000000..6bb5ea596c5
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/cp-special-function.cc
@@ -0,0 +1,661 @@
+/* Copyright 2015 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 <cstddef>
+
+class MyInteger;
+static MyInteger *global_integer;
+
+class MyInteger
+{
+public:
+ MyInteger (int val) : pub_var (0), int_ (val) {}
+ int get (void) const { return int_; }
+
+ /* Don't assume that these operators do exactly what you
+ think they will -- especially the unary versions of +,-,*,&. */
+
+ friend MyInteger operator+ (const MyInteger& i);
+ friend int operator+ (const MyInteger& i1, const MyInteger& i2);
+ friend int operator+ (const MyInteger& i1, int i2);
+ friend int operator+ (int i1, const MyInteger& i2);
+
+ friend MyInteger operator- (const MyInteger& i);
+ friend int operator- (const MyInteger& i1, const MyInteger& i2);
+ friend int operator- (const MyInteger& i1, int i2);
+ friend int operator- (int i1, const MyInteger& i2);
+
+ friend MyInteger operator& (const MyInteger& i);
+ friend int operator& (const MyInteger& i1, const MyInteger& i2);
+ friend int operator& (const MyInteger& i1, int i2);
+ friend int operator& (int i1, const MyInteger& i2);
+
+ friend MyInteger operator* (const MyInteger& i);
+ friend int operator* (const MyInteger& i1, const MyInteger& i2);
+ friend int operator* (const MyInteger& i1, int i2);
+ friend int operator* (int i1, const MyInteger& i2);
+
+ friend MyInteger operator~ (const MyInteger& i);
+
+ friend int operator/ (const MyInteger& i1, const MyInteger& i2);
+ friend int operator/ (const MyInteger& i1, int i2);
+ friend int operator/ (int i1, const MyInteger& i2);
+
+ friend int operator% (const MyInteger& i1, const MyInteger& i2);
+ friend int operator% (const MyInteger& i1, int i2);
+ friend int operator% (int i1, const MyInteger& i2);
+
+ friend int operator| (const MyInteger& i1, const MyInteger& i2);
+ friend int operator| (const MyInteger& i1, int i2);
+ friend int operator| (int i1, const MyInteger& i2);
+
+ friend int operator^ (const MyInteger& i1, const MyInteger& i2);
+ friend int operator^ (const MyInteger& i1, int i2);
+ friend int operator^ (int i1, const MyInteger& i2);
+
+ void operator= (const MyInteger& i) { int_ = i.int_; }
+ void operator= (int i) { int_ = i; }
+
+ void operator+= (const MyInteger& i) { int_ += i.int_; }
+ void operator+= (int i) { int_ += i; }
+
+ void operator-= (const MyInteger& i) { int_ -= i.int_; }
+ void operator-= (int i) { int_ -= i; }
+
+ void operator*= (const MyInteger& i) { int_ *= i.int_; }
+ void operator*= (int i) { int_ *= i; }
+
+ void operator/= (const MyInteger& i) { int_ /= i.int_; }
+ void operator/= (int i) { int_ /= i; }
+
+ void operator%= (const MyInteger& i) { int_ %= i.int_; }
+ void operator%= (int i) { int_ %= i; }
+
+ void operator&= (const MyInteger& i) { int_ &= i.int_; }
+ void operator&= (int i) { int_ &= i; }
+
+ void operator|= (const MyInteger& i) { int_ |= i.int_; }
+ void operator|= (int i) { int_ |= i; }
+
+ void operator^= (const MyInteger& i) { int_ ^= i.int_; }
+ void operator^= (int i) { int_ ^= i; }
+
+ friend int operator<< (const MyInteger& i1, const MyInteger& i2);
+ friend int operator<< (const MyInteger& i1, int i2);
+ friend int operator<< (int i1, const MyInteger& i2);
+
+ friend int operator>> (const MyInteger& i1, const MyInteger& i2);
+ friend int operator>> (const MyInteger& i1, int i2);
+ friend int operator>> (int i1, const MyInteger& i2);
+
+ void operator<<= (const MyInteger& i) { int_ <<= i.int_; }
+ void operator<<= (int i) { int_ <<= i; }
+
+ void operator>>= (const MyInteger& i) { int_ >>= i.int_; }
+ void operator>>= (int i) { int_ >>= i; }
+
+ friend bool operator== (const MyInteger& i1, const MyInteger& i2);
+ friend bool operator== (const MyInteger& i1, int i2);
+ friend bool operator== (int i1, const MyInteger& i2);
+
+ friend bool operator!= (const MyInteger& i1, const MyInteger& i2);
+ friend bool operator!= (const MyInteger& i1, int i2);
+ friend bool operator!= (int i1, const MyInteger& i2);
+
+ friend bool operator< (const MyInteger& i1, const MyInteger& i2);
+ friend bool operator< (const MyInteger& i1, int i2);
+ friend bool operator< (int i1, const MyInteger& i2);
+
+ friend bool operator> (const MyInteger& i1, const MyInteger& i2);
+ friend bool operator> (const MyInteger& i1, int i2);
+ friend bool operator> (int i1, const MyInteger& i2);
+
+ friend bool operator<= (const MyInteger& i1, const MyInteger& i2);
+ friend bool operator<= (const MyInteger& i1, int i2);
+ friend bool operator<= (int i1, const MyInteger& i2);
+
+ friend bool operator>= (const MyInteger& i1, const MyInteger& i2);
+ friend bool operator>= (const MyInteger& i1, int i2);
+ friend bool operator>= (int i1, const MyInteger& i2);
+
+ friend int operator! (const MyInteger& i);
+
+ friend bool operator&& (const MyInteger& i1, const MyInteger& i2);
+ friend bool operator&& (const MyInteger& i1, int i2);
+ friend bool operator&& (int i1, const MyInteger& i2);
+
+ friend bool operator|| (const MyInteger& i1, const MyInteger& i2);
+ friend bool operator|| (const MyInteger& i1, int i2);
+ friend bool operator|| (int i1, const MyInteger& i2);
+
+ MyInteger& operator++ (void) { ++int_; return *this; }
+ MyInteger operator++ (int dummy)
+ {
+ MyInteger tmp (int_);
+ operator++ ();
+ return tmp;
+ }
+
+ MyInteger& operator-- (void) { --int_; return *this; }
+ MyInteger operator-- (int dummy)
+ {
+ MyInteger tmp (int_);
+ operator-- ();
+ return tmp;
+ }
+
+ friend MyInteger& operator, (MyInteger& i1, MyInteger& i2);
+
+ friend int operator->* (const MyInteger& i1, int i2);
+ friend int operator->* (const MyInteger& i1, const MyInteger& i2);
+
+ MyInteger* operator-> (void) { return global_integer; }
+
+ int operator() (void) { return -int_; }
+ int operator() (const MyInteger& i) { return int_ + i; }
+ int operator() (int i) { return int_ + i; }
+
+ int operator[] (const MyInteger& i) { return int_ - i; }
+ int operator[] (int i) { return int_ - i; }
+
+#if 1
+ static void* operator new (std::size_t sz);
+#endif
+
+ operator int() const { return -int_; }
+ operator char() const { return int_ & 0xff; }
+
+public:
+ int pub_var;
+private:
+ int int_;
+};
+
+MyInteger
+operator+ (const MyInteger& i)
+{
+ return MyInteger (i + 10);
+}
+
+int
+operator+ (const MyInteger& i1, const MyInteger& i2)
+{
+ return i1.int_ + i2.int_;
+}
+
+int
+operator+ (const MyInteger& i1, int i2)
+{
+ return i1.int_ + i2;
+}
+
+int
+operator+ (int i1, const MyInteger& i2)
+{
+ return operator+ (i2, i1);
+}
+
+MyInteger
+operator- (const MyInteger& i)
+{
+ return MyInteger (i + 20);
+}
+
+int
+operator- (const MyInteger& i1, const MyInteger& i2)
+{
+ return i1.int_ - i2.int_;
+}
+
+int
+operator- (const MyInteger& i1, int i2)
+{
+ return i1.int_ - i2;
+}
+
+int
+operator- (int i1, const MyInteger& i2)
+{
+ return i1 - i2.int_;
+}
+
+MyInteger
+operator& (const MyInteger& i)
+{
+ return MyInteger (i + 30);
+}
+
+int
+operator& (const MyInteger& i1, const MyInteger& i2)
+{
+ return i1.int_ & i2.int_;
+}
+
+int
+operator& (const MyInteger& i1, int i2)
+{
+ return i1.int_ & i2;
+}
+
+int
+operator& (int i1, const MyInteger& i2)
+{
+ return operator& (i2, i1);
+}
+
+MyInteger
+operator* (const MyInteger& i)
+{
+ return MyInteger (i + 40);
+}
+
+int
+operator* (const MyInteger& i1, const MyInteger& i2)
+{
+ return i1.int_ * i2.int_;
+}
+
+int
+operator* (const MyInteger& i1, int i2)
+{
+ return i1.int_ * i2;
+}
+
+int
+operator* (int i1, const MyInteger& i2)
+{
+ return operator* (i2, i1);
+}
+
+MyInteger
+operator~ (const MyInteger& i)
+{
+ return MyInteger (~i.int_);
+}
+
+int
+operator/ (const MyInteger& i1, const MyInteger& i2)
+{
+ return i1.int_ / i2.int_;
+}
+
+int
+operator/ (const MyInteger& i1, int i2)
+{
+ return i1.int_ / i2;
+}
+
+int
+operator/ (int i1, const MyInteger& i2)
+{
+ return i1 / i2.int_;
+}
+
+int
+operator% (const MyInteger& i1, const MyInteger& i2)
+{
+ return i1.int_ % i2.int_;
+}
+
+int
+operator% (const MyInteger& i1, int i2)
+{
+ return i1.int_ % i2;
+}
+
+int
+operator% (int i1, const MyInteger& i2)
+{
+ return i1 % i2.int_;
+}
+
+int
+operator| (const MyInteger& i1, const MyInteger& i2)
+{
+ return i1.int_ | i2.int_;
+}
+
+int
+operator| (const MyInteger& i1, int i2)
+{
+ return i1.int_ | i2;
+}
+
+int
+operator| (int i1, const MyInteger& i2)
+{
+ return i1 | i2.int_;
+}
+
+int
+operator^ (const MyInteger& i1, const MyInteger& i2)
+{
+ return i1.int_ ^ i2.int_;
+}
+
+int
+operator^ (const MyInteger& i1, int i2)
+{
+ return i1.int_ ^ i2;
+}
+
+int
+operator^ (int i1, const MyInteger& i2)
+{
+ return i1 ^ i2.int_;
+}
+
+int
+operator<< (const MyInteger& i1, const MyInteger& i2)
+{
+ return i1.int_ << i2.int_;
+}
+
+int
+operator<< (const MyInteger& i1, int i2)
+{
+ return i1.int_ << i2;
+}
+
+int
+operator<< (int i1, const MyInteger& i2)
+{
+ return i1 << i2.int_;
+}
+
+int
+operator>> (const MyInteger& i1, const MyInteger& i2)
+{
+ return i1.int_ >> i2.int_;
+}
+
+int
+operator>> (const MyInteger& i1, int i2)
+{
+ return i1.int_ >> i2;
+}
+
+int
+operator>> (int i1, const MyInteger& i2)
+{
+ return i1 >> i2.int_;
+}
+
+bool
+operator== (const MyInteger& i1, const MyInteger& i2)
+{
+ return i1.int_ == i2.int_;
+}
+
+bool
+operator== (const MyInteger& i1, int i2)
+{
+ return i1.int_ == i2;
+}
+
+bool
+operator== (int i1, const MyInteger& i2)
+{
+ return operator== (i2, i1);
+}
+
+bool
+operator!= (const MyInteger& i1, const MyInteger& i2)
+{
+ return i1.int_ != i2.int_;
+}
+
+bool
+operator!= (const MyInteger& i1, int i2)
+{
+ return i1.int_ != i2;
+}
+
+bool
+operator!= (int i1, const MyInteger& i2)
+{
+ return operator!= (i2, i1);
+}
+
+bool
+operator< (const MyInteger& i1, const MyInteger& i2)
+{
+ return i1.int_ < i2.int_;
+}
+
+bool
+operator< (const MyInteger& i1, int i2)
+{
+ return i1.int_ < i2;
+}
+
+bool
+operator< (int i1, const MyInteger& i2)
+{
+ return i1 < i2.int_;
+}
+
+bool
+operator> (const MyInteger& i1, const MyInteger& i2)
+{
+ return i1.int_ > i2.int_;
+}
+
+bool
+operator> (const MyInteger& i1, int i2)
+{
+ return i1.int_ > i2;
+}
+
+bool
+operator> (int i1, const MyInteger& i2)
+{
+ return i1 > i2.int_;
+}
+
+bool
+operator<= (const MyInteger& i1, const MyInteger& i2)
+{
+ return i1.int_ <= i2.int_;
+}
+
+bool
+operator<= (const MyInteger& i1, int i2)
+{
+ return i1.int_ <= i2;
+}
+
+bool
+operator<= (int i1, const MyInteger& i2)
+{
+ return i1 <= i2.int_;
+}
+
+bool
+operator>= (const MyInteger& i1, const MyInteger& i2)
+{
+ return i1.int_ >= i2.int_;
+}
+
+bool
+operator>= (const MyInteger& i1, int i2)
+{
+ return i1.int_ >= i2;
+}
+
+bool
+operator>= (int i1, const MyInteger& i2)
+{
+ return i1 >= i2.int_;
+}
+
+int
+operator! (const MyInteger& i)
+{
+ return !(i.int_);
+}
+
+bool
+operator&& (const MyInteger& i1, const MyInteger& i2)
+{
+ return i1.int_ && i2.int_;
+}
+
+bool
+operator&& (const MyInteger& i1, int i2)
+{
+ return i1.int_ && i2;
+}
+
+bool
+operator&& (int i1, const MyInteger& i2)
+{
+ return operator&& (i2, i1);
+}
+
+bool
+operator|| (const MyInteger& i1, const MyInteger& i2)
+{
+ return i1.int_ || i2.int_;
+}
+
+bool
+operator|| (const MyInteger& i1, int i2)
+{
+ return i1.int_ || i2;
+}
+
+bool
+operator|| (int i1, const MyInteger& i2)
+{
+ return operator|| (i2, i1);
+}
+
+MyInteger&
+operator, (MyInteger& i1, MyInteger& i2)
+{
+ return i1;
+}
+
+int
+operator->* (const MyInteger& i1, int i2)
+{
+ return i1 + i2;
+}
+
+int
+operator->* (const MyInteger& i1, const MyInteger& i2)
+{
+ return i1 + i2;
+}
+
+int
+operator"" _MI (unsigned long long i)
+{
+ return 100;
+}
+
+int
+operator"" _MI (char c)
+{
+ return 200;
+}
+
+int
+operator"" _MI (const char *str, std::size_t len)
+{
+ return 300;
+}
+
+#if 1
+static void*
+MyInteger::operator new (std::size_t sz)
+{
+ void* p = ::operator new (sz);
+ MyInteger* obj = static_cast<MyInteger*> (p);
+
+ obj->pub_var = 1234;
+ return p;
+}
+#endif
+
+int
+main (void)
+{
+ char ch;
+ int var;
+ MyInteger a (1), b (2), c (-3), d (0);
+
+ global_integer = new MyInteger (21);
+ global_integer->pub_var = -21;
+ ch = *global_integer;
+ d = a;
+ d = 0;
+ d += a;
+ d += 1;
+ d -= a;
+ d -= 1;
+ d *= 1;
+ d *= d;
+ d = 2;
+ d /= 1;
+ d /= d;
+ d %= 2;
+ d %= a;
+ d = 2;
+ d &= 1;
+ d &= a;
+ d |= 2;
+ d |= a;
+ d ^= 1;
+ d ^= b;
+ d <<= 2;
+ d <<= a;
+ d >>= 2;
+ d >>= a;
+ d++;
+ ++d;
+ d--;
+ --d;
+ d = 1234;
+ var = d;
+ return +c + a + b + 3 + a.get ()
+ - a - 2 - a - b + (-c)
+ + a & b + a & 1
+ * a * b * 2 * c
+ + ~c
+ + a / 1 + b / a + 1 / a
+ + a % b + a % 1 + 2 % b
+ + 1|b + a|2 + a|b
+ + 1^a + b^2 + a^b
+ + 1 << a + a << 1 + a << a
+ + 10 >> a + b >> 1 + b >> a
+ + a == 1 + a == b + 1 == a
+ + a != 1 + a != b + 1 != a
+ + (a < 1) + (a < b) + (2 < a)
+ + (a > 1) + (a > b) + (2 > a)
+ + (a <= 1) + (a <= b) + (2 <= a)
+ + (a >= 1) + (a >= b) + (2 >= a)
+ + (!a)
+ + (a && 0) + (a && b) + (1 && a)
+ + (a || 0) + (a || b) + (1 || a)
+ + (a,b)
+ + a->*1 + a->*b
+ + a->pub_var
+ + a () + a (a) + a (2)
+ + a [1] + b [a]
+ + 'a'_MI + 1234_MI + "hello"_MI
+ ; // break here
+}
diff --git a/gdb/testsuite/gdb.compile/cp-special-function.exp b/gdb/testsuite/gdb.compile/cp-special-function.exp
new file mode 100644
index 00000000000..fcbbfcea65e
--- /dev/null
+++ b/gdb/testsuite/gdb.compile/cp-special-function.exp
@@ -0,0 +1,260 @@
+# Copyright 2015, 2016 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/>.
+
+# (Very) simple method tests.
+
+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++ additional_flags=-std=c++11}]} {
+ return -1
+}
+
+if {![runto_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 "a + 1" 2
+CompileExpression::test "a + b" 3
+CompileExpression::test "a + b + 3" 6
+CompileExpression::test "1 + a + a" 3
+CompileExpression::test "1 + b + 1" 4
+CompileExpression::test "(+a).get ()" 11
+CompileExpression::test "(+c).get ()" 7
+CompileExpression::test "a + (+c).get ()" 8
+
+CompileExpression::test "a - 2" -1
+CompileExpression::test "a - b" -1
+CompileExpression::test "a - b - 3" -4
+CompileExpression::test "2 - a - a" 0
+CompileExpression::test "2 - b - 2" -2
+CompileExpression::test "(-a).get ()" 21
+CompileExpression::test "(-c).get ()" 17
+CompileExpression::test "a - (-c).get ()" -16
+
+CompileExpression::test "a & 3" 1
+CompileExpression::test "a & b" 0
+CompileExpression::test "a & b & 3" 0
+CompileExpression::test "3 & a & a" 1
+CompileExpression::test "3 & b & 3" 2
+CompileExpression::test "(&a).get ()" 31
+CompileExpression::test "(&c).get ()" 27
+CompileExpression::test "a & (&c).get ()" 1
+
+CompileExpression::test "a * 4" 4
+CompileExpression::test "a * b" 2
+CompileExpression::test "a * b * 4" 8
+CompileExpression::test "4 * a * a" 4
+CompileExpression::test "4 * b * 4" 32
+CompileExpression::test "(*a).get ()" 41
+CompileExpression::test "(*c).get ()" 37
+CompileExpression::test "a * (*c).get ()" 37
+
+CompileExpression::test "(~a).get ()" -2
+CompileExpression::test "(~b).get ()" -3
+CompileExpression::test "(~c).get ()" 2
+
+CompileExpression::test "a / 1" 1
+CompileExpression::test "10 / b" 5
+CompileExpression::test "b / a" 2
+CompileExpression::test "-3 / c / 1 / a" 1
+
+CompileExpression::test "a % 1" 0
+CompileExpression::test "5 % c" 2
+CompileExpression::test "a % c" 1
+CompileExpression::test "-2 % c % b % 1" 0
+
+CompileExpression::test "a | 1" 1
+CompileExpression::test "1 | b" 3
+CompileExpression::test "b | c" -1
+CompileExpression::test "1 | a | b | 4" 7
+
+CompileExpression::test "a ^ 1" 0
+CompileExpression::test "1 ^ b" 3
+CompileExpression::test "b ^ c" -1
+CompileExpression::test "1 ^ a ^ b ^ 4" 6
+
+# !!keiths: I don't know why this is failing...
+CompileExpression::test "d = b; var = d.get ();" 2 -explicit
+CompileExpression::test "d = 21; var = d.get ();" 21 -explicit
+CompileExpression::test "d = 0; var = d.get ();" 0 -explicit
+
+CompileExpression::test "d.int_ = 1; var = d.get ()" 1 -explicit
+CompileExpression::test "d += a; var = d.get ();" 2 -explicit
+CompileExpression::test "d += 2; var = d.get ();" 4 -explicit
+
+CompileExpression::test "d.int_ = 2; var = d.get ()" 2 -explicit
+CompileExpression::test "d -= a; var = d.get ();" 1 -explicit
+CompileExpression::test "d -= 2; var = d.get ();" -1 -explicit
+
+CompileExpression::test "d.int_ = 3; var = d.get ()" 3 -explicit
+CompileExpression::test "d *= 2; var = d.get ()" 6 -explicit
+CompileExpression::test "d *= d; var = d.get ()" 36 -explicit
+
+CompileExpression::test "d.int_ = 6; var = d.get ()" 6 -explicit
+CompileExpression::test "d /= 2; var = d.get ()" 3 -explicit
+CompileExpression::test "d /= d; var = d.get ()" 1 -explicit
+
+CompileExpression::test "d.int_ = 4; var = d.get ()" 4 -explicit
+CompileExpression::test "d %= 3; var = d.get ()" 1 -explicit
+CompileExpression::test "d %= d; var = d.get ()" 0 -explicit
+
+CompileExpression::test "d.int_ = 5; var = d.get ()" 5 -explicit
+CompileExpression::test "d &= 4; var = d.get ()" 4 -explicit
+CompileExpression::test "d &= a; var = d.get ()" 0 -explicit
+
+CompileExpression::test "d.int_ = 8; var = d.get ()" 8 -explicit
+CompileExpression::test "d |= a; var = d.get ()" 9 -explicit
+CompileExpression::test "d |= 16; var = d.get ()" 25 -explicit
+
+CompileExpression::test "d.int_ = 9; var = d.get ()" 9 -explicit
+CompileExpression::test "d ^= 2; var = d.get ()" 11 -explicit
+CompileExpression::test "d ^= d; var = d.get ()" 0 -explicit
+
+CompileExpression::test "d.int_ = 10; var = d.get ()" 10 -explicit
+CompileExpression::test "d << 2" 40
+CompileExpression::test "d << a" 20
+CompileExpression::test "1 << b" 4
+
+CompileExpression::test "d.int_ = 12; var = d.get ()" 12 -explicit
+CompileExpression::test "d >> 2" 3
+CompileExpression::test "d >> a" 6
+CompileExpression::test "10 >> a" 5
+
+CompileExpression::test "d.int_ = 13; var = d.get ()" 13 -explicit
+CompileExpression::test "d <<= 2; var = d.get ()" 52 -explicit
+CompileExpression::test "d <<= a; var = d.get ()" 104 -explicit
+
+CompileExpression::test "d.int_ = 14; var = d.get ()" 14 -explicit
+CompileExpression::test "d >>= 2; var = d.get ()" 3 -explicit
+CompileExpression::test "d >>= a; var = d.get ()" 1 -explicit
+
+CompileExpression::test "d.int_ = 1013; var = d.get ()" 1013 -explicit
+CompileExpression::test "d == 2" {(0|false)}
+CompileExpression::test "d == d" {(1|true)}
+CompileExpression::test "1 == d" {(0|false)}
+
+CompileExpression::test "d.int_ = 1014; var = d.get ()" 1014 -explicit
+CompileExpression::test "d != 2" {(1|true)}
+CompileExpression::test "d != d" {(0|false)}
+CompileExpression::test "1014 == d" {(1|true)}
+
+CompileExpression::test "d.int_ = 15; var = d.get ()" 15 -explicit
+CompileExpression::test "d < 2" {(0|false)}
+CompileExpression::test "a < d" {(1|true)}
+CompileExpression::test "16 < d" {(0|false)}
+
+CompileExpression::test "d.int_ = 16; var = d.get ()" 16 -explicit
+CompileExpression::test "d > 2" {(1|true)}
+CompileExpression::test "d < a" {(0|false)}
+CompileExpression::test "15 < d" {(1|true)}
+
+CompileExpression::test "d.int_ = 17; var = d.get ()" 17 -explicit
+CompileExpression::test "d <= 2" {(0|false)}
+CompileExpression::test "a <= d" {(1|true)}
+CompileExpression::test "18 <= d" {(0|false)}
+
+CompileExpression::test "d.int_ = 18; var = d.get ()" 18 -explicit
+CompileExpression::test "d >= 2" {(1|true)}
+CompileExpression::test "d <= a" {(0|false)}
+CompileExpression::test "15 <= d" {(1|true)}
+
+CompileExpression::test "d.int_ = 19; var = d.get ()" 19 -explicit
+CompileExpression::test "!d" {(0|false)}
+
+CompileExpression::test "d.int_ = 20; var = d.get ()" 20 -explicit
+CompileExpression::test "d && 0" {(0|false)}
+CompileExpression::test "d && a" {(1|true)}
+CompileExpression::test "0 && d" {(0|false)}
+
+CompileExpression::test "d.int_ = 21; var = d.get ()" 21 -explicit
+CompileExpression::test "d || 0" {(1|true)}
+CompileExpression::test "d || a" {(1|true)}
+CompileExpression::test "0 || d" {(1|true)}
+
+CompileExpression::test "d.int_ = 22; var = d.get ()" 22 -explicit
+CompileExpression::test "(d++).get ()" 22 -noprint
+CompileExpression::test "(d++).get ()" 23 -nocode
+CompileExpression::test "d.get ()" 24 -name "get value of post-incr d"
+CompileExpression::test "(++d).get ()" 25 -noprint
+CompileExpression::test "(++d).get ()" 26 -nocode
+
+CompileExpression::test "d.int_ = 23; var = d.get ()" 23 -explicit
+CompileExpression::test "(d--).get ()" 23 -noprint
+CompileExpression::test "(d--).get ()" 22 -nocode
+CompileExpression::test "d.get ()" 21 -name "get value of post-decr d"
+CompileExpression::test "(--d).get ()" 20 -noprint
+CompileExpression::test "(--d).get ()" 19 -nocode
+
+CompileExpression::test "d.int_ = 24; var = d.get ()" 24 -explicit
+CompileExpression::test "(a,d).get ()" 1
+CompileExpression::test "(d,a).get ()" 24
+
+CompileExpression::test "d.int_ = 25; var = d.get ()" 25 -explicit
+CompileExpression::test "d->*3" 28
+CompileExpression::test "d->*b" 27 "d->*b 1"
+
+CompileExpression::test "d.int_ = 26; var = d.get ()" 26 -explicit
+CompileExpression::test "d->*4" 30
+CompileExpression::test "d->*b" 28 "d->*b 2"
+
+CompileExpression::test "d.pub_var = 1; var = d.pub_var" 1 -explicit
+CompileExpression::test "d->pub_var" -21
+
+# "'d' cannot be used as function"
+ CompileExpression::test "d.int_ = 27; var = d.get ()" 27 -explicit
+ CompileExpression::test "d ()" -27
+ CompileExpression::test "d (3)" 30
+ CompileExpression::test "a (b)" 3
+
+CompileExpression::test "d.int_ = 28; var = d.get ()" 28 -explicit
+CompileExpression::test "d\[10\]" 18
+CompileExpression::test "d\[b\]" 26
+
+# "unable to find XYZ literal operator 'operator""_MI'"
+ CompileExpression::test "10_MI" 100
+ CompileExpression::test "'c'_MI" 200
+ CompileExpression::test "\"foo\"_MI" 300
+
+# crash
+ CompileExpression::test \
+ "MyInteger *myint_ptr = new MyInteger (1); var = myint_ptr->pub_var" \
+ 1234 -explicit
+
+CompileExpression::test "d.int_ = 29; var = d.int_" 29 -explicit
+CompileExpression::test "ch = d; var = ch;" 29 -explicit
+CompileExpression::test "char a_char = d; var = a_char - 9" 20 -explicit
+
+CompileExpression::test "d.int_ = 30; var = d.int_" 30 -explicit
+CompileExpression::test "d" {(-30|{pub_var = 1, int_ = 30})}
+CompileExpression::test "int integer = d; var = integer - 10" -40 -explicit
diff --git a/gdb/testsuite/lib/compile-support.exp b/gdb/testsuite/lib/compile-support.exp
new file mode 100644
index 00000000000..935ea5522f6
--- /dev/null
+++ b/gdb/testsuite/lib/compile-support.exp
@@ -0,0 +1,208 @@
+# Copyright 2015, 2016 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.
+# 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.
+#
+# Otherwise, all expressions are considered implicit.
+#
+# Pass -value, -compile, and/or -print to indicate that the value,
+# compile, or print steps will optionally fail. Specify "xfail" or
+# "kfail" to indicate how each particular step will fail. These may be
+# followed by any accepted DejaGNU parameters such as architecture and
+# bug#.
+#
+# -compile and -value are used when a "code" test is run, the former
+# specifying that the "compile code" command (to GDB) will fail or pass
+# in the prescribed manner. -value indicates that the "print $VARIABLE"
+# command (to GDB) will fail in the prescribed manner.
+#
+# -print is used to specify that an expression will fail in the presribed
+# 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 {{compile {"" ""}} {value {"" ""}} {print {"" ""}} {name ""}
+ {noprint} {nocode} {explicit}}
+
+ 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.
+ }
+ }
+ }
+}
diff --git a/include/gcc-cp-fe.def b/include/gcc-cp-fe.def
new file mode 100644
index 00000000000..c367c1db1eb
--- /dev/null
+++ b/include/gcc-cp-fe.def
@@ -0,0 +1,1050 @@
+/* Interface between GCC C++ FE and GDB -*- c -*-
+
+ Copyright (C) 2014-2017 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ 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/>. */
+
+
+
+/* Push namespace NAME as the current binding level, to which
+ newly-introduced decls will be bound. An empty string identifies
+ the global namespace, whereas NULL identifies an anonymous
+ namespace. A namespace named NAME is created in the current scope,
+ if needed.
+
+ If the newly-created namespace is to be an inline namespace, see
+ make_namespace_inline. */
+
+GCC_METHOD1 (int /* bool */, push_namespace,
+ const char *) /* Argument NAME. */
+
+/* Push TYPE as the current binding level, making its members visible
+ for name lookup. The current scope before the call must be the
+ scope in which the class was declared. This should be used if the
+ definition of a class is already finished, but one wishes to define
+ a nested class, or to enter the scope of one of its member
+ functions. */
+
+GCC_METHOD1 (int /* bool */, push_class,
+ gcc_type) /* Argument TYPE. */
+
+/* Push FUNCTION_DECL as the current (empty) binding level (see
+ reactivate_decl). The current enclosing scope before the call must
+ be the scope in which the function was declared. */
+
+GCC_METHOD1 (int /* bool */, push_function,
+ gcc_decl) /* Argument FUNCTION_DECL. */
+
+/* Make DECL visible (again?) within SCOPE. When SCOPE is NULL, it
+ means the current scope; if it is not NULL, it must name a function
+ that is currently active, even if not at the top of the binding
+ chain.
+
+ This function can be used to make e.g. a global function or
+ variable visible in a namespace or local scope (overriding another
+ enclosing definition of the same name), but its most common
+ expected use of this primitive, that gives it its name, is to make
+ declarations visible again after reentering a function scope,
+ because when a function is entered with push_function, that does
+ NOT make any of the declarations nested in it visible for name
+ lookup.
+
+ There is a reason/excuse for that: unlike namespaces and classes,
+ G++ doesn't ever have to reenter function scopes, so its name
+ resolution infrastructure is not prepared to do that. But wait,
+ there is also a good use for this apparent limitation: a function
+ may contain multiple scopes (blocks), and the name may be bound to
+ different symbols in each of these scopes. With this interface, as
+ we reenter a function scope, we may choose which symbols to make
+ visible for the code snippet, or, if there could be template
+ functions in local scopes, for unresolved names in nested template
+ class default arguments, or in nested template function signatures.
+
+ As for making a local declaration visible for the code snippet,
+ there are two possibilities: a) introduce it upfront, while
+ entering the scope for the user expression (see the enter_scope
+ callback, called by g++ when encountering the push_user_expression
+ pragma), which might save some scope switching and reactivate_decl
+ (though this can't be helped if some declarations have to be
+ introduced and discarded, because of multiple definitions of the
+ same name in different scopes within a function: they have to be
+ defined in discriminator order); or b) introduce it when its name
+ is looked up, entering the scope, introducing the declaration,
+ leaving the scope, and then reactivating the declaration in its
+ local scope.
+
+ Here's some more detail on how reactivate_decl works. Say there's
+ a function foo whose body looks like this:
+
+ {
+ {
+// point 1
+ class c {} o __attribute__ ((__used__)); // c , o
+ }
+ struct c {
+ void f() {
+// point 2
+ }
+ } o __attribute__ ((__used__)); // c_0, o_0
+ {
+ class c {} p __attribute__ ((__used__)); // c_1, p
+// point 3
+ o.f();
+ }
+ }
+
+ When we are about to define class c at point 1, we enter the
+ function foo scope, and since no symbols are visible at point 1, we
+ proceed to declare class c. We may then define the class right
+ away, or, if we leave the function scope, and we later wish to
+ define it, or to define object o, we can reenter the scope and just
+ use the previously-obtained gcc_decl to define the class, without
+ having to reactivate the declaration.
+
+ Now, if we are to set up the binding context for point 2, we have
+ to define c_0::f, and in order to do so, we have to declare and
+ define c_0. Before we can declare c_0, we MUST at least declare c.
+
+ As a general rule, before we can declare or define any local name
+ with a discriminator, we have to at least declare any other
+ occurrences of the same name in the same enclosing entity with
+ lower or absent discriminator.
+
+ So, we declare c, then we leave the function scope and reenter it
+ so as to declare c_0 (also with name "c", which is why we have to
+ leave and reenter the function scope, otherwise we would get an
+ error because of the duplicate definition; g++ will assign a
+ discriminator because it still remembers there was an earlier
+ declaration of c_0 within the function, it's just no longer in
+ scope), then we can define c_0, including its member function f.
+
+ Likewise, if we wish to define o_0, we have to define o first. If
+ we wish to declare (and maybe then define) c_1, we have to at least
+ declare (c and then) c_0 first.
+
+ Then, as we set up the binding context to compile a code snippet at
+ point 3, we may choose to activate c_1, o_0 and p upfront,
+ declaring and discarding c, c_0 and o, and then reentering the
+ funciton scope to declare c_1, o_0 and p; or we can wait for oracle
+ lookups of c, o or p. If c is looked up, and the debugger resolves
+ c in the scope to c_1, it is expected to enter the function scope
+ from the top level, declare c, leave it, reenter it, declare c_0,
+ leave it, reenter it, declare c_1, leave it, and then reactivate
+ c_1 in the function scope. If c_1 is needed as a complete type,
+ the definition may be given right after the declaration, or the
+ scope will have to be reentered in order to define the class.
+
+. If the code snippet is at point 2, we don't need to (re)activate
+ any declaration: nothing from any local scope is visible. Just
+ entering the scope of the class containing member function f
+ reactivates the names of its members, including the class name
+ itself. */
+
+GCC_METHOD2 (int /* bool */, reactivate_decl,
+ gcc_decl, /* Argument DECL. */
+ gcc_decl) /* Argument SCOPE. */
+
+/* Pop the namespace last entered with push_namespace, or class last
+ entered with push_class, or function last entered with
+ push_function, restoring the binding level in effect before the
+ matching push_* call. */
+
+GCC_METHOD0 (int /* bool */, pop_binding_level)
+
+/* Return the NAMESPACE_DECL, TYPE_DECL or FUNCTION_DECL of the
+ binding level that would be popped by pop_scope. */
+
+GCC_METHOD0 (gcc_decl, get_current_binding_level_decl)
+
+/* Make the current binding level an inline namespace. It must be a
+ namespace to begin with. It is safe to call this more than once
+ for the same namespace, but after the first call, subsequent ones
+ will not return a success status. */
+
+GCC_METHOD0 (int /* bool */, make_namespace_inline)
+
+/* Add USED_NS to the namespaces used by the current binding level.
+ Use get_current_binding_level_decl to obtain USED_NS's
+ gcc_decl. */
+
+GCC_METHOD1 (int /* bool */, add_using_namespace,
+ gcc_decl) /* Argument USED_NS. */
+
+/* Introduce a namespace alias declaration, as in:
+
+ namespace foo = [... ::] bar;
+
+ After this call, namespace TARGET will be visible as ALIAS within
+ the current namespace. Get the declaration for TARGET by calling
+ get_current_binding_level_decl after pushing into it. */
+
+GCC_METHOD2 (int /* bool */, add_namespace_alias,
+ const char *, /* Argument ALIAS. */
+ gcc_decl) /* Argument TARGET. */
+
+/* Introduce a using declaration, as in:
+
+ using foo::bar;
+
+ The TARGET decl names the qualifying scope (foo:: above) and the
+ identifier (bar), but that does not mean that only TARGET will be
+ brought into the current scope: all bindings of TARGET's identifier
+ in the qualifying scope will be brought in.
+
+ FLAGS should specify GCC_CP_SYMBOL_USING. If the current scope is
+ a class scope, visibility flags must be supplied.
+
+ Even when TARGET is template dependent, we don't need to specify
+ whether or not it is a typename: the supplied declaration (that
+ could be a template-dependent type converted to declaration by
+ get_type_decl) indicates so. */
+
+GCC_METHOD2 (int /* bool */, add_using_decl,
+ enum gcc_cp_symbol_kind, /* Argument FLAGS. */
+ gcc_decl) /* Argument TARGET. */
+
+/* Create a new "decl" in GCC, and bind it in the current binding
+ level. A decl is a declaration, basically a kind of symbol.
+
+ NAME is the name of the new symbol. SYM_KIND is the kind of
+ symbol being requested. SYM_TYPE is the new symbol's C++ type;
+ except for labels, where this is not meaningful and should be
+ zero. If SUBSTITUTION_NAME is not NULL, then a reference to this
+ decl in the source will later be substituted with a dereference
+ of a variable of the given name. Otherwise, for symbols having
+ an address (e.g., functions), ADDRESS is the address. FILENAME
+ and LINE_NUMBER refer to the symbol's source location. If this
+ is not known, FILENAME can be NULL and LINE_NUMBER can be 0.
+ This function returns the new decl.
+
+ Use this function to register typedefs, functions and variables to
+ namespace and local binding levels, and typedefs, member functions
+ (static or not), and static data members to class binding levels.
+ Class members must have their access controls specified with
+ GCC_CP_ACCESS_* flags in SYM_KIND.
+
+ Note that, since access controls are disabled, we have no means to
+ express private, protected and public.
+
+ There are various flags that can be set in SYM_KIND to specify
+ additional semantics. Look for GCC_CP_FLAGs in the definition of
+ enum gcc_cp_symbol_kind in gcc-cp-interface.h.
+
+ In order to define member functions, pass GCC_CP_SYMBOL_FUNCTION in
+ SYM_KIND, and a function_type for static member functions or a
+ method type for non-static member functions, including constructors
+ and destructors. Use build_function_type to create a function
+ type; for a method type, start by creating a function type without
+ any compiler-introduced artificial arguments (the implicit this
+ pointer, and the __in_chrg added to constructors and destructors,
+ and __vtt_parm added to the former), and then use build_method_type
+ to create the method type out of the class type and the function
+ type.
+
+ For operator functions, set GCC_CP_FLAG_SPECIAL_FUNCTION in
+ SYM_KIND, in addition to any other applicable flags, and pass as
+ NAME a string starting with the two-character mangling for operator
+ name: "ps" for unary plus, "mL" for multiply and assign, *=; etc.
+ Use "cv" for type converstion operators (the target type portion
+ may be omitted, as it is taken from the return type in SYM_TYPE).
+ For operator"", use "li" followed by the identifier (the mangled
+ name mandates digits specifying the length of the identifier; if
+ present, they determine the end of the identifier, otherwise, the
+ identifier extents to the end of the string, so that "li3_Kme" and
+ "li_Km" are equivalent).
+
+ Constructors and destructors need special care, because for each
+ constructor and destructor there may be multiple clones defined
+ internally by the compiler. With build_decl, you can introduce the
+ base declaration of a constructor or a destructor, setting
+ GCC_CP_FLAG_SPECIAL_FUNCTION the flag and using names starting with
+ capital "C" or "D", respectively, followed by a digit (see below),
+ a blank, or NUL ('\0'). DO NOT supply an ADDRESS or a
+ SUBSTITUTION_NAME to build_decl, it would be meaningless (and
+ rejected) for the base declaration; use define_cdtor_clone to
+ introduce the address of each clone. For constructor templates,
+ declare the template with build_decl, and then, for each
+ specialization, introduce it with
+ build_function_template_specialization, and then define the
+ addresses of each of its clones with define_cdtor_clone.
+
+ NAMEs for GCC_CP_FLAG_SPECIAL_FUNCTION:
+
+ NAME meaning
+ C? constructor base declaration (? may be 1, 2, 4, blank or NUL)
+ D? destructor base declaration (? may be 0, 1, 2, 4, blank or NUL)
+ nw operator new
+ na operator new[]
+ dl operator delete
+ da operator delete[]
+ ps operator + (unary)
+ ng operator - (unary)
+ ad operator & (unary)
+ de operator * (unary)
+ co operator ~
+ pl operator +
+ mi operator -
+ ml operator *
+ dv operator /
+ rm operator %
+ an operator &
+ or operator |
+ eo operator ^
+ aS operator =
+ pL operator +=
+ mI operator -=
+ mL operator *=
+ dV operator /=
+ rM operator %=
+ aN operator &=
+ oR operator |=
+ eO operator ^=
+ ls operator <<
+ rs operator >>
+ lS operator <<=
+ rS operator >>=
+ eq operator ==
+ ne operator !=
+ lt operator <
+ gt operator >
+ le operator <=
+ ge operator >=
+ nt operator !
+ aa operator &&
+ oo operator ||
+ pp operator ++
+ mm operator --
+ cm operator ,
+ pm operator ->*
+ pt operator ->
+ cl operator ()
+ ix operator []
+ qu operator ?
+ cv operator <T> (conversion operator)
+ li<id> operator "" <id>
+
+ FIXME: How about attributes? */
+
+GCC_METHOD7 (gcc_decl, build_decl,
+ const char *, /* Argument NAME. */
+ enum gcc_cp_symbol_kind, /* Argument SYM_KIND. */
+ gcc_type, /* Argument SYM_TYPE. */
+ const char *, /* Argument SUBSTITUTION_NAME. */
+ gcc_address, /* Argument ADDRESS. */
+ const char *, /* Argument FILENAME. */
+ unsigned int) /* Argument LINE_NUMBER. */
+
+/* Supply the ADDRESS of one of the multiple clones of constructor or
+ destructor CDTOR. The clone is specified by NAME, using the
+ following name mangling conventions:
+
+ C1 in-charge constructor
+ C2 not-in-charge constructor
+ C4 unified constructor
+ D0 deleting destructor
+ D1 in-charge destructor
+ D2 not-in-charge destructor
+ D4 unified destructor
+
+ The following information is not necessary to use the API.
+
+ C1 initializes an instance of the class (rather than of derived
+ classes), including virtual base classes, whereas C2 initializes a
+ sub-object (of the given class type) of an instance of some derived
+ class (or a full object that doesn't have any virtual base
+ classes).
+
+ D0 and D1 destruct an instance of the class, including virtual base
+ classes, but only the former calls operator delete to release the
+ object's storage at the end; D2 destructs a sub-object (of the
+ given class type) of an instance of a derived class (or a full
+ object that doesn't have any virtual base classes).
+
+ The [CD]4 manglings (and symbol definitions) are non-standard, but
+ GCC uses them in some cases: rather than assuming they are
+ in-charge or not-in-charge, they test the implicit argument that
+ the others ignore to tell how to behave. These are used instead of
+ cloning when we just can't use aliases. */
+
+GCC_METHOD3 (gcc_decl, define_cdtor_clone,
+ const char *, /* Argument NAME. */
+ gcc_decl, /* Argument CDTOR. */
+ gcc_address) /* Argument ADDRESS. */
+
+/* Return the type associated with the given declaration. This is
+ most useful to obtain the type associated with a forward-declared
+ class, because it is the gcc_type, rather than the gcc_decl, that
+ has to be used to build other types, but build_decl returns a
+ gcc_decl rather than a gcc_type. This call can in theory be used
+ to obtain the type from any other declaration; it is supposed to
+ return the same type that was supplied when the declaration was
+ created. */
+
+GCC_METHOD1 (gcc_type, get_decl_type,
+ gcc_decl) /* Argument DECL. */
+
+/* Return the declaration for a type. */
+
+GCC_METHOD1 (gcc_decl, get_type_decl,
+ gcc_type) /* Argument TYPE. */
+
+/* Declare DECL as a friend of the current class scope, if TYPE is
+ NULL, or of TYPE itself otherwise. DECL may be a function or a
+ class, be they template generics, template specializations or not
+ templates. TYPE must be a class type (not a template generic).
+
+ The add_friend call cannot introduce a declaration; even if the
+ friend is first declared as a friend in the source code, the
+ declaration belongs in the enclosing namespace, so it must be
+ introduced in that namespace, and the resulting declaration can
+ then be made a friend.
+
+ DECL cannot, however, be a member of a template class generic,
+ because we have no means to introduce their declarations. This
+ interface has no notion of definitions for template generics. As a
+ consequence, users of this interface must introduce each friend
+ template member specialization separately, i.e., instead of:
+
+ template <typename T> friend struct X<T>::M;
+
+ they must be declared as if they were:
+
+ friend struct X<onetype>::M;
+ friend struct X<anothertype>::M;
+ ... for each specialization of X.
+
+
+ Specializations of a template can have each others' members as
+ friends:
+
+ template <typename T> class foo {
+ int f();
+ template <typename U> friend int foo<U>::f();
+ };
+
+ It wouldn't always be possible to define all specializations of a
+ template class before introducing the friend declarations in their
+ expanded, per-specialization form.
+
+ In order to simplify such friend declarations, and to enable
+ incremental friend declarations as template specializations are
+ introduced, add_friend can be called after the befriending class is
+ fully defined, passing it a non-NULL TYPE argument naming the
+ befriending class type. */
+
+GCC_METHOD2 (int /* bool */, add_friend,
+ gcc_decl, /* Argument DECL. */
+ gcc_type) /* Argument TYPE. */
+
+/* Return the type of a pointer to a given base type. */
+
+GCC_METHOD1 (gcc_type, build_pointer_type,
+ gcc_type) /* Argument BASE_TYPE. */
+
+/* Return the type of a reference to a given base type. */
+
+GCC_METHOD2 (gcc_type, build_reference_type,
+ gcc_type, /* Argument BASE_TYPE. */
+ enum gcc_cp_ref_qualifiers) /* Argument RQUALS. */
+
+/* Create a new pointer-to-member type. MEMBER_TYPE is the data
+ member type, while CLASS_TYPE is the class type containing the data
+ member. For pointers to member functions, MEMBER_TYPE must be a
+ method type, and CLASS_TYPE must be specified even though it might
+ be possible to extract it from the method type. */
+
+GCC_METHOD2 (gcc_type, build_pointer_to_member_type,
+ gcc_type, /* Argument CLASS_TYPE. */
+ gcc_type) /* Argument MEMBER_TYPE. */
+
+/* Start a template parameter list scope and enters it, so that
+ subsequent build_type_template_parameter and
+ build_value_template_parameter calls create template parameters in
+ the list. The list is closed by a build_decl call with
+ GCC_CP_SYMBOL_FUNCTION or GCC_CP_SYMBOL_CLASS, that, when the scope
+ is a template parameter list, declares a template function or a
+ template class with the then-closed parameter list. The scope in
+ which the new declaration is to be introduced by build_decl must be
+ entered before calling start_template_decl, and build_decl returns
+ to that scope, from the template parameter list scope, before
+ introducing the declaration. */
+
+GCC_METHOD0 (int /* bool */, start_template_decl)
+
+/* Build a typename template-parameter (e.g., the T in template
+ <typename T = X>). Either PACK_P should be nonzero, to indicate an
+ argument pack (the last argument in a variadic template argument
+ list, as in template <typename... T>), or DEFAULT_TYPE may be
+ non-NULL to set the default type argument (e.g. X) for the template
+ parameter. FILENAME and LINE_NUMBER may specify the source
+ location in which the template parameter was declared. */
+
+GCC_METHOD5 (gcc_type, build_type_template_parameter,
+ const char *, /* Argument ID. */
+ int /* bool */, /* Argument PACK_P. */
+ gcc_type, /* Argument DEFAULT_TYPE. */
+ const char *, /* Argument FILENAME. */
+ unsigned int) /* Argument LINE_NUMBER. */
+
+/* Build a template template-parameter (e.g., the T in template
+ <template <[...]> class T = X>). DEFAULT_TEMPL may be non-NULL to
+ set the default type-template argument (e.g. X) for the template
+ template parameter. FILENAME and LINE_NUMBER may specify the
+ source location in which the template parameter was declared. */
+
+GCC_METHOD5 (gcc_utempl, build_template_template_parameter,
+ const char *, /* Argument ID. */
+ int /* bool */, /* Argument PACK_P. */
+ gcc_utempl, /* Argument DEFAULT_TEMPL. */
+ const char *, /* Argument FILENAME. */
+ unsigned int) /* Argument LINE_NUMBER. */
+
+/* Build a value template-parameter (e.g., the V in template <typename
+ T, T V> or in template <int V = X>). DEFAULT_VALUE may be non-NULL
+ to set the default value argument for the template parameter (e.g.,
+ X). FILENAME and LINE_NUMBER may specify the source location in
+ which the template parameter was declared. */
+
+GCC_METHOD5 (gcc_decl, build_value_template_parameter,
+ gcc_type, /* Argument TYPE. */
+ const char *, /* Argument ID. */
+ gcc_expr, /* Argument DEFAULT_VALUE. */
+ const char *, /* Argument FILENAME. */
+ unsigned int) /* Argument LINE_NUMBER. */
+
+/* Build a template-dependent typename (e.g., typename T::bar or
+ typename T::template bart<X>). ENCLOSING_TYPE should be the
+ template-dependent nested name specifier (e.g., T), ID should be
+ the name of the member of the ENCLOSING_TYPE (e.g., bar or bart),
+ and TARGS should be non-NULL and specify the template arguments
+ (e.g. <X>) iff ID is to name a class template.
+
+ In this and other calls, a template-dependent nested name specifier
+ may be a template class parameter (build_type_template_parameter),
+ a specialization (returned by build_dependent_type_template_id) of
+ a template template parameter (returned by
+ build_template_template_parameter) or a member type thereof
+ (returned by build_dependent_typename itself). */
+
+GCC_METHOD3 (gcc_type, build_dependent_typename,
+ gcc_type, /* Argument ENCLOSING_TYPE. */
+ const char *, /* Argument ID. */
+ const struct gcc_cp_template_args *) /* Argument TARGS. */
+
+/* Build a template-dependent class template (e.g., T::template bart).
+ ENCLOSING_TYPE should be the template-dependent nested name
+ specifier (e.g., T), ID should be the name of the class template
+ member of the ENCLOSING_TYPE (e.g., bart). */
+
+GCC_METHOD2 (gcc_utempl, build_dependent_class_template,
+ gcc_type, /* Argument ENCLOSING_TYPE. */
+ const char *) /* Argument ID. */
+
+/* Build a template-dependent type template-id (e.g., T<A>).
+ TEMPLATE_DECL should be a template template parameter (e.g., the T
+ in template <template <[...]> class T = X>), and TARGS should
+ specify the template arguments (e.g. <A>). */
+
+GCC_METHOD2 (gcc_type, build_dependent_type_template_id,
+ gcc_utempl, /* Argument TEMPLATE_DECL. */
+ const struct gcc_cp_template_args *) /* Argument TARGS. */
+
+/* Build a template-dependent expression (e.g., S::val or S::template
+ mtf<X>, or unqualified f or template tf<X>).
+
+ ENCLOSING_SCOPE should be a template-dependent nested name
+ specifier (e.g., T), a resolved namespace or class decl, or NULL
+ for unqualified names; ID should be the name of the member of the
+ ENCLOSING_SCOPE (e.g., val or mtf) or unqualified overloaded
+ function; and TARGS should list template arguments (e.g. <X>) when
+ mtf or tf are to name a template function, or be NULL otherwise.
+
+ Unqualified names and namespace- or class-qualified names can only
+ resolve to overloaded functions, to be used in contexts that
+ involve overload resolution that cannot be resolved because of
+ template-dependent argument or return types, such as call
+ expressions with template-dependent arguments, conversion
+ expressions to function types with template-dependent argument
+ types or the like. Other cases of unqualified or
+ non-template-dependent-qualified names should NOT use this
+ function, and use decl_expr to convert the appropriate function or
+ object declaration to an expression.
+
+ If ID is the name of a special member function, FLAGS should be
+ GCC_CP_SYMBOL_FUNCTION|GCC_CP_FLAG_SPECIAL_FUNCTION, and ID should
+ be one of the encodings for special member functions documented in
+ build_decl. Otherwise, FLAGS should be GCC_CP_SYMBOL_MASK, which
+ suggests the symbol kind is not known (though we know it is not a
+ type).
+
+ If ID denotes a conversion operator, CONV_TYPE should name the
+ target type of the conversion. Otherwise, CONV_TYPE must be
+ NULL. */
+
+GCC_METHOD5 (gcc_expr, build_dependent_expr,
+ gcc_decl, /* Argument ENCLOSING_SCOPE. */
+ enum gcc_cp_symbol_kind, /* Argument FLAGS. */
+ const char *, /* Argument NAME. */
+ gcc_type, /* Argument CONV_TYPE. */
+ const struct gcc_cp_template_args *) /* Argument TARGS. */
+
+/* Build a gcc_expr for the value VALUE in type TYPE. */
+
+GCC_METHOD2 (gcc_expr, build_literal_expr,
+ gcc_type, /* Argument TYPE. */
+ unsigned long) /* Argument VALUE. */
+
+/* Build a gcc_expr that denotes DECL, the declaration of a variable
+ or function in namespace scope, or of a static member variable or
+ function. Use QUALIFIED_P to build the operand of unary & so as to
+ compute a pointer-to-member, rather than a regular pointer. */
+
+GCC_METHOD2 (gcc_expr, build_decl_expr,
+ gcc_decl, /* Argument DECL. */
+ int /* bool */) /* Argument QUALIFIED_P. */
+
+/* Build a gcc_expr that denotes the unary operation UNARY_OP applied
+ to the gcc_expr OPERAND. For non-expr operands, see
+ unary_type_expr. Besides the UNARY_OP encodings used for operator
+ names, we support "pp_" for preincrement, and "mm_" for
+ predecrement, "nx" for noexcept, "tw" for throw, "tr" for rethrow
+ (pass NULL as the operand), "te" for typeid, "sz" for sizeof, "az"
+ for alignof, "dl" for delete, "gsdl" for ::delete, "da" for
+ delete[], "gsda" for ::delete[], "sp" for pack expansion, "sZ" for
+ sizeof...(function argument pack). */
+
+GCC_METHOD2 (gcc_expr, build_unary_expr,
+ const char *, /* Argument UNARY_OP. */
+ gcc_expr) /* Argument OPERAND. */
+
+/* Build a gcc_expr that denotes the binary operation BINARY_OP
+ applied to gcc_exprs OPERAND1 and OPERAND2. Besides the BINARY_OP
+ encodings used for operator names, we support "ds" for the operator
+ token ".*" and "dt" for the operator token ".". When using
+ operators that take a name as their second operand ("." and "->")
+ use decl_expr to convert the gcc_decl of the member name to a
+ gcc_expr, if the member name wasn't created with
+ e.g. build_dependent_expr. */
+
+GCC_METHOD3 (gcc_expr, build_binary_expr,
+ const char *, /* Argument BINARY_OP. */
+ gcc_expr, /* Argument OPERAND1. */
+ gcc_expr) /* Argument OPERAND2. */
+
+/* Build a gcc_expr that denotes the ternary operation TERNARY_OP
+ applied to gcc_exprs OPERAND1, OPERAND2 and OPERAND3. The only
+ supported TERNARY_OP is "qu", for the "?:" operator. */
+
+GCC_METHOD4 (gcc_expr, build_ternary_expr,
+ const char *, /* Argument TERNARY_OP. */
+ gcc_expr, /* Argument OPERAND1. */
+ gcc_expr, /* Argument OPERAND2. */
+ gcc_expr) /* Argument OPERAND3. */
+
+/* Build a gcc_expr that denotes the unary operation UNARY_OP applied
+ to the gcc_type OPERAND. Supported unary operations taking types
+ are "ti" for typeid, "st" for sizeof, "at" for alignof, and "sZ"
+ for sizeof...(template argument pack). */
+
+GCC_METHOD2 (gcc_expr, build_unary_type_expr,
+ const char *, /* Argument UNARY_OP. */
+ gcc_type) /* Argument OPERAND. */
+
+/* Build a gcc_expr that denotes the binary operation BINARY_OP
+ applied to gcc_type OPERAND1 and gcc_expr OPERAND2. Use this for
+ all kinds of (single-argument) type casts ("dc", "sc", "cc", "rc"
+ for dynamic, static, const and reinterpret casts, respectively;
+ "cv" for functional or C-style casts). */
+
+GCC_METHOD3 (gcc_expr, build_cast_expr,
+ const char *, /* Argument BINARY_OP. */
+ gcc_type, /* Argument OPERAND1. */
+ gcc_expr) /* Argument OPERAND2. */
+
+/* Build a gcc_expr that denotes the conversion of an expression list
+ VALUES to TYPE, with ("tl") or without ("cv") braces, or a braced
+ initializer list of unspecified type (e.g., a component of another
+ braced initializer list; pass "il" for CONV_OP, and NULL for
+ TYPE). */
+
+GCC_METHOD3 (gcc_expr, build_expression_list_expr,
+ const char *, /* Argument CONV_OP. */
+ gcc_type, /* Argument TYPE. */
+ const struct gcc_cp_function_args *) /* Argument VALUES. */
+
+/* Build a gcc_expr that denotes a new ("nw") or new[] ("na")
+ expression of TYPE, with or without a GLOBAL_NS qualifier (prefix
+ the NEW_OP with "gs"), with or without PLACEMENT, with or without
+ INITIALIZER. If it's not a placement new, PLACEMENT must be NULL
+ (rather than a zero-length placement arg list). If there's no
+ specified initializer, INITIALIZER must be NULL; a zero-length arg
+ list stands for a default initializer. */
+
+GCC_METHOD4 (gcc_expr, build_new_expr,
+ const char *, /* Argument NEW_OP. */
+ const struct gcc_cp_function_args *, /* Argument PLACEMENT. */
+ gcc_type, /* Argument TYPE. */
+ const struct gcc_cp_function_args *) /* Argument INITIALIZER. */
+
+/* Return a call expression that calls CALLABLE with arguments ARGS.
+ CALLABLE may be a function, a callable object, a pointer to
+ function, an unresolved expression, an unresolved overload set, an
+ object expression combined with a member function overload set or a
+ pointer-to-member. If QUALIFIED_P, CALLABLE will be interpreted as
+ a qualified name, preventing virtual function dispatch. */
+
+GCC_METHOD3 (gcc_expr, build_call_expr,
+ gcc_expr, /* Argument CALLABLE. */
+ int /* bool */, /* Argument QUALIFIED_P. */
+ const struct gcc_cp_function_args *) /* Argument ARGS. */
+
+/* Return the type of the gcc_expr OPERAND.
+ Use this for decltype.
+ For decltype (auto), pass a NULL OPERAND.
+
+ Note: for template-dependent expressions, the result is NULL,
+ because the type is only computed when template argument
+ substitution is performed. */
+
+GCC_METHOD1 (gcc_type, get_expr_type,
+ gcc_expr) /* Argument OPERAND. */
+
+/* Introduce a specialization of a template function.
+
+ TEMPLATE_DECL is the template function, and TARGS are the arguments
+ for the specialization. ADDRESS is the address of the
+ specialization. FILENAME and LINE_NUMBER specify the source
+ location associated with the template function specialization. */
+
+GCC_METHOD5 (gcc_decl, build_function_template_specialization,
+ gcc_decl, /* Argument TEMPLATE_DECL. */
+ const struct gcc_cp_template_args *, /* Argument TARGS. */
+ gcc_address, /* Argument ADDRESS. */
+ const char *, /* Argument FILENAME. */
+ unsigned int) /* Argument LINE_NUMBER. */
+
+/* Specialize a template class as an incomplete type. A definition
+ can be supplied later, with start_class_type.
+
+ TEMPLATE_DECL is the template class, and TARGS are the arguments
+ for the specialization. FILENAME and LINE_NUMBER specify the
+ source location associated with the template class
+ specialization. */
+
+GCC_METHOD4 (gcc_decl, build_class_template_specialization,
+ gcc_decl, /* Argument TEMPLATE_DECL. */
+ const struct gcc_cp_template_args *, /* Argument TARGS. */
+ const char *, /* Argument FILENAME. */
+ unsigned int) /* Argument LINE_NUMBER. */
+
+/* Start defining a 'class', 'struct' or 'union' type, entering its
+ own binding level. Initially it has no fields.
+
+ TYPEDECL is the forward-declaration of the type, returned by
+ build_decl. BASE_CLASSES indicate the base classes of class NAME.
+ FILENAME and LINE_NUMBER specify the source location associated
+ with the class definition, should they be different from those of
+ the forward declaration. */
+
+GCC_METHOD4 (gcc_type, start_class_type,
+ gcc_decl, /* Argument TYPEDECL. */
+ const struct gcc_vbase_array *,/* Argument BASE_CLASSES. */
+ const char *, /* Argument FILENAME. */
+ unsigned int) /* Argument LINE_NUMBER. */
+
+/* Create a new closure class type, record it as the
+ DISCRIMINATOR-numbered closure type in the current scope (or
+ associated with EXTRA_SCOPE, if non-NULL), and enter the closure
+ type's own binding level. This primitive would sort of combine
+ build_decl and start_class_type, if they could be used to introduce
+ a closure type. Initially it has no fields.
+
+ FILENAME and LINE_NUMBER specify the source location associated
+ with the class. EXTRA_SCOPE, if non-NULL, must be a PARM_DECL of
+ the current function, or a FIELD_DECL of the current class. If it
+ is NULL, the current scope must be a function. */
+
+GCC_METHOD5 (gcc_type, start_closure_class_type,
+ int, /* Argument DISCRIMINATOR. */
+ gcc_decl, /* Argument EXTRA_SCOPE. */
+ enum gcc_cp_symbol_kind, /* Argument FLAGS. */
+ const char *, /* Argument FILENAME. */
+ unsigned int) /* Argument LINE_NUMBER. */
+
+/* Add a non-static data member to the most-recently-started
+ unfinished struct or union type. FIELD_NAME is the field's name.
+ FIELD_TYPE is the type of the field. BITSIZE and BITPOS indicate
+ where in the struct the field occurs. */
+
+GCC_METHOD5 (gcc_decl, build_field,
+ const char *, /* Argument FIELD_NAME. */
+ gcc_type, /* Argument FIELD_TYPE. */
+ enum gcc_cp_symbol_kind, /* Argument FIELD_FLAGS. */
+ unsigned long, /* Argument BITSIZE. */
+ unsigned long) /* Argument BITPOS. */
+
+/* After all the fields have been added to a struct, class or union,
+ the struct or union type must be "finished". This does some final
+ cleanups in GCC, and pops to the binding level that was in effect
+ before the matching start_class_type or
+ start_closure_class_type. */
+
+GCC_METHOD1 (int /* bool */, finish_class_type,
+ unsigned long) /* Argument SIZE_IN_BYTES. */
+
+/* Create a new 'enum' type, and record it in the current binding
+ level. The new type initially has no associated constants.
+
+ NAME is the enum name. FILENAME and LINE_NUMBER specify its source
+ location. */
+
+GCC_METHOD5 (gcc_type, start_enum_type,
+ const char *, /* Argument NAME. */
+ gcc_type, /* Argument UNDERLYING_INT_TYPE. */
+ enum gcc_cp_symbol_kind, /* Argument FLAGS. */
+ const char *, /* Argument FILENAME. */
+ unsigned int) /* Argument LINE_NUMBER. */
+
+/* Add a new constant to an enum type. NAME is the constant's name
+ and VALUE is its value. Returns a gcc_decl for the constant. */
+
+GCC_METHOD3 (gcc_decl, build_enum_constant,
+ gcc_type, /* Argument ENUM_TYPE. */
+ const char *, /* Argument NAME. */
+ unsigned long) /* Argument VALUE. */
+
+/* After all the constants have been added to an enum, the type must
+ be "finished". This does some final cleanups in GCC. */
+
+GCC_METHOD1 (int /* bool */, finish_enum_type,
+ gcc_type) /* Argument ENUM_TYPE. */
+
+/* Create a new function type. RETURN_TYPE is the type returned by
+ the function, and ARGUMENT_TYPES is a vector, of length NARGS, of
+ the argument types. IS_VARARGS is true if the function is
+ varargs. */
+
+GCC_METHOD3 (gcc_type, build_function_type,
+ gcc_type, /* Argument RETURN_TYPE. */
+ const struct gcc_type_array *,/* Argument ARGUMENT_TYPES. */
+ int /* bool */) /* Argument IS_VARARGS. */
+
+/* Create a variant of a function type with an exception
+ specification. FUNCTION_TYPE is a function or method type.
+ EXCEPT_TYPES is an array with the list of exception types. Zero as
+ the array length implies throw() AKA noexcept(true); NULL as the
+ pointer to gcc_type_array implies noexcept(false), which is almost
+ equivalent (but distinguishable by the compiler) to an unspecified
+ exception list. */
+
+GCC_METHOD2 (gcc_type, build_exception_spec_variant,
+ gcc_type, /* Argument FUNCTION_TYPE. */
+ const struct gcc_type_array *)/* Argument EXCEPT_TYPES. */
+
+/* Create a new non-static member function type. FUNC_TYPE is the
+ method prototype, without the implicit THIS pointer, added as a
+ pointer to the QUALS-qualified CLASS_TYPE. If CLASS_TYPE is NULL,
+ this creates a cv-qualified (member) function type not associated
+ with any specific class, as needed to support "typedef void f(int)
+ const;", which can later be used to declare member functions and
+ pointers to member functions. */
+
+GCC_METHOD4 (gcc_type, build_method_type,
+ gcc_type, /* Argument CLASS_TYPE. */
+ gcc_type, /* Argument FUNC_TYPE. */
+ enum gcc_cp_qualifiers, /* Argument QUALS. */
+ enum gcc_cp_ref_qualifiers) /* Argument RQUALS. */
+
+/* Return a declaration for the (INDEX - 1)th argument of
+ FUNCTION_DECL, i.e., for the first argument, use zero as the index.
+ If FUNCTION_DECL is a non-static member function, use -1 to get the
+ implicit THIS parameter. */
+
+GCC_METHOD2 (gcc_decl, get_function_parameter_decl,
+ gcc_decl, /* Argument FUNCTION_DECL. */
+ int) /* Argument INDEX. */
+
+/* Return a lambda expr that constructs an instance of CLOSURE_TYPE.
+ Only lambda exprs without any captures can be correctly created
+ through these mechanisms; that's all we need to support lambdas
+ expressions in default parameters, the only kind that may have to
+ be introduced through this interface. */
+
+GCC_METHOD1 (gcc_expr, build_lambda_expr,
+ gcc_type) /* Argument CLOSURE_TYPE. */
+
+/* Return an integer type with the given properties. If BUILTIN_NAME
+ is non-NULL, it must name a builtin integral type with the given
+ signedness and size, and that is the type that will be returned. */
+
+GCC_METHOD3 (gcc_type, get_int_type,
+ int /* bool */, /* Argument IS_UNSIGNED. */
+ unsigned long, /* Argument SIZE_IN_BYTES. */
+ const char *) /* Argument BUILTIN_NAME. */
+
+/* Return the 'char' type, a distinct type from both 'signed char' and
+ 'unsigned char' returned by int_type. */
+
+GCC_METHOD0 (gcc_type, get_char_type)
+
+/* Return a floating point type with the given properties. If BUILTIN_NAME
+ is non-NULL, it must name a builtin integral type with the given
+ signedness and size, and that is the type that will be returned. */
+
+GCC_METHOD2 (gcc_type, get_float_type,
+ unsigned long, /* Argument SIZE_IN_BYTES. */
+ const char *) /* Argument BUILTIN_NAME. */
+
+/* Return the 'void' type. */
+
+GCC_METHOD0 (gcc_type, get_void_type)
+
+/* Return the 'bool' type. */
+
+GCC_METHOD0 (gcc_type, get_bool_type)
+
+/* Return the std::nullptr_t type. */
+
+GCC_METHOD0 (gcc_type, get_nullptr_type)
+
+/* Return the nullptr constant. */
+
+GCC_METHOD0 (gcc_expr, get_nullptr_constant)
+
+/* Create a new array type. If NUM_ELEMENTS is -1, then the array
+ is assumed to have an unknown length. */
+
+GCC_METHOD2 (gcc_type, build_array_type,
+ gcc_type, /* Argument ELEMENT_TYPE. */
+ int) /* Argument NUM_ELEMENTS. */
+
+/* Create a new array type. NUM_ELEMENTS is a template-dependent
+ expression. */
+
+GCC_METHOD2 (gcc_type, build_dependent_array_type,
+ gcc_type, /* Argument ELEMENT_TYPE. */
+ gcc_expr) /* Argument NUM_ELEMENTS. */
+
+/* Create a new variably-sized array type. UPPER_BOUND_NAME is the
+ name of a local variable that holds the upper bound of the array;
+ it is one less than the array size. */
+
+GCC_METHOD2 (gcc_type, build_vla_array_type,
+ gcc_type, /* Argument ELEMENT_TYPE. */
+ const char *) /* Argument UPPER_BOUND_NAME. */
+
+/* Return a qualified variant of a given base type. QUALIFIERS says
+ which qualifiers to use; it is composed of or'd together
+ constants from 'enum gcc_cp_qualifiers'. */
+
+GCC_METHOD2 (gcc_type, build_qualified_type,
+ gcc_type, /* Argument UNQUALIFIED_TYPE. */
+ enum gcc_cp_qualifiers) /* Argument QUALIFIERS. */
+
+/* Build a complex type given its element type. */
+
+GCC_METHOD1 (gcc_type, build_complex_type,
+ gcc_type) /* Argument ELEMENT_TYPE. */
+
+/* Build a vector type given its element type and number of
+ elements. */
+
+GCC_METHOD2 (gcc_type, build_vector_type,
+ gcc_type, /* Argument ELEMENT_TYPE. */
+ int) /* Argument NUM_ELEMENTS. */
+
+/* Build a constant. NAME is the constant's name and VALUE is its
+ value. FILENAME and LINE_NUMBER refer to the type's source
+ location. If this is not known, FILENAME can be NULL and
+ LINE_NUMBER can be 0. */
+
+GCC_METHOD5 (int /* bool */, build_constant,
+ gcc_type, /* Argument TYPE. */
+ const char *, /* Argument NAME. */
+ unsigned long, /* Argument VALUE. */
+ const char *, /* Argument FILENAME. */
+ unsigned int) /* Argument LINE_NUMBER. */
+
+/* Emit an error and return an error type object. */
+
+GCC_METHOD1 (gcc_type, error,
+ const char *) /* Argument MESSAGE. */
+
+/* Declare a static_assert with the given CONDITION and ERRORMSG at
+ FILENAME:LINE_NUMBER. */
+
+GCC_METHOD4 (int /* bool */, add_static_assert,
+ gcc_expr, /* Argument CONDITION. */
+ const char *, /* Argument ERRORMSG. */
+ const char *, /* Argument FILENAME. */
+ unsigned int) /* Argument LINE_NUMBER. */
+
+#if 0
+
+/* FIXME: We don't want to expose the internal implementation detail
+ that default parms are stored in function types, and it's not clear
+ how this or other approaches would interact with the type sharing
+ of e.g. ctor clones, so we're leaving this out, since default args
+ are not even present in debug information anyway. Besides, the set
+ of default args for a function may grow within its scope, and vary
+ independently in other scopes. */
+
+/* Create a modified version of a function type that has default
+ values for some of its arguments. The returned type should ONLY be
+ used to define functions or methods, never to declare parameters,
+ variables, types or the like.
+
+ DEFAULTS must have at most as many N_ELEMENTS as there are
+ arguments without default values in FUNCTION_TYPE. Say, if
+ FUNCTION_TYPE has an argument list such as (T1, T2, T3, T4 = V0)
+ and DEFAULTS has 2 elements (V1, V2), the returned type will have
+ the following argument list: (T1, T2 = V1, T3 = V2, T4 = V0).
+
+ Any NULL expressions in DEFAULTS will be marked as deferred, and
+ they should be filled in with set_deferred_function_default_args. */
+
+GCC_METHOD2 (gcc_type, add_function_default_args,
+ gcc_type, /* Argument FUNCTION_TYPE. */
+ const struct gcc_cp_function_args *) /* Argument DEFAULTS. */
+
+/* Fill in the first deferred default args in FUNCTION_DECL with the
+ expressions given in DEFAULTS. This can be used when the
+ declaration of a parameter is needed to create a default
+ expression, such as taking the size of an earlier parameter, or
+ building a lambda expression in the parameter's context. */
+
+GCC_METHOD2 (int /* bool */, set_deferred_function_default_args,
+ gcc_decl, /* Argument FUNCTION_DECL. */
+ const struct gcc_cp_function_args *) /* Argument DEFAULTS. */
+
+#endif
+
+
+/* When you add entry points, add them at the end, so that the new API
+ version remains compatible with the old version.
+
+ The following conventions have been observed as to naming entry points:
+
+ - build_* creates (and maybe records) something and returns it;
+ - add_* creates and records something, but doesn't return it;
+ - get_* obtains something without creating it;
+ - start_* marks the beginning of a compound (type, list, ...);
+ - finish_* completes the compound when needed.
+
+ Entry points that return an int (bool) and don't have a return value
+ specification return nonzero (true) on success and zero (false) on
+ failure. This is in line with libcc1's conventions of returning a
+ zero-initialized value in case of e.g. a transport error. */
diff --git a/include/gcc-cp-interface.h b/include/gcc-cp-interface.h
new file mode 100644
index 00000000000..6ef9e22f50c
--- /dev/null
+++ b/include/gcc-cp-interface.h
@@ -0,0 +1,496 @@
+/* Interface between GCC C++ FE and GDB
+
+ Copyright (C) 2014-2017 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ 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 GCC_CP_INTERFACE_H
+#define GCC_CP_INTERFACE_H
+
+#include "gcc-interface.h"
+
+/* This header defines the interface to the GCC API. It must be both
+ valid C and valid C++, because it is included by both programs. */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Forward declaration. */
+
+struct gcc_cp_context;
+
+/*
+ * Definitions and declarations for the C++ front end.
+ */
+
+/* Defined versions of the C++ front-end API. */
+
+enum gcc_cp_api_version
+{
+ GCC_CP_FE_VERSION_0 = 0
+};
+
+/* Qualifiers. */
+
+enum gcc_cp_qualifiers
+{
+ GCC_CP_QUALIFIER_CONST = 1,
+ GCC_CP_QUALIFIER_VOLATILE = 2,
+ GCC_CP_QUALIFIER_RESTRICT = 4
+};
+
+/* Ref qualifiers. */
+
+enum gcc_cp_ref_qualifiers {
+ GCC_CP_REF_QUAL_NONE = 0,
+ GCC_CP_REF_QUAL_LVALUE = 1,
+ GCC_CP_REF_QUAL_RVALUE = 2
+};
+
+/* Opaque typedef for unbound class templates. They are used for
+ template arguments, and defaults for template template
+ parameters. */
+
+typedef unsigned long long gcc_utempl;
+
+/* Opaque typedef for expressions. They are used for template
+ arguments, defaults for non-type template parameters, and defaults
+ for function arguments. */
+
+typedef unsigned long long gcc_expr;
+
+typedef enum
+ { GCC_CP_TPARG_VALUE, GCC_CP_TPARG_CLASS,
+ GCC_CP_TPARG_TEMPL, GCC_CP_TPARG_PACK }
+gcc_cp_template_arg_kind;
+
+typedef union
+{ gcc_expr value; gcc_type type; gcc_utempl templ; gcc_type pack; }
+gcc_cp_template_arg;
+
+/* An array of template arguments. */
+
+struct gcc_cp_template_args
+{
+ /* Number of elements. */
+
+ int n_elements;
+
+ /* kind[i] indicates what kind of template argument type[i] is. */
+
+ char /* gcc_cp_template_arg_kind */ *kinds;
+
+ /* The template arguments. */
+
+ gcc_cp_template_arg *elements;
+};
+
+/* An array of (default) function arguments. */
+
+struct gcc_cp_function_args
+{
+ /* Number of elements. */
+
+ int n_elements;
+
+ /* The (default) values for each argument. */
+
+ gcc_expr *elements;
+};
+
+/* This enumerates the kinds of decls that GDB can create. */
+
+enum gcc_cp_symbol_kind
+{
+ /* A function. */
+
+ GCC_CP_SYMBOL_FUNCTION,
+
+ /* A variable. */
+
+ GCC_CP_SYMBOL_VARIABLE,
+
+ /* A typedef, or an alias declaration (including template ones). */
+
+ GCC_CP_SYMBOL_TYPEDEF,
+
+ /* A label. */
+
+ GCC_CP_SYMBOL_LABEL,
+
+ /* A class, forward declared in build_decl (to be later defined in
+ start_class_definition), or, in a template parameter list scope,
+ a declaration of a template class, closing the parameter
+ list. */
+
+ GCC_CP_SYMBOL_CLASS,
+
+ /* A union, forward declared in build_decl (to be later defined in
+ start_class_definition). */
+
+ GCC_CP_SYMBOL_UNION,
+
+ /* An enumeration type being introduced with start_new_enum_type. */
+
+ GCC_CP_SYMBOL_ENUM,
+
+ /* A nonstatic data member being introduced with new_field. */
+
+ GCC_CP_SYMBOL_FIELD,
+
+ /* A base class in a gcc_vbase_array. */
+
+ GCC_CP_SYMBOL_BASECLASS,
+
+ /* A using declaration in new_using_decl. */
+
+ GCC_CP_SYMBOL_USING,
+
+ /* A (lambda) closure class type. In many regards this is just like
+ a regular class, but it's not supposed to have base classes, some
+ of the member functions that are usually implicitly-defined are
+ deleted, and it should have an operator() member function that
+ holds the lambda body. We can't instantiate objects of lambda
+ types from the snippet, but we can interact with them in such
+ ways as passing them to functions that take their types, and
+ calling their body. */
+
+ GCC_CP_SYMBOL_LAMBDA_CLOSURE,
+
+ /* Marker to check that we haven't exceeded GCC_CP_SYMBOL_MASK. */
+ GCC_CP_SYMBOL_END,
+
+ GCC_CP_SYMBOL_MASK = 15,
+
+ /* When defining a class member, at least one of the
+ GCC_CP_ACCESS_MASK bits must be set; when defining a namespace-
+ or union-scoped symbol, none of them must be set. */
+
+ GCC_CP_ACCESS_PRIVATE,
+ GCC_CP_ACCESS_PUBLIC = GCC_CP_ACCESS_PRIVATE << 1,
+ GCC_CP_ACCESS_MASK = (GCC_CP_ACCESS_PUBLIC
+ | GCC_CP_ACCESS_PRIVATE),
+ GCC_CP_ACCESS_PROTECTED = GCC_CP_ACCESS_MASK,
+ GCC_CP_ACCESS_NONE = 0,
+
+ GCC_CP_FLAG_BASE = GCC_CP_ACCESS_PRIVATE << 2,
+
+ /* Flags to be used along with GCC_CP_SYMBOL_FUNCTION: */
+
+ /* This flag should be set for constructors, destructors and
+ operators. */
+ GCC_CP_FLAG_SPECIAL_FUNCTION = GCC_CP_FLAG_BASE,
+
+ /* We intentionally cannot express inline, constexpr, or virtual
+ override for functions. We can't inline or constexpr-replace
+ without a source-level body. The override keyword is only
+ meaningful within the definition of the containing class. */
+
+ /* This indicates a "virtual" member function, explicitly or
+ implicitly (due to a virtual function with the same name and
+ prototype in a base class) declared as such. */
+ GCC_CP_FLAG_VIRTUAL_FUNCTION = GCC_CP_FLAG_BASE << 1,
+
+ /* The following two flags should only be set when the flag above is
+ set. */
+
+ /* This indicates a pure virtual member function, i.e., one that is
+ declared with "= 0", even if a body is provided in the
+ definition. */
+ GCC_CP_FLAG_PURE_VIRTUAL_FUNCTION = GCC_CP_FLAG_BASE << 2,
+
+ /* This indicates a "final" virtual member function. */
+ GCC_CP_FLAG_FINAL_VIRTUAL_FUNCTION = GCC_CP_FLAG_BASE << 3,
+
+ /* This indicates a special member function should have its default
+ implementation. This either means the function declaration
+ contains the "= default" tokens, or that the member function was
+ implicitly generated by the compiler, although the latter use is
+ discouraged: just let the compiler implicitly introduce it.
+
+ A member function defaulted after its first declaration has
+ slightly different ABI implications from one implicitly generated
+ or explicitly defaulted at the declaration (and definition)
+ point. To avoid silent (possibly harmless) violation of the one
+ definition rule, it is recommended that this flag not be used for
+ such functions, and that the address of the definition be
+ supplied instead. */
+ GCC_CP_FLAG_DEFAULTED_FUNCTION = GCC_CP_FLAG_BASE << 4,
+
+ /* This indicates a deleted member function, i.e., one that has been
+ defined as "= delete" at its declaration point, or one that has
+ been implicitly defined as deleted (with or without an explicit
+ "= default" definition).
+
+ This should not be used for implicitly-declared member functions
+ that resolve to deleted definitions, as it may affect the
+ implicit declaration of other member functions. */
+ GCC_CP_FLAG_DELETED_FUNCTION = GCC_CP_FLAG_BASE << 5,
+
+ /* This indicates a constructor or type-conversion operator declared
+ as "explicit". */
+
+ GCC_CP_FLAG_EXPLICIT_FUNCTION = GCC_CP_FLAG_BASE << 6,
+
+ GCC_CP_FLAG_END_FUNCTION,
+ GCC_CP_FLAG_MASK_FUNCTION = (((GCC_CP_FLAG_END_FUNCTION - 1) << 1)
+ - GCC_CP_FLAG_BASE),
+
+ /* Flags to be used along with GCC_CP_SYMBOL_VARIABLE: */
+
+ /* This indicates a variable declared as "constexpr". */
+
+ GCC_CP_FLAG_CONSTEXPR_VARIABLE = GCC_CP_FLAG_BASE,
+
+ /* This indicates a variable declared as "thread_local". ??? What
+ should the ADDRESS be? */
+
+ GCC_CP_FLAG_THREAD_LOCAL_VARIABLE = GCC_CP_FLAG_BASE << 1,
+
+ GCC_CP_FLAG_END_VARIABLE,
+ GCC_CP_FLAG_MASK_VARIABLE = (((GCC_CP_FLAG_END_VARIABLE - 1) << 1)
+ - GCC_CP_FLAG_BASE),
+
+ /* Flags to be used when defining nonstatic data members of classes
+ with new_field. */
+
+ /* Use this when no flags are present. */
+ GCC_CP_FLAG_FIELD_NOFLAG = 0,
+
+ /* This indicates the field is declared as mutable. */
+ GCC_CP_FLAG_FIELD_MUTABLE = GCC_CP_FLAG_BASE,
+
+ GCC_CP_FLAG_END_FIELD,
+ GCC_CP_FLAG_MASK_FIELD = (((GCC_CP_FLAG_END_FIELD - 1) << 1)
+ - GCC_CP_FLAG_BASE),
+
+ /* Flags to be used when defining an enum with
+ start_new_enum_type. */
+
+ /* This indicates an enum type without any flags. */
+ GCC_CP_FLAG_ENUM_NOFLAG = 0,
+
+ /* This indicates a scoped enum type. */
+ GCC_CP_FLAG_ENUM_SCOPED = GCC_CP_FLAG_BASE,
+
+ GCC_CP_FLAG_END_ENUM,
+ GCC_CP_FLAG_MASK_ENUM = (((GCC_CP_FLAG_END_ENUM - 1) << 1)
+ - GCC_CP_FLAG_BASE),
+
+
+ /* Flags to be used when introducing a class or a class template
+ with build_decl. */
+
+ /* This indicates an enum type without any flags. */
+ GCC_CP_FLAG_CLASS_NOFLAG = 0,
+
+ /* This indicates the class is actually a struct. This has no
+ effect whatsoever on access control in this interface, since all
+ class members must have explicit access control bits set, but it
+ may affect error messages. */
+ GCC_CP_FLAG_CLASS_IS_STRUCT = GCC_CP_FLAG_BASE,
+
+ GCC_CP_FLAG_END_CLASS,
+ GCC_CP_FLAG_MASK_CLASS = (((GCC_CP_FLAG_END_CLASS - 1) << 1)
+ - GCC_CP_FLAG_BASE),
+
+
+ /* Flags to be used when introducing a virtual base class in a
+ gcc_vbase_array. */
+
+ /* This indicates an enum type without any flags. */
+ GCC_CP_FLAG_BASECLASS_NOFLAG = 0,
+
+ /* This indicates the class is actually a struct. This has no
+ effect whatsoever on access control in this interface, since all
+ class members must have explicit access control bits set, but it
+ may affect error messages. */
+ GCC_CP_FLAG_BASECLASS_VIRTUAL = GCC_CP_FLAG_BASE,
+
+ GCC_CP_FLAG_END_BASECLASS,
+ GCC_CP_FLAG_MASK_BASECLASS = (((GCC_CP_FLAG_END_BASECLASS - 1) << 1)
+ - GCC_CP_FLAG_BASE),
+
+
+ GCC_CP_FLAG_MASK = (GCC_CP_FLAG_MASK_FUNCTION
+ | GCC_CP_FLAG_MASK_VARIABLE
+ | GCC_CP_FLAG_MASK_FIELD
+ | GCC_CP_FLAG_MASK_ENUM
+ | GCC_CP_FLAG_MASK_CLASS
+ | GCC_CP_FLAG_MASK_BASECLASS
+ )
+};
+
+
+/* An array of types used for creating lists of base classes. */
+
+struct gcc_vbase_array
+{
+ /* Number of elements. */
+
+ int n_elements;
+
+ /* The base classes. */
+
+ gcc_type *elements;
+
+ /* Flags for each base class. Used to indicate access control and
+ virtualness. */
+
+ enum gcc_cp_symbol_kind *flags;
+};
+
+
+/* This enumerates the types of symbols that GCC might request from
+ GDB. */
+
+enum gcc_cp_oracle_request
+{
+ /* An identifier in namespace scope -- type, variable, function,
+ namespace, template. All namespace-scoped symbols with the
+ requested name, in any namespace (including the global
+ namespace), should be defined in response to this request. */
+
+ GCC_CP_ORACLE_IDENTIFIER
+};
+
+/* The type of the function called by GCC to ask GDB for a symbol's
+ definition. DATUM is an arbitrary value supplied when the oracle
+ function is registered. CONTEXT is the GCC context in which the
+ request is being made. REQUEST specifies what sort of symbol is
+ being requested, and IDENTIFIER is the name of the symbol. */
+
+typedef void gcc_cp_oracle_function (void *datum,
+ struct gcc_cp_context *context,
+ enum gcc_cp_oracle_request request,
+ const char *identifier);
+
+/* The type of the function called by GCC to ask GDB for a symbol's
+ address. This should return 0 if the address is not known. */
+
+typedef gcc_address gcc_cp_symbol_address_function (void *datum,
+ struct gcc_cp_context *ctxt,
+ const char *identifier);
+
+/* The type of the function called by GCC to ask GDB to enter or leave
+ the user expression scope. */
+
+typedef void gcc_cp_enter_leave_user_expr_scope_function (void *datum,
+ struct gcc_cp_context
+ *context);
+
+/* The vtable used by the C front end. */
+
+struct gcc_cp_fe_vtable
+{
+ /* The version of the C interface. The value is one of the
+ gcc_cp_api_version constants. */
+
+ unsigned int cp_version;
+
+ /* Set the callbacks for this context.
+
+ The binding oracle is called whenever the C++ parser needs to
+ look up a symbol. This gives the caller a chance to lazily
+ instantiate symbols using other parts of the gcc_cp_fe_interface
+ API. The symbol is looked up without a scope, and the oracle
+ must supply a definition for ALL namespace-scoped definitions
+ bound to the symbol.
+
+ The address oracle is called whenever the C++ parser needs to
+ look up a symbol. This may be called for symbols not provided by
+ the symbol oracle, such as built-in functions where GCC provides
+ the declaration; other internal symbols, such as those related
+ with thunks, rtti, and virtual tables are likely to be queried
+ through this interface too. The identifier is a mangled symbol
+ name.
+
+ DATUM is an arbitrary piece of data that is passed back verbatim
+ to the callbacks in requests. */
+
+ void (*set_callbacks) (struct gcc_cp_context *self,
+ 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);
+
+#define GCC_METHOD0(R, N) \
+ R (*N) (struct gcc_cp_context *);
+#define GCC_METHOD1(R, N, A) \
+ R (*N) (struct gcc_cp_context *, A);
+#define GCC_METHOD2(R, N, A, B) \
+ R (*N) (struct gcc_cp_context *, A, B);
+#define GCC_METHOD3(R, N, A, B, C) \
+ R (*N) (struct gcc_cp_context *, A, B, C);
+#define GCC_METHOD4(R, N, A, B, C, D) \
+ R (*N) (struct gcc_cp_context *, A, B, C, D);
+#define GCC_METHOD5(R, N, A, B, C, D, E) \
+ R (*N) (struct gcc_cp_context *, A, B, C, D, E);
+#define GCC_METHOD7(R, N, A, B, C, D, E, F, G) \
+ R (*N) (struct gcc_cp_context *, A, B, C, D, E, F, G);
+
+#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
+
+};
+
+/* The C front end object. */
+
+struct gcc_cp_context
+{
+ /* Base class. */
+
+ struct gcc_base_context base;
+
+ /* Our vtable. This is a separate field because this is simpler
+ than implementing a vtable inheritance scheme in C. */
+
+ const struct gcc_cp_fe_vtable *cp_ops;
+};
+
+/* The name of the .so that the compiler builds. We dlopen this
+ later. */
+
+#define GCC_CP_FE_LIBCC libcc1.so
+
+/* The compiler exports a single initialization function. This macro
+ holds its name as a symbol. */
+
+#define GCC_CP_FE_CONTEXT gcc_cp_fe_context
+
+/* The type of the initialization function. The caller passes in the
+ desired base version and desired C-specific version. If the
+ request can be satisfied, a compatible gcc_context object will be
+ returned. Otherwise, the function returns NULL. */
+
+typedef struct gcc_cp_context *gcc_cp_fe_context_function
+ (enum gcc_base_api_version,
+ enum gcc_cp_api_version);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* GCC_CP_INTERFACE_H */