From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 515 invoked by alias); 2 Jun 2010 22:44:06 -0000 Received: (qmail 473 invoked by uid 22791); 2 Jun 2010 22:43:59 -0000 X-SWARE-Spam-Status: No, hits=-4.9 required=5.0 tests=AWL,BAYES_00,KAM_STOCKGEN,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,TW_BJ,TW_CP,T_FILL_THIS_FORM_SHORT,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 02 Jun 2010 22:43:49 +0000 Received: from int-mx08.intmail.prod.int.phx2.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o52MhmUZ003848 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 2 Jun 2010 18:43:48 -0400 Received: from host0.dyn.jankratochvil.net (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx08.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o52MhhWh025580 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 2 Jun 2010 18:43:45 -0400 Received: from host0.dyn.jankratochvil.net (localhost [127.0.0.1]) by host0.dyn.jankratochvil.net (8.14.4/8.14.4) with ESMTP id o52MhhVM003111; Thu, 3 Jun 2010 00:43:43 +0200 Received: (from jkratoch@localhost) by host0.dyn.jankratochvil.net (8.14.4/8.14.4/Submit) id o52Mhgxt003109; Thu, 3 Jun 2010 00:43:42 +0200 Date: Wed, 02 Jun 2010 22:44:00 -0000 From: Jan Kratochvil To: Tom Tromey Cc: gdb-patches@sourceware.org Subject: Re: [patch 3/3] Fortran modules namespaces [rediff] Message-ID: <20100602224342.GA2934@host0.dyn.jankratochvil.net> References: <20100430182409.GC19190@host0.dyn.jankratochvil.net> <20100508055452.GA27443@host0.dyn.jankratochvil.net> <20100602211612.GA30562@host0.dyn.jankratochvil.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.20 (2009-12-10) X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2010-06/txt/msg00086.txt.bz2 On Thu, 03 Jun 2010 00:02:45 +0200, Tom Tromey wrote: > This patch is ok. Thanks. Checked-in; it needed a small rediff for my patch: [obv] typename_concat: char * -> const char * http://sourceware.org/ml/gdb-patches/2010-06/msg00053.html Thanks, Jan http://sourceware.org/ml/gdb-cvs/2010-06/msg00027.html --- src/gdb/ChangeLog 2010/06/02 22:21:52 1.11866 +++ src/gdb/ChangeLog 2010/06/02 22:41:55 1.11867 @@ -1,3 +1,51 @@ +2010-06-02 Jan Kratochvil + + Support DW_TAG_module as separate namespaces. + * dwarf2read.c (typename_concat): New parameter physname. + (read_module_type): New function and declaration. + (scan_partial_symbols): Scan also DW_TAG_module children. + (partial_die_parent_scope): Accept scope even from DW_TAG_module. Pass + to typename_concat backward compatible physname value 0. + (partial_die_full_name, read_namespace_type): Pass to typename_concat + backward compatible physname value 0. + (add_partial_module, read_module): Remove FIXME comment. + (process_die) : Set PROCESSING_HAS_NAMESPACE_INFO. + (die_needs_namespace) : Allow returning true even for + DIEs under DW_TAG_module. + (dwarf2_compute_name): Move the ada block for DW_AT_linkage_name and + DW_AT_MIPS_linkage_name first, extend it for language_fortran + && physname and return there instead of just setting NAME. Extend + the main block for language_fortran. Pass physname parameter to the + typename_concat call. + (read_import_statement, read_func_scope, get_scope_pc_bounds) + (load_partial_dies, determine_prefix): Support also DW_TAG_module. + (new_symbol): Fill in cplus_specific.demangled_name if it is still + missing from SYMBOL_SET_NAMES in the language_fortran case. + (new_symbol) : Force LOC_UNRESOLVED for gfortran module + variables. + (read_type_die) : New. + (MAX_SEP_LEN): Increase to 7. + (typename_concat): New parameter physname. New variable lead. Support + also language_fortran. + * f-exp.y (yylex): Consider : also as a symbol name character class. + * f-lang.c: Include cp-support.h. + (f_word_break_characters, f_make_symbol_completion_list): New functions. + (f_language_defn): Use cp_lookup_symbol_nonlocal, + f_word_break_characters and f_make_symbol_completion_list. + * f-typeprint.c (f_type_print_base) : New. + * gdbtypes.h (enum type_code) : New. + * symtab.c (symbol_init_language_specific): Support language_fortran. + (symbol_find_demangled_name): New comment on language_fortran. + (symbol_natural_name, symbol_demangled_name): Use demangled_name even + for language_fortran. + (lookup_symbol_aux_local): Check imports also for language_fortran. + (default_make_symbol_completion_list): Rename to ... + (default_make_symbol_completion_list_break_on): ... this name. New + parameter break_on, use it. + (default_make_symbol_completion_list): New stub. + * symtab.h (default_make_symbol_completion_list_break_on): New + prototype. + 2010-06-02 Joel Brobecker * remote.c (remote_get_noisy_reply): Remove trailing "\n" in call --- src/gdb/testsuite/ChangeLog 2010/06/02 22:24:15 1.2309 +++ src/gdb/testsuite/ChangeLog 2010/06/02 22:41:56 1.2310 @@ -1,5 +1,22 @@ 2010-06-02 Jan Kratochvil + Support DW_TAG_module as separate namespaces. + * gdb.fortran/library-module.exp, gdb.fortran/library-module-main.f90, + gdb.fortran/library-module-lib.f90: New. + * gdb.fortran/module.exp: Replace startup by a prepare_for_testing call. + (print i): Remove. + (continue to breakpoint: i-is-1, print var_i value 1) + (continue to breakpoint: i-is-2, print var_i value 2) + (continue to breakpoint: a-b-c-d, print var_a, print var_b, print var_c) + (print var_d, print var_i value 14, ptype modmany, complete `modm) + (complete `modmany, complete `modmany`, complete `modmany`var) + (show language, setting breakpoint at module): New tests. + * gdb.fortran/module.f90 (module mod): Remove. + (module mod1, module mod2, module modmany, subroutine sub1) + (subroutine sub2, program module): New. + +2010-06-02 Jan Kratochvil + * gdb.cp/ref-types.exp (pass, pass, pass): Rename to ... (print value of rUC, print value of rI, print value of UI): ... here. * gdb.cp/anon-union.exp (pass): Rename to ... --- src/gdb/dwarf2read.c 2010/06/02 20:03:42 1.392 +++ src/gdb/dwarf2read.c 2010/06/02 22:41:55 1.393 @@ -905,10 +905,9 @@ static char *determine_prefix (struct die_info *die, struct dwarf2_cu *); -static char *typename_concat (struct obstack *, - const char *prefix, - const char *suffix, - struct dwarf2_cu *); +static char *typename_concat (struct obstack *obs, const char *prefix, + const char *suffix, int physname, + struct dwarf2_cu *cu); static void read_file_scope (struct die_info *, struct dwarf2_cu *); @@ -955,6 +954,9 @@ static void read_import_statement (struct die_info *die, struct dwarf2_cu *); +static struct type *read_module_type (struct die_info *die, + struct dwarf2_cu *cu); + static const char *namespace_name (struct die_info *die, int *is_anonymous, struct dwarf2_cu *); @@ -2198,12 +2200,12 @@ { fixup_partial_die (pdi, cu); - /* Anonymous namespaces have no name but have interesting + /* Anonymous namespaces or modules have no name but have interesting children, so we need to look at them. Ditto for anonymous enums. */ if (pdi->name != NULL || pdi->tag == DW_TAG_namespace - || pdi->tag == DW_TAG_enumeration_type) + || pdi->tag == DW_TAG_module || pdi->tag == DW_TAG_enumeration_type) { switch (pdi->tag) { @@ -2316,6 +2318,7 @@ } if (parent->tag == DW_TAG_namespace + || parent->tag == DW_TAG_module || parent->tag == DW_TAG_structure_type || parent->tag == DW_TAG_class_type || parent->tag == DW_TAG_interface_type @@ -2326,7 +2329,7 @@ parent->scope = parent->name; else parent->scope = typename_concat (&cu->comp_unit_obstack, grandparent_scope, - parent->name, cu); + parent->name, 0, cu); } else if (parent->tag == DW_TAG_enumerator) /* Enumerators should not get the name of the enumeration as a prefix. */ @@ -2358,7 +2361,7 @@ if (parent_scope == NULL) return NULL; else - return typename_concat (NULL, parent_scope, pdi->name, cu); + return typename_concat (NULL, parent_scope, pdi->name, 0, cu); } static void @@ -2544,9 +2547,7 @@ 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. - - FIXME: Support the separate Fortran module namespaces. */ + /* Now scan partial symbols in that module. */ if (pdi->has_children) scan_partial_symbols (pdi->die_child, lowpc, highpc, need_pc, cu); @@ -3208,6 +3209,7 @@ read_namespace (die, cu); break; case DW_TAG_module: + processing_has_namespace_info = 1; read_module (die, cu); break; case DW_TAG_imported_declaration: @@ -3263,7 +3265,8 @@ } attr = dwarf2_attr (die, DW_AT_external, cu); - if (attr == NULL && die->parent->tag != DW_TAG_namespace) + if (attr == NULL && die->parent->tag != DW_TAG_namespace + && die->parent->tag != DW_TAG_module) return 0; /* A variable in a lexical block of some kind does not need a namespace, even though in C++ such variables may be external @@ -3296,9 +3299,29 @@ if (name == NULL) name = dwarf2_name (die, cu); + /* For Fortran GDB prefers DW_AT_*linkage_name if present but otherwise + compute it by typename_concat inside GDB. */ + if (cu->language == language_ada + || (cu->language == language_fortran && physname)) + { + /* For Ada unit, we prefer the linkage name over the name, as + the former contains the exported name, which the user expects + to be able to reference. Ideally, we want the user to be able + to reference this entity using either natural or linkage name, + but we haven't started looking at this enhancement yet. */ + struct attribute *attr; + + attr = dwarf2_attr (die, DW_AT_linkage_name, cu); + if (attr == NULL) + attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu); + if (attr && DW_STRING (attr)) + return DW_STRING (attr); + } + /* These are the only languages we know how to qualify names in. */ if (name != NULL - && (cu->language == language_cplus || cu->language == language_java)) + && (cu->language == language_cplus || cu->language == language_java + || cu->language == language_fortran)) { if (die_needs_namespace (die, cu)) { @@ -3310,7 +3333,8 @@ buf = mem_fileopen (); if (*prefix != '\0') { - char *prefixed_name = typename_concat (NULL, prefix, name, cu); + char *prefixed_name = typename_concat (NULL, prefix, name, + physname, cu); fputs_unfiltered (prefixed_name, buf); xfree (prefixed_name); @@ -3361,21 +3385,6 @@ } } } - else if (cu->language == language_ada) - { - /* For Ada unit, we prefer the linkage name over the name, as - the former contains the exported name, which the user expects - to be able to reference. Ideally, we want the user to be able - to reference this entity using either natural or linkage name, - but we haven't started looking at this enhancement yet. */ - struct attribute *attr; - - attr = dwarf2_attr (die, DW_AT_linkage_name, cu); - if (attr == NULL) - attr = dwarf2_attr (die, DW_AT_MIPS_linkage_name, cu); - if (attr && DW_STRING (attr)) - name = DW_STRING (attr); - } return name; } @@ -3482,7 +3491,8 @@ to the name of the imported die. */ imported_name_prefix = determine_prefix (imported_die, imported_cu); - if (imported_die->tag != DW_TAG_namespace) + if (imported_die->tag != DW_TAG_namespace + && imported_die->tag != DW_TAG_module) { imported_declaration = imported_name; canonical_name = imported_name_prefix; @@ -3979,7 +3989,7 @@ lowpc, highpc, objfile); /* For C++, set the block's scope. */ - if (cu->language == language_cplus) + if (cu->language == language_cplus || cu->language == language_fortran) cp_set_block_scope (new->name, block, &objfile->objfile_obstack, determine_prefix (die, cu), processing_has_namespace_info); @@ -4314,6 +4324,7 @@ dwarf2_get_subprogram_pc_bounds (child, &best_low, &best_high, cu); break; case DW_TAG_namespace: + case DW_TAG_module: /* FIXME: carlton/2004-01-16: Should we do this for DW_TAG_class_type/DW_TAG_structure_type, too? I think that current GCC's always emit the DIEs corresponding @@ -5640,7 +5651,7 @@ previous_prefix = determine_prefix (die, cu); if (previous_prefix[0] != '\0') name = typename_concat (&objfile->objfile_obstack, - previous_prefix, name, cu); + previous_prefix, name, 0, cu); /* Create the type. */ type = init_type (TYPE_CODE_NAMESPACE, 0, 0, NULL, @@ -5693,6 +5704,29 @@ } } +/* Read a Fortran module as type. This DIE can be only a declaration used for + imported module. Still we need that type as local Fortran "use ... only" + declaration imports depend on the created type in determine_prefix. */ + +static struct type * +read_module_type (struct die_info *die, struct dwarf2_cu *cu) +{ + struct objfile *objfile = cu->objfile; + char *module_name; + struct type *type; + + 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); + + /* determine_prefix uses TYPE_TAG_NAME. */ + TYPE_TAG_NAME (type) = TYPE_NAME (type); + + return set_die_type (die, type, cu); +} + /* Read a Fortran module. */ static void @@ -5700,8 +5734,6 @@ { struct die_info *child_die = die->child; - /* FIXME: Support the separate Fortran module namespaces. */ - while (child_die && child_die->tag) { process_die (child_die, cu); @@ -6691,6 +6723,7 @@ && 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. */ @@ -6822,6 +6855,7 @@ if (last_die->has_children && (load_all || last_die->tag == DW_TAG_namespace + || last_die->tag == DW_TAG_module || last_die->tag == DW_TAG_enumeration_type || (cu->language != language_c && (last_die->tag == DW_TAG_class_type @@ -8543,6 +8577,13 @@ linkagename = dwarf2_physname (name, die, cu); SYMBOL_SET_NAMES (sym, linkagename, strlen (linkagename), 0, objfile); + /* Fortran does not have mangling standard and the mangling does differ + between gfortran, iFort etc. */ + if (cu->language == language_fortran + && sym->ginfo.language_specific.cplus_specific.demangled_name == NULL) + sym->ginfo.language_specific.cplus_specific.demangled_name + = (char *) dwarf2_full_name (name, die, cu); + /* Default assumptions. Use the passed type or decode it from the die. */ SYMBOL_DOMAIN (sym) = VAR_DOMAIN; @@ -8646,6 +8687,20 @@ { struct pending **list_to_add; + /* 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 the minimal symbol + which may come from inferior's executable using copy + relocation. Make this workaround only for gfortran as for + other compilers GDB cannot guess the minimal symbol + Fortran mangling kind. */ + if (cu->language == language_fortran && die->parent + && die->parent->tag == DW_TAG_module + && cu->producer + && strncmp (cu->producer, "GNU Fortran ", 12) == 0) + SYMBOL_CLASS (sym) = LOC_UNRESOLVED; + /* A variable with DW_AT_external is never static, but it may be block-scoped. */ list_to_add = (cu->list_in_scope == &file_symbols @@ -9127,6 +9182,9 @@ 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)); @@ -9158,8 +9216,8 @@ struct dwarf2_cu *spec_cu; struct type *parent_type; - if (cu->language != language_cplus - && cu->language != language_java) + if (cu->language != language_cplus && cu->language != language_java + && cu->language != language_fortran) return ""; /* We have to be careful in the presence of DW_AT_specification. @@ -9211,6 +9269,7 @@ case DW_TAG_interface_type: case DW_TAG_structure_type: case DW_TAG_union_type: + case DW_TAG_module: parent_type = read_type_die (parent, cu); if (TYPE_TAG_NAME (parent_type) != NULL) return TYPE_TAG_NAME (parent_type); @@ -9230,18 +9289,27 @@ perform an obconcat, otherwise allocate storage for the result. The CU argument is used to determine the language and hence, the appropriate separator. */ -#define MAX_SEP_LEN 2 /* sizeof ("::") */ +#define MAX_SEP_LEN 7 /* strlen ("__") + strlen ("_MOD_") */ static char * -typename_concat (struct obstack *obs, const char *prefix, const char *suffix, - struct dwarf2_cu *cu) +typename_concat (struct obstack *obs, const char *prefix, const char *suffix, + int physname, struct dwarf2_cu *cu) { + const char *lead = ""; const char *sep; if (suffix == NULL || suffix[0] == '\0' || prefix == NULL || prefix[0] == '\0') sep = ""; else if (cu->language == language_java) sep = "."; + else if (cu->language == language_fortran && physname) + { + /* This is gfortran specific mangling. Normally DW_AT_linkage_name or + DW_AT_MIPS_linkage_name is preferred and used instead. */ + + lead = "__"; + sep = "_MOD_"; + } else sep = "::"; @@ -9254,7 +9322,8 @@ { char *retval = xmalloc (strlen (prefix) + MAX_SEP_LEN + strlen (suffix) + 1); - strcpy (retval, prefix); + strcpy (retval, lead); + strcat (retval, prefix); strcat (retval, sep); strcat (retval, suffix); return retval; @@ -9262,7 +9331,7 @@ else { /* We have an obstack. */ - return obconcat (obs, prefix, sep, suffix, (char *) NULL); + return obconcat (obs, lead, prefix, sep, suffix, (char *) NULL); } } --- src/gdb/f-exp.y 2010/04/20 17:22:18 1.32 +++ src/gdb/f-exp.y 2010/06/02 22:41:55 1.33 @@ -1128,14 +1128,14 @@ return c; } - if (!(c == '_' || c == '$' + if (!(c == '_' || c == '$' || c ==':' || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))) /* We must have come across a bad character (e.g. ';'). */ error ("Invalid character '%c' in expression.", c); namelen = 0; for (c = tokstart[namelen]; - (c == '_' || c == '$' || (c >= '0' && c <= '9') + (c == '_' || c == '$' || c == ':' || (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')); c = tokstart[++namelen]); --- src/gdb/f-lang.c 2010/05/06 23:36:39 1.61 +++ src/gdb/f-lang.c 2010/06/02 22:41:55 1.62 @@ -31,6 +31,7 @@ #include "f-lang.h" #include "valprint.h" #include "value.h" +#include "cp-support.h" /* Following is dubious stuff that had been in the xcoff reader. */ @@ -308,6 +309,38 @@ lai->bool_type_default = builtin->builtin_logical_s2; } +/* Remove the modules separator :: from the default break list. */ + +static char * +f_word_break_characters (void) +{ + static char *retval; + + if (!retval) + { + char *s; + + retval = xstrdup (default_word_break_characters ()); + s = strchr (retval, ':'); + if (s) + { + char *last_char = &s[strlen (s) - 1]; + + *s = *last_char; + *last_char = 0; + } + } + return retval; +} + +/* Consider the modules separator :: as a valid symbol name character class. */ + +static char ** +f_make_symbol_completion_list (char *text, char *word) +{ + return default_make_symbol_completion_list_break_on (text, word, ":"); +} + /* 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 *, @@ -335,15 +368,15 @@ c_value_print, /* FIXME */ NULL, /* Language specific skip_trampoline */ NULL, /* name_of_this */ - basic_lookup_symbol_nonlocal, /* lookup_symbol_nonlocal */ + cp_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 */ f_op_print_tab, /* expression operators for printing */ 0, /* arrays are first-class (not c-style) */ 1, /* String lower bound */ - default_word_break_characters, - default_make_symbol_completion_list, + f_word_break_characters, + f_make_symbol_completion_list, f_language_arch_info, default_print_array_index, default_pass_by_reference, --- src/gdb/f-typeprint.c 2010/05/07 00:28:32 1.30 +++ src/gdb/f-typeprint.c 2010/06/02 22:41:55 1.31 @@ -370,6 +370,10 @@ fputs_filtered (TYPE_TAG_NAME (type), stream); break; + case TYPE_CODE_MODULE: + fprintfi_filtered (level, stream, "module %s", TYPE_TAG_NAME (type)); + break; + default_case: default: /* Handle types not explicitly handled by the other cases, --- src/gdb/gdbtypes.h 2010/05/05 17:07:40 1.128 +++ src/gdb/gdbtypes.h 2010/06/02 22:41:55 1.129 @@ -136,6 +136,8 @@ TYPE_CODE_DECFLOAT, /* Decimal floating point. */ + TYPE_CODE_MODULE, /* Fortran module. */ + /* Internal function type. */ TYPE_CODE_INTERNAL_FUNCTION }; --- src/gdb/symtab.c 2010/05/16 23:49:58 1.237 +++ src/gdb/symtab.c 2010/06/02 22:41:55 1.238 @@ -351,7 +351,8 @@ if (gsymbol->language == language_cplus || gsymbol->language == language_d || gsymbol->language == language_java - || gsymbol->language == language_objc) + || gsymbol->language == language_objc + || gsymbol->language == language_fortran) { gsymbol->language_specific.cplus_specific.demangled_name = NULL; } @@ -465,6 +466,11 @@ return demangled; } } + /* We could support `gsymbol->language == language_fortran' here to provide + module namespaces also for inferiors with only minimal symbol table (ELF + symbols). Just the mangling standard is not standardized across compilers + and there is no DW_AT_producer available for inferiors with only the ELF + symbols to check the mangling kind. */ return NULL; } @@ -645,6 +651,7 @@ case language_d: 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; @@ -671,6 +678,7 @@ case language_d: 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; @@ -1156,7 +1164,7 @@ if (sym != NULL) return sym; - if (language == language_cplus) + if (language == language_cplus || language == language_fortran) { sym = cp_lookup_symbol_imports (scope, name, @@ -3582,7 +3590,8 @@ } char ** -default_make_symbol_completion_list (char *text, char *word) +default_make_symbol_completion_list_break_on (char *text, char *word, + const char *break_on) { /* Problem: All of the symbols have to be copied because readline frees them. I'm not going to worry about this; hopefully there @@ -3645,7 +3654,7 @@ while (p > text) { if (isalnum (p[-1]) || p[-1] == '_' || p[-1] == '\0' - || p[-1] == ':') + || p[-1] == ':' || strchr (break_on, p[-1]) != NULL) --p; else break; @@ -3771,6 +3780,12 @@ return (return_val); } +char ** +default_make_symbol_completion_list (char *text, char *word) +{ + return default_make_symbol_completion_list_break_on (text, word, ""); +} + /* Return a NULL terminated array of all symbols (regardless of class) which begin by matching TEXT. If the answer is no symbols, then the return value is an array which contains only a NULL pointer. */ --- src/gdb/symtab.h 2010/04/22 23:15:42 1.152 +++ src/gdb/symtab.h 2010/06/02 22:41:55 1.153 @@ -1116,6 +1116,8 @@ extern void select_source_symtab (struct symtab *); +extern char **default_make_symbol_completion_list_break_on + (char *text, char *word, const char *break_on); extern char **default_make_symbol_completion_list (char *, char *); extern char **make_symbol_completion_list (char *, char *); extern char **make_symbol_completion_list_fn (struct cmd_list_element *, --- src/gdb/testsuite/gdb.fortran/library-module-lib.f90 +++ src/gdb/testsuite/gdb.fortran/library-module-lib.f90 2010-06-02 22:42:12.757644000 +0000 @@ -0,0 +1,29 @@ +! Copyright 2010 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 . + +module lib + integer :: var_i = 1 +contains + subroutine lib_func + if (var_i .ne. 1) call abort + var_i = 2 + var_i = var_i ! i-is-2-in-lib + end subroutine lib_func +end module lib + +module libmany + integer :: var_j = 3 + integer :: var_k = 4 +end module libmany --- src/gdb/testsuite/gdb.fortran/library-module-main.f90 +++ src/gdb/testsuite/gdb.fortran/library-module-main.f90 2010-06-02 22:42:13.071128000 +0000 @@ -0,0 +1,23 @@ +! Copyright 2010 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 . + + 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-in-main +end --- src/gdb/testsuite/gdb.fortran/library-module.exp +++ src/gdb/testsuite/gdb.fortran/library-module.exp 2010-06-02 22:42:13.376698000 +0000 @@ -0,0 +1,58 @@ +# Copyright 2010 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 . + +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}" $objdir/$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 $objdir/$subdir/$libfile] $objdir/$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 $srclibfile:[gdb_get_line_number "i-is-2-in-lib" $srclibfile] +gdb_continue_to_breakpoint "i-is-2-in-lib" ".*i-is-2-in-lib.*" +gdb_test "print var_i" " = 2" "print var_i in lib" + +gdb_breakpoint $srcfile:[gdb_get_line_number "i-is-2-in-main" $srcfile] +gdb_continue_to_breakpoint "i-is-2-in-main" ".*i-is-2-in-main.*" +gdb_test "print var_i" " = 2" "print var_i in main" + +gdb_test "print var_j" " = 3" +gdb_test "print var_k" "No symbol \"var_k\" in current context\\." --- src/gdb/testsuite/gdb.fortran/module.exp 2010/01/01 07:32:02 1.2 +++ src/gdb/testsuite/gdb.fortran/module.exp 2010/06/02 22:41:56 1.3 @@ -15,21 +15,54 @@ 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" +gdb_test "print var_i" " = 14" "print var_i value 14" + +gdb_test "ptype modmany" {No symbol "modmany" in current context.} + +proc complete {expr list} { + set cmd "complete p $expr" + set expect [join [concat [list $cmd] $list] "\r\np "] + gdb_test $cmd $expect "complete $expr" +} +set modmany_list {modmany::var_a modmany::var_b modmany::var_c modmany::var_i} +complete "modm" $modmany_list +complete "modmany" $modmany_list +complete "modmany::" $modmany_list +complete "modmany::var" $modmany_list + +# Breakpoint would work in language "c". +gdb_test "show language" {The current source language is "(auto; currently )?fortran".} + +# gcc-4.4.2: The main program is always MAIN__ in .symtab so "runto" above +# works. But DWARF DW_TAG_subprogram contains the name specified by +# the "program" Fortran statement. +if [gdb_breakpoint "module"] { + pass "setting breakpoint at module" +} --- src/gdb/testsuite/gdb.fortran/module.f90 2010/01/01 09:44:07 1.2 +++ src/gdb/testsuite/gdb.fortran/module.f90 2010/06/02 22:41:56 1.3 @@ -13,10 +13,39 @@ ! You should have received a copy of the GNU General Public License ! along with this program. If not, see . -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, var_i = 14 +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 + + program module + + use modmany, only: var_b, var_d => var_c, var_i + + call sub1 + call sub2 + + if (var_b .ne. 11) call abort + if (var_d .ne. 12) call abort + if (var_i .ne. 14) call abort + var_b = var_b ! a-b-c-d end