mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-11-16 12:34:43 +00:00
Compare commits
4 Commits
efbd9add96
...
users/bhec
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bee226f9b2 | ||
|
|
1c04575472 | ||
|
|
671c004cc4 | ||
|
|
57ed8b65cc |
3
gdb/doc/gdb.texinfo
Normal file → Executable file
3
gdb/doc/gdb.texinfo
Normal file → Executable file
@@ -15228,6 +15228,9 @@ The access component operator. Normally used to access elements in derived
|
||||
types. Also suitable for unions. As unions aren't part of regular Fortran,
|
||||
this can only happen when accessing a register that uses a gdbarch-defined
|
||||
union type.
|
||||
@item ::
|
||||
The scope operator. Normally used to access variables in modules or to set breakpoints
|
||||
on subroutines nested in modules or in other subroutines (internal subroutines).
|
||||
@end table
|
||||
|
||||
@node Fortran Defaults
|
||||
|
||||
120
gdb/dwarf2read.c
120
gdb/dwarf2read.c
@@ -1425,6 +1425,10 @@ static void add_partial_module (struct partial_die_info *pdi, CORE_ADDR *lowpc,
|
||||
static void add_partial_enumeration (struct partial_die_info *enum_pdi,
|
||||
struct dwarf2_cu *cu);
|
||||
|
||||
static void add_partial_entry_point (struct partial_die_info *pdi,
|
||||
CORE_ADDR *lowpc, CORE_ADDR *highpc,
|
||||
int need_pc, struct dwarf2_cu *cu);
|
||||
|
||||
static void add_partial_subprogram (struct partial_die_info *pdi,
|
||||
CORE_ADDR *lowpc, CORE_ADDR *highpc,
|
||||
int need_pc, struct dwarf2_cu *cu);
|
||||
@@ -6817,6 +6821,7 @@ partial_die_parent_scope (struct partial_die_info *pdi,
|
||||
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;
|
||||
@@ -6826,7 +6831,10 @@ partial_die_parent_scope (struct partial_die_info *pdi,
|
||||
|| 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;
|
||||
@@ -6911,9 +6919,30 @@ add_partial_symbol (struct partial_die_info *pdi, struct dwarf2_cu *cu)
|
||||
|
||||
switch (pdi->tag)
|
||||
{
|
||||
case DW_TAG_entry_point:
|
||||
addr = gdbarch_adjust_dwarf2_addr (gdbarch, pdi->lowpc + baseaddr);
|
||||
/* DW_TAG_entry_point provides an additional entry_point to an
|
||||
existing sub_program. Therefore, we inherit the "external"
|
||||
attribute from the sub_program to which the entry_point
|
||||
belongs to. */
|
||||
if (pdi->die_parent->is_external)
|
||||
add_psymbol_to_list (actual_name, strlen (actual_name),
|
||||
built_actual_name != NULL,
|
||||
VAR_DOMAIN, LOC_BLOCK,
|
||||
&objfile->global_psymbols,
|
||||
addr, cu->language, objfile);
|
||||
else
|
||||
add_psymbol_to_list (actual_name, strlen (actual_name),
|
||||
built_actual_name != NULL,
|
||||
VAR_DOMAIN, LOC_BLOCK,
|
||||
&objfile->static_psymbols,
|
||||
addr, cu->language, objfile);
|
||||
break;
|
||||
case DW_TAG_subprogram:
|
||||
addr = gdbarch_adjust_dwarf2_addr (gdbarch, pdi->lowpc + baseaddr);
|
||||
if (pdi->is_external || cu->language == language_ada)
|
||||
if (pdi->is_external
|
||||
|| cu->language == language_ada
|
||||
|| cu->language == language_fortran)
|
||||
{
|
||||
/* brobecker/2007-12-26: Normally, only "external" DIEs are part
|
||||
of the global scope. But in Ada, we want to be able to access
|
||||
@@ -7108,6 +7137,17 @@ add_partial_module (struct partial_die_info *pdi, CORE_ADDR *lowpc,
|
||||
scan_partial_symbols (pdi->die_child, lowpc, highpc, set_addrmap, cu);
|
||||
}
|
||||
|
||||
static void
|
||||
add_partial_entry_point (struct partial_die_info *pdi,
|
||||
CORE_ADDR *p_lowpc, CORE_ADDR *p_highpc,
|
||||
int set_addrmap, struct dwarf2_cu *cu)
|
||||
{
|
||||
if (pdi->name == NULL)
|
||||
complaint (&symfile_complaints, _("DW_TAG_entry_point have to have a name"));
|
||||
else
|
||||
add_partial_symbol (pdi, cu);
|
||||
}
|
||||
|
||||
/* Read a partial die corresponding to a subprogram and create a partial
|
||||
symbol for that subprogram. When the CU language allows it, this
|
||||
routine also defines a partial symbol for each nested subprogram
|
||||
@@ -7178,6 +7218,18 @@ add_partial_subprogram (struct partial_die_info *pdi,
|
||||
pdi = pdi->die_sibling;
|
||||
}
|
||||
}
|
||||
else if (cu->language == language_fortran)
|
||||
{
|
||||
pdi = pdi->die_child;
|
||||
while (pdi != NULL)
|
||||
{
|
||||
if (pdi->tag == DW_TAG_entry_point)
|
||||
add_partial_entry_point (pdi, lowpc, highpc, set_addrmap, cu);
|
||||
else if (pdi->tag == DW_TAG_subprogram)
|
||||
add_partial_subprogram (pdi, lowpc, highpc, set_addrmap, cu);
|
||||
pdi = pdi->die_sibling;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Read a partial die corresponding to an enumeration type. */
|
||||
@@ -8283,6 +8335,12 @@ process_die (struct die_info *die, struct dwarf2_cu *cu)
|
||||
read_type_unit_scope (die, cu);
|
||||
break;
|
||||
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;
|
||||
@@ -12063,6 +12121,27 @@ dwarf2_get_pc_bounds (struct die_info *die, CORE_ADDR *lowpc,
|
||||
CORE_ADDR high = 0;
|
||||
enum pc_bounds_kind ret;
|
||||
|
||||
if (die->tag == DW_TAG_entry_point)
|
||||
{
|
||||
/* Entry_point is embedded in an subprogram. Therefore, we can use
|
||||
the highpc from it's enveloping subprogram and get the
|
||||
lowpc from DWARF. */
|
||||
if (PC_BOUNDS_INVALID == dwarf2_get_pc_bounds (die->parent, lowpc, highpc, cu, pst))
|
||||
return PC_BOUNDS_INVALID;
|
||||
|
||||
attr = dwarf2_attr (die, DW_AT_low_pc, cu);
|
||||
if (!attr)
|
||||
{
|
||||
complaint (&symfile_complaints,
|
||||
_("DW_TAG_entry_point is missing DW_AT_low_pc"));
|
||||
return PC_BOUNDS_INVALID;
|
||||
}
|
||||
low = attr_value_as_address (attr);
|
||||
*lowpc = low;
|
||||
|
||||
return PC_BOUNDS_HIGH_LOW;
|
||||
}
|
||||
|
||||
attr_high = dwarf2_attr (die, DW_AT_high_pc, cu);
|
||||
if (attr_high)
|
||||
{
|
||||
@@ -15632,6 +15711,7 @@ load_partial_dies (const struct die_reader_specs *reader,
|
||||
&& abbrev->tag != DW_TAG_constant
|
||||
&& abbrev->tag != DW_TAG_enumerator
|
||||
&& abbrev->tag != DW_TAG_subprogram
|
||||
&& abbrev->tag != DW_TAG_entry_point
|
||||
&& abbrev->tag != DW_TAG_lexical_block
|
||||
&& abbrev->tag != DW_TAG_variable
|
||||
&& abbrev->tag != DW_TAG_namespace
|
||||
@@ -15758,6 +15838,7 @@ load_partial_dies (const struct die_reader_specs *reader,
|
||||
if (load_all
|
||||
|| abbrev->tag == DW_TAG_constant
|
||||
|| abbrev->tag == DW_TAG_subprogram
|
||||
|| abbrev->tag == DW_TAG_entry_point
|
||||
|| abbrev->tag == DW_TAG_variable
|
||||
|| abbrev->tag == DW_TAG_namespace
|
||||
|| part_die->is_declaration)
|
||||
@@ -15799,7 +15880,9 @@ load_partial_dies (const struct die_reader_specs *reader,
|
||||
|| last_die->tag == DW_TAG_union_type))
|
||||
|| (cu->language == language_ada
|
||||
&& (last_die->tag == DW_TAG_subprogram
|
||||
|| last_die->tag == DW_TAG_lexical_block))))
|
||||
|| last_die->tag == DW_TAG_lexical_block))
|
||||
|| (cu->language == language_fortran
|
||||
&& last_die->tag == DW_TAG_subprogram)))
|
||||
{
|
||||
nesting_level++;
|
||||
parent_die = last_die;
|
||||
@@ -18440,13 +18523,28 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
|
||||
SYMBOL_ACLASS_INDEX (sym) = LOC_LABEL;
|
||||
add_symbol_to_list (sym, cu->list_in_scope);
|
||||
break;
|
||||
case DW_TAG_entry_point:
|
||||
/* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
|
||||
finish_block. */
|
||||
SYMBOL_ACLASS_INDEX (sym) = LOC_BLOCK;
|
||||
/* DW_TAG_entry_point provides an additional entry_point to an
|
||||
existing sub_program. Therefore, we inherit the "external"
|
||||
attribute from the sub_program to which the entry_point
|
||||
belongs to. */
|
||||
attr2 = dwarf2_attr (die->parent, DW_AT_external, cu);
|
||||
if (attr2 && (DW_UNSND (attr2) != 0))
|
||||
list_to_add = &global_symbols;
|
||||
else
|
||||
list_to_add = cu->list_in_scope;
|
||||
break;
|
||||
case DW_TAG_subprogram:
|
||||
/* SYMBOL_BLOCK_VALUE (sym) will be filled in later by
|
||||
finish_block. */
|
||||
SYMBOL_ACLASS_INDEX (sym) = LOC_BLOCK;
|
||||
attr2 = dwarf2_attr (die, DW_AT_external, cu);
|
||||
if ((attr2 && (DW_UNSND (attr2) != 0))
|
||||
|| cu->language == language_ada)
|
||||
|| cu->language == language_ada
|
||||
|| cu->language == language_fortran)
|
||||
{
|
||||
/* Subprograms marked external are stored as a global symbol.
|
||||
Ada subprograms, whether marked external or not, are always
|
||||
@@ -19124,6 +19222,7 @@ read_type_die_1 (struct die_info *die, struct dwarf2_cu *cu)
|
||||
case DW_TAG_enumeration_type:
|
||||
this_type = read_enumeration_type (die, cu);
|
||||
break;
|
||||
case DW_TAG_entry_point:
|
||||
case DW_TAG_subprogram:
|
||||
case DW_TAG_subroutine_type:
|
||||
case DW_TAG_inlined_subroutine:
|
||||
@@ -19450,6 +19549,19 @@ determine_prefix (struct die_info *die, struct dwarf2_cu *cu)
|
||||
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);
|
||||
|
||||
70
gdb/testsuite/gdb.fortran/entry_point.exp
Executable file
70
gdb/testsuite/gdb.fortran/entry_point.exp
Executable file
@@ -0,0 +1,70 @@
|
||||
# Copyright 2016 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/>.
|
||||
|
||||
if { [skip_fortran_tests] } { return -1 }
|
||||
|
||||
standard_testfile .f90
|
||||
load_lib "fortran.exp"
|
||||
|
||||
if {[prepare_for_testing $testfile.exp $testfile $srcfile {debug f90}]} {
|
||||
return -1
|
||||
}
|
||||
|
||||
if ![runto MAIN__] then {
|
||||
perror "couldn't run to breakpoint MAIN__"
|
||||
continue
|
||||
}
|
||||
|
||||
# Test if we can set a breakpoint via entry-point name
|
||||
set ept_name "foo"
|
||||
gdb_breakpoint $ept_name
|
||||
gdb_test "continue" \
|
||||
[multi_line "Breakpoint $decimal, $ept_name \\(j=1, k=2, l=3, i1=4\\) at .*" \
|
||||
".*"] \
|
||||
"continue to breakpoint: $ept_name"
|
||||
|
||||
gdb_test "print j" "= 1" "print j, entered via $ept_name"
|
||||
gdb_test "print k" "= 2" "print k, entered via $ept_name"
|
||||
gdb_test "print l" "= 3" "print l, entered via $ept_name"
|
||||
gdb_test "print i1" "= 4" "print i1, entered via $ept_name"
|
||||
gdb_test "info args" \
|
||||
[multi_line "j = 1" \
|
||||
"k = 2" \
|
||||
"l = 3" \
|
||||
"i1 = 4"] \
|
||||
"info args, entered via $ept_name"
|
||||
|
||||
# Test if we can set a breakpoint via function name
|
||||
set ept_name "bar"
|
||||
gdb_breakpoint $ept_name
|
||||
gdb_test "continue" \
|
||||
[multi_line "Breakpoint $decimal, $ept_name \\(i=4, j=5, k=6, i1=7\\) at .*" \
|
||||
".*"] \
|
||||
"continue to breakpoint: $ept_name"
|
||||
|
||||
gdb_test "print i" "= 4" "print i, entered via $ept_name"
|
||||
gdb_test "print j" "= 5" "print j, entered via $ept_name"
|
||||
gdb_test "print k" "= 6" "print k, entered via $ept_name"
|
||||
gdb_test "print i1" "= 7" "print i1, entered via $ept_name"
|
||||
|
||||
set ept_name "tim"
|
||||
gdb_breakpoint $ept_name
|
||||
gdb_test "continue" \
|
||||
[multi_line "Breakpoint $decimal, $ept_name \\(j=1\\) at .*" \
|
||||
".*"] \
|
||||
"continue to breakpoint: $ept_name"
|
||||
|
||||
gdb_test "print j" "= 1" "print j, entered via $ept_name"
|
||||
gdb_test "info args" "j = 1" "info args, entered via $ept_name"
|
||||
48
gdb/testsuite/gdb.fortran/entry_point.f90
Executable file
48
gdb/testsuite/gdb.fortran/entry_point.f90
Executable file
@@ -0,0 +1,48 @@
|
||||
! Copyright 2016 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/>.
|
||||
|
||||
program TestEntryPoint
|
||||
|
||||
call foo(1,2,3,4)
|
||||
call bar(4,5,6,7)
|
||||
call tim(1)
|
||||
|
||||
end program TestEntryPoint
|
||||
|
||||
subroutine bar(I,J,K,I1)
|
||||
INTEGER I,J,K,L,I1
|
||||
INTEGER A
|
||||
REAL C
|
||||
|
||||
A = 0
|
||||
C = 0.0
|
||||
|
||||
A = I + K + I1
|
||||
goto 1000
|
||||
|
||||
entry foo(J,K,L,I1)
|
||||
A = J + K + L + I1
|
||||
|
||||
200 C = J
|
||||
goto 1000
|
||||
|
||||
entry tim(J)
|
||||
goto 200
|
||||
|
||||
1000 A = C + 1
|
||||
C = J * 1.5
|
||||
|
||||
return
|
||||
end subroutine
|
||||
@@ -30,6 +30,10 @@ if ![runto MAIN__] then {
|
||||
continue
|
||||
}
|
||||
|
||||
# Test if we can set a breakpoint in a nested function
|
||||
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.
|
||||
gdb_breakpoint [gdb_get_line_number "! BP_outer"]
|
||||
@@ -39,10 +43,17 @@ gdb_test "set index = 42"
|
||||
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 "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.
|
||||
gdb_breakpoint [gdb_get_line_number "! BP_inner"]
|
||||
@@ -51,12 +62,29 @@ gdb_test "print index" "= 42" "print index at BP_inner"
|
||||
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"
|
||||
|
||||
@@ -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 @@ program TestNestedFuncs
|
||||
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user