aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog19
-rw-r--r--gdb/cp-namespace.c42
-rw-r--r--gdb/cp-support.h29
-rw-r--r--gdb/defs.h3
-rw-r--r--gdb/dwarf2read.c55
-rw-r--r--gdb/testsuite/ChangeLog8
-rw-r--r--gdb/testsuite/gdb.fortran/module.exp3
-rw-r--r--gdb/testsuite/gdb.fortran/module.f907
8 files changed, 159 insertions, 7 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 9cabcaf..af9f505a2 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,24 @@
2011-06-29 Jan Kratochvil <jan.kratochvil@redhat.com>
+ Fix non-only rename list for Fortran modules import.
+ * cp-namespace.c (cp_scan_for_anonymous_namespaces): Adjust the
+ cp_add_using_directive caller.
+ (cp_add_using_directive): New parameter excludes, describe it. New
+ variables ix and param. Compare if also excludes match. Allocate NEW
+ with variable size, initialize EXCLUDES there.
+ (cp_lookup_symbol_imports): New variable excludep, test
+ current->EXCLUDES with it.
+ * cp-support.h: Include vec.h.
+ (struct using_direct): New field excludes, describe it.
+ (DEF_VEC_P (const_char_ptr)): New.
+ (cp_add_using_directive): New parameter excludes.
+ * defs.h (const_char_ptr): New typedef.
+ * dwarf2read.c (read_import_statement): New variables child_die,
+ excludes and cleanups, read in excludes.
+ (read_namespace): Adjust the cp_add_using_directive caller.
+
+2011-06-29 Jan Kratochvil <jan.kratochvil@redhat.com>
+
Code cleanup.
* cp-namespace.c (cp_add_using_directive): Turn positive comparison to
negative comparisons.
diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c
index ff4d63e..68febcd 100644
--- a/gdb/cp-namespace.c
+++ b/gdb/cp-namespace.c
@@ -95,7 +95,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, NULL, NULL,
+ cp_add_using_directive (dest, src, NULL, NULL, NULL,
&SYMBOL_SYMTAB (symbol)->objfile->objfile_obstack);
}
/* The "+ 2" is for the "::". */
@@ -116,14 +116,17 @@ cp_scan_for_anonymous_namespaces (const struct symbol *symbol)
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. The arguments are copied into newly allocated memory
- so they can be temporaries. */
+ it is NULL. EXCLUDES is a list of names not to import from an imported
+ module or NULL. 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,
struct obstack *obstack)
{
struct using_direct *current;
@@ -133,6 +136,9 @@ cp_add_using_directive (const char *dest,
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)
@@ -148,11 +154,23 @@ cp_add_using_directive (const char *dest,
&& 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;
}
- new = OBSTACK_ZALLOC (obstack, struct using_direct);
+ new = obstack_alloc (obstack, (sizeof (*new)
+ + (VEC_length (const_char_ptr, excludes)
+ * sizeof (*new->excludes))));
+ memset (new, 0, sizeof (*new));
new->import_src = obsavestring (src, strlen (src), obstack);
new->import_dest = obsavestring (dest, strlen (dest), obstack);
@@ -164,6 +182,10 @@ cp_add_using_directive (const char *dest,
new->declaration = obsavestring (declaration, strlen (declaration),
obstack);
+ memcpy (new->excludes, VEC_address (const_char_ptr, excludes),
+ VEC_length (const_char_ptr, excludes) * sizeof (*new->excludes));
+ new->excludes[VEC_length (const_char_ptr, excludes)] = NULL;
+
new->next = using_directives;
using_directives = new;
}
@@ -332,6 +354,8 @@ cp_lookup_symbol_imports (const char *scope,
current != NULL;
current = current->next)
{
+ const char **excludep;
+
len = strlen (current->import_dest);
directive_match = (search_parents
? (strncmp (scope, current->import_dest,
@@ -377,6 +401,16 @@ cp_lookup_symbol_imports (const char *scope,
continue;
}
+ /* Do not follow CURRENT if NAME matches its EXCLUDES. */
+ for (excludep = current->excludes; *excludep; excludep++)
+ if (strcmp (name, *excludep) == 0)
+ break;
+ if (*excludep)
+ {
+ discard_cleanups (searched_cleanup);
+ continue;
+ }
+
if (current->alias != NULL
&& strcmp (name, current->alias) == 0)
/* If the import is creating an alias and the alias matches
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index 52d4cb7..d23f19e 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -27,6 +27,8 @@
#include "symtab.h"
+#include "vec.h"
+
/* Opaque declarations. */
struct symbol;
@@ -60,6 +62,7 @@ struct demangle_component;
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
@@ -67,14 +70,32 @@ struct demangle_component;
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.
@@ -85,6 +106,7 @@ struct demangle_component;
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. */
@@ -101,6 +123,10 @@ struct using_direct
/* 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];
};
@@ -136,10 +162,13 @@ extern int cp_validate_operator (const char *input);
extern int cp_is_anonymous (const char *namespace);
+DEF_VEC_P (const_char_ptr);
+
extern void cp_add_using_directive (const char *dest,
const char *src,
const char *alias,
const char *declaration,
+ VEC (const_char_ptr) *excludes,
struct obstack *obstack);
extern void cp_initialize_namespace (void);
diff --git a/gdb/defs.h b/gdb/defs.h
index c637a09..71b7cd2 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -271,9 +271,10 @@ struct cleanup
void *arg;
};
-/* vec.h-style vectors of strings want a typedef for char * . */
+/* vec.h-style vectors of strings want a typedef for char * or const char *. */
typedef char * char_ptr;
+typedef const char * const_char_ptr;
/* Needed for various prototypes */
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index bc958bb..ce43284 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -5178,7 +5178,7 @@ static void
read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
{
struct attribute *import_attr;
- struct die_info *imported_die;
+ struct die_info *imported_die, *child_die;
struct dwarf2_cu *imported_cu;
const char *imported_name;
const char *imported_name_prefix;
@@ -5186,6 +5186,8 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
const char *import_alias;
const char *imported_declaration = NULL;
const char *import_prefix;
+ VEC (const_char_ptr) *excludes = NULL;
+ struct cleanup *cleanups;
char *temp;
@@ -5265,11 +5267,60 @@ read_import_statement (struct die_info *die, struct dwarf2_cu *cu)
else
canonical_name = imported_name;
+ cleanups = make_cleanup (VEC_cleanup (const_char_ptr), &excludes);
+
+ if (die->tag == DW_TAG_imported_module && cu->language == language_fortran)
+ for (child_die = die->child; child_die && child_die->tag;
+ child_die = sibling_die (child_die))
+ {
+ /* DWARF-4: A Fortran use statement with a “rename list” may be
+ represented by an imported module entry with an import attribute
+ referring to the module and owned entries corresponding to those
+ entities that are renamed as part of being imported. */
+
+ if (child_die->tag != DW_TAG_imported_declaration)
+ {
+ complaint (&symfile_complaints,
+ _("child DW_TAG_imported_declaration expected "
+ "- DIE at 0x%x [in module %s]"),
+ child_die->offset, cu->objfile->name);
+ continue;
+ }
+
+ import_attr = dwarf2_attr (child_die, DW_AT_import, cu);
+ if (import_attr == NULL)
+ {
+ complaint (&symfile_complaints, _("Tag '%s' has no DW_AT_import"),
+ dwarf_tag_name (child_die->tag));
+ continue;
+ }
+
+ imported_cu = cu;
+ imported_die = follow_die_ref_or_sig (child_die, import_attr,
+ &imported_cu);
+ imported_name = dwarf2_name (imported_die, imported_cu);
+ if (imported_name == NULL)
+ {
+ complaint (&symfile_complaints,
+ _("child DW_TAG_imported_declaration has unknown "
+ "imported name - DIE at 0x%x [in module %s]"),
+ child_die->offset, cu->objfile->name);
+ continue;
+ }
+
+ VEC_safe_push (const_char_ptr, excludes, imported_name);
+
+ process_die (child_die, cu);
+ }
+
cp_add_using_directive (import_prefix,
canonical_name,
import_alias,
imported_declaration,
+ excludes,
&cu->objfile->objfile_obstack);
+
+ do_cleanups (cleanups);
}
static void
@@ -7797,7 +7848,7 @@ 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, &objfile->objfile_obstack);
+ NULL, NULL, &objfile->objfile_obstack);
}
}
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index f826b19..b0e0fe5 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2011-06-29 Jan Kratochvil <jan.kratochvil@redhat.com>
+
+ Fix non-only rename list for Fortran modules import.
+ * gdb.fortran/module.exp (print var_x, print var_y, print var_z): New
+ tests.
+ * gdb.fortran/module.f90 (module moduse): New.
+ (program module): use moduse, test var_x, var_y and var_z.
+
2011-06-29 Tom Tromey <tromey@redhat.com>
PR testsuite/12040:
diff --git a/gdb/testsuite/gdb.fortran/module.exp b/gdb/testsuite/gdb.fortran/module.exp
index 364c59d..6df56b5 100644
--- a/gdb/testsuite/gdb.fortran/module.exp
+++ b/gdb/testsuite/gdb.fortran/module.exp
@@ -51,6 +51,9 @@ gdb_test "print var_b" " = 11"
gdb_test "print var_c" "No symbol \"var_c\" in current context\\."
gdb_test "print var_d" " = 12"
gdb_test "print var_i" " = 14" "print var_i value 14"
+gdb_test "print var_x" " = 30" "print var_x value 30"
+gdb_test "print var_y" "No symbol \"var_y\" in current context\\."
+gdb_test "print var_z" " = 31" "print var_x value 31"
gdb_test "ptype modmany" {No symbol "modmany" in current context.}
diff --git a/gdb/testsuite/gdb.fortran/module.f90 b/gdb/testsuite/gdb.fortran/module.f90
index 843ad89..d9eb1b3 100644
--- a/gdb/testsuite/gdb.fortran/module.f90
+++ b/gdb/testsuite/gdb.fortran/module.f90
@@ -27,6 +27,10 @@ module modmany
integer :: var_a = 10, var_b = 11, var_c = 12, var_i = 14
end module modmany
+module moduse
+ integer :: var_x = 30, var_y = 31
+end module moduse
+
subroutine sub1
use mod1
if (var_i .ne. 1) call abort
@@ -42,6 +46,7 @@ end module modmany
program module
use modmany, only: var_b, var_d => var_c, var_i
+ use moduse, var_z => var_y
call sub1
call sub2
@@ -49,5 +54,7 @@ end module modmany
if (var_b .ne. 11) call abort
if (var_d .ne. 12) call abort
if (var_i .ne. 14) call abort
+ if (var_x .ne. 30) call abort
+ if (var_z .ne. 31) call abort
var_b = var_b ! a-b-c-d
end