/* Deprecated? */
object_dtor_group
};
+
+/* Kinds of template arguments. */
+enum template_argument_kinds
+{
+ /* A type argument, e.g., "<typename T>". */
+ type_parameter,
+
+ /* A value argument, e.g., "<int V>". */
+ value_parameter,
+
+ /* A template argument, e.g., "<template <...> class T = X>". */
+ template_parameter,
+
+ /* A variadic template pack, e.g., "<class ... Types>". */
+ variadic_parameter
+};
/* Return non-zero iff NAME is the mangled name of a destructor.
Actually, return an `enum dtor_kind' value describing what *kind*
demangle_parse_info::demangle_parse_info ()
: info (NULL),
- tree (NULL)
+ tree (NULL),
+ memory (NULL)
{
obstack_init (&obstack);
}
/* Free any memory allocated during typedef replacement. */
obstack_free (&obstack, NULL);
+
+ /* Free any memory used for demangling. */
+ free (memory);
}
/* Merge the two parse trees given by DEST and SRC. The parse tree
{
struct template_symbol *templ
= (struct template_symbol *) function;
- struct symbol *sym = search_symbol_list (name,
- templ->n_template_arguments,
- templ->template_arguments);
+ struct symbol *sym
+ = search_symbol_list (name, templ->template_arguments->n_arguments,
+ templ->template_arguments->arguments);
if (sym != NULL)
{
#include "gdb_setjmp.h"
#include "safe-ctype.h"
-#define d_left(dc) (dc)->u.s_binary.left
-#define d_right(dc) (dc)->u.s_binary.right
-
/* Functions related to demangled name parsing. */
static unsigned int cp_find_first_component_aux (const char *name,
return ret;
}
-/* Convert a mangled name to a demangle_component tree. *MEMORY is
- set to the block of used memory that should be freed when finished
- with the tree. DEMANGLED_P is set to the char * that should be
- freed when finished with the tree, or NULL if none was needed.
- OPTIONS will be passed to the demangler. */
+/* See description in cp-support.h. */
-static std::unique_ptr<demangle_parse_info>
-mangled_name_to_comp (const char *mangled_name, int options,
- void **memory, char **demangled_p)
+std::unique_ptr<demangle_parse_info>
+cp_mangled_name_to_comp (const char *mangled_name, int options)
{
char *demangled_name;
if (mangled_name[0] == '_' && mangled_name[1] == 'Z')
{
struct demangle_component *ret;
+ void *memory;
ret = cplus_demangle_v3_components (mangled_name,
- options, memory);
+ options, &memory);
if (ret)
{
std::unique_ptr<demangle_parse_info> info (new demangle_parse_info);
info->tree = ret;
- *demangled_p = NULL;
+ info->memory = memory;
return info;
}
}
return NULL;
}
- *demangled_p = demangled_name;
+ long len;
+ copy_string_to_obstack (&info->obstack, demangled_name, &len);
return info;
}
char *
cp_class_name_from_physname (const char *physname)
{
- void *storage = NULL;
- char *demangled_name = NULL, *ret;
+ char *ret;
struct demangle_component *ret_comp, *prev_comp, *cur_comp;
std::unique_ptr<demangle_parse_info> info;
int done;
- info = mangled_name_to_comp (physname, DMGL_ANSI,
- &storage, &demangled_name);
+ info = cp_mangled_name_to_comp (physname, DMGL_ANSI);
if (info == NULL)
return NULL;
ret = cp_comp_to_string (ret_comp, 10);
}
- xfree (storage);
- xfree (demangled_name);
return ret;
}
char *
method_name_from_physname (const char *physname)
{
- void *storage = NULL;
- char *demangled_name = NULL, *ret;
+ char *ret;
struct demangle_component *ret_comp;
std::unique_ptr<demangle_parse_info> info;
- info = mangled_name_to_comp (physname, DMGL_ANSI,
- &storage, &demangled_name);
+ info = cp_mangled_name_to_comp (physname, DMGL_ANSI);
if (info == NULL)
return NULL;
estimate. */
ret = cp_comp_to_string (ret_comp, 10);
- xfree (storage);
- xfree (demangled_name);
return ret;
}
cplus_print_vtable (value);
}
+/* See description in cp-support.h. */
+
+void
+cp_decode_template_type_indices (struct template_symbol *tsymbol,
+ const struct demangle_parse_info *opt_info)
+{
+ const struct demangle_parse_info *info;
+ int idx;
+ struct demangle_component *ret_comp;
+ struct objfile *objfile;
+
+ /* Only do this once. */
+ if (tsymbol->template_argument_indices != NULL)
+ return;
+
+ if (tsymbol->linkage_name == NULL)
+ {
+ warning (_("Template symbol \"%s\" has no linkage name."),
+ SYMBOL_NATURAL_NAME (&tsymbol->base));
+ return;
+ }
+
+ /* Initialize values to be returned to caller. */
+ gdb_assert (SYMBOL_OBJFILE_OWNED (&tsymbol->base));
+ objfile = symbol_objfile (&tsymbol->base);
+ tsymbol->template_return_index = -1;
+ tsymbol->template_argument_indices
+ = XOBNEWVEC (&objfile->objfile_obstack, long,
+ TYPE_NFIELDS (SYMBOL_TYPE (&tsymbol->base)));
+
+ for (idx = 0; idx < TYPE_NFIELDS (SYMBOL_TYPE (&tsymbol->base)); ++idx)
+ tsymbol->template_argument_indices[idx] = -1;
+
+ std::unique_ptr<demangle_parse_info> dpi;
+
+ if (opt_info != NULL)
+ info = opt_info;
+ else
+ {
+ dpi = cp_mangled_name_to_comp (tsymbol->linkage_name,
+ DMGL_ANSI | DMGL_PARAMS);
+ if (dpi == NULL)
+ return;
+
+ info = dpi.get ();
+ }
+
+ /* Determine the return type index. */
+ ret_comp = info->tree;
+ if (ret_comp->type == DEMANGLE_COMPONENT_TYPED_NAME)
+ {
+ if (d_left (ret_comp)->type == DEMANGLE_COMPONENT_TEMPLATE
+ && d_right (ret_comp)->type == DEMANGLE_COMPONENT_FUNCTION_TYPE)
+ {
+ int done = 0;
+ struct demangle_component *func_comp = d_right (ret_comp);
+
+ /* Move to looking at the return type node. */
+ ret_comp = d_left (func_comp);
+ if (ret_comp != NULL)
+ {
+ while (!done)
+ {
+ switch (ret_comp->type)
+ {
+ case DEMANGLE_COMPONENT_CONST:
+ case DEMANGLE_COMPONENT_RESTRICT:
+ case DEMANGLE_COMPONENT_VOLATILE:
+ case DEMANGLE_COMPONENT_POINTER:
+ case DEMANGLE_COMPONENT_REFERENCE:
+ case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
+ ret_comp = d_left (ret_comp);
+ break;
+
+ /*TYPED_NAME et al? */
+
+ case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
+ /* The return type was based on a template parameter.
+ Return the index of that parameter. */
+ tsymbol->template_return_index
+ = ret_comp->u.s_number.number;
+ done = 1;
+ break;
+
+ default:
+ done = 1;
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* The function had no marked return type. Check if it is
+ a conversion operator and record the template parameter
+ index for that. */
+
+ ret_comp = d_left (info->tree);
+ while (!done)
+ {
+ switch (ret_comp->type)
+ {
+ case DEMANGLE_COMPONENT_TEMPLATE:
+ case DEMANGLE_COMPONENT_CONVERSION:
+ case DEMANGLE_COMPONENT_CONST:
+ case DEMANGLE_COMPONENT_RESTRICT:
+ case DEMANGLE_COMPONENT_VOLATILE:
+ case DEMANGLE_COMPONENT_POINTER:
+ case DEMANGLE_COMPONENT_REFERENCE:
+ case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
+ ret_comp = d_left (ret_comp);
+ break;
+
+ case DEMANGLE_COMPONENT_QUAL_NAME:
+ ret_comp = d_right (ret_comp);
+ break;
+
+ case DEMANGLE_COMPONENT_TEMPLATE_PARAM:
+ tsymbol->conversion_operator_index
+ = ret_comp->u.s_number.number;
+ done = 1;
+ break;
+
+ default:
+ done = 1;
+ break;
+ }
+ }
+ }
+
+ /* Determine the same information for the function arguments. */
+ ret_comp = d_right (func_comp);
+ idx = 0;
+ while (ret_comp != NULL
+ && ret_comp->type == DEMANGLE_COMPONENT_ARGLIST)
+ {
+ struct demangle_component *comp;
+
+ comp = d_left (ret_comp);
+ if (comp == NULL)
+ break;
+ done = 0;
+ while (!done)
+ {
+ switch (comp->type)
+ {
+ case DEMANGLE_COMPONENT_CONST:
+ case DEMANGLE_COMPONENT_RESTRICT:
+ case DEMANGLE_COMPONENT_VOLATILE:
+ case DEMANGLE_COMPONENT_POINTER:
+ case DEMANGLE_COMPONENT_REFERENCE:
+ case DEMANGLE_COMPONENT_RVALUE_REFERENCE:
+ comp = d_left (comp);
+ break;
+ default:
+ done = 1;
+ break;
+ }
+ }
+
+ if (comp->type == DEMANGLE_COMPONENT_TEMPLATE_PARAM)
+ tsymbol->template_argument_indices[idx]
+ = comp->u.s_number.number;
+ ++idx;
+
+ ret_comp = d_right (ret_comp);
+ }
+ }
+ }
+}
+
void
_initialize_cp_support (void)
{
#include "gdb_vecs.h"
#include "gdb_obstack.h"
+#include <string>
+
/* Opaque declarations. */
struct symbol;
/* The result of the parse. */
struct demangle_component *tree;
- /* Any temporary memory used during typedef replacement. */
+ /* Any temporary memory used, e.g., during typedef replacement
+ or demangling a name. */
struct obstack obstack;
-};
+ /* The memory used for demangling a name prior to parsing. */
+ void *memory;
+};
/* Functions from cp-support.c. */
extern std::unique_ptr<demangle_parse_info> cp_demangled_name_to_comp
(const char *demangled_name, const char **errmsg);
+/* Convert a mangled name to a demangle_component tree. OPTIONS will be
+ passed to the demangler. */
+
+extern std::unique_ptr<demangle_parse_info>
+ cp_mangled_name_to_comp (const char *mangled_name, int options);
+
+/* Convenience macros to move through the demangle tree. */
+
+#define d_left(dc) (dc)->u.s_binary.left
+#define d_right(dc) (dc)->u.s_binary.right
+
extern char *cp_comp_to_string (struct demangle_component *result,
int estimated_len);
char *gdb_demangle (const char *name, int options);
+/* Decode template information for TSYMBOL. This function determines whether
+ the template's return and argument types are concrete types or template
+ parameters. The symbol's obstack is used to allocate any needed memory.
+ If OPT_INFO is non-NULL, use the given demangle tree to do this. Otherwise,
+ this function will demangle the template's linkage name. */
+
+extern void
+ cp_decode_template_type_indices (struct template_symbol *tsymbol,
+ const struct demangle_parse_info *opt_info);
+
/* Like gdb_demangle, but suitable for use as la_sniff_from_mangled_name. */
int gdb_sniff_from_mangled_name (const char *mangled, char **demangled);
typedef struct symbol *symbolp;
DEF_VEC_P (symbolp);
+typedef enum template_argument_kinds template_argument_kinds_t;
+DEF_VEC_I (template_argument_kinds_t);
+
/* When == 1, print basic high level tracing messages.
When > 1, be more verbose.
This is in contrast to the low level DIE reading of dwarf_die_debug. */
}
}
+/* Return the type of the template parameter given by TAG. */
+
+static enum template_argument_kinds
+dw2_template_param_kind (enum dwarf_tag tag)
+{
+ enum template_argument_kinds kind;
+
+ switch (tag)
+ {
+ case DW_TAG_template_type_param:
+ kind = type_parameter;
+ break;
+ case DW_TAG_template_value_param:
+ kind = value_parameter;
+ break;
+ case DW_TAG_GNU_template_template_param:
+ kind = template_parameter;
+ break;
+ case DW_TAG_GNU_template_parameter_pack:
+ kind = variadic_parameter;
+ break;
+ default:
+ gdb_assert_not_reached ("unexpected template parameter tag");
+ }
+
+ return kind;
+}
+
static void
read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
{
struct block *block;
int inlined_func = (die->tag == DW_TAG_inlined_subroutine);
VEC (symbolp) *template_args = NULL;
+ VEC (template_argument_kinds_t) *template_args_kinds = NULL;
+ VEC (symbolp) *template_arg_defaults = NULL;
struct template_symbol *templ_func = NULL;
+ struct type *type;
if (inlined_func)
{
}
}
+ type = read_type_die (die, cu);
newobj = push_context (0, lowpc);
- newobj->name = new_symbol_full (die, read_type_die (die, cu), cu,
- (struct symbol *) templ_func);
+ newobj->name = new_symbol_full (die, type, cu, (struct symbol *) templ_func);
/* If there is a location expression for DW_AT_frame_base, record
it. */
struct symbol *arg = new_symbol (child_die, NULL, cu);
if (arg != NULL)
- VEC_safe_push (symbolp, template_args, arg);
+ {
+ VEC_safe_push (symbolp, template_args, arg);
+ VEC_safe_push (template_argument_kinds_t,
+ template_args_kinds,
+ dw2_template_param_kind (child_die->tag));
+ if (dwarf2_flag_true_p (child_die,
+ DW_AT_default_value, cu))
+ VEC_safe_push (symbolp, template_arg_defaults, arg);
+ else
+ VEC_safe_push (symbolp, template_arg_defaults, NULL);
+ }
}
else
process_die (child_die, cu);
{
gdb_assert (templ_func != NULL);
- templ_func->n_template_arguments = VEC_length (symbolp, template_args);
templ_func->template_arguments
+ = XOBNEW (&objfile->objfile_obstack, struct template_argument_info);
+ templ_func->template_arguments->n_arguments = VEC_length (symbolp, template_args);
+ templ_func->template_arguments->arguments
= XOBNEWVEC (&objfile->objfile_obstack, struct symbol *,
- templ_func->n_template_arguments);
- memcpy (templ_func->template_arguments,
+ templ_func->template_arguments->n_arguments);
+ memcpy (templ_func->template_arguments->arguments,
VEC_address (symbolp, template_args),
- (templ_func->n_template_arguments * sizeof (struct symbol *)));
+ (templ_func->template_arguments->n_arguments * sizeof (struct symbol *)));
+ templ_func->template_arguments->argument_kinds
+ = XOBNEWVEC (&objfile->objfile_obstack, enum template_argument_kinds,
+ templ_func->template_arguments->n_arguments);
+ memcpy (templ_func->template_arguments->argument_kinds,
+ VEC_address (template_argument_kinds_t, template_args_kinds),
+ (templ_func->template_arguments->n_arguments
+ * sizeof (enum template_argument_kinds)));
+ templ_func->template_arguments->default_arguments
+ = XOBNEWVEC (&objfile->objfile_obstack, struct symbol *,
+ templ_func->template_arguments->n_arguments);
+ memcpy (templ_func->template_arguments->default_arguments,
+ VEC_address (symbolp, template_arg_defaults),
+ (templ_func->template_arguments->n_arguments * sizeof (struct symbol *)));
+
VEC_free (symbolp, template_args);
+ VEC_free (template_argument_kinds_t, template_args_kinds);
+ VEC_free (symbolp, template_arg_defaults);
+
+ /* Determine whether the template's return and argument types were
+ specified using template parameters. */
const char *linkage_name = dw2_linkage_name (die, cu);
+ templ_func->linkage_name = linkage_name;
if (linkage_name != NULL)
{
char *str;
{
struct field_info fi;
VEC (symbolp) *template_args = NULL;
+ VEC (template_argument_kinds_t) *template_args_kinds = NULL;
+ VEC (symbolp) *template_arg_defaults = NULL;
struct cleanup *back_to = make_cleanup (null_cleanup, 0);
memset (&fi, 0, sizeof (struct field_info));
struct symbol *arg = new_symbol (child_die, NULL, cu);
if (arg != NULL)
- VEC_safe_push (symbolp, template_args, arg);
+ {
+ VEC_safe_push (symbolp, template_args, arg);
+ VEC_safe_push (template_argument_kinds_t,
+ template_args_kinds,
+ dw2_template_param_kind (child_die->tag));
+ if (dwarf2_flag_true_p (child_die,
+ DW_AT_default_value, cu))
+ VEC_safe_push (symbolp, template_arg_defaults, arg);
+ else
+ VEC_safe_push (symbolp, template_arg_defaults, NULL);
+ }
}
child_die = sibling_die (child_die);
if (! VEC_empty (symbolp, template_args))
{
ALLOCATE_CPLUS_STRUCT_TYPE (type);
- TYPE_N_TEMPLATE_ARGUMENTS (type)
+ TYPE_TEMPLATE_ARGUMENT_INFO (type)
+ = XOBNEW (&objfile->objfile_obstack, struct template_argument_info);
+ TYPE_TEMPLATE_ARGUMENT_INFO (type)->n_arguments
= VEC_length (symbolp, template_args);
- TYPE_TEMPLATE_ARGUMENTS (type)
+ TYPE_TEMPLATE_ARGUMENT_INFO (type)->arguments
= XOBNEWVEC (&objfile->objfile_obstack,
struct symbol *,
TYPE_N_TEMPLATE_ARGUMENTS (type));
- memcpy (TYPE_TEMPLATE_ARGUMENTS (type),
+ memcpy (TYPE_TEMPLATE_ARGUMENT_INFO (type)->arguments,
VEC_address (symbolp, template_args),
(TYPE_N_TEMPLATE_ARGUMENTS (type)
* sizeof (struct symbol *)));
+ TYPE_TEMPLATE_ARGUMENT_KINDS (type)
+ = XOBNEWVEC (&objfile->objfile_obstack,
+ enum template_argument_kinds,
+ TYPE_N_TEMPLATE_ARGUMENTS (type));
+ memcpy (TYPE_TEMPLATE_ARGUMENT_KINDS (type),
+ VEC_address (template_argument_kinds_t, template_args_kinds),
+ (TYPE_N_TEMPLATE_ARGUMENTS (type)
+ * sizeof (enum template_argument_kinds)));
+ TYPE_TEMPLATE_DEFAULT_ARGUMENTS (type)
+ = XOBNEWVEC (&objfile->objfile_obstack, struct symbol *,
+ TYPE_N_TEMPLATE_ARGUMENTS (type));
+ memcpy (TYPE_TEMPLATE_DEFAULT_ARGUMENTS (type),
+ VEC_address (symbolp, template_arg_defaults),
+ (TYPE_N_TEMPLATE_ARGUMENTS (type)
+ * sizeof (struct symbol *)));
VEC_free (symbolp, template_args);
+ VEC_free (template_argument_kinds_t, template_args_kinds);
+ VEC_free (symbolp, template_arg_defaults);
}
/* Attach fields and member functions to the type. */
unsigned int dummy : 13;
};
+/* * Template function/type argument information. */
+
+struct template_argument_info
+{
+ /* * Number of template arguments. */
+ unsigned short n_arguments;
+
+ /* * The template arguments. This is an array with n_arguments elements. */
+ struct symbol **arguments;
+
+ /* * Default values. An array with n_arguments elements. Note that this
+ array only describes this particular instance! It will not describe
+ default values for /all/ template instances (unless this instance uses
+ all the defaults). This is a DWARF limitation. */
+ struct symbol **default_arguments;
+
+ /* * The kinds of arguments. An array with n_arguments elements. */
+ enum template_argument_kinds *argument_kinds;
+};
+
/* * C++ language-specific information for TYPE_CODE_STRUCT and
TYPE_CODE_UNION nodes. */
short nfn_fields;
- /* * Number of template arguments. */
+ /* * Template arguments, if any, or NULL if this type does not represent a
+ templated type. */
- unsigned short n_template_arguments;
+ struct template_argument_info *template_arguments;
/* * One if this struct is a dynamic class, as defined by the
Itanium C++ ABI: if it requires a virtual table pointer,
struct decl_field *nested_types;
unsigned nested_types_count;
-
- /* * The template arguments. This is an array with
- N_TEMPLATE_ARGUMENTS elements. This is NULL for non-template
- classes. */
-
- struct symbol **template_arguments;
};
/* * Struct used to store conversion rankings. */
#define TYPE_FN_FIELDLIST_NAME(thistype, n) TYPE_CPLUS_SPECIFIC(thistype)->fn_fieldlists[n].name
#define TYPE_FN_FIELDLIST_LENGTH(thistype, n) TYPE_CPLUS_SPECIFIC(thistype)->fn_fieldlists[n].length
+#define TYPE_TEMPLATE_ARGUMENT_INFO(thistype) \
+ TYPE_CPLUS_SPECIFIC (thistype)->template_arguments
#define TYPE_N_TEMPLATE_ARGUMENTS(thistype) \
- TYPE_CPLUS_SPECIFIC (thistype)->n_template_arguments
+ (TYPE_TEMPLATE_ARGUMENT_INFO (thistype) == NULL ? 0 \
+ : TYPE_TEMPLATE_ARGUMENT_INFO (thistype)->n_arguments)
#define TYPE_TEMPLATE_ARGUMENTS(thistype) \
- TYPE_CPLUS_SPECIFIC (thistype)->template_arguments
+ (TYPE_TEMPLATE_ARGUMENT_INFO (thistype) == NULL ? NULL \
+ : TYPE_TEMPLATE_ARGUMENT_INFO (thistype)->arguments)
#define TYPE_TEMPLATE_ARGUMENT(thistype, n) \
- TYPE_CPLUS_SPECIFIC (thistype)->template_arguments[n]
+ TYPE_TEMPLATE_ARGUMENT_INFO (thistype)->arguments[n]
+#define TYPE_TEMPLATE_ARGUMENT_KINDS(thistype) \
+ TYPE_TEMPLATE_ARGUMENT_INFO (thistype)->argument_kinds
+#define TYPE_TEMPLATE_ARGUMENT_KIND(thistype, n) \
+ TYPE_TEMPLATE_ARGUMENT_INFO (thistype)->argument_kinds[n]
+#define TYPE_TEMPLATE_DEFAULT_ARGUMENTS(thistype) \
+ TYPE_TEMPLATE_ARGUMENT_INFO (thistype)->default_arguments
+#define TYPE_TEMPLATE_DEFAULT_ARGUMENT(thistype, n) \
+ TYPE_TEMPLATE_ARGUMENT_INFO (thistype)->default_arguments[n]
#define TYPE_FN_FIELD(thisfn, n) (thisfn)[n]
#define TYPE_FN_FIELD_PHYSNAME(thisfn, n) (thisfn)[n].physname
result = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct template_symbol);
initialize_objfile_symbol_1 (&result->base);
+ result->template_return_index = -1;
+ result->conversion_operator_index = -1;
return result;
}
/* Search name of the template (it's name sans parameters). */
char *search_name;
- /* The number of template arguments. */
- int n_template_arguments;
+ /* Information on template arguments. */
+ struct template_argument_info *template_arguments;
- /* The template arguments. This is an array with
- N_TEMPLATE_ARGUMENTS elements. */
- struct symbol **template_arguments;
+ /* The template's linkage name. */
+ const char *linkage_name;
+
+ /* The template argument substitutions below are populated lazily to speed
+ up initial symbol reading. This is done by parsing the symbol's
+ linkage name. */
+
+ /* If the return type was specified as a template parameter, this will
+ hold the index of the template parameter used; -1 otherwise. */
+ long template_return_index;
+
+ /* Index into template_arguments describing the function's arguments
+ or -1 if the argument is not a template parameter. There are
+ TYPE_NFIELDS entries. */
+ long *template_argument_indices;
+
+ /* If this symbol is a conversion operator, this records which template
+ parameter is used for the conversion; -1 otherwise. */
+ long conversion_operator_index;
};
\f