[Ada] Add support for subprogram renamings

Message ID 55C225E1.6020109@adacore.com
State New, archived
Headers

Commit Message

Pierre-Marie de Rodat Aug. 5, 2015, 3:04 p.m. UTC
  Hi Doug,

Thanks again for reviewing my patches!

On 07/26/2015 11:29 AM, Doug Evans wrote:
>> 	* ada-lang.c: Include cp-support.h
>
> ada-foo including cp-foo?
> We need to clean this up.
> Things are even muddier as this stuff is recorded in
> block.language_specific.cplus_specific, so cleaning this up now will be good.
>
> I gather cp-support.h is needed here for struct using_direct.
> I think (at least) three things need to happen.
> 1) Move the definition of struct using_direct out of cp-support.h.
> 2) Move the definition of cp_add_using_directive out of cp-namespace.c.
>     And delete the leading "cp_".
> 3) Reorg block.language_specific.
>
> For the first two I'd be ok with lang-support.[ch].
> Yeah, it'll be a small file for now, but that's ok IMO.
> Alternatives are language.[ch] or block.[ch].

Quoting myself on IRC:
> xdje: hello! in
> https://sourceware.org/ml/gdb-patches/2015-07/msg00768.html you
> suggested to move namespace bits in a new file
>
> I think that makes sense too, but lang-support.* does not
>
> I mean… symtab, block, etc. all are about source debugging… and thus
> languages support
>
> so I’m tempted to create instead namespace.* or else to move this to
> block.*
>
> what do you think?

So I created namespace.[ch]. Please tell me if that's fine, otherwise I 
can switch to the names you suggested.

> For (3), in the absence of needing anything more at the moment,
> I'd be ok with replacing:
>
>    union
>    {
>      struct
>      {
>        /* Contains information about namespace-related info relevant to
> 	 this block: using directives and the current namespace
> 	 scope.  */
>
>        struct block_namespace_info *the_namespace;
>      }
>      cplus_specific;
>    }
>    language_specific;
>
> with just:
>
>    /* Contains information about namespace-related info relevant to
>       this block: using directives and the current namespace scope.  */
>    struct block_namespace_info *the_namespace;
>
> though I'd probably rename "the_namespace" to "namespace_info"
> or some such.

Done.

> Missing "All callers updated."
>
>> 	(cp_scan_for_anonymous_namespaces): Update call to
>> 	cp_add_using_directive.
>
> ====
> Don't write individual changelog entries for updates to function calls.
> Instead, just write "All callers updated." at the description of
> the function that was changed.

Understood. I updated the ChangeLog accordingly.

>> @@ -1018,6 +1025,7 @@ prepare_for_building (const char *name, CORE_ADDR start_addr)
>>        a symtab, or by the really_free_pendings cleanup.  */
>>     gdb_assert (file_symbols == NULL);
>>     gdb_assert (global_symbols == NULL);
>> +  gdb_assert (global_using_directives == NULL);
>
> ====
> I've put a lot of time into cleaning up buildsym.[ch] but we
> still have a long way to go (for at least a few reasons).
> I don't have a strong preference, but prepare_for_building should do
> *something* with local_using_directives.  I think it doesn't because
> I was making so many changes I punted on this part.  What's there
> now leaves one wondering (e.g., why does buildsym_init initialize
> local_using_directives? and why doesn't reset_symtab_globals reset
> local_using_directives? and there are more.).
> But I'm happy with leaving this for later,
> I just wanted to point out the issue.

Understood, thank you for the background. I tried anyway to make this as 
consistent as possible between global/local_using_directives: I added 
resetting local_using_directives in prepare_for_building and 
reset_symtab_globals and I removed the reset in buildsym_init.

>> +	  cp_add_using_directive ((context_stack_depth > 0)
>> +				    ? &local_using_directives
>> +				    : &global_using_directives,
>
> ====
> Indentation is wrong.
> Typically what we do is surround the entire argument in () and indent
> like so:
>
>     (foo > 0
>      ? bar
>      : baz),

Thanks. I have fixed this occurence and the other ones.

> Plus this needs a language_ada check (right?).

Yes indeed! As the check has a big comment explaining it, I've created a 
function (using_directives) to have a single place for it and updated 
code to reference it.

So the updated patch is attached, tested with a trunk GCC on 
x86_64-linux. For the record, the corresponding GCC patch isn't in trunk 
yet (pending review).
  

Comments

Doug Evans Aug. 13, 2015, 3:55 a.m. UTC | #1
Pierre-Marie de Rodat <derodat@adacore.com> writes:
> Hi Doug,
>
> Thanks again for reviewing my patches!
>
> ...
> Quoting myself on IRC:
>> xdje: hello! in
>> https://sourceware.org/ml/gdb-patches/2015-07/msg00768.html you
>> suggested to move namespace bits in a new file
>>
>> I think that makes sense too, but lang-support.* does not
>>
>> I mean… symtab, block, etc. all are about source debugging… and thus
>> languages support
>>
>> so I’m tempted to create instead namespace.* or else to move this to
>> block.*
>>
>> what do you think?
>
> So I created namespace.[ch]. Please tell me if that's fine, otherwise
> I can switch to the names you suggested.

Fine by me.

>...
>
> 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.

LGTM
  
Pierre-Marie de Rodat Aug. 13, 2015, 7:38 a.m. UTC | #2
On 08/13/2015 05:55 AM, Doug Evans wrote:
> LGTM

It is pushed, now. Thanks again, Doug. :-)
  

Patch

From 072bac50a606f9445b3dba7d7eb81928990dfa7f Mon Sep 17 00:00:00 2001
From: Pierre-Marie de Rodat <derodat@adacore.com>
Date: Wed, 22 Jul 2015 15:30:57 +0200
Subject: [PATCH] [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>.
---
 gdb/Makefile.in                                    |   3 +-
 gdb/ada-lang.c                                     | 199 +++++++++++++++------
 gdb/block.h                                        |  19 +-
 gdb/buildsym.c                                     |  24 ++-
 gdb/buildsym.h                                     |   8 +-
 gdb/cp-namespace.c                                 | 102 +----------
 gdb/cp-support.c                                   |   1 +
 gdb/cp-support.h                                   |  92 +---------
 gdb/dwarf2read.c                                   |  49 +++--
 gdb/namespace.c                                    | 117 ++++++++++++
 gdb/namespace.h                                    | 118 ++++++++++++
 gdb/testsuite/gdb.ada/fun_renaming.exp             |  83 +++++++++
 .../gdb.ada/fun_renaming/fun_renaming.adb          |  23 +++
 gdb/testsuite/gdb.ada/fun_renaming/pack.adb        |  26 +++
 gdb/testsuite/gdb.ada/fun_renaming/pack.ads        |  22 +++
 15 files changed, 608 insertions(+), 278 deletions(-)
 create mode 100644 gdb/namespace.c
 create mode 100644 gdb/namespace.h
 create mode 100644 gdb/testsuite/gdb.ada/fun_renaming.exp
 create mode 100644 gdb/testsuite/gdb.ada/fun_renaming/fun_renaming.adb
 create mode 100644 gdb/testsuite/gdb.ada/fun_renaming/pack.adb
 create mode 100644 gdb/testsuite/gdb.ada/fun_renaming/pack.ads

diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 4080ba4..93487ba 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -859,6 +859,7 @@  SFILES = ada-exp.y ada-lang.c ada-typeprint.c ada-valprint.c ada-tasks.c \
 	macrotab.c macroexp.c macrocmd.c macroscope.c main.c maint.c \
 	mdebugread.c memattr.c mem-break.c minsyms.c mipsread.c memory-map.c \
 	memrange.c mi/mi-common.c \
+	namespace.c \
 	objc-lang.c \
 	objfiles.c osabi.c observer.c osdata.c \
 	opencl-lang.c \
@@ -1022,7 +1023,7 @@  COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
 	charset.o continuations.o corelow.o disasm.o dummy-frame.o dfp.o \
 	source.o value.o eval.o valops.o valarith.o valprint.o printcmd.o \
 	block.o symtab.o psymtab.o symfile.o symfile-debug.o symmisc.o \
-	linespec.o dictionary.o \
+	linespec.o dictionary.o namespace.o \
 	infcall.o \
 	infcmd.o infrun.o \
 	expprint.o environ.o stack.o thread.o \
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 9f9be64..1fa65244 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -53,6 +53,7 @@ 
 #include "stack.h"
 #include "gdb_vecs.h"
 #include "typeprint.h"
+#include "namespace.h"
 
 #include "psymtab.h"
 #include "value.h"
@@ -108,6 +109,9 @@  static void ada_add_block_symbols (struct obstack *,
                                    const struct block *, const char *,
                                    domain_enum, struct objfile *, int);
 
+static void ada_add_all_symbols (struct obstack *, const struct block *,
+				 const char *, domain_enum, int, int *);
+
 static int is_nonfunction (struct block_symbol *, int);
 
 static void add_defn_to_vec (struct obstack *, struct symbol *,
@@ -5289,7 +5293,7 @@  struct match_data
   int found_sym;
 };
 
-/* A callback for add_matching_symbols that adds SYM, found in BLOCK,
+/* A callback for add_nonlocal_symbols that adds SYM, found in BLOCK,
    to a list of symbols.  DATA0 is a pointer to a struct match_data *
    containing the obstack that collects the symbol list, the file that SYM
    must come from, a flag indicating whether a non-argument symbol has
@@ -5329,6 +5333,62 @@  aux_add_nonlocal_symbols (struct block *block, struct symbol *sym, void *data0)
   return 0;
 }
 
+/* Helper for add_nonlocal_symbols.  Find symbols in DOMAIN which are targetted
+   by renamings matching NAME in BLOCK.  Add these symbols to OBSTACKP.  If
+   WILD_MATCH_P is nonzero, perform the naming matching in "wild" mode (see
+   function "wild_match" for more information).  Return whether we found such
+   symbols.  */
+
+static int
+ada_add_block_renamings (struct obstack *obstackp,
+			 const struct block *block,
+			 const char *name,
+			 domain_enum domain,
+			 int wild_match_p)
+{
+  struct using_direct *renaming;
+  int defns_mark = num_defns_collected (obstackp);
+
+  for (renaming = block_using (block);
+       renaming != NULL;
+       renaming = renaming->next)
+    {
+      const char *r_name;
+      int name_match;
+
+      /* Avoid infinite recursions: skip this renaming if we are actually
+	 already traversing it.
+
+	 Currently, symbol lookup in Ada don't use the namespace machinery from
+	 C++/Fortran support: skip namespace imports that use them.  */
+      if (renaming->searched
+	  || (renaming->import_src != NULL
+	      && renaming->import_src[0] != '\0')
+	  || (renaming->import_dest != NULL
+	      && renaming->import_dest[0] != '\0'))
+	continue;
+      renaming->searched = 1;
+
+      /* TODO: here, we perform another name-based symbol lookup, which can
+	 pull its own multiple overloads.  In theory, we should be able to do
+	 better in this case since, in DWARF, DW_AT_import is a DIE reference,
+	 not a simple name.  But in order to do this, we would need to enhance
+	 the DWARF reader to associate a symbol to this renaming, instead of a
+	 name.  So, for now, we do something simpler: re-use the C++/Fortran
+	 namespace machinery.  */
+      r_name = (renaming->alias != NULL
+		? renaming->alias
+		: renaming->declaration);
+      name_match
+	= wild_match_p ? wild_match (r_name, name) : strcmp (r_name, name);
+      if (name_match == 0)
+	ada_add_all_symbols (obstackp, block, renaming->declaration, domain,
+			     1, NULL);
+      renaming->searched = 0;
+    }
+  return num_defns_collected (obstackp) != defns_mark;
+}
+
 /* Implements compare_names, but only applying the comparision using
    the given CASING.  */
 
@@ -5424,6 +5484,7 @@  add_nonlocal_symbols (struct obstack *obstackp, const char *name,
 		      int is_wild_match)
 {
   struct objfile *objfile;
+  struct compunit_symtab *cu;
   struct match_data data;
 
   memset (&data, 0, sizeof data);
@@ -5441,6 +5502,16 @@  add_nonlocal_symbols (struct obstack *obstackp, const char *name,
 	objfile->sf->qf->map_matching_symbols (objfile, name, domain, global,
 					       aux_add_nonlocal_symbols, &data,
 					       full_match, compare_names);
+
+      ALL_OBJFILE_COMPUNITS (objfile, cu)
+	{
+	  const struct block *global_block
+	    = BLOCKVECTOR_BLOCK (COMPUNIT_BLOCKVECTOR (cu), GLOBAL_BLOCK);
+
+	  if (ada_add_block_renamings (obstackp, global_block , name, domain,
+				       is_wild_match))
+	    data.found_sym = 1;
+	}
     }
 
   if (num_defns_collected (obstackp) == 0 && global && !is_wild_match)
@@ -5460,43 +5531,35 @@  add_nonlocal_symbols (struct obstack *obstackp, const char *name,
     }      	
 }
 
-/* Find symbols in DOMAIN matching NAME0, in BLOCK0 and, if full_search is
+/* Find symbols in DOMAIN matching NAME, in BLOCK and, if FULL_SEARCH is
    non-zero, enclosing scope and in global scopes, returning the number of
-   matches.
-   Sets *RESULTS to point to a vector of (SYM,BLOCK) tuples,
-   indicating the symbols found and the blocks and symbol tables (if
-   any) in which they were found.  This vector is transient---good only to
-   the next call of ada_lookup_symbol_list.
+   matches.  Add these to OBSTACKP.
 
-   When full_search is non-zero, any non-function/non-enumeral
-   symbol match within the nest of blocks whose innermost member is BLOCK0,
+   When FULL_SEARCH is non-zero, any non-function/non-enumeral
+   symbol match within the nest of blocks whose innermost member is BLOCK,
    is the one match returned (no other matches in that or
    enclosing blocks is returned).  If there are any matches in or
-   surrounding BLOCK0, then these alone are returned.
+   surrounding BLOCK, then these alone are returned.
 
    Names prefixed with "standard__" are handled specially: "standard__"
-   is first stripped off, and only static and global symbols are searched.  */
+   is first stripped off, and only static and global symbols are searched.
 
-static int
-ada_lookup_symbol_list_worker (const char *name0, const struct block *block0,
-			       domain_enum domain,
-			       struct block_symbol **results,
-			       int full_search)
+   If MADE_GLOBAL_LOOKUP_P is non-null, set it before return to whether we had
+   to lookup global symbols.  */
+
+static void
+ada_add_all_symbols (struct obstack *obstackp,
+		     const struct block *block,
+		     const char *name,
+		     domain_enum domain,
+		     int full_search,
+		     int *made_global_lookup_p)
 {
   struct symbol *sym;
-  const struct block *block;
-  const char *name;
-  const int wild_match_p = should_use_wild_match (name0);
-  int syms_from_global_search = 0;
-  int ndefns;
-
-  obstack_free (&symbol_list_obstack, NULL);
-  obstack_init (&symbol_list_obstack);
-
-  /* Search specified block and its superiors.  */
+  const int wild_match_p = should_use_wild_match (name);
 
-  name = name0;
-  block = block0;
+  if (made_global_lookup_p)
+    *made_global_lookup_p = 0;
 
   /* Special case: If the user specifies a symbol name inside package
      Standard, do a non-wild matching of the symbol name without
@@ -5505,10 +5568,10 @@  ada_lookup_symbol_list_worker (const char *name0, const struct block *block0,
      using, for instance, Standard.Constraint_Error when Constraint_Error
      is ambiguous (due to the user defining its own Constraint_Error
      entity inside its program).  */
-  if (startswith (name0, "standard__"))
+  if (startswith (name, "standard__"))
     {
       block = NULL;
-      name = name0 + sizeof ("standard__") - 1;
+      name = name + sizeof ("standard__") - 1;
     }
 
   /* Check the non-global symbols.  If we have ANY match, then we're done.  */
@@ -5516,61 +5579,88 @@  ada_lookup_symbol_list_worker (const char *name0, const struct block *block0,
   if (block != NULL)
     {
       if (full_search)
-	{
-	  ada_add_local_symbols (&symbol_list_obstack, name, block,
-				 domain, wild_match_p);
-	}
+	ada_add_local_symbols (obstackp, name, block, domain, wild_match_p);
       else
 	{
 	  /* In the !full_search case we're are being called by
 	     ada_iterate_over_symbols, and we don't want to search
 	     superblocks.  */
-	  ada_add_block_symbols (&symbol_list_obstack, block, name,
-				 domain, NULL, wild_match_p);
+	  ada_add_block_symbols (obstackp, block, name, domain, NULL,
+				 wild_match_p);
 	}
-      if (num_defns_collected (&symbol_list_obstack) > 0 || !full_search)
-	goto done;
+      if (num_defns_collected (obstackp) > 0 || !full_search)
+	return;
     }
 
   /* No non-global symbols found.  Check our cache to see if we have
      already performed this search before.  If we have, then return
      the same result.  */
 
-  if (lookup_cached_symbol (name0, domain, &sym, &block))
+  if (lookup_cached_symbol (name, domain, &sym, &block))
     {
       if (sym != NULL)
-        add_defn_to_vec (&symbol_list_obstack, sym, block);
-      goto done;
+        add_defn_to_vec (obstackp, sym, block);
+      return;
     }
 
-  syms_from_global_search = 1;
+  if (made_global_lookup_p)
+    *made_global_lookup_p = 1;
 
   /* Search symbols from all global blocks.  */
  
-  add_nonlocal_symbols (&symbol_list_obstack, name, domain, 1,
-			wild_match_p);
+  add_nonlocal_symbols (obstackp, name, domain, 1, wild_match_p);
 
   /* Now add symbols from all per-file blocks if we've gotten no hits
      (not strictly correct, but perhaps better than an error).  */
 
-  if (num_defns_collected (&symbol_list_obstack) == 0)
-    add_nonlocal_symbols (&symbol_list_obstack, name, domain, 0,
-			  wild_match_p);
+  if (num_defns_collected (obstackp) == 0)
+    add_nonlocal_symbols (obstackp, name, domain, 0, wild_match_p);
+}
+
+/* Find symbols in DOMAIN matching NAME, in BLOCK and, if full_search is
+   non-zero, enclosing scope and in global scopes, returning the number of
+   matches.
+   Sets *RESULTS to point to a vector of (SYM,BLOCK) tuples,
+   indicating the symbols found and the blocks and symbol tables (if
+   any) in which they were found.  This vector is transient---good only to
+   the next call of ada_lookup_symbol_list.
+
+   When full_search is non-zero, any non-function/non-enumeral
+   symbol match within the nest of blocks whose innermost member is BLOCK,
+   is the one match returned (no other matches in that or
+   enclosing blocks is returned).  If there are any matches in or
+   surrounding BLOCK, then these alone are returned.
+
+   Names prefixed with "standard__" are handled specially: "standard__"
+   is first stripped off, and only static and global symbols are searched.  */
+
+static int
+ada_lookup_symbol_list_worker (const char *name, const struct block *block,
+			       domain_enum domain,
+			       struct block_symbol **results,
+			       int full_search)
+{
+  const int wild_match_p = should_use_wild_match (name);
+  int syms_from_global_search;
+  int ndefns;
+
+  obstack_free (&symbol_list_obstack, NULL);
+  obstack_init (&symbol_list_obstack);
+  ada_add_all_symbols (&symbol_list_obstack, block, name, domain,
+		       full_search, &syms_from_global_search);
 
-done:
   ndefns = num_defns_collected (&symbol_list_obstack);
   *results = defns_collected (&symbol_list_obstack, 1);
 
   ndefns = remove_extra_symbols (*results, ndefns);
 
   if (ndefns == 0 && full_search && syms_from_global_search)
-    cache_symbol (name0, domain, NULL, NULL);
+    cache_symbol (name, domain, NULL, NULL);
 
   if (ndefns == 1 && full_search && syms_from_global_search)
-    cache_symbol (name0, domain, (*results)[0].symbol, (*results)[0].block);
-
-  ndefns = remove_irrelevant_renamings (*results, ndefns, block0);
+    cache_symbol (name, domain, (*results)[0].symbol, (*results)[0].block);
 
+  ndefns = remove_irrelevant_renamings (*results, ndefns, block);
   return ndefns;
 }
 
@@ -6037,6 +6127,11 @@  ada_add_block_symbols (struct obstack *obstackp,
       }
     }
 
+  /* Handle renamings.  */
+
+  if (ada_add_block_renamings (obstackp, block, name, domain, wild))
+    found_sym = 1;
+
   if (!found_sym && arg_sym != NULL)
     {
       add_defn_to_vec (obstackp,
diff --git a/gdb/block.h b/gdb/block.h
index d8ad343..3dbcbcb 100644
--- a/gdb/block.h
+++ b/gdb/block.h
@@ -82,21 +82,10 @@  struct block
 
   struct dictionary *dict;
 
-  /* Used for language-specific info.  */
+  /* Contains information about namespace-related info relevant to this block:
+     using directives and the current namespace scope.  */
 
-  union
-  {
-    struct
-    {
-      /* Contains information about namespace-related info relevant to
-	 this block: using directives and the current namespace
-	 scope.  */
-      
-      struct block_namespace_info *the_namespace;
-    }
-    cplus_specific;
-  }
-  language_specific;
+  struct block_namespace_info *namespace_info;
 };
 
 /* The global block is singled out so that we can provide a back-link
@@ -118,7 +107,7 @@  struct global_block
 #define BLOCK_FUNCTION(bl)	(bl)->function
 #define BLOCK_SUPERBLOCK(bl)	(bl)->superblock
 #define BLOCK_DICT(bl)		(bl)->dict
-#define BLOCK_NAMESPACE(bl)   (bl)->language_specific.cplus_specific.the_namespace
+#define BLOCK_NAMESPACE(bl)	(bl)->namespace_info
 
 struct blockvector
 {
diff --git a/gdb/buildsym.c b/gdb/buildsym.c
index 2a24a25..92c42d5 100644
--- a/gdb/buildsym.c
+++ b/gdb/buildsym.c
@@ -503,8 +503,15 @@  finish_block_internal (struct symbol *symbol, struct pending **listhead,
       opblock = pblock;
     }
 
-  block_set_using (block, using_directives, &objfile->objfile_obstack);
-  using_directives = NULL;
+  block_set_using (block,
+		   (is_global
+		    ? global_using_directives
+		    : local_using_directives),
+		   &objfile->objfile_obstack);
+  if (is_global)
+    global_using_directives = NULL;
+  else
+    local_using_directives = NULL;
 
   record_pending_block (objfile, block, opblock);
 
@@ -1009,6 +1016,7 @@  prepare_for_building (const char *name, CORE_ADDR start_addr)
   last_source_start_addr = start_addr;
 
   local_symbols = NULL;
+  local_using_directives = NULL;
   within_function = 0;
   have_line_numbers = 0;
 
@@ -1018,6 +1026,7 @@  prepare_for_building (const char *name, CORE_ADDR start_addr)
      a symtab, or by the really_free_pendings cleanup.  */
   gdb_assert (file_symbols == NULL);
   gdb_assert (global_symbols == NULL);
+  gdb_assert (global_using_directives == NULL);
   gdb_assert (pending_macros == NULL);
   gdb_assert (pending_addrmap == NULL);
   gdb_assert (current_subfile == NULL);
@@ -1177,8 +1186,10 @@  reset_symtab_globals (void)
   set_last_source_file (NULL);
 
   local_symbols = NULL;
+  local_using_directives = NULL;
   file_symbols = NULL;
   global_symbols = NULL;
+  global_using_directives = NULL;
 
   /* We don't free pending_macros here because if the symtab was successfully
      built then ownership was transferred to the symtab.  */
@@ -1281,7 +1292,8 @@  end_symtab_get_static_block (CORE_ADDR end_addr, int expandable, int required)
       && file_symbols == NULL
       && global_symbols == NULL
       && have_line_numbers == 0
-      && pending_macros == NULL)
+      && pending_macros == NULL
+      && global_using_directives == NULL)
     {
       /* Ignore symtabs that have no functions with real debugging info.  */
       return NULL;
@@ -1637,11 +1649,11 @@  push_context (int desc, CORE_ADDR valu)
   newobj->locals = local_symbols;
   newobj->old_blocks = pending_blocks;
   newobj->start_addr = valu;
-  newobj->using_directives = using_directives;
+  newobj->local_using_directives = local_using_directives;
   newobj->name = NULL;
 
   local_symbols = NULL;
-  using_directives = NULL;
+  local_using_directives = NULL;
 
   return newobj;
 }
@@ -1740,7 +1752,6 @@  get_last_source_file (void)
 void
 buildsym_init (void)
 {
-  using_directives = NULL;
   subfile_stack = NULL;
 
   pending_addrmap_interesting = 0;
@@ -1760,6 +1771,7 @@  buildsym_init (void)
   gdb_assert (pending_blocks == NULL);
   gdb_assert (file_symbols == NULL);
   gdb_assert (global_symbols == NULL);
+  gdb_assert (global_using_directives == NULL);
   gdb_assert (pending_macros == NULL);
   gdb_assert (pending_addrmap == NULL);
   gdb_assert (buildsym_compunit == NULL);
diff --git a/gdb/buildsym.h b/gdb/buildsym.h
index f98203e..4c0ec15 100644
--- a/gdb/buildsym.h
+++ b/gdb/buildsym.h
@@ -118,7 +118,11 @@  EXTERN struct pending *local_symbols;
 
 /* "using" directives local to lexical context.  */
 
-EXTERN struct using_direct *using_directives;
+EXTERN struct using_direct *local_using_directives;
+
+/* global "using" directives.  */
+
+EXTERN struct using_direct *global_using_directives;
 
 /* Stack representing unclosed lexical contexts (that will become
    blocks, eventually).  */
@@ -131,7 +135,7 @@  struct context_stack
 
     /* Pending using directives at the time we entered.  */
 
-    struct using_direct *using_directives;
+    struct using_direct *local_using_directives;
 
     /* Pointer into blocklist as of entry */
 
diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c
index f5f4bad..b8b19ed 100644
--- a/gdb/cp-namespace.c
+++ b/gdb/cp-namespace.c
@@ -31,6 +31,7 @@ 
 #include "frame.h"
 #include "buildsym.h"
 #include "language.h"
+#include "namespace.h"
 
 static struct block_symbol
   cp_lookup_nested_symbol_1 (struct type *container_type,
@@ -91,8 +92,9 @@  cp_scan_for_anonymous_namespaces (const struct symbol *const symbol,
 		 anonymous namespace.  So add symbols in it to the
 		 namespace given by the previous component if there is
 		 one, or to the global namespace if there isn't.  */
-	      cp_add_using_directive (dest, src, NULL, NULL, NULL, 1,
-	                              &objfile->objfile_obstack);
+	      add_using_directive (&local_using_directives,
+				   dest, src, NULL, NULL, NULL, 1,
+				   &objfile->objfile_obstack);
 	    }
 	  /* The "+ 2" is for the "::".  */
 	  previous_component = next_component + 2;
@@ -103,102 +105,6 @@  cp_scan_for_anonymous_namespaces (const struct symbol *const symbol,
     }
 }
 
-/* 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
-cp_add_using_directive (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;
-}
-
 /* Test whether or not NAMESPACE looks like it mentions an anonymous
    namespace; return nonzero if so.  */
 
diff --git a/gdb/cp-support.c b/gdb/cp-support.c
index 1625d72..dc0a057 100644
--- a/gdb/cp-support.c
+++ b/gdb/cp-support.c
@@ -32,6 +32,7 @@ 
 #include "expression.h"
 #include "value.h"
 #include "cp-abi.h"
+#include "namespace.h"
 #include <signal.h>
 
 #include "safe-ctype.h"
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index f9aac3f..12d8d80 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -36,6 +36,7 @@  struct block;
 struct objfile;
 struct type;
 struct demangle_component;
+struct using_direct;
 
 /* A string representing the name of the anonymous namespace used in GDB.  */
 
@@ -59,89 +60,6 @@  struct demangle_parse_info
   struct obstack obstack;
 };
 
-/* This struct is designed to store data from using directives.  It
-   says that names from namespace IMPORT_SRC should be visible within
-   namespace IMPORT_DEST.  These form a linked list; NEXT is the next
-   element of the list.  If the imported namespace or declaration has
-   been aliased within the IMPORT_DEST namespace, ALIAS is set to a
-   string representing the alias.  Otherwise, ALIAS is NULL.
-   DECLARATION is the name of the imported declaration, if this import
-   statement represents one.  Otherwise DECLARATION is NULL and this
-   import statement represents a namespace.
-
-   C++:      using namespace A;
-   Fortran:  use A
-   import_src = "A"
-   import_dest = local scope of the import statement even such as ""
-   alias = NULL
-   declaration = NULL
-   excludes = NULL
-
-   C++:      using A::x;
-   Fortran:  use A, only: x
-   import_src = "A"
-   import_dest = local scope of the import statement even such as ""
-   alias = NULL
-   declaration = "x"
-   excludes = NULL
-   The declaration will get imported as import_dest::x.
-
-   C++ has no way to import all names except those listed ones.
-   Fortran:  use A, localname => x
-   import_src = "A"
-   import_dest = local scope of the import statement even such as ""
-   alias = "localname"
-   declaration = "x"
-   excludes = NULL
-   +
-   import_src = "A"
-   import_dest = local scope of the import statement even such as ""
-   alias = NULL
-   declaration = NULL
-   excludes = ["x"]
-   All the entries of A get imported except of "x".  "x" gets imported as
-   "localname".  "x" is not defined as a local name by this statement.
-
-   C++:      namespace LOCALNS = A;
-   Fortran has no way to address non-local namespace/module.
-   import_src = "A"
-   import_dest = local scope of the import statement even such as ""
-   alias = "LOCALNS"
-   declaration = NULL
-   excludes = NULL
-   The namespace will get imported as the import_dest::LOCALNS
-   namespace.
-
-   C++ cannot express it, it would be something like: using localname
-   = A::x;
-   Fortran:  use A, only localname => x
-   import_src = "A"
-   import_dest = local scope of the import statement even such as ""
-   alias = "localname"
-   declaration = "x"
-   excludes = NULL
-   The declaration will get imported as localname or
-   `import_dest`localname.  */
-
-struct using_direct
-{
-  const char *import_src;
-  const char *import_dest;
-
-  const char *alias;
-  const char *declaration;
-
-  struct using_direct *next;
-
-  /* Used during import search to temporarily mark this node as
-     searched.  */
-  int searched;
-
-  /* USING_DIRECT has variable allocation size according to the number of
-     EXCLUDES entries, the last entry is NULL.  */
-  const char *excludes[1];
-};
-
 
 /* Functions from cp-support.c.  */
 
@@ -181,14 +99,6 @@  extern struct type *cp_lookup_rtti_type (const char *name,
 
 extern int cp_is_in_anonymous (const char *symbol_name);
 
-extern void cp_add_using_directive (const char *dest,
-                                    const char *src,
-                                    const char *alias,
-				    const char *declaration,
-				    VEC (const_char_ptr) *excludes,
-				    int copy_names,
-                                    struct obstack *obstack);
-
 extern void cp_scan_for_anonymous_namespaces (const struct symbol *symbol,
 					      struct objfile *objfile);
 
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index b5ffd04..b38e8fc 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -69,6 +69,7 @@ 
 #include "source.h"
 #include "filestuff.h"
 #include "build-id.h"
+#include "namespace.h"
 
 #include <fcntl.h>
 #include <sys/types.h>
@@ -1635,6 +1636,8 @@  static void read_namespace (struct die_info *die, struct dwarf2_cu *);
 
 static void read_module (struct die_info *die, struct dwarf2_cu *cu);
 
+static struct using_direct **using_directives (enum language);
+
 static void read_import_statement (struct die_info *die, struct dwarf2_cu *);
 
 static int read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu);
@@ -8863,6 +8866,24 @@  read_namespace_alias (struct die_info *die, struct dwarf2_cu *cu)
   return 0;
 }
 
+/* Return the using directives repository (global or local?) to use in the
+   current context for LANGUAGE.
+
+   For Ada, imported declarations can materialize renamings, which *may* be
+   global.  However it is impossible (for now?) in DWARF to distinguish
+   "external" imported declarations and "static" ones.  As all imported
+   declarations seem to be static in all other languages, make them all CU-wide
+   global only in Ada.  */
+
+static struct using_direct **
+using_directives (enum language language)
+{
+  if (language == language_ada && context_stack_depth == 0)
+    return &global_using_directives;
+  else
+    return &local_using_directives;
+}
+
 /* Read the import statement specified by the given die and record it.  */
 
 static void
@@ -8999,13 +9020,14 @@  read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
 	process_die (child_die, cu);
       }
 
-  cp_add_using_directive (import_prefix,
-                          canonical_name,
-                          import_alias,
-                          imported_declaration,
-			  excludes,
-			  0,
-                          &objfile->objfile_obstack);
+  add_using_directive (using_directives (cu->language),
+		       import_prefix,
+		       canonical_name,
+		       import_alias,
+		       imported_declaration,
+		       excludes,
+		       0,
+		       &objfile->objfile_obstack);
 
   do_cleanups (cleanups);
 }
@@ -11485,7 +11507,7 @@  read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
      when we finish processing a function scope, we may need to go
      back to building a containing block's symbol lists.  */
   local_symbols = newobj->locals;
-  using_directives = newobj->using_directives;
+  local_using_directives = newobj->local_using_directives;
 
   /* If we've finished processing a top-level function, subsequent
      symbols go in the file symbol list.  */
@@ -11531,7 +11553,7 @@  read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
   inherit_abstract_dies (die, cu);
   newobj = pop_context ();
 
-  if (local_symbols != NULL || using_directives != NULL)
+  if (local_symbols != NULL || local_using_directives != NULL)
     {
       struct block *block
         = finish_block (0, &local_symbols, newobj->old_blocks,
@@ -11550,7 +11572,7 @@  read_lexical_block_scope (struct die_info *die, struct dwarf2_cu *cu)
       dwarf2_record_block_ranges (die, block, baseaddr, cu);
     }
   local_symbols = newobj->locals;
-  using_directives = newobj->using_directives;
+  local_using_directives = newobj->local_using_directives;
 }
 
 /* Read in DW_TAG_GNU_call_site and insert it to CU->call_site_htab.  */
@@ -14075,7 +14097,7 @@  read_namespace_type (struct die_info *die, struct dwarf2_cu *cu)
   return set_die_type (die, type, cu);
 }
 
-/* Read a C++ namespace.  */
+/* Read a namespace scope.  */
 
 static void
 read_namespace (struct die_info *die, struct dwarf2_cu *cu)
@@ -14099,8 +14121,9 @@  read_namespace (struct die_info *die, struct dwarf2_cu *cu)
 	{
 	  const char *previous_prefix = determine_prefix (die, cu);
 
-	  cp_add_using_directive (previous_prefix, TYPE_NAME (type), NULL,
-				  NULL, NULL, 0, &objfile->objfile_obstack);
+	  add_using_directive (using_directives (cu->language),
+			       previous_prefix, TYPE_NAME (type), NULL,
+			       NULL, NULL, 0, &objfile->objfile_obstack);
 	}
     }
 
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;
+}
diff --git a/gdb/namespace.h b/gdb/namespace.h
new file mode 100644
index 0000000..aa73f4a
--- /dev/null
+++ b/gdb/namespace.h
@@ -0,0 +1,118 @@ 
+/* 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/>.  */
+
+#ifndef NAMESPACE_H
+#define NAMESPACE_H
+
+#include "vec.h"
+#include "gdb_vecs.h"
+#include "gdb_obstack.h"
+
+/* This struct is designed to store data from using directives.  It
+   says that names from namespace IMPORT_SRC should be visible within
+   namespace IMPORT_DEST.  These form a linked list; NEXT is the next
+   element of the list.  If the imported namespace or declaration has
+   been aliased within the IMPORT_DEST namespace, ALIAS is set to a
+   string representing the alias.  Otherwise, ALIAS is NULL.
+   DECLARATION is the name of the imported declaration, if this import
+   statement represents one.  Otherwise DECLARATION is NULL and this
+   import statement represents a namespace.
+
+   C++:      using namespace A;
+   Fortran:  use A
+   import_src = "A"
+   import_dest = local scope of the import statement even such as ""
+   alias = NULL
+   declaration = NULL
+   excludes = NULL
+
+   C++:      using A::x;
+   Fortran:  use A, only: x
+   import_src = "A"
+   import_dest = local scope of the import statement even such as ""
+   alias = NULL
+   declaration = "x"
+   excludes = NULL
+   The declaration will get imported as import_dest::x.
+
+   C++ has no way to import all names except those listed ones.
+   Fortran:  use A, localname => x
+   import_src = "A"
+   import_dest = local scope of the import statement even such as ""
+   alias = "localname"
+   declaration = "x"
+   excludes = NULL
+   +
+   import_src = "A"
+   import_dest = local scope of the import statement even such as ""
+   alias = NULL
+   declaration = NULL
+   excludes = ["x"]
+   All the entries of A get imported except of "x".  "x" gets imported as
+   "localname".  "x" is not defined as a local name by this statement.
+
+   C++:      namespace LOCALNS = A;
+   Fortran has no way to address non-local namespace/module.
+   import_src = "A"
+   import_dest = local scope of the import statement even such as ""
+   alias = "LOCALNS"
+   declaration = NULL
+   excludes = NULL
+   The namespace will get imported as the import_dest::LOCALNS
+   namespace.
+
+   C++ cannot express it, it would be something like: using localname
+   = A::x;
+   Fortran:  use A, only localname => x
+   import_src = "A"
+   import_dest = local scope of the import statement even such as ""
+   alias = "localname"
+   declaration = "x"
+   excludes = NULL
+   The declaration will get imported as localname or
+   `import_dest`localname.  */
+
+struct using_direct
+{
+  const char *import_src;
+  const char *import_dest;
+
+  const char *alias;
+  const char *declaration;
+
+  struct using_direct *next;
+
+  /* Used during import search to temporarily mark this node as
+     searched.  */
+  int searched;
+
+  /* USING_DIRECT has variable allocation size according to the number of
+     EXCLUDES entries, the last entry is NULL.  */
+  const char *excludes[1];
+};
+
+extern 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);
+
+#endif /* NAMESPACE_H */
diff --git a/gdb/testsuite/gdb.ada/fun_renaming.exp b/gdb/testsuite/gdb.ada/fun_renaming.exp
new file mode 100644
index 0000000..fa76171
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/fun_renaming.exp
@@ -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/>.
+
+load_lib "ada.exp"
+
+standard_ada_testfile fun_renaming
+
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug]] != "" } {
+  return -1
+}
+
+clean_restart ${testfile}
+
+set bp_location [gdb_get_line_number "BREAK" ${testdir}/fun_renaming.adb]
+runto "fun_renaming.adb:$bp_location"
+
+# Sanity check: make sure we can call a regular global function.
+gdb_test "print next(1)" " = 2"
+
+# Starting with GCC 6, renamed subprograms are materialized in the debugging
+# information: make sure we can call the regular global function using its
+# multiple names.
+
+set test "print n(1)"
+gdb_test_multiple $test $test {
+    -re " = 2\..*$gdb_prompt $"  {
+        pass $test
+    }
+    -re "No definition of \"n\" in current context\..*$gdb_prompt $" {
+        if {[test_compiler_info {gcc-6*}]} {
+            fail $test
+        } else {
+            xfail $test
+        }
+    }
+
+}
+set test "print renamed_next(1)"
+gdb_test_multiple $test $test {
+    -re " = 2\..*$gdb_prompt $" {
+        pass $test
+    }
+    -re "No definition of \"renamed_next\" in current context\..*$gdb_prompt $" {
+        if {[test_compiler_info {gcc-6*}]} {
+            fail $test
+        } else {
+            xfail $test
+        }
+    }
+}
+
+set test "print pack.renamed_next(1)"
+gdb_test_multiple $test $test {
+    -re " = 2\..*$gdb_prompt $" {
+        pass $test
+    }
+    -re "No definition of \"pack\.renamed_next\" in current context\..*$gdb_prompt $" {
+        if {[test_compiler_info {gcc-6*}]} {
+            fail $test
+        } else {
+            xfail $test
+        }
+    }
+    -re "Type <data variable, no debug info> is not a structure or union type\..*$gdb_prompt $" {
+        if {[test_compiler_info {gcc-6*}]} {
+            fail $test
+        } else {
+            xfail $test
+        }
+    }
+}
diff --git a/gdb/testsuite/gdb.ada/fun_renaming/fun_renaming.adb b/gdb/testsuite/gdb.ada/fun_renaming/fun_renaming.adb
new file mode 100644
index 0000000..c933585
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/fun_renaming/fun_renaming.adb
@@ -0,0 +1,23 @@ 
+--  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/>.
+
+with Pack;
+
+procedure Fun_Renaming is
+   function N (I : Integer) return Integer renames Pack.Next;
+begin
+   Pack.Discard (N (1)); --  BREAK
+   Pack.Discard (Pack.Renamed_Next (1)); --  BREAK
+end Fun_Renaming;
diff --git a/gdb/testsuite/gdb.ada/fun_renaming/pack.adb b/gdb/testsuite/gdb.ada/fun_renaming/pack.adb
new file mode 100644
index 0000000..bdcd432
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/fun_renaming/pack.adb
@@ -0,0 +1,26 @@ 
+--  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/>.
+
+package body Pack is
+   function Next (I : Integer) return Integer is
+   begin
+      return I + 1;
+   end Next;
+
+   procedure Discard (I : Integer) is
+   begin
+      null;
+   end Discard;
+end Pack;
diff --git a/gdb/testsuite/gdb.ada/fun_renaming/pack.ads b/gdb/testsuite/gdb.ada/fun_renaming/pack.ads
new file mode 100644
index 0000000..2cf722c
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/fun_renaming/pack.ads
@@ -0,0 +1,22 @@ 
+--  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/>.
+
+package Pack is
+
+   function Next (I : Integer) return Integer;
+   function Renamed_Next (I : Integer) return Integer renames Next;
+   procedure Discard (I : Integer);
+
+end Pack;
-- 
2.4.6