diff options
author | Pierre-Marie de Rodat <derodat@adacore.com> | 2015-07-22 15:30:57 +0200 |
---|---|---|
committer | Pierre-Marie de Rodat <derodat@adacore.com> | 2015-08-13 09:33:42 +0200 |
commit | 22cee43f9af76fc4c10c3d4018a9ada6d7c5c1a5 (patch) | |
tree | ed55bfc1342e44a3889337a8106eb75c21ccfad1 /gdb/namespace.c | |
parent | 19c2883a9b92e2be695368e19788fd0210d732d4 (diff) | |
download | gdb-22cee43f9af76fc4c10c3d4018a9ada6d7c5c1a5.zip gdb-22cee43f9af76fc4c10c3d4018a9ada6d7c5c1a5.tar.gz gdb-22cee43f9af76fc4c10c3d4018a9ada6d7c5c1a5.tar.bz2 |
[Ada] Add support for subprogram renamings
Consider the following declaration:
function Foo (I : Integer) return Integer renames Pack.Bar;
As Foo is not materialized as a routine whose name is derived from Foo,
GDB currently cannot use it:
(gdb) print foo(0)
No definition of "foo" in current context.
However, compilers can emit DW_TAG_imported_declaration in order to
materialize the fact that Foo is actually another name for Pack.Bar.
This commit enhances the DWARF reader to record global renamings (it
used to put global ones in a static block) and enhances the Ada engine
to leverage this information during symbol lookup.
gdb/ChangeLog:
* ada-lang.c: Include namespace.h
(aux_add_nonlocal_symbols): Fix a function name in comment.
(ada_add_block_renamings): New.
(add_nonlocal_symbols): Add global renamings handling.
(ada_lookup_symbol_list_worker): Move the symbol lookup part
to...
(ada_add_all_symbols): ... this new function.
(ada_add_block_symbols): Try to match the input name against the
"using directives list", perform a recursive symbol lookup on
the matched declarations.
* block.h (struct block): Move the_namespace to top-level as
namespace_info. Remove the language_specific field.
(BLOCK_NAMESPACE): Update access to the namespace_info field.
* buildsym.h (using_directives): Rename into...
(local_using_directives): ... this.
(global_using_directives): New.
(struct context_stack): Rename the using_directives field into
local_using_directives.
* buildsym.c (finish_block_internal): Deal with the proper
using directives repository (local or global).
(prepare_for_building): Reset local_using_directives. Assert
that there is no pending global using directive.
(reset_symtab_globals): Reset global_using_directives and
local_using_directives.
(end_symtab_get_static_block): Don't ignore symtabs that have
only using directives.
(push_context): Update references to local_using_directives.
(buildsym_init): Do not reset using_directives.
* cp-support.c: Include namespace.h.
* cp-support.h (struct using_direct): Move to namespace.h.
(cp_add_using_directives): Move to namespace.h.
* cp-namespace.c: Include namespace.h
(cp_add_using_directive): Move to namespace.c, rename it to
add_using_directive, add a "using_directives" argument and use
it as the pending using directives repository. All callers
updated.
* dwarf2read.c (using_directives): New.
(read_import_statement): Call using_directives.
(read_func_scope): Update references to local_using_directives.
(read_lexical_block_scope): Likewise.
(read_namespace): Update the heading comment, call
using_directives.
* namespace.h: New file.
* namespace.c: New file.
* Makefile.in (SFILES): Add namespace.c.
(COMMON_OBS): Add namespace.o
gdb/testsuite/ChangeLog:
* gdb.ada/fun_renaming.exp: New testcase.
* gdb.ada/fun_renaming/fun_renaming.adb: New file.
* gdb.ada/fun_renaming/pack.adb: New file.
* gdb.ada/fun_renaming/pack.ads: New file.
Tested on x86_64-linux. Support for this in GCC is in the pipeline: see
<https://gcc.gnu.org/ml/gcc-patches/2015-07/msg02166.html>.
Diffstat (limited to 'gdb/namespace.c')
-rw-r--r-- | gdb/namespace.c | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/gdb/namespace.c b/gdb/namespace.c new file mode 100644 index 0000000..fdbe51b --- /dev/null +++ b/gdb/namespace.c @@ -0,0 +1,117 @@ +/* Code dealing with "using" directives for GDB. + Copyright (C) 2003-2015 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include "defs.h" +#include "namespace.h" + +/* Add a using directive to USING_DIRECTIVES. If the using directive + in question has already been added, don't add it twice. + + Create a new struct using_direct which imports the namespace SRC + into the scope DEST. ALIAS is the name of the imported namespace + in the current scope. If ALIAS is NULL then the namespace is known + by its original name. DECLARATION is the name if the imported + varable if this is a declaration import (Eg. using A::x), otherwise + it is NULL. EXCLUDES is a list of names not to import from an + imported module or NULL. If COPY_NAMES is non-zero, then the + arguments are copied into newly allocated memory so they can be + temporaries. For EXCLUDES the VEC pointers are copied but the + pointed to characters are not copied. */ + +void +add_using_directive (struct using_direct **using_directives, + const char *dest, + const char *src, + const char *alias, + const char *declaration, + VEC (const_char_ptr) *excludes, + int copy_names, + struct obstack *obstack) +{ + struct using_direct *current; + struct using_direct *newobj; + + /* Has it already been added? */ + + for (current = *using_directives; current != NULL; current = current->next) + { + int ix; + const char *param; + + if (strcmp (current->import_src, src) != 0) + continue; + if (strcmp (current->import_dest, dest) != 0) + continue; + if ((alias == NULL && current->alias != NULL) + || (alias != NULL && current->alias == NULL) + || (alias != NULL && current->alias != NULL + && strcmp (alias, current->alias) != 0)) + continue; + if ((declaration == NULL && current->declaration != NULL) + || (declaration != NULL && current->declaration == NULL) + || (declaration != NULL && current->declaration != NULL + && strcmp (declaration, current->declaration) != 0)) + continue; + + /* Compare the contents of EXCLUDES. */ + for (ix = 0; VEC_iterate (const_char_ptr, excludes, ix, param); ix++) + if (current->excludes[ix] == NULL + || strcmp (param, current->excludes[ix]) != 0) + break; + if (ix < VEC_length (const_char_ptr, excludes) + || current->excludes[ix] != NULL) + continue; + + /* Parameters exactly match CURRENT. */ + return; + } + + newobj = obstack_alloc (obstack, (sizeof (*newobj) + + (VEC_length (const_char_ptr, excludes) + * sizeof (*newobj->excludes)))); + memset (newobj, 0, sizeof (*newobj)); + + if (copy_names) + { + newobj->import_src = obstack_copy0 (obstack, src, strlen (src)); + newobj->import_dest = obstack_copy0 (obstack, dest, strlen (dest)); + } + else + { + newobj->import_src = src; + newobj->import_dest = dest; + } + + if (alias != NULL && copy_names) + newobj->alias = obstack_copy0 (obstack, alias, strlen (alias)); + else + newobj->alias = alias; + + if (declaration != NULL && copy_names) + newobj->declaration = obstack_copy0 (obstack, + declaration, strlen (declaration)); + else + newobj->declaration = declaration; + + memcpy (newobj->excludes, VEC_address (const_char_ptr, excludes), + VEC_length (const_char_ptr, excludes) * sizeof (*newobj->excludes)); + newobj->excludes[VEC_length (const_char_ptr, excludes)] = NULL; + + newobj->next = *using_directives; + *using_directives = newobj; +} |