Fortran: Nested functions, add scope parameter.

In order to avoid name clashing in GDB, we add a scope
to nested subroutines. Enveloping function gives the
scope.

Change-Id: I7d424b1e3039613d938aae56ec1a3b3d1cdda744
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index cba551d..40a1881 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -6821,6 +6821,7 @@
       return NULL;
     }
 
+  /* Internal (nested) subroutines in Fortran get a prefix.  */
   if (pdi->tag == DW_TAG_enumerator)
     /* Enumerators should not get the name of the enumeration as a prefix.  */
     parent->scope = grandparent_scope;
@@ -6830,7 +6831,10 @@
       || parent->tag == DW_TAG_class_type
       || parent->tag == DW_TAG_interface_type
       || parent->tag == DW_TAG_union_type
-      || parent->tag == DW_TAG_enumeration_type)
+      || parent->tag == DW_TAG_enumeration_type
+      || (cu->language == language_fortran
+	  && parent->tag == DW_TAG_subprogram
+	  && pdi->tag == DW_TAG_subprogram))
     {
       if (grandparent_scope == NULL)
 	parent->scope = parent->name;
@@ -8330,8 +8334,13 @@
     case DW_TAG_type_unit:
       read_type_unit_scope (die, cu);
       break;
-    case DW_TAG_entry_point:
     case DW_TAG_subprogram:
+      /* Internal subprograms in Fortran get a prefix.  */
+      if (cu->language == language_fortran
+	  && die->parent != NULL
+	  && die->parent->tag == DW_TAG_subprogram)
+      cu->processing_has_namespace_info = 1;
+    case DW_TAG_entry_point:
     case DW_TAG_inlined_subroutine:
       read_func_scope (die, cu);
       break;
@@ -19540,6 +19549,19 @@
 	      return TYPE_TAG_NAME (parent_type);
 	    return "";
 	  }
+      case DW_TAG_subprogram:
+	/* Only internal subroutines in Fortran get a prefix with the name
+	   of the parent's subroutine.  */
+	if (cu->language == language_fortran)
+	  {
+	    if ((die->tag ==  DW_TAG_subprogram)
+		&& (dwarf2_name (parent, cu) != NULL))
+	      return dwarf2_name (parent, cu);
+	    else
+	      return "";
+	  }
+	else
+	  return determine_prefix (parent, cu);
 	/* Fall through.  */
       default:
 	return determine_prefix (parent, cu);
diff --git a/gdb/testsuite/gdb.fortran/nested-funcs.exp b/gdb/testsuite/gdb.fortran/nested-funcs.exp
index d098ba1..9e9ef60 100755
--- a/gdb/testsuite/gdb.fortran/nested-funcs.exp
+++ b/gdb/testsuite/gdb.fortran/nested-funcs.exp
@@ -31,8 +31,8 @@
 }

 

 # Test if we can set a breakpoint in a nested function

-gdb_breakpoint "sub_nested_outer"

-gdb_continue_to_breakpoint "sub_nested_outer" ".*local_int = 19"

+gdb_breakpoint "testnestedfuncs::sub_nested_outer"

+gdb_continue_to_breakpoint "testnestedfuncs::sub_nested_outer" ".*local_int = 19"

 

 # Test if we can access local and

 # non-local variables defined one level up.

@@ -43,13 +43,16 @@
 gdb_test "print index" "= 42" "print index at BP_outer, manipulated"

 gdb_test "print local_int" "= 19" "print local_int in outer function"

 

+

 # Non-local variable should be affected in one frame up as well.

 gdb_test "up"

 gdb_test "print index" "= 42" "print index at BP1, one frame up"

 

+

 # Test if we can set a breakpoint in a nested function

-gdb_breakpoint "sub_nested_inner"

-gdb_continue_to_breakpoint "sub_nested_inner" ".*local_int = 17"

+gdb_breakpoint "testnestedfuncs::sub_nested_inner"

+gdb_continue_to_breakpoint "testnestedfuncs::sub_nested_inner" ".*local_int = 17"

+

 

 # Test if we can access local and

 # non-local variables defined two level up.

@@ -59,12 +62,29 @@
 gdb_test "print v_state%code" "= 61" "print v_state%code at BP_inner"

 gdb_test "print local_int" "= 17" "print local_int in inner function"

 

+

 # Test if local variable is still correct.

 gdb_breakpoint [gdb_get_line_number "! BP_outer_2"]

 gdb_continue_to_breakpoint "! BP_outer_2" ".*! BP_outer_2"

 gdb_test "print local_int" "= 19" \

   "print local_int in outer function, after sub_nested_inner"

 

+

+# Test if we can set a breakpoint in public routine with the same name as the internal

+gdb_breakpoint "sub_nested_outer"

+gdb_continue_to_breakpoint "sub_nested_outer" ".*name = 'sub_nested_outer external'"

+

+

+# Test if we can set a breakpoint in public routine with the same name as the internal

+gdb_breakpoint "sub_with_sub_nested_outer::sub_nested_outer"

+gdb_continue_to_breakpoint "sub_with_sub_nested_outer::sub_nested_outer" ".*local_int = 11"

+

+

+# Test if we can set a breakpoint in public routine with the same name as the internal

+gdb_breakpoint "mod1::sub_nested_outer"

+gdb_continue_to_breakpoint "mod1::sub_nested_outer" ".*name = 'sub_nested_outer_mod1'"

+

+

 # Sanity check in main.

 gdb_breakpoint [gdb_get_line_number "! BP_main"]

 gdb_continue_to_breakpoint "! BP_main" ".*! BP_main"

diff --git a/gdb/testsuite/gdb.fortran/nested-funcs.f90 b/gdb/testsuite/gdb.fortran/nested-funcs.f90
index 5501b3b..23fdd35 100755
--- a/gdb/testsuite/gdb.fortran/nested-funcs.f90
+++ b/gdb/testsuite/gdb.fortran/nested-funcs.f90
@@ -13,8 +13,64 @@
 ! You should have received a copy of the GNU General Public License

 ! along with this program.  If not, see <http://www.gnu.org/licenses/>.

 

-program TestNestedFuncs

 

+module mod1

+  integer :: var_i = 1

+  integer :: var_const

+  parameter (var_const = 20)

+

+CONTAINS

+

+  SUBROUTINE sub_nested_outer

+    integer :: local_int

+    character (len=20) :: name

+

+    name = 'sub_nested_outer_mod1'

+    local_int = 11

+

+  END SUBROUTINE sub_nested_outer

+end module mod1

+

+

+! Public sub_nested_outer

+SUBROUTINE sub_nested_outer

+  integer :: local_int

+  character (len=16) :: name

+

+  name = 'sub_nested_outer external'

+  local_int = 11

+END SUBROUTINE sub_nested_outer

+

+! Needed indirection to call public sub_nested_outer from main

+SUBROUTINE sub_nested_outer_ind

+  character (len=20) :: name

+

+  name = 'sub_nested_outer_ind'

+  CALL sub_nested_outer

+END SUBROUTINE sub_nested_outer_ind

+

+! public routine with internal subroutine

+SUBROUTINE sub_with_sub_nested_outer()

+  integer :: local_int

+  character (len=16) :: name

+

+  name = 'subroutine_with_int_sub'

+  local_int = 1

+

+  CALL sub_nested_outer  ! Should call the internal fct

+

+CONTAINS

+

+  SUBROUTINE sub_nested_outer

+	integer :: local_int

+	local_int = 11

+  END SUBROUTINE sub_nested_outer

+	

+END SUBROUTINE sub_with_sub_nested_outer

+

+! Main

+program TestNestedFuncs

+  USE mod1, sub_nested_outer_use_mod1 => sub_nested_outer

   IMPLICIT NONE

 

   TYPE :: t_State

@@ -22,10 +78,14 @@
   END TYPE t_State

 

   TYPE (t_State) :: v_state

-  integer index

+  integer index, local_int

 

+  local_int = 14

   index = 13

-  CALL sub_nested_outer

+  CALL sub_nested_outer            ! Call internal sub_nested_outer

+  CALL sub_nested_outer_ind        ! Call external sub_nested_outer via sub_nested_outer_ind

+  CALL sub_with_sub_nested_outer   ! Call external routine with nested sub_nested_outer

+  CALL sub_nested_outer_use_mod1   ! Call sub_nested_outer imported via module

   index = 11              ! BP_main

   v_state%code = 27