This is the mail archive of the archer@sourceware.org mailing list for the Archer project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]