This is the mail archive of the
archer@sourceware.org
mailing list for the Archer project.
[fortran-module] [commit] Implement Fortran modules namespaces
- From: Jan Kratochvil <jan dot kratochvil at redhat dot com>
- To: archer at sourceware dot org
- Date: Wed, 6 May 2009 14:31:43 +0200
- Subject: [fortran-module] [commit] Implement Fortran modules namespaces
Hi,
currently GDB considers all Fortran modules share one flat namespace. Fix it.
Original bugreport:
https://bugzilla.redhat.com/show_bug.cgi?id=466118
Formerly I did intend to merge it first with C++ namespacing but it looks to
me it may rather stay as a separate code as Fortran vs. C++ namespaces are
different enough.
For FSF GDB check-in:
(1) Move BLOCK_FORTRAN_USE into a union with BLOCK_NAMESPACE - the
prerequisite is a patch which prevents accesses to BLOCK_NAMESPACE for
non-C++ languages.
(2) Check resolving gfortran PR debug/40040 so that GDB may not need to deal
with the gfortran symbol names mangling/demangling at all.
Regards,
Jan
gdb/
Implement Fortran modules namespaces.
* block.c (allocate_block): Initialize BLOCK_FORTRAN_USE.
* block.h (struct block <fortran_specific>, BLOCK_FORTRAN_USE): New.
* dwarf2read.c: Include block.h and f-lang.h.
(struct dwarf2_cu <language_specific>)
(add_partial_symbol <DW_TAG_module>): New.
(add_partial_module): Call add_partial_symbol, remove children scanning.
(process_die <DW_TAG_imported_module>,
(process_die <DW_TAG_imported_declaration): Call for Fortran CUs
read_fortran_imported_module and read_fortran_imported_declaration
respectively.
(read_func_scope): Intialize CU FORTRAN.USE and BLOCK_FORTRAN_USE.
(read_module): Implement modules reading.
(read_module_type, read_fortran_imported_module)
(read_fortran_imported_declaration): New.
(load_partial_dies): Read also DW_TAG_module.
(new_symbol): Set SYMBOL_LINKAGE_NAME for Fortran symbols from modules.
(new_symbol <DW_TAG_variable> <DW_AT_location> <DW_AT_external>):
Workaround gfortran PR debug/40040.
(new_symbol <DW_TAG_module>, read_type_die <DW_TAG_module>)
(fortran_module_linkage_name): New.
* f-lang.c: Include block.h and gdb_assert.h.
(f_lookup_symbol_nonlocal): New.
(f_language_defn <lookup_symbol_nonlocal>): Use the new function.
* f-lang.h (struct fortran_using): New.
* gdbtypes.h (enum type_code <TYPE_CODE_MODULE>)
(struct main_type <type_specific.module_block, TYPE_MODULE_BLOCK): New.
* symtab.c (symbol_init_language_specific, symbol_natural_name)
(symbol_demangled_name): Use CPLUS_SPECIFIC.DEMANGLED_NAME for Fortran.
* symtab.h (domain_enum <MODULE_DOMAIN>): New.
gdb/testsuite/
* gdb.fortran/library-module.exp, gdb.fortran/library-module-lib.f90,
gdb.fortran/library-module-main.f90: New.
* gdb.fortran/module.f90: Extend the testing for multiple modules.
* gdb.fortran/module.exp: Likewise. Use prepare_for_testing.
diff --git a/gdb/block.c b/gdb/block.c
index 8f0140c..1a73ff6 100644
--- a/gdb/block.c
+++ b/gdb/block.c
@@ -306,6 +306,7 @@ allocate_block (struct obstack *obstack)
BLOCK_SUPERBLOCK (bl) = NULL;
BLOCK_DICT (bl) = NULL;
BLOCK_NAMESPACE (bl) = NULL;
+ BLOCK_FORTRAN_USE (bl) = NULL;
return bl;
}
diff --git a/gdb/block.h b/gdb/block.h
index 9b43144..20d32ae 100644
--- a/gdb/block.h
+++ b/gdb/block.h
@@ -96,6 +96,15 @@ struct block
cplus_specific;
}
language_specific;
+
+ /* FIXME: It should be in the LANGUAGE_SPECIFIC region but the
+ BLOCK_NAMESPACE accessor is not protected by the C language check. */
+
+ struct
+ {
+ struct fortran_using *use;
+ }
+ fortran_specific;
};
#define BLOCK_START(bl) (bl)->startaddr
@@ -104,6 +113,7 @@ struct block
#define BLOCK_SUPERBLOCK(bl) (bl)->superblock
#define BLOCK_DICT(bl) (bl)->dict
#define BLOCK_NAMESPACE(bl) (bl)->language_specific.cplus_specific.namespace
+#define BLOCK_FORTRAN_USE(bl) (bl)->fortran_specific.use
/* Macro to loop through all symbols in a block BL, in no particular
order. ITER helps keep track of the iteration, and should be a
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 6ddaecd..324c9c1 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -47,6 +47,8 @@
#include "command.h"
#include "gdbcmd.h"
#include "addrmap.h"
+#include "block.h"
+#include "f-lang.h"
#include <fcntl.h>
#include "gdb_string.h"
@@ -352,6 +354,19 @@ struct dwarf2_cu
/* Field `ranges_offset' is filled in; flag as the value may be zero. */
unsigned int has_ranges_offset : 1;
+
+ /* Fields are valid according to the LANGUAGE field. */
+ union
+ {
+ /* language_fortran */
+ struct
+ {
+ /* Module names imported to the block being currently read in. */
+ struct fortran_using *use;
+ }
+ fortran;
+ }
+ language_specific;
};
/* Persistent data held for a compilation unit, even when not
@@ -971,6 +986,15 @@ 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 type *read_module_type (struct die_info *die,
+ struct dwarf2_cu *cu);
+
+static void read_fortran_imported_module (struct die_info *die,
+ struct dwarf2_cu *cu);
+
+static void read_fortran_imported_declaration (struct die_info *die,
+ struct dwarf2_cu *cu);
+
static const char *namespace_name (struct die_info *die,
int *is_anonymous, struct dwarf2_cu *);
@@ -1002,6 +1026,9 @@ static void process_die (struct die_info *, struct dwarf2_cu *);
static char *dwarf2_linkage_name (struct die_info *, struct dwarf2_cu *);
+static char *fortran_module_linkage_name (struct die_info *die,
+ struct dwarf2_cu *cu);
+
static char *dwarf2_canonicalize_name (char *, struct dwarf2_cu *,
struct obstack *);
@@ -2092,6 +2119,12 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
&objfile->global_psymbols,
0, (CORE_ADDR) 0, cu->language, objfile);
break;
+ case DW_TAG_module:
+ add_psymbol_to_list (actual_name, strlen (actual_name),
+ MODULE_DOMAIN, LOC_STATIC,
+ &objfile->global_psymbols,
+ 0, (CORE_ADDR) 0, cu->language, objfile);
+ break;
case DW_TAG_class_type:
case DW_TAG_interface_type:
case DW_TAG_structure_type:
@@ -2203,12 +2236,12 @@ static void
add_partial_module (struct partial_die_info *pdi, CORE_ADDR *lowpc,
CORE_ADDR *highpc, int need_pc, struct dwarf2_cu *cu)
{
- /* Now scan partial symbols in that module.
+ /* Add a symbol for the module. */
- FIXME: Support the separate Fortran module namespaces. */
+ add_partial_symbol (pdi, cu);
- if (pdi->has_children)
- scan_partial_symbols (pdi->die_child, lowpc, highpc, need_pc, cu);
+ /* Partial symbols in that module are not scanned as they are never globally
+ visible. They get imported to the specific scopes on the full read. */
}
/* Read a partial die corresponding to a subprogram and create a partial
@@ -2878,16 +2911,21 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
case DW_TAG_module:
read_module (die, cu);
break;
- case DW_TAG_imported_declaration:
case DW_TAG_imported_module:
- /* FIXME: carlton/2002-10-16: Eventually, we should use the
- information contained in these. DW_TAG_imported_declaration
- dies shouldn't have children; DW_TAG_imported_module dies
- shouldn't in the C++ case, but conceivably could in the
- Fortran case. */
processing_has_namespace_info = 1;
- complaint (&symfile_complaints, _("unsupported tag: '%s'"),
- dwarf_tag_name (die->tag));
+ if (cu->language == language_fortran)
+ read_fortran_imported_module (die, cu);
+ else
+ complaint (&symfile_complaints, _("unsupported tag: '%s'"),
+ dwarf_tag_name (die->tag));
+ break;
+ case DW_TAG_imported_declaration:
+ processing_has_namespace_info = 1;
+ if (cu->language == language_fortran)
+ read_fortran_imported_declaration (die, cu);
+ else
+ complaint (&symfile_complaints, _("unsupported tag: '%s'"),
+ dwarf_tag_name (die->tag));
break;
default:
new_symbol (die, NULL, cu);
@@ -3234,6 +3272,13 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
cu->list_in_scope = &local_symbols;
+ switch (cu->language)
+ {
+ case language_fortran:
+ cu->language_specific.fortran.use = NULL;
+ break;
+ }
+
if (die->child != NULL)
{
child_die = die->child;
@@ -3257,6 +3302,13 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu)
determine_prefix (die, cu),
processing_has_namespace_info);
+ switch (cu->language)
+ {
+ case language_fortran:
+ BLOCK_FORTRAN_USE (block) = cu->language_specific.fortran.use;
+ break;
+ }
+
/* If we have address ranges, record them. */
dwarf2_record_block_ranges (die, block, baseaddr, cu);
@@ -4886,20 +4938,155 @@ read_namespace (struct die_info *die, struct dwarf2_cu *cu)
}
}
-/* Read a Fortran module. */
+/* Read a Fortran module as global symbol which can be later looked up by
+ f_lookup_symbol_nonlocal. */
static void
read_module (struct die_info *die, struct dwarf2_cu *cu)
{
- struct die_info *child_die = die->child;
+ struct type *type;
+
+ type = read_module_type (die, cu);
+
+ if (type)
+ new_symbol (die, type, cu);
+}
+
+/* Read a Fortran module as type.
+
+ Modules present only as declarations - being used only for DW_AT_import of
+ DW_TAG_imported_module - are ignored here. They are read in only in form of
+ the module name by read_fortran_imported_module. */
+
+static struct type *
+read_module_type (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct objfile *objfile = cu->objfile;
+ struct die_info *child_die;
+ struct type *type;
+ char *module_name;
+ struct context_stack *new;
+ struct pending *save_file_symbols;
+ struct pending *save_global_symbols;
+ struct pending **save_list_in_scope;
+
+ if (die_is_declaration (die, cu))
+ return NULL;
+
+ module_name = dwarf2_name (die, cu);
+ if (!module_name)
+ complaint (&symfile_complaints, _("DW_TAG_module has no name, offset 0x%x"),
+ die->offset);
+ type = init_type (TYPE_CODE_MODULE, 0, 0, module_name, objfile);
+
+ /* Create a context for reading the module variables. */
- /* FIXME: Support the separate Fortran module namespaces. */
+ new = push_context (0, 0);
+ save_file_symbols = file_symbols;
+ file_symbols = NULL;
+ save_global_symbols = global_symbols;
+ global_symbols = NULL;
+ save_list_in_scope = cu->list_in_scope;
+
+ /* Process the child DIEs. */
+
+ child_die = die->child;
while (child_die && child_die->tag)
{
+ /* Any DW_TAG_subprogram will reset LIST_IN_SCOPE to LOCAL_SYMBOLS. */
+ cu->list_in_scope = &global_symbols;
+
process_die (child_die, cu);
child_die = sibling_die (child_die);
}
+
+ /* Finish this module and restore the context. */
+
+ TYPE_MODULE_BLOCK (type) = finish_block (NULL, &global_symbols,
+ new->old_blocks, 0, 0, objfile);
+
+ if (file_symbols)
+ complaint (&symfile_complaints, _("DW_TAG_module contains static symbols"));
+ if (local_symbols)
+ complaint (&symfile_complaints, _("DW_TAG_module contains local symbols"));
+ if (param_symbols)
+ complaint (&symfile_complaints, _("DW_TAG_module contains function "
+ "parameters"));
+
+ file_symbols = save_file_symbols;
+ global_symbols = save_global_symbols;
+ cu->list_in_scope = save_list_in_scope;
+
+ pop_context ();
+
+ set_die_type (die, type, cu);
+
+ return type;
+}
+
+/* Import a Fortran module. Only store the module name for its later lookup by
+ f_lookup_symbol_nonlocal. */
+
+static void
+read_fortran_imported_module (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct objfile *objfile = cu->objfile;
+ struct attribute *attr;
+ struct die_info *module_die;
+ char *module_name;
+ struct fortran_using *use;
+
+ attr = dwarf2_attr (die, DW_AT_import, cu);
+ if (attr == NULL)
+ return;
+
+ module_die = follow_die_ref (die, attr, &cu);
+ module_name = dwarf2_name (module_die, cu);
+ if (module_name == NULL)
+ {
+ complaint (&symfile_complaints,
+ _("Imported DIE at offset 0x%x has no name"), die->offset);
+ return;
+ }
+
+ /* Fortran does not allow any duplicity between local and any of the imported
+ symbols. Therefore the order of the USE statements is not portant.
+ gfortran prints:
+ Error: Name 'X' at (1) is an ambiguous reference to 'X' from module 'Y' */
+
+ use = obstack_alloc (&objfile->objfile_obstack, sizeof (*use)
+ + strlen (module_name));
+ strcpy (use->module_name, module_name);
+ gdb_assert (cu->language == language_fortran);
+ use->next = cu->language_specific.fortran.use;
+ cu->language_specific.fortran.use = use;
+}
+
+/* Import a single Fortran declaration and possibly rename it. */
+
+static void
+read_fortran_imported_declaration (struct die_info *die, struct dwarf2_cu *cu)
+{
+ struct attribute *attr;
+ struct die_info *imported_die;
+ struct symbol *sym;
+ char *rename = dwarf2_name (die, cu);
+
+ attr = dwarf2_attr (die, DW_AT_import, cu);
+ if (attr == NULL)
+ {
+ complaint (&symfile_complaints,
+ _("Fortran DW_TAG_imported_declaration is missing "
+ "DW_AT_import at offset 0x%x"), die->offset);
+ return;
+ }
+ imported_die = follow_die_ref (die, attr, &cu);
+
+ sym = new_symbol (imported_die, NULL, cu);
+
+ if (sym && rename)
+ SYMBOL_CPLUS_DEMANGLED_NAME (sym) = rename;
}
/* Return the name of the namespace represented by DIE. Set
@@ -5861,6 +6048,7 @@ load_partial_dies (bfd *abfd, gdb_byte *info_ptr, int building_psymtab,
&& abbrev->tag != DW_TAG_lexical_block
&& abbrev->tag != DW_TAG_variable
&& abbrev->tag != DW_TAG_namespace
+ && abbrev->tag != DW_TAG_module
&& abbrev->tag != DW_TAG_member)
{
/* Otherwise we skip to the next sibling, if any. */
@@ -7677,6 +7865,11 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
/* Cache this symbol's name and the name's demangled form (if any). */
SYMBOL_LANGUAGE (sym) = cu->language;
SYMBOL_SET_NAMES (sym, name, strlen (name), objfile);
+ if (cu->language == language_fortran)
+ {
+ SYMBOL_CPLUS_DEMANGLED_NAME (sym) = SYMBOL_LINKAGE_NAME (sym);
+ SYMBOL_LINKAGE_NAME (sym) = fortran_module_linkage_name (die, cu);
+ }
/* Default assumptions.
Use the passed type or decode it from the die. */
@@ -7764,7 +7957,18 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
var_decode_location (attr, sym, cu);
attr2 = dwarf2_attr (die, DW_AT_external, cu);
if (attr2 && (DW_UNSND (attr2) != 0))
- add_symbol_to_list (sym, &global_symbols);
+ {
+ /* Workaround gfortran PR debug/40040 - it uses
+ DW_AT_location for variables in -fPIC libraries which may
+ get overriden by other libraries/executable and get
+ a different address. Resolve it by .dynsym instead. */
+
+ if (cu->language == language_fortran && die->parent
+ && die->parent->tag == DW_TAG_module)
+ SYMBOL_CLASS (sym) = LOC_UNRESOLVED;
+
+ add_symbol_to_list (sym, &global_symbols);
+ }
else
add_symbol_to_list (sym, cu->list_in_scope);
}
@@ -7911,6 +8115,11 @@ new_symbol (struct die_info *die, struct type *type, struct dwarf2_cu *cu)
SYMBOL_CLASS (sym) = LOC_TYPEDEF;
add_symbol_to_list (sym, &global_symbols);
break;
+ case DW_TAG_module:
+ SYMBOL_CLASS (sym) = LOC_STATIC;
+ SYMBOL_DOMAIN (sym) = MODULE_DOMAIN;
+ add_symbol_to_list (sym, &global_symbols);
+ break;
default:
/* Not a tag we recognize. Hopefully we aren't processing
trash data, but since we must specifically ignore things
@@ -8173,6 +8382,9 @@ read_type_die (struct die_info *die, struct dwarf2_cu *cu)
case DW_TAG_namespace:
this_type = read_namespace_type (die, cu);
break;
+ case DW_TAG_module:
+ this_type = read_module_type (die, cu);
+ break;
default:
complaint (&symfile_complaints, _("unexpected tag in read_type_die: '%s'"),
dwarf_tag_name (die->tag));
@@ -8326,6 +8538,39 @@ dwarf2_linkage_name (struct die_info *die, struct dwarf2_cu *cu)
return dwarf2_name (die, cu);
}
+/* Return the fully qualified .symtab name for symbols contained in Fortran
+ modules. Return DWARF2_NAME otherwise. */
+
+static char *
+fortran_module_linkage_name (struct die_info *die, struct dwarf2_cu *cu)
+{
+ char *name;
+
+ gdb_assert (cu->language == language_fortran);
+
+ name = dwarf2_name (die, cu);
+
+ if (name && die->parent && die->parent->tag == DW_TAG_module)
+ {
+ char *module_name = dwarf2_name (die->parent, cu);
+
+ if (module_name)
+ {
+ char *retval;
+
+ /* `__modulename_MOD_variablename0'. */
+ retval = obstack_alloc (&cu->objfile->objfile_obstack,
+ 2 + strlen (module_name) + 5 + strlen (name)
+ + 1);
+ sprintf (retval, "__%s_MOD_%s", module_name, name);
+
+ return retval;
+ }
+ }
+
+ return name;
+}
+
/* Get name of a die, return NULL if not found. */
static char *
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
index c60bfdb..867c727 100644
--- a/gdb/f-lang.c
+++ b/gdb/f-lang.c
@@ -31,6 +31,8 @@
#include "f-lang.h"
#include "valprint.h"
#include "value.h"
+#include "block.h"
+#include "gdb_assert.h"
/* Following is dubious stuff that had been in the xcoff reader. */
@@ -306,6 +308,48 @@ f_language_arch_info (struct gdbarch *gdbarch,
lai->bool_type_default = builtin->builtin_logical_s2;
}
+/* Find if NAME is not contained in any of the Fortran modules imported by the
+ Fortran USE statement.
+
+ As Fortran has no nested blocks such lookup can be processed from
+ lookup_symbol_nonlocal - when no local blocks could satisfy the lookup. */
+
+struct symbol *
+f_lookup_symbol_nonlocal (const char *name,
+ const char *linkage_name,
+ const struct block *block,
+ const domain_enum domain)
+{
+ struct fortran_using *use;
+
+ if (!block)
+ return NULL;
+
+ for (use = BLOCK_FORTRAN_USE (block); use; use = use->next)
+ {
+ struct symbol *sym;
+ struct type *type;
+ struct symbol *retval;
+
+ sym = lookup_symbol_global (use->module_name, NULL, block, MODULE_DOMAIN);
+
+ /* Module name lookup should not fail with correct debug info. */
+ if (sym == NULL)
+ continue;
+
+ type = SYMBOL_TYPE (sym);
+ gdb_assert (TYPE_CODE (type) == TYPE_CODE_MODULE);
+ gdb_assert (TYPE_MODULE_BLOCK (type) != NULL);
+
+ retval = lookup_block_symbol (TYPE_MODULE_BLOCK (type), name,
+ linkage_name, domain);
+ if (retval)
+ return retval;
+ }
+
+ return NULL;
+}
+
/* This is declared in c-lang.h but it is silly to import that file for what
is already just a hack. */
extern int c_value_print (struct value *, struct ui_file *,
@@ -333,7 +377,7 @@ const struct language_defn f_language_defn =
c_value_print, /* FIXME */
NULL, /* Language specific skip_trampoline */
NULL, /* name_of_this */
- basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
+ f_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */
basic_lookup_transparent_type,/* lookup_transparent_type */
NULL, /* Language specific symbol demangler */
NULL, /* Language specific class_name_from_physname */
diff --git a/gdb/f-lang.h b/gdb/f-lang.h
index 711bdba..2c701eb 100644
--- a/gdb/f-lang.h
+++ b/gdb/f-lang.h
@@ -125,3 +125,10 @@ struct builtin_f_type
/* Return the Fortran type table for the specified architecture. */
extern const struct builtin_f_type *builtin_f_type (struct gdbarch *gdbarch);
+/* List of module names being imported by a block though BLOCK_FORTRAN_USE. */
+
+struct fortran_using
+ {
+ struct fortran_using *next;
+ char module_name[1];
+ };
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index fc54acc..f0f5aeb 100644
--- a/gdb/gdbtypes.h
+++ b/gdb/gdbtypes.h
@@ -136,6 +136,8 @@ enum type_code
TYPE_CODE_DECFLOAT, /* Decimal floating point. */
+ TYPE_CODE_MODULE, /* Fortran module. */
+
/* Internal function type. */
TYPE_CODE_INTERNAL_FUNCTION
};
@@ -524,6 +526,9 @@ struct main_type
supporting multiple ABIs. Right now this is only fetched from
the Dwarf-2 DW_AT_calling_convention attribute. */
unsigned calling_convention;
+
+ /* For TYPE_CODE_MODULE, the list of symbols contained in the module. */
+ struct block *module_block;
} type_specific;
};
@@ -842,6 +847,7 @@ extern void allocate_cplus_struct_type (struct type *);
#define TYPE_CPLUS_SPECIFIC(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.cplus_stuff
#define TYPE_FLOATFORMAT(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.floatformat
#define TYPE_CALLING_CONVENTION(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.calling_convention
+#define TYPE_MODULE_BLOCK(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.module_block
#define TYPE_BASECLASS(thistype,index) TYPE_MAIN_TYPE(thistype)->fields[index].type
#define TYPE_N_BASECLASSES(thistype) TYPE_CPLUS_SPECIFIC(thistype)->n_baseclasses
#define TYPE_BASECLASS_NAME(thistype,index) TYPE_MAIN_TYPE(thistype)->fields[index].name
diff --git a/gdb/symtab.c b/gdb/symtab.c
index b8a6c31..77a9a87 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -417,7 +417,8 @@ symbol_init_language_specific (struct general_symbol_info *gsymbol,
gsymbol->language = language;
if (gsymbol->language == language_cplus
|| gsymbol->language == language_java
- || gsymbol->language == language_objc)
+ || gsymbol->language == language_objc
+ || gsymbol->language == language_fortran)
{
gsymbol->language_specific.cplus_specific.demangled_name = NULL;
}
@@ -636,6 +637,7 @@ symbol_natural_name (const struct general_symbol_info *gsymbol)
case language_cplus:
case language_java:
case language_objc:
+ case language_fortran:
if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
return gsymbol->language_specific.cplus_specific.demangled_name;
break;
@@ -661,6 +663,7 @@ symbol_demangled_name (const struct general_symbol_info *gsymbol)
case language_cplus:
case language_java:
case language_objc:
+ case language_fortran:
if (gsymbol->language_specific.cplus_specific.demangled_name != NULL)
return gsymbol->language_specific.cplus_specific.demangled_name;
break;
diff --git a/gdb/symtab.h b/gdb/symtab.h
index f7689f6..669de05 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -394,7 +394,10 @@ typedef enum domain_enum_tag
FUNCTIONS_DOMAIN,
/* All defined types */
- TYPES_DOMAIN
+ TYPES_DOMAIN,
+
+ /* Fortran module. Their naming must be separate. */
+ MODULE_DOMAIN
}
domain_enum;
diff --git a/gdb/testsuite/gdb.fortran/library-module-lib.f90 b/gdb/testsuite/gdb.fortran/library-module-lib.f90
new file mode 100644
index 0000000..6369d34
--- /dev/null
+++ b/gdb/testsuite/gdb.fortran/library-module-lib.f90
@@ -0,0 +1,28 @@
+! Copyright 2009 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/>.
+
+module lib
+ integer :: var_i = 1
+contains
+ subroutine lib_func
+ if (var_i .ne. 1) call abort
+ var_i = 2
+ end subroutine lib_func
+end module lib
+
+module libmany
+ integer :: var_j = 3
+ integer :: var_k = 4
+end module libmany
diff --git a/gdb/testsuite/gdb.fortran/library-module-main.f90 b/gdb/testsuite/gdb.fortran/library-module-main.f90
new file mode 100644
index 0000000..de63a65
--- /dev/null
+++ b/gdb/testsuite/gdb.fortran/library-module-main.f90
@@ -0,0 +1,23 @@
+! Copyright 2009 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/>.
+
+ use lib
+ use libmany, only: var_j
+ if (var_i .ne. 1) call abort
+ call lib_func
+ if (var_i .ne. 2) call abort
+ if (var_j .ne. 3) call abort
+ var_i = var_i ! i-is-2
+end
diff --git a/gdb/testsuite/gdb.fortran/library-module.exp b/gdb/testsuite/gdb.fortran/library-module.exp
new file mode 100644
index 0000000..25abac3
--- /dev/null
+++ b/gdb/testsuite/gdb.fortran/library-module.exp
@@ -0,0 +1,53 @@
+# Copyright 2009 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/>.
+
+set testfile "library-module"
+set srcfile ${testfile}-main.f90
+set srclibfile ${testfile}-lib.f90
+set libfile ${testfile}-lib.so
+set binfile ${testfile}
+
+# Required for -fPIC by gdb_compile_shlib.
+if [get_compiler_info not-used] {
+ warning "Could not get compiler info"
+ return -1
+}
+
+if { [gdb_compile_shlib "${srcdir}/${subdir}/${srclibfile}" $srcdir/$subdir/$libfile {debug f77}] != "" } {
+ untested "Couldn't compile ${srclibfile}"
+ return -1
+}
+
+# prepare_for_testing cannot be used as linking with $libfile cannot be passed
+# just for the linking phase (and not the source compilation phase). And any
+# warnings on ignored $libfile abort the process.
+
+if { [gdb_compile [list $srcdir/$subdir/$srcfile $srcdir/$subdir/$libfile] $srcdir/$subdir/$binfile executable {debug f77}] != "" } {
+ untested "Couldn't compile ${srcfile}"
+ return -1
+}
+
+clean_restart $binfile
+
+if ![runto MAIN__] then {
+ perror "couldn't run to breakpoint MAIN__"
+ continue
+}
+
+gdb_breakpoint [gdb_get_line_number "i-is-2"]
+gdb_continue_to_breakpoint "i-is-2" ".*i-is-2.*"
+gdb_test "print var_i" " = 2"
+gdb_test "print var_j" " = 3"
+gdb_test "print var_k" "No symbol \"var_k\" in current context\\."
diff --git a/gdb/testsuite/gdb.fortran/module.exp b/gdb/testsuite/gdb.fortran/module.exp
index 342ccee..5f078a3 100644
--- a/gdb/testsuite/gdb.fortran/module.exp
+++ b/gdb/testsuite/gdb.fortran/module.exp
@@ -15,21 +15,30 @@
set testfile "module"
set srcfile ${testfile}.f90
-set binfile ${objdir}/${subdir}/${testfile}
-if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug f77 quiet}] != "" } {
- untested "Couldn't compile ${srcfile}"
+if { [prepare_for_testing $testfile.exp $testfile $srcfile {debug f77}] } {
return -1
}
-gdb_exit
-gdb_start
-gdb_reinitialize_dir $srcdir/$subdir
-gdb_load ${binfile}
-
if ![runto MAIN__] then {
perror "couldn't run to breakpoint MAIN__"
continue
}
-gdb_test "print i" " = 42"
+# Do not use simple single-letter names as GDB would pick up for expectedly
+# nonexisting symbols some static variables from system libraries debuginfos.
+
+gdb_breakpoint [gdb_get_line_number "i-is-1"]
+gdb_continue_to_breakpoint "i-is-1" ".*i-is-1.*"
+gdb_test "print var_i" " = 1" "print var_i value 1"
+
+gdb_breakpoint [gdb_get_line_number "i-is-2"]
+gdb_continue_to_breakpoint "i-is-2" ".*i-is-2.*"
+gdb_test "print var_i" " = 2" "print var_i value 2"
+
+gdb_breakpoint [gdb_get_line_number "a-b-c-d"]
+gdb_continue_to_breakpoint "a-b-c-d" ".*a-b-c-d.*"
+gdb_test "print var_a" "No symbol \"var_a\" in current context\\."
+gdb_test "print var_b" " = 11"
+gdb_test "print var_c" "No symbol \"var_c\" in current context\\."
+gdb_test "print var_d" " = 12"
diff --git a/gdb/testsuite/gdb.fortran/module.f90 b/gdb/testsuite/gdb.fortran/module.f90
index 501ccc8..99013dd 100644
--- a/gdb/testsuite/gdb.fortran/module.f90
+++ b/gdb/testsuite/gdb.fortran/module.f90
@@ -13,10 +13,36 @@
! You should have received a copy of the GNU General Public License
! along with this program. If not, see <http://www.gnu.org/licenses/>.
-module mod
- integer :: i = 42
-end module mod
+module mod1
+ integer :: var_i = 1
+end module mod1
- use mod
- print *, i
+module mod2
+ integer :: var_i = 2
+end module mod2
+
+module modmany
+ integer :: var_a = 10, var_b = 11, var_c = 12
+end module modmany
+
+ subroutine sub1
+ use mod1
+ if (var_i .ne. 1) call abort
+ var_i = var_i ! i-is-1
+ end
+
+ subroutine sub2
+ use mod2
+ if (var_i .ne. 2) call abort
+ var_i = var_i ! i-is-2
+ end
+
+ use modmany, only: var_b, var_d => var_c
+
+ call sub1
+ call sub2
+
+ if (var_b .ne. 11) call abort
+ if (var_d .ne. 12) call abort
+ var_b = var_b ! a-b-c-d
end