c_get_string,
ada_get_symbol_name_cmp, /* la_get_symbol_name_cmp */
ada_iterate_over_symbols,
+ default_compute_string_hash,
&ada_varobj_ops,
NULL,
NULL,
/* The compunit we are building. */
struct compunit_symtab *compunit_symtab;
+
+ /* Language of this compunit_symtab. */
+ enum language language;
};
/* The work-in-progress of the compunit we are building.
if (symbol)
{
- BLOCK_DICT (block) = dict_create_linear (&objfile->objfile_obstack,
- *listhead);
+ BLOCK_DICT (block)
+ = dict_create_linear (&objfile->objfile_obstack,
+ buildsym_compunit->language, *listhead);
}
else
{
if (expandable)
{
- BLOCK_DICT (block) = dict_create_hashed_expandable ();
+ BLOCK_DICT (block)
+ = dict_create_hashed_expandable (buildsym_compunit->language);
dict_add_pending (BLOCK_DICT (block), *listhead);
}
else
{
BLOCK_DICT (block) =
- dict_create_hashed (&objfile->objfile_obstack, *listhead);
+ dict_create_hashed (&objfile->objfile_obstack,
+ buildsym_compunit->language, *listhead);
}
}
(or NULL if not known). */
static struct buildsym_compunit *
-start_buildsym_compunit (struct objfile *objfile, const char *comp_dir)
+start_buildsym_compunit (struct objfile *objfile, const char *comp_dir,
+ enum language language)
{
struct buildsym_compunit *bscu;
bscu->objfile = objfile;
bscu->comp_dir = (comp_dir == NULL) ? NULL : xstrdup (comp_dir);
+ bscu->language = language;
/* Initialize the debug format string to NULL. We may supply it
later via a call to record_debugformat. */
struct compunit_symtab *
start_symtab (struct objfile *objfile, const char *name, const char *comp_dir,
- CORE_ADDR start_addr)
+ CORE_ADDR start_addr, enum language language)
{
prepare_for_building (name, start_addr);
- buildsym_compunit = start_buildsym_compunit (objfile, comp_dir);
+ buildsym_compunit = start_buildsym_compunit (objfile, comp_dir, language);
/* Allocate the compunit symtab now. The caller needs it to allocate
non-primary symtabs. It is also needed by get_macro_table. */
prepare_for_building (name, start_addr);
buildsym_compunit = start_buildsym_compunit (COMPUNIT_OBJFILE (cust),
- COMPUNIT_DIRNAME (cust));
+ COMPUNIT_DIRNAME (cust),
+ compunit_language (cust));
buildsym_compunit->compunit_symtab = cust;
}
struct symbol;
struct addrmap;
struct compunit_symtab;
+enum language;
/* This module provides definitions used for creating and adding to
the symbol table. These routines are called from various symbol-
extern struct compunit_symtab *start_symtab (struct objfile *objfile,
const char *name,
const char *comp_dir,
- CORE_ADDR start_addr);
+ CORE_ADDR start_addr,
+ enum language language);
extern void restart_symtab (struct compunit_symtab *cust,
const char *name, CORE_ADDR start_addr);
#include "gdb_obstack.h"
#include <ctype.h>
#include "gdbcore.h"
+#include "symtab.h"
+#include "block.h"
+#include "linespec.h" /* for find_toplevel_char */
extern void _initialize_c_language (void);
return evaluate_subexp_standard (expect_type, exp, pos, noside);
}
+/* Compute the C++ hash for STRING0.
+
+ For dictionaries, we group like-symbols together.
+ That means that all templates with the same unparameterized names
+ must yield the same hash. Likewise, overloaded functions must also
+ yield the same hash.
+
+ The following code deals largely with templates. The dreaded
+ strcmp_iw already enforces overloads to be grouped. */
+
+static unsigned int
+cplus_compute_string_hash (const char *string0)
+{
+ /* If '<' doesn't appear at all in STRING), there is no way we could
+ be dealing with a template name. */
+ if (find_toplevel_char (string0, '<') == NULL)
+ return default_compute_string_hash (string0);
+
+ /* Locate the last qualified component of STRING0. */
+ const char *p = find_toplevel_string (string0, "::");
+ const char *last_scope = NULL;
+
+ while (p != NULL)
+ {
+ last_scope = p;
+ p = find_toplevel_string (p + 2, "::");
+ }
+
+ /* last_scope points to the last "::". If NULL, then no scope operator
+ was seen in STRING0, and we use the entire string. */
+ if (last_scope == NULL)
+ last_scope = string0;
+
+ /* Find a possible template parameter list. Valid operators will be
+ dealt with later. */
+ p = find_toplevel_char (last_scope, '<');
+
+ /* P points to toplevel '<', but it could still be a valid operator
+ and not be a template at all. */
+ if ((p - last_scope) > 8 && strncmp (p - 8, "operator", 8) == 0)
+ {
+ /* Skip <,=. */
+ while (strchr ("<=", *p) != NULL)
+ ++p;
+
+ /* Check if this operator contains a template parameter list marker. */
+ p = find_toplevel_char (p, '<');
+ }
+
+ /* If NULL, the string represents an operator (<, <=, <<, <<=) and is not
+ a template function itself. */
+ if (p == NULL)
+ return default_compute_string_hash (string0);
+
+ char *copy = ASTRDUP (string0);
+
+ copy[p - string0] = '\0';
+
+ /* It is a template, compute the hash based only until P. */
+ return default_compute_string_hash (copy);
+}
\f
/* Table mapping opcodes into strings for printing operators
c_get_string,
NULL, /* la_get_symbol_name_cmp */
iterate_over_symbols,
+ default_compute_string_hash,
&c_varobj_ops,
c_get_compile_context,
c_compute_program,
c_get_string,
NULL, /* la_get_symbol_name_cmp */
iterate_over_symbols,
+ cplus_compute_string_hash,
&cplus_varobj_ops,
NULL,
NULL,
c_get_string,
NULL, /* la_get_symbol_name_cmp */
iterate_over_symbols,
+ default_compute_string_hash,
&default_varobj_ops,
NULL,
NULL,
c_get_string,
NULL, /* la_get_symbol_name_cmp */
iterate_over_symbols,
+ default_compute_string_hash,
&default_varobj_ops,
NULL,
NULL,
NULL,
/* The start address is irrelevant, since we set
last_source_start_addr in coff_end_symtab. */
- 0);
+ 0,
+ /* Let buildsym.c deduce the language for this symtab. */
+ language_unknown);
record_debugformat ("COFF");
}
return ret;
}
+/* See description in cp-support.h. */
+
+char *
+cp_strip_template_parameters (const char *linkage_or_phys_name)
+{
+ /* We do not turn the linkage name into demangle components since we cannot
+ walk the tree in any usable way when dealing with conversion operators.
+ Instead we use a heuristic approach that works for all cases. */
+ char *stripped = NULL;
+ const char *name;
+
+ char *demangled_name = gdb_demangle (linkage_or_phys_name, DMGL_ANSI);
+ if (demangled_name != NULL)
+ name = demangled_name;
+ else
+ name = linkage_or_phys_name;
+
+ /* Only attempt to strip this if it looks like a template. */
+ if (strchr (name, '<') != NULL && strchr (name, '>') != NULL)
+ {
+ const char *p;
+ size_t len = strlen (name) - 1;
+
+ /* This is evil, but since we cannot use demangler trees, we have
+ no choice but to do textual searches. It is simply easiest to
+ do this backwards. */
+
+ /* Since we are searching backwards, we need only find the opening
+ '<' from the end of the string (at the "top level"). */
+ p = find_toplevel_char_r (name, len, '<');
+ if (p != NULL)
+ {
+ /* Remove any trailing whitespace. */
+ while (p > name && (ISSPACE (*(p - 1))))
+ --p;
+ stripped = savestring (name, p - name);
+ }
+ }
+
+ xfree (demangled_name);
+ return stripped;
+}
+
/* DEMANGLED_NAME is the name of a function, including parameters and
(optionally) a return type. Return the name of the function without
parameters or return type, or NULL if we can not parse the name. */
extern char *cp_func_name (const char *full_name);
+/* Strip any template parameters from the template in LINKAGE_NAME.
+ Result must be free'd. */
+
+extern char *cp_strip_template_parameters (const char *linkage_name);
+
extern char *cp_remove_params (const char *demangled_name);
extern struct symbol **make_symbol_overload_list (const char *,
c_get_string,
NULL, /* la_get_symbol_name_cmp */
iterate_over_symbols,
+ default_compute_string_hash,
&default_varobj_ops,
NULL,
NULL,
#include "cp-support.h"
#include "psympriv.h"
#include "block.h"
-
#include "aout/aout64.h"
#include "aout/stab_gnu.h" /* We always use GNU stabs, not
native, now. */
int symbol_offset;
int string_offset;
int file_string_offset;
+ enum language pst_language;
};
#define LDSYMOFF(p) (((struct symloc *)((p)->read_symtab_private))->ldsymoff)
#define SYMBOL_OFFSET(p) (SYMLOC(p)->symbol_offset)
#define STRING_OFFSET(p) (SYMLOC(p)->string_offset)
#define FILE_STRING_OFFSET(p) (SYMLOC(p)->file_string_offset)
+#define PST_LANGUAGE(p) (SYMLOC(p)->pst_language)
\f
/* The objfile we are currently reading. */
|| psymtab_language != language_cplus))
psymtab_language = tmp_language;
+
/* In C++, one may expect the same filename to come round many
times, when code is coming alternately from the main file
and from inline functions in other files. So I check to see
/* Deduce the source language from the filename for this psymtab. */
psymtab_language = deduce_language_from_filename (filename);
+ PST_LANGUAGE (result) = psymtab_language;
return result;
}
positive offsets. */
nlist.n_value = (nlist.n_value ^ 0x80000000) - 0x80000000;
process_one_symbol (type, nlist.n_desc, nlist.n_value,
- namestring, section_offsets, objfile);
+ namestring, section_offsets, objfile,
+ PST_LANGUAGE (pst));
}
/* We skip checking for a new .o or -l file; that should never
happen in this routine. */
void
process_one_symbol (int type, int desc, CORE_ADDR valu, char *name,
const struct section_offsets *section_offsets,
- struct objfile *objfile)
+ struct objfile *objfile, enum language language)
{
struct gdbarch *gdbarch = get_objfile_arch (objfile);
struct context_stack *newobj;
function_start_offset = 0;
start_stabs ();
- start_symtab (objfile, name, NULL, valu);
+ start_symtab (objfile, name, NULL, valu, language);
record_debugformat ("stabs");
break;
struct dictionary
{
+ const struct language_defn *language;
const struct dict_vector *vector;
union
{
/* Accessor macros. */
#define DICT_VECTOR(d) (d)->vector
+#define DICT_LANGUAGE(d) (d)->language
/* These can be used for DICT_HASHED_EXPANDABLE, too. */
symbol_compare_ftype *compare,
struct dict_iterator *iterator);
-static unsigned int dict_hash (const char *string);
-
/* Functions only for DICT_HASHED. */
static int size_hashed (const struct dictionary *dict);
struct dictionary *
dict_create_hashed (struct obstack *obstack,
+ enum language language,
const struct pending *symbol_list)
{
struct dictionary *retval;
retval = XOBNEW (obstack, struct dictionary);
DICT_VECTOR (retval) = &dict_hashed_vector;
+ DICT_LANGUAGE (retval) = language_def (language);
/* Calculate the number of symbols, and allocate space for them. */
for (list_counter = symbol_list;
it. */
extern struct dictionary *
-dict_create_hashed_expandable (void)
+dict_create_hashed_expandable (enum language language)
{
struct dictionary *retval = XNEW (struct dictionary);
DICT_VECTOR (retval) = &dict_hashed_expandable_vector;
+ DICT_LANGUAGE (retval) = language_def (language);
DICT_HASHED_NBUCKETS (retval) = DICT_EXPANDABLE_INITIAL_CAPACITY;
DICT_HASHED_BUCKETS (retval) = XCNEWVEC (struct symbol *,
DICT_EXPANDABLE_INITIAL_CAPACITY);
struct dictionary *
dict_create_linear (struct obstack *obstack,
+ enum language language,
const struct pending *symbol_list)
{
struct dictionary *retval;
retval = XOBNEW (obstack, struct dictionary);
DICT_VECTOR (retval) = &dict_linear_vector;
+ DICT_LANGUAGE (retval) = language_def (language);
/* Calculate the number of symbols, and allocate space for them. */
for (list_counter = symbol_list;
it. */
struct dictionary *
-dict_create_linear_expandable (void)
+dict_create_linear_expandable (enum language language)
{
struct dictionary *retval = XNEW (struct dictionary);
DICT_VECTOR (retval) = &dict_linear_expandable_vector;
+ DICT_LANGUAGE (retval) = language_def (language);
DICT_LINEAR_NSYMS (retval) = 0;
DICT_LINEAR_EXPANDABLE_CAPACITY (retval) = DICT_EXPANDABLE_INITIAL_CAPACITY;
DICT_LINEAR_SYMS (retval)
symbol_compare_ftype *compare,
struct dict_iterator *iterator)
{
- unsigned int hash_index = dict_hash (name) % DICT_HASHED_NBUCKETS (dict);
+ unsigned int hash_index = (DICT_LANGUAGE (dict)->la_compute_string_hash (name)
+ % DICT_HASHED_NBUCKETS (dict));
struct symbol *sym;
DICT_ITERATOR_DICT (iterator) = dict;
sym != NULL;
sym = sym->hash_next)
{
+ //printf ("compare (%s, %s)\n", name, SYMBOL_SEARCH_NAME (sym));
/* Warning: the order of arguments to compare matters! */
if (compare (SYMBOL_SEARCH_NAME (sym), name) == 0)
+ break;
+ else if (SYMBOL_IS_CPLUS_TEMPLATE_FUNCTION (sym))
{
- break;
+ struct template_symbol *tsym = (struct template_symbol *) sym;
+
+ if (tsym->search_name != NULL
+ && compare (tsym->search_name, name) == 0)
+ break;
}
-
}
DICT_ITERATOR_CURRENT (iterator) = sym;
{
if (compare (SYMBOL_SEARCH_NAME (next), name) == 0)
break;
+ else if (SYMBOL_IS_CPLUS_TEMPLATE_FUNCTION (next))
+ {
+ struct template_symbol *tsym = (struct template_symbol *) next;
+
+ if (tsym->search_name != NULL
+ && compare (tsym->search_name, name) == 0)
+ break;
+ }
}
DICT_ITERATOR_CURRENT (iterator) = next;
unsigned int hash_index;
struct symbol **buckets = DICT_HASHED_BUCKETS (dict);
- hash_index =
- dict_hash (SYMBOL_SEARCH_NAME (sym)) % DICT_HASHED_NBUCKETS (dict);
+ /* We don't want to insert a symbol into a dictionary of a different
+ language. The two may not use the same hashing algorithm. */
+ gdb_assert (SYMBOL_LANGUAGE (sym) == DICT_LANGUAGE (dict)->la_language);
+
+ hash_index
+ = (DICT_LANGUAGE (dict)->la_compute_string_hash (SYMBOL_SEARCH_NAME (sym))
+ % DICT_HASHED_NBUCKETS (dict));
sym->hash_next = buckets[hash_index];
buckets[hash_index] = sym;
}
That is, two identifiers equivalent according to any of those three
comparison operators hash to the same value. */
-static unsigned int
+unsigned int
dict_hash (const char *string0)
{
/* The Ada-encoded version of a name P1.P2...Pn has either the form
retval = sym;
break;
}
+ else if (SYMBOL_IS_CPLUS_TEMPLATE_FUNCTION (sym))
+ {
+ struct template_symbol *tsym = (struct template_symbol *) sym;
+
+ if (tsym->search_name != NULL
+ && compare (tsym->search_name, name) == 0)
+ {
+ retval = sym;
+ break;
+ }
+ }
}
DICT_ITERATOR_INDEX (iterator) = i;
struct symbol;
struct obstack;
struct pending;
-
+struct language_defn;
/* The creation functions for various implementations of
dictionaries. */
initialized from SYMBOL_LIST. */
extern struct dictionary *dict_create_hashed (struct obstack *obstack,
+ enum language language,
const struct pending
*symbol_list);
it, call dict_add_symbol(). Call dict_free() when you're done with
it. */
-extern struct dictionary *dict_create_hashed_expandable (void);
+extern struct dictionary *
+ dict_create_hashed_expandable (enum language language);
/* Create a dictionary implemented via a fixed-size array. All memory
it uses is allocated on OBSTACK; the environment is initialized
that they're found in SYMBOL_LIST. */
extern struct dictionary *dict_create_linear (struct obstack *obstack,
+ enum language language,
const struct pending
*symbol_list);
it, call dict_add_symbol(). Call dict_free() when you're done with
it. */
-extern struct dictionary *dict_create_linear_expandable (void);
+extern struct dictionary *
+ dict_create_linear_expandable (enum language language);
+
+/* A default hashing function for symbols. */
+extern unsigned int dict_hash (const char *string0);
/* The functions providing the interface to dictionaries. Note that
the most common parts of the interface, namely symbol lookup, are
VEC_address (symbolp, template_args),
(templ_func->n_template_arguments * sizeof (struct symbol *)));
VEC_free (symbolp, template_args);
+ const char *linkage_name = dw2_linkage_name (die, cu);
+ if (linkage_name != NULL)
+ {
+ char *str;
+
+ str = cp_strip_template_parameters (linkage_name);
+ if (str != NULL)
+ {
+ /* It would be nice to assert on the return value. Alas,
+ the demangler could be old/outdated and unable to demangle
+ the given linkage name. We have to cope with that
+ gracefully, even though a small part of me dies every time
+ this happens. */
+ templ_func->search_name
+ = obstack_strdup (&objfile->objfile_obstack, str);
+ xfree (str);
+ }
+ }
}
/* In C++, we can have functions nested inside functions (e.g., when
const char *name, const char *comp_dir, CORE_ADDR low_pc)
{
struct compunit_symtab *cust
- = start_symtab (cu->objfile, name, comp_dir, low_pc);
+ = start_symtab (cu->objfile, name, comp_dir, low_pc, cu->language);
record_debugformat ("DWARF 2");
record_producer (cu->producer);
default_get_string,
NULL, /* la_get_symbol_name_cmp */
iterate_over_symbols,
+ default_compute_string_hash,
&default_varobj_ops,
NULL,
NULL,
c_get_string,
NULL,
iterate_over_symbols,
+ default_compute_string_hash,
&default_varobj_ops,
NULL,
NULL,
size_t blockvector_size;
CORE_ADDR begin, end;
struct blockvector *bv;
+ enum language language;
actual_nblocks = FIRST_LOCAL_BLOCK + stab->nblocks;
cust = allocate_compunit_symtab (objfile, stab->file_name);
allocate_symtab (cust, stab->file_name);
add_compunit_symtab_to_objfile (cust);
+ language = compunit_language (cust);
/* JIT compilers compile in memory. */
COMPUNIT_DIRNAME (cust) = NULL;
"void");
BLOCK_DICT (new_block) = dict_create_linear (&objfile->objfile_obstack,
- NULL);
+ language, NULL);
/* The address range. */
BLOCK_START (new_block) = (CORE_ADDR) gdb_block_iter->begin;
BLOCK_END (new_block) = (CORE_ADDR) gdb_block_iter->end;
? allocate_global_block (&objfile->objfile_obstack)
: allocate_block (&objfile->objfile_obstack));
BLOCK_DICT (new_block) = dict_create_linear (&objfile->objfile_obstack,
- NULL);
+ language, NULL);
BLOCK_SUPERBLOCK (new_block) = block_iter;
block_iter = new_block;
#include "symfile.h"
#include "cp-support.h"
#include "frame.h"
+#include "dictionary.h" /* for dict_hash */
extern void _initialize_language (void);
error (_("Getting a string is unsupported in this language."));
}
+/* See language.h. */
+
+unsigned int
+default_compute_string_hash (const char *name)
+{
+ return dict_hash (name);
+}
+
/* Define the language that is no language. */
static int
default_get_string,
NULL, /* la_get_symbol_name_cmp */
iterate_over_symbols,
+ default_compute_string_hash,
&default_varobj_ops,
NULL,
NULL,
default_get_string,
NULL, /* la_get_symbol_name_cmp */
iterate_over_symbols,
+ default_compute_string_hash,
&default_varobj_ops,
NULL,
NULL,
default_get_string,
NULL, /* la_get_symbol_name_cmp */
iterate_over_symbols,
+ default_compute_string_hash,
&default_varobj_ops,
NULL,
NULL,
symbol_found_callback_ftype *callback,
void *data);
+ /* Hash the given STRING. Use default_compute_string_hash if no
+ special treatment is required. */
+ unsigned int (*la_compute_string_hash) (const char *name);
+
/* Various operations on varobj. */
const struct lang_varobj_ops *la_varobj_ops;
void default_get_string (struct value *value, gdb_byte **buffer, int *length,
struct type **char_type, const char **charset);
+/* Default name hashing function. */
+
+extern unsigned int default_compute_string_hash (const char *string);
+
void c_get_string (struct value *value, gdb_byte **buffer, int *length,
struct type **char_type, const char **charset);
VEC_safe_push (typep, *superclasses, TYPE_BASECLASS (t, ibase));
}
-/* Find an instance of the character C in the string S that is outside
- of all parenthesis pairs, single-quoted strings, and double-quoted
- strings. Also, ignore the char within a template name, like a ','
- within foo<int, int>. */
-
-const char *
-find_toplevel_char (const char *s, char c)
-{
- int quoted = 0; /* zero if we're not in quotes;
- '"' if we're in a double-quoted string;
- '\'' if we're in a single-quoted string. */
- int depth = 0; /* Number of unclosed parens we've seen. */
- const char *scan;
-
- for (scan = s; *scan; scan++)
- {
- if (quoted)
- {
- if (*scan == quoted)
- quoted = 0;
- else if (*scan == '\\' && *(scan + 1))
- scan++;
- }
- else if (*scan == c && ! quoted && depth == 0)
- return scan;
- else if (*scan == '"' || *scan == '\'')
- quoted = *scan;
- else if (*scan == '(' || *scan == '<')
- depth++;
- else if ((*scan == ')' || *scan == '>') && depth > 0)
- depth--;
- }
-
- return 0;
-}
-
-/* The string equivalent of find_toplevel_char. Returns a pointer
- to the location of NEEDLE in HAYSTACK, ignoring any occurrences
- inside "()" and "<>". Returns NULL if NEEDLE was not found. */
-
-static const char *
-find_toplevel_string (const char *haystack, const char *needle)
-{
- const char *s = haystack;
-
- do
- {
- s = find_toplevel_char (s, *needle);
-
- if (s != NULL)
- {
- /* Found first char in HAYSTACK; check rest of string. */
- if (startswith (s, needle))
- return s;
-
- /* Didn't find it; loop over HAYSTACK, looking for the next
- instance of the first character of NEEDLE. */
- ++s;
- }
- }
- while (s != NULL && *s != '\0');
-
- /* NEEDLE was not found in HAYSTACK. */
- return NULL;
-}
-
/* Convert CANONICAL to its string representation using
symtab_to_fullname for SYMTAB. The caller must xfree the result. */
extern int is_ada_operator (const char *string);
-/* Find an instance of the character C in the string S that is outside
- of all parenthesis pairs, single-quoted strings, and double-quoted
- strings. Also, ignore the char within a template name, like a ','
- within foo<int, int>. */
-
-extern const char *find_toplevel_char (const char *s, char c);
-
/* Find the end of the (first) linespec pointed to by *STRINGP.
STRINGP will be advanced to this point. */
default_get_string,
NULL, /* la_get_symbol_name_cmp */
iterate_over_symbols,
+ default_compute_string_hash,
&default_varobj_ops,
NULL,
NULL,
enum block_type { FUNCTION_BLOCK, NON_FUNCTION_BLOCK };
-static struct block *new_block (enum block_type);
+static struct block *new_block (enum block_type, enum language);
static struct compunit_symtab *new_symtab (const char *, int, struct objfile *);
TYPE_PROTOTYPED (SYMBOL_TYPE (s)) = 1;
/* Create and enter a new lexical context. */
- b = new_block (FUNCTION_BLOCK);
+ b = new_block (FUNCTION_BLOCK, SYMBOL_LANGUAGE (s));
SYMBOL_BLOCK_VALUE (s) = b;
BLOCK_FUNCTION (b) = s;
BLOCK_START (b) = BLOCK_END (b) = sh->value;
}
top_stack->blocktype = stBlock;
- b = new_block (NON_FUNCTION_BLOCK);
+ b = new_block (NON_FUNCTION_BLOCK, SYMBOL_LANGUAGE (s));
BLOCK_START (b) = sh->value + top_stack->procadr;
BLOCK_SUPERBLOCK (b) = top_stack->cur_block;
top_stack->cur_block = b;
if (ECOFF_IS_STAB (&sh) || (name[0] == '#'))
{
int type_code = ECOFF_UNMARK_STAB (sh.index);
+ enum language language = PST_PRIVATE (pst)->pst_language;
/* We should never get non N_STAB symbols here, but they
should be harmless, so keep process_one_symbol from
{
last_symtab_ended = 0;
process_one_symbol (type_code, 0, valu, name,
- section_offsets, objfile);
+ section_offsets, objfile, language);
}
}
/* Similarly a hack. */
else if (name[0] == '#')
{
process_one_symbol (N_SLINE, 0, valu, name,
- section_offsets, objfile);
+ section_offsets, objfile, language);
}
if (type_code == N_FUN)
{
struct compunit_symtab *cust = allocate_compunit_symtab (objfile, name);
struct symtab *symtab;
struct blockvector *bv;
+ enum language lang;
add_compunit_symtab_to_objfile (cust);
symtab = allocate_symtab (cust, name);
SYMTAB_LINETABLE (symtab) = new_linetable (maxlines);
+ lang = compunit_language (cust);
/* All symtabs must have at least two blocks. */
bv = new_bvect (2);
- BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = new_block (NON_FUNCTION_BLOCK);
- BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = new_block (NON_FUNCTION_BLOCK);
+ BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK) = new_block (NON_FUNCTION_BLOCK, lang);
+ BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK) = new_block (NON_FUNCTION_BLOCK, lang);
BLOCK_SUPERBLOCK (BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK)) =
BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
COMPUNIT_BLOCKVECTOR (cust) = bv;
hashed. */
static struct block *
-new_block (enum block_type type)
+new_block (enum block_type type, enum language language)
{
/* FIXME: carlton/2003-09-11: This should use allocate_block to
allocate the block. Which, in turn, suggests that the block
struct block *retval = XCNEW (struct block);
if (type == FUNCTION_BLOCK)
- BLOCK_DICT (retval) = dict_create_linear_expandable ();
+ BLOCK_DICT (retval) = dict_create_linear_expandable (language);
else
- BLOCK_DICT (retval) = dict_create_hashed_expandable ();
+ BLOCK_DICT (retval) = dict_create_hashed_expandable (language);
return retval;
}
default_get_string,
NULL, /* la_get_symbol_name_cmp */
iterate_over_symbols,
+ default_compute_string_hash,
&default_varobj_ops,
NULL,
NULL,
c_get_string,
NULL, /* la_get_symbol_name_cmp */
iterate_over_symbols,
+ default_compute_string_hash,
&default_varobj_ops,
NULL,
NULL,
default_get_string,
NULL, /* la_get_symbol_name_cmp */
iterate_over_symbols,
+ default_compute_string_hash,
&default_varobj_ops,
NULL,
NULL,
c_get_string,
NULL, /* la_get_symbol_name_cmp */
iterate_over_symbols,
+ default_compute_string_hash,
&default_varobj_ops,
NULL,
NULL,
along with this program. If not, see <http://www.gnu.org/licenses/>. */
struct objfile;
+enum language;
/* Definitions, prototypes, etc for stabs debugging format support
functions.
extern void process_one_symbol (int, int, CORE_ADDR, char *,
const struct section_offsets *,
- struct objfile *);
+ struct objfile *, enum language);
extern void elfstab_build_psymtabs (struct objfile *objfile,
asection *stabsect,
/* The base class. */
struct symbol base;
+ /* Search name of the template (it's name sans parameters). */
+ char *search_name;
+
/* The number of template arguments. */
int n_template_arguments;
std::cout << "hi\n"; // set breakpoint here
}
+template<typename T>
+T bar (void)
+{
+ return -100;
+}
+
+template<typename T>
+T bar(T i)
+{
+ return i;
+}
+
+template<typename T>
+T bar(T i, T j)
+{
+ return i - j;
+}
+
+namespace N
+{
+ template<typename T, int V>
+ T bar (void)
+ {
+ return static_cast<T> (V);
+ }
+
+ template<typename T, int V>
+ T bar (T i)
+ {
+ return i - static_cast<T> (V);
+ }
+
+ template<typename T, int V>
+ T bar (T i, T j)
+ {
+ return 100;
+ }
+};
+
template<class T>
void multi_line_foo(T i)
{
multi_line_foo<int>(0);
multi_line_foo<double>(0);
- return 0;
+ using namespace N;
+ return bar<int> () + bar<int> (1) + bar<int> (2, 3)
+ + bar<char> (1) + bar<char> (2, 3)
+ + bar<int, 10> () + bar<int, 10> (0) + bar<int, 10> (1, 2)
+ + bar<int, 0> ();
}
gdb_test_multiple "" $test {
-re "Breakpoint \[0-9\]+,.*foo<int> \\(i=1\\).*$gdb_prompt $" {
pass $test
- break
}
}
gdb_test "continue" \
".*Breakpoint.*multi_line_foo<double> \\(i=0\\).*" \
"run to multi_line_foo breakpoint 2 <double>"
+
+# Test setting breakpoints on template "base" names.
+
+# gdb_breakpoint is avoid in several test because we want to test
+# that multiple locations were set for each breakpoint.
+
+gdb_test "break bar" [string_to_regexp "(5 locations)"]
+gdb_test "break bar<int>" [string_to_regexp "(3 locations)"]
+gdb_test "break bar<char>" [string_to_regexp "(2 locations)"]
+gdb_breakpoint "bar<int>(void)" message
+gdb_breakpoint "bar<char>(char)" message
+gdb_test "break N::bar" [string_to_regexp "(4 locations)"]
+gdb_test "break N::bar<int,10>" [string_to_regexp "(3 locations)"]
+gdb_breakpoint "N::bar<int,10>(void)" message
+gdb_breakpoint "N::bar<int, 0> (void)" message
return p;
}
+/* See description in utils.h. */
+
+const char *
+find_toplevel_char (const char *s, char c)
+{
+ int quoted = 0; /* zero if we're not in quotes;
+ '"' if we're in a double-quoted string;
+ '\'' if we're in a single-quoted string. */
+ int depth = 0; /* Number of unclosed parens we've seen. */
+ const char *scan;
+
+ for (scan = s; *scan; scan++)
+ {
+ if (quoted)
+ {
+ if (*scan == quoted)
+ quoted = 0;
+ else if (*scan == '\\' && *(scan + 1))
+ scan++;
+ }
+ else if (*scan == c && ! quoted && depth == 0)
+ return scan;
+ else if (*scan == '"' || *scan == '\'')
+ quoted = *scan;
+ else if (*scan == '(' || *scan == '<')
+ depth++;
+ else if ((*scan == ')' || *scan == '>') && depth > 0)
+ depth--;
+ }
+
+ return 0;
+}
+
+/* See description in utils.h. */
+
+const char *
+find_toplevel_char_r (const char *s, size_t len, char c)
+{
+ int quoted = 0;
+ int depth = 0;
+ const char *scan;
+
+ for (scan = s + len; scan >= s; --scan)
+ {
+ if (quoted)
+ {
+ if (*scan == quoted)
+ quoted = 0;
+ }
+ else if (*scan == ')' || *scan == '>')
+ ++depth;
+ else if ((*scan == '(' || *scan == '<') && depth > 0)
+ --depth;
+
+ if (*scan == c && !quoted && depth == 0)
+ return scan;
+ else if ((*scan == '"' || *scan == '\'')
+ && scan > s && *(scan - 1) != '\\')
+ quoted = *scan;
+ }
+
+ return NULL;
+}
+
+/* See description in utils.h. */
+
+const char *
+find_toplevel_string (const char *haystack, const char *needle)
+{
+ const char *s = haystack;
+
+ do
+ {
+ s = find_toplevel_char (s, *needle);
+
+ if (s != NULL)
+ {
+ /* Found first char in HAYSTACK; check rest of string. */
+ if (startswith (s, needle))
+ return s;
+
+ /* Didn't find it; loop over HAYSTACK, looking for the next
+ instance of the first character of NEEDLE. */
+ ++s;
+ }
+ }
+ while (s != NULL && *s != '\0');
+
+ /* NEEDLE was not found in HAYSTACK. */
+ return NULL;
+}
+
/* Provide a prototype to silence -Wmissing-prototypes. */
extern initialize_file_ftype _initialize_utils;
extern char *make_hex_string (const gdb_byte *data, size_t length);
+/* Find an instance of the character C in the string S that is outside
+ of all parenthesis pairs, single-quoted strings, and double-quoted
+ strings. Also, ignore the char within a template name, like a ','
+ within foo<int, int>. */
+
+extern const char *find_toplevel_char (const char *s, char c);
+
+/* Like find_toplevel_char but searches S backwards, starting LEN characters
+ into S. */
+
+extern const char *find_toplevel_char_r (const char *s, size_t len, char c);
+
+/* The string equivalent of find_toplevel_char. Returns a pointer
+ to the location of NEEDLE in HAYSTACK, ignoring any occurrences
+ inside "()" and "<>". Returns NULL if NEEDLE was not found. */
+
+const char *find_toplevel_string (const char *haystack, const char *needle);
+
#endif /* UTILS_H */
last_csect_name = 0;
start_stabs ();
- start_symtab (objfile, filestring, (char *) NULL, file_start_addr);
+ start_symtab (objfile, filestring, (char *) NULL, file_start_addr,
+ language_unknown);
record_debugformat (debugfmt);
symnum = ((struct symloc *) pst->read_symtab_private)->first_symnum;
max_symnum =
}
start_stabs ();
- start_symtab (objfile, "_globals_", (char *) NULL, (CORE_ADDR) 0);
+ start_symtab (objfile, "_globals_", (char *) NULL, (CORE_ADDR) 0,
+ language_unknown);
record_debugformat (debugfmt);
cur_src_end_addr = first_object_file_end;
/* Done with all files, everything from here on is globals. */
/* Give all csects for this source file the same
name. */
start_symtab (objfile, filestring, NULL,
- (CORE_ADDR) 0);
+ (CORE_ADDR) 0, language_unknown);
record_debugformat (debugfmt);
}
filestring = cs->c_name;
start_stabs ();
- start_symtab (objfile, filestring, (char *) NULL, (CORE_ADDR) 0);
+ start_symtab (objfile, filestring, (char *) NULL, (CORE_ADDR) 0,
+ language_unknown);
record_debugformat (debugfmt);
last_csect_name = 0;