[patch] Add namespace aliasing support.

Sami Wagiaalla
2010-01-29T16:27:59Z

[-- Attachment #1: Type: text/plain, Size: 8731 bytes --]

gdb/7935

This patch adds support for namespace aliasing.
Eg.

namespace A{
int x;
}

void foo(){
namespace B=A
}

...

(gdb) p B::x

PR gdb/7935:
2010-01-29 Sami Wagiaalla <swagiaal@redhat.com>

* cp-support.h: Added char* alias element to using_direct data
struct.
(cp_add_using): Added char* alias argument.
(cp_add_using_directive): Ditto.
* cp-namespace.c: Updated with the above changes.
(cp_lookup_symbol_imports): Check for aliases.
* dwarf2read.c (read_import_statement): Figure out local alias
for the import and pass it on to cp_add_using.
(read_namespace): Pass alias argument to cp_add_using.

2010-01-29 Sami Wagiaalla <swagiaal@redhat.com>

* gdb.cp/namespace-using.exp: Removed kfail; bug has been fixed.

diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c
index 8ca9c20..a6ecb26 100644
--- a/gdb/cp-namespace.c
+++ b/gdb/cp-namespace.c
@@ -117,7 +117,7 @@ cp_scan_for_anonymous_namespaces (const struct symbol *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);
+ cp_add_using_directive (dest, src, "");
}
/* The "+ 2" is for the "::". */
previous_component = next_component + 2;
@@ -132,7 +132,7 @@ cp_scan_for_anonymous_namespaces (const struct symbol *symbol)
has already been added, don't add it twice. */

void
-cp_add_using_directive (const char *dest, const char *src)
+cp_add_using_directive (const char *dest, const char *src, const char* alias)
{
struct using_direct *current;
struct using_direct *new;
@@ -146,7 +146,7 @@ cp_add_using_directive (const char *dest, const char *src)
return;
}

- using_directives = cp_add_using (dest, src, using_directives);
+ using_directives = cp_add_using (dest, src, alias, using_directives);

}

@@ -198,8 +198,10 @@ cp_is_anonymous (const char *namespace)
!= NULL);
}

-/* Create a new struct using direct which imports the namespace SRC
- into the scope DEST.
+/* 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 an empty string then the namespace is known by its
+ original name.
Set its next member in the linked list to NEXT; allocate all memory
using xmalloc. It copies the strings, so NAME can be a temporary
string. */
@@ -207,6 +209,7 @@ cp_is_anonymous (const char *namespace)
struct using_direct *
cp_add_using (const char *dest,
const char *src,
+ const char *alias,
struct using_direct *next)
{
struct using_direct *retval;
@@ -214,6 +217,8 @@ cp_add_using (const char *dest,
retval = xmalloc (sizeof (struct using_direct));
retval->import_src = savestring (src, strlen(src));
retval->import_dest = savestring (dest, strlen(dest));
+ retval->alias = savestring (alias, strlen(alias));
+
retval->next = next;
retval->searched = 0;

@@ -344,13 +349,28 @@ cp_lookup_symbol_imports (const char *scope,
current->searched = 1;
searched_cleanup = make_cleanup (reset_directive_searched, current);

- sym = cp_lookup_symbol_namespace (current->import_src,
+ if (strcmp (name, current->alias) == 0)
+ /* If the import is creating an alias and the alias matches the
+ sought name. Pass current->import_src as the NAME to direct the
+ search towards the aliased namespace. */
+ {
+ sym = cp_lookup_symbol_in_namespace (scope,
+ current->import_src,
+ linkage_name,
+ block,
+ domain);
+ }
+ else if (strcmp ("", current->alias) == 0)
+ {
+ /* If this import statement creates no alias, pass current->inner as
+ NAMESPACE to direct the search towards the imported namespace. */
+ sym = cp_lookup_symbol_imports (current->import_src,
name,
linkage_name,
block,
domain,
0);
-
+ }
current->searched = 0;
discard_cleanups (searched_cleanup);

diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index 33b1b44..5d28bf9 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -38,14 +38,20 @@ struct demangle_component;

/* 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. IMPORT_DEST should always be a strict initial
- substring of IMPORT_SRC. These form a linked list; NEXT is the next element
- of the list. */
+ namespace IMPORT_DEST. These form a linked list; NEXT is the next element
+ of the list. ALIAS is set to a non empty string if the imported namespace
+ has been aliased.
+ Eg:
+ namespace C=A::B;
+*/

struct using_direct
{
char *import_src;
char *import_dest;
+
+ char *alias;
+
struct using_direct *next;

/* Used during import search to temporarily mark this node as searched. */
@@ -82,10 +88,12 @@ extern int cp_validate_operator (const char *input);
extern int cp_is_anonymous (const char *namespace);

extern void cp_add_using_directive (const char *dest,
- const char *src);
+ const char *src,
+ const char *alias);

extern struct using_direct *cp_add_using (const char *dest,
const char *src,
+ const char *alias,
struct using_direct *next);

extern void cp_initialize_namespace (void);
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 2f671ca..ae089eb 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -3385,6 +3385,8 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
struct dwarf2_cu *imported_cu;
const char *imported_name;
const char *imported_name_prefix;
+ char *import_alias;
+
const char *import_prefix;
char *canonical_name;

@@ -3436,7 +3438,12 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
return;
}

- /* FIXME: dwarf2_name (die); for the local name after import. */
+ /* Figure out the local name after import. */
+ import_alias = dwarf2_name (die, cu);
+ if (import_alias == NULL)
+ {
+ import_alias = "";
+ }

/* Figure out where the statement is being imported to. */
import_prefix = determine_prefix (die, cu);
@@ -3447,7 +3454,8 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)

if (strlen (imported_name_prefix) > 0)
{
- canonical_name = alloca (strlen (imported_name_prefix) + 2 + strlen (imported_name) + 1);
+ canonical_name = alloca (strlen (imported_name_prefix)
+ + 2 + strlen (imported_name) + 1);
strcpy (canonical_name, imported_name_prefix);
strcat (canonical_name, "::");
strcat (canonical_name, imported_name);
@@ -3458,7 +3466,10 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
strcpy (canonical_name, imported_name);
}

- using_directives = cp_add_using (import_prefix,canonical_name, using_directives);
+ using_directives = cp_add_using (import_prefix,
+ canonical_name,
+ import_alias,
+ using_directives);
}

static void
@@ -5616,7 +5627,7 @@ read_namespace (struct die_info *die, struct dwarf2_cu *cu)
if (is_anonymous)
{
const char *previous_prefix = determine_prefix (die, cu);
- cp_add_using_directive (previous_prefix, TYPE_NAME (type));
+ cp_add_using_directive (previous_prefix, TYPE_NAME (type), "");
}
}

diff --git a/gdb/testsuite/gdb.cp/nsusing.exp b/gdb/testsuite/gdb.cp/nsusing.exp
index bd115c4..72a616e 100644
--- a/gdb/testsuite/gdb.cp/nsusing.exp
+++ b/gdb/testsuite/gdb.cp/nsusing.exp
@@ -116,14 +116,11 @@ if ![runto marker2] then {
continue
}

-setup_kfail "gdb/7935" "*-*-*"
gdb_test "print B::_a" "= 1"

-setup_kfail "gdb/7935" "*-*-*"
gdb_test "print _a" "No symbol \"_a\" in current context." \
"print _a in namespace alias scope"

-setup_kfail "gdb/7935" "*-*-*"
gdb_test "print x" "No symbol \"x\" in current context." \
"print x in namespace alias scope"

[-- Attachment #2: namespace-alias.patch --]
[-- Type: text/plain, Size: 7842 bytes --]

diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c
index 8ca9c20..a6ecb26 100644
--- a/gdb/cp-namespace.c
+++ b/gdb/cp-namespace.c
@@ -117,7 +117,7 @@ cp_scan_for_anonymous_namespaces (const struct symbol *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);
+ cp_add_using_directive (dest, src, "");
}
/* The "+ 2" is for the "::". */
previous_component = next_component + 2;
@@ -132,7 +132,7 @@ cp_scan_for_anonymous_namespaces (const struct symbol *symbol)
has already been added, don't add it twice. */

void
-cp_add_using_directive (const char *dest, const char *src)
+cp_add_using_directive (const char *dest, const char *src, const char* alias)
{
struct using_direct *current;
struct using_direct *new;
@@ -146,7 +146,7 @@ cp_add_using_directive (const char *dest, const char *src)
return;
}

- using_directives = cp_add_using (dest, src, using_directives);
+ using_directives = cp_add_using (dest, src, alias, using_directives);

}

@@ -198,8 +198,10 @@ cp_is_anonymous (const char *namespace)
!= NULL);
}

-/* Create a new struct using direct which imports the namespace SRC
- into the scope DEST.
+/* 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 an empty string then the namespace is known by its
+ original name.
Set its next member in the linked list to NEXT; allocate all memory
using xmalloc. It copies the strings, so NAME can be a temporary
string. */
@@ -207,6 +209,7 @@ cp_is_anonymous (const char *namespace)
struct using_direct *
cp_add_using (const char *dest,
const char *src,
+ const char *alias,
struct using_direct *next)
{
struct using_direct *retval;
@@ -214,6 +217,8 @@ cp_add_using (const char *dest,
retval = xmalloc (sizeof (struct using_direct));
retval->import_src = savestring (src, strlen(src));
retval->import_dest = savestring (dest, strlen(dest));
+ retval->alias = savestring (alias, strlen(alias));
+
retval->next = next;
retval->searched = 0;

@@ -344,13 +349,28 @@ cp_lookup_symbol_imports (const char *scope,
current->searched = 1;
searched_cleanup = make_cleanup (reset_directive_searched, current);

- sym = cp_lookup_symbol_namespace (current->import_src,
+ if (strcmp (name, current->alias) == 0)
+ /* If the import is creating an alias and the alias matches the
+ sought name. Pass current->import_src as the NAME to direct the
+ search towards the aliased namespace. */
+ {
+ sym = cp_lookup_symbol_in_namespace (scope,
+ current->import_src,
+ linkage_name,
+ block,
+ domain);
+ }
+ else if (strcmp ("", current->alias) == 0)
+ {
+ /* If this import statement creates no alias, pass current->inner as
+ NAMESPACE to direct the search towards the imported namespace. */
+ sym = cp_lookup_symbol_imports (current->import_src,
name,
linkage_name,
block,
domain,
0);
-
+ }
current->searched = 0;
discard_cleanups (searched_cleanup);

diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index 33b1b44..5d28bf9 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -38,14 +38,20 @@ struct demangle_component;

/* 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. IMPORT_DEST should always be a strict initial
- substring of IMPORT_SRC. These form a linked list; NEXT is the next element
- of the list. */
+ namespace IMPORT_DEST. These form a linked list; NEXT is the next element
+ of the list. ALIAS is set to a non empty string if the imported namespace
+ has been aliased.
+ Eg:
+ namespace C=A::B;
+*/

struct using_direct
{
char *import_src;
char *import_dest;
+
+ char *alias;
+
struct using_direct *next;

/* Used during import search to temporarily mark this node as searched. */
@@ -82,10 +88,12 @@ extern int cp_validate_operator (const char *input);
extern int cp_is_anonymous (const char *namespace);

extern void cp_add_using_directive (const char *dest,
- const char *src);
+ const char *src,
+ const char *alias);

extern struct using_direct *cp_add_using (const char *dest,
const char *src,
+ const char *alias,
struct using_direct *next);

extern void cp_initialize_namespace (void);
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 2f671ca..ae089eb 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -3385,6 +3385,8 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
struct dwarf2_cu *imported_cu;
const char *imported_name;
const char *imported_name_prefix;
+ char *import_alias;
+
const char *import_prefix;
char *canonical_name;

@@ -3436,7 +3438,12 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
return;
}

- /* FIXME: dwarf2_name (die); for the local name after import. */
+ /* Figure out the local name after import. */
+ import_alias = dwarf2_name (die, cu);
+ if (import_alias == NULL)
+ {
+ import_alias = "";
+ }

/* Figure out where the statement is being imported to. */
import_prefix = determine_prefix (die, cu);
@@ -3447,7 +3454,8 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)

if (strlen (imported_name_prefix) > 0)
{
- canonical_name = alloca (strlen (imported_name_prefix) + 2 + strlen (imported_name) + 1);
+ canonical_name = alloca (strlen (imported_name_prefix)
+ + 2 + strlen (imported_name) + 1);
strcpy (canonical_name, imported_name_prefix);
strcat (canonical_name, "::");
strcat (canonical_name, imported_name);
@@ -3458,7 +3466,10 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
strcpy (canonical_name, imported_name);
}

- using_directives = cp_add_using (import_prefix,canonical_name, using_directives);
+ using_directives = cp_add_using (import_prefix,
+ canonical_name,
+ import_alias,
+ using_directives);
}

static void
@@ -5616,7 +5627,7 @@ read_namespace (struct die_info *die, struct dwarf2_cu *cu)
if (is_anonymous)
{
const char *previous_prefix = determine_prefix (die, cu);
- cp_add_using_directive (previous_prefix, TYPE_NAME (type));
+ cp_add_using_directive (previous_prefix, TYPE_NAME (type), "");
}
}

diff --git a/gdb/testsuite/gdb.cp/nsusing.exp b/gdb/testsuite/gdb.cp/nsusing.exp
index bd115c4..72a616e 100644
--- a/gdb/testsuite/gdb.cp/nsusing.exp
+++ b/gdb/testsuite/gdb.cp/nsusing.exp
@@ -116,14 +116,11 @@ if ![runto marker2] then {
continue
}

-setup_kfail "gdb/7935" "*-*-*"
gdb_test "print B::_a" "= 1"

-setup_kfail "gdb/7935" "*-*-*"
gdb_test "print _a" "No symbol \"_a\" in current context." \
"print _a in namespace alias scope"

-setup_kfail "gdb/7935" "*-*-*"
gdb_test "print x" "No symbol \"x\" in current context." \
"print x in namespace alias scope"