While testing mixed-lang-stack I realized that valgrind actually
complained about a double free in the test.
All done
==2503051==
==2503051== HEAP SUMMARY:
==2503051== in use at exit: 0 bytes in 0 blocks
==2503051== total heap usage: 26 allocs, 27 frees, 87,343 bytes allocated
==2503051==
==2503051== All heap blocks were freed -- no leaks are possible
==2503051==
==2503051== For lists of detected and suppressed errors, rerun with: -s
==2503051== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Reason for this is that in mixed-lang-stack.cpp in mixed_func_1f an
object "derived_type obj" goes on the stack which is then passed-by-value
(so copied) to mixed_func_1g. The default copy-ctor will be called but,
since derived_type contains a heap allocated string and the copy
constructor is not implemented it will only be able to shallow copy the
object. Right after each of the functions the object gets freed - on the
other hand the d'tor of derived_type actually is implemented and calls
free on the heap allocated string which leads to a double free. Instead
of obeying the rule of 3/5 I just got rid of all that since it does not
serve the test. The string is now just a const char* = ".." object
member.
For ifort, ifx, and flang the tests "complete modm" and "complete
modmany" fail. This is because all three emit additional completion
suggestions. These additional suggestions have their origin in symbols
emitted by the compilers which can also be completed from the respective
incomplete word (modm or modmany). For this specific example gfortran
does not emit any additional symbols.
For example, in this test the linkage name for var_a in ifx is
"modmany_mp_var_a_" while gfortran uses "__modmany_MOD_var_a" instead.
Since modmany_mp_var_a can be completed from modm and also modmany they
will get displayed, while gfortran's symbol starts with "__" and thus will
be ignored (it cannot be a completion of a word starting with "m").
Similar things happen in flang and ifort. Some example output is shown
below:
FLANG
(gdb) complete p modm
p modmany
p modmany::var_a
p modmany::var_b
p modmany::var_c
p modmany::var_i
p modmany_
IFX/IFORT
(gdb) complete p modm
p modmany
p modmany._
p modmany::var_a
p modmany::var_b
p modmany::var_c
p modmany::var_i
p modmany_mp_var_a_
p modmany_mp_var_b_
p modmany_mp_var_c_
p modmany_mp_var_i_
GFORTRAN
(gdb) complete p modm
p modmany
p modmany::var_a
p modmany::var_b
p modmany::var_c
p modmany::var_i
I want to emphasize: for Fortran (and also C/C++) the complete command
does not actually check whether its suggestions make sense - all it does
is look for any symbol (in the minimal symbols, partial symbols etc.)
that a given substring can be completed to (meaning that the given substring
is the beginning of the symbol). One can easily produce a similar
output for the gfortran compiled executable. For this look at the
slightly modified "complete p mod" in gfortran:
(gdb) complete p mod
p mod1
p mod1::var_const
...
p mod_1.c
p modcounter
p mode_t
p modf
...
p modify_ldt
p modmany
p modmany::var_a
p modmany::var_b
p modmany::var_c
p modmany::var_i
p module
p module.f90
p module_entry
p moduse
p moduse::var_x
p moduse::var_y
Many of the displayed symbols do not actually work with print:
(gdb) p mode_t
Attempt to use a type name as an expression
(gdb) p mod_1.c
No symbol "mod_1" in current context.
(gdb)
I think that in the given test the output for gfortran only looks nice
"by chance" rather than is actually expected. Expected is any output
that also contains the completions
p modmany
p modmany::var_a
p modmany::var_b
p modmany::var_c
p modmany::var_i
while anythings else can be displayed as well (depending on the
compiler and its emitted symbols).
This, I'd consider all three outputs as valid and expected - one is just
somewhat lucky that gfortran does not produce any additional symbols that
got matched.
The given patch improves test performance for all three compilers
by allowing additional suggested completions inbetween and after
the two given blocks in the test. I did not allow additional print
within the modmany_list block since the output is ordered alphabetically
and there should normally not appear any additional symbols there.
For flang/ifx/ifort I each see 2 failures less (which are exactly the two
complete tests).
As a side note and since I mentioned C++ in the beginning: I also tried
the gdb.cp/completion.exp. The output seems a bit more reasonable,
mainly since C++ actually has a demangler in place and linkage symbols
do not appear in the output of complete. Still, with a poor enough
to-be-completed string one can easily produce similar results:
(gdb) complete p t
...
p typeinfo name for void
p typeinfo name for void const*
p typeinfo name for void*
p typeinfo name for wchar_t
p typeinfo name for wchar_t const*
p typeinfo name for wchar_t*
p t *** List may be truncated, max-completions reached. ***
(gdb) p typeinfo name for void*
No symbol "typeinfo" in current context.
(gdb) complete p B
p BACK_SLASH
p BUF_FIRST
p BUF_LAST
...
p Base
p Base::Base()
p Base::get_foo()
p bad_key_err
p buf
p buffer
p buffer_size
p buflen
p bufsize
p build_charclass.isra
(gdb) p bad_key_err
No symbol "bad_key_err" in current context.
(compiled with gcc/g++ and breaking at main).
This patch is only about making the referenced test more 'fair' for the
other compilers. Generally, I find the behavior of complete a bit
confusing and maybe one wants to change this at some point but this
would be a bigger task.
This info-types.exp test case had a few issues that this patch fixes.
First, the emitted symbol character(kind=1)/character*1 (different
compilers use different naming converntions here) which is checkedin the
test is not actually expected given the test program. There is no
variable of that type in the test. Still, gfortran emits it for every
Fortran program there is. The reason is the way gfortran handles Fortran's
named main program. It generates a wrapper around the Fortran program
that is quite similar to a C main function. This C-like wrapper has
argc and argv arguments for command line argument passing and the argv
pointer type has a base type character(kind=1) DIE emitted at CU scope.
Given the program
program prog
end program prog
the degbug info gfortran emits looks somewhat like
<0><c>: Abbrev Number: 3 (DW_TAG_compile_unit)
...
<1><2f>: Abbrev Number: 4 (DW_TAG_subprogram)
<30> DW_AT_external : 1
<30> DW_AT_name : (indirect string, ...): main
...
<2><51>: Abbrev Number: 1 (DW_TAG_formal_parameter)
<52> DW_AT_name : (indirect string, ...): argc
...
<2><5d>: Abbrev Number: 1 (DW_TAG_formal_parameter)
<5e> DW_AT_name : (indirect string, ...): argv
...
<62> DW_AT_type : <0x77>
...
<2><6a>: Abbrev Number: 0
...
<1><77>: Abbrev Number: 6 (DW_TAG_pointer_type)
<78> DW_AT_byte_size : 8
<79> DW_AT_type : <0x7d>
<1><7d>: Abbrev Number: 2 (DW_TAG_base_type)
<7e> DW_AT_byte_size : 1
<7f> DW_AT_encoding : 8 (unsigned char)
<80> DW_AT_name : (indirect string, ...): character(kind=1)
<1><84>: Abbrev Number: 7 (DW_TAG_subprogram)
<85> DW_AT_name : (indirect string, ...): prog
...
Ifx and flang do not emit any debug info for a wrapper main method so
the type is missing here. There was the possibility of actually adding
a character*1 type variable to the Fortran executable, but both, ifx and
gfortran chose to emit this variable's type as a DW_TAG_string_type of
length one (instead of a character(kind=1), or whatever the respective
compiler naming convention is). While string types are printed as
character*LENGHT in the fortran language part (e.g. when issuing a
'ptype') they do not generate any symbols inside GDB. In read.c it says
/* These dies have a type, but processing them does not create
a symbol or recurse to process the children. Therefore we can
read them on-demand through read_type_die. */
So they did not add any output to 'info types'. Only flang did emit a
character type here.
As adding a type would have a) not solved the problem for ifx and would
have b) somehow hidden the curious behavior of gfortran, instead, the
check for this character type was chagened to optional with the
check_optional_entry to allow for the symbols's absence and to allow
flang and ifx to pass this test as well.
Second, the line checked for s1 was hardcoded as 37 in the test. Given
that the type is actually defined on line 41 (which is what is emitted by
ifx) it even seems wrong. The line check for s1 was changed to actually
check for 41 and a gfortran bug has been filed here
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105454
The test is now marked as xfail for gfortran.
Third, the whole test of checking for the 'Type s1' in info types seemed
questionable. The type s1 is declared iside the scope of the Fortran
program info_types_test. Its DIE however is emitted as a child of the
whole compilation unit making it visible outside of the program's scope.
The 'info types' command checks for types stored in the GLOBAL_BLOCK,
or STATIC_BLOCKm wgucm according to block.h
The GLOBAL_BLOCK contains all the symbols defined in this compilation
whose scope is the entire program linked together.
The STATIC_BLOCK contains all the symbols whose scope is the
entire compilation excluding other separate compilations.
so for gfortran, the type shows up in the output of 'info types'. For
flang and ifx on the other hand this is not the case. The two compilers
emit the type (correctly) as a child of the Fortran program, thus not
adding it to either, the GLOBAL_BLOCK nor the LOCAL_BLOCK. A bug has
been opened for the gfortran scoping issue:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105454
While the most correct change might have been removing the check for s1,
the change made here was to only check for this type in case of gfortran
being used as the compiler, as this check also covers the declaration
line issue mentioned above. A comment was added to maybe remove this
check once the scoping issue is resolved (and it starts to fail with
newer gfortran versions). The one used to test these changes was 13.0.
The test was earlier not using the compiler dependent type print system
in fortran.exp. I changed this. It should generally improve the test
performance for different compilers. For ifx and gfortran I do not see
any failures.
Currenlty, ifx/ifort cannot compile the given executable as it is not
valid Fortran. It is missing the external keyword on the
no_arg_subroutine. Gfortran compiles the example but this is actually
a bug and there is an open gcc ticket for this here:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=50377
Adding the keyword does not change the gfortran compiling of the example.
It will, however, prevent a future fail once 50377 has been addressed.
The test specifically tests for the Fortran CHARACTER(KIND=4) which is
not available in ifx/ifort.
Since the other characters are also printed elsewhere, we disable this
test for the unsupported compilers.
This commit adds a separate Fortran compiler identification mechanism to
the testsuite, similar to the existing one for C/C++. Before this
change, the options and version for the Fortran compiler specified when
running the testsuite with F90_FOR_TARGET set, was detected via its
respective C compiler. So running the testsuite as
make check TEST=gdb.fortran/*.exp CC_FOR_TARGET=gcc F90_FOR_TARGET=ifx
or even
make check TEST=gdb.fortran/*.exp F90_FOR_TARGET=ifx
would use the gcc compiler inside the procedures get_compiler_info and
test_compiler_info to identify compiler flags and the compiler version.
This could sometimes lead to unpredictable outputs. It also limited
testsuite execution to combinations where C and Fortran compiler would
come from the same family of compiers (gcc/gfortran, icc/ifort, icx/ifx,
clang/flang ..). This commit enables GDB to detect C and Fortran
compilers independently of each other.
As most/nearly all Fortran compilers have a mechanism for preprocessing
files in a C like fashion we added the exact same meachnism that already
existed for C/CXX. We let GDB preprocess a file with the compilers
Fortran preprocessor and evaluate the preprocessor defined macros in that
file.
This enables GDB to properly run heterogeneous combinations of C and
Fortran compilers such as
CC_FOR_TARGET='gcc' and F90_FOR_TARGET='ifort'
or enables one to run the testsuite without specifying a C compiler as in
make check TESTS=gdb.fortran/*.exp F90_FOR_TARGET='ifx'
make check TESTS=gdb.fortran/*.exp F90_FOR_TARGET='flang'
On the other hand this also requires one to always specify a
identification mechanism for Fortran compilers in the compiler.F90 file.
We added identification for GFORTRAN, FLANG (CLASSIC and LLVM) IFX,
IFORT, and ARMFLANG for now.
Classic and LLVM flang were each tested with their latest releases on
their respective release pages. Both get recognized by the new compiler
identification and we introduced the two names flang-classic and
flang-llvm to distinguish the two. While LLVM flang is not quite mature
enough yet for running the testsuite we still thought it would be a good
idea to include it already. For this we added a case for the fortran_main
procedure. LLVM flang uses 'MAIN__' as opposed to classic flang which
uses 'MAIN_' here.
We did not have the possibility to test ARMFLANG - the versioning scheme
here was extracted from its latest online documentation.
We changed the test_compiler_info procedure to take another optional
argument, the language string, which will be passed though to the
get_compiler_info procedure. Passing 'f90' or 'c++' here will then
trigger the C++/Fortran compiler identification within
get_compiler_info. The latter procedure was extended to also handle
the 'f90' argument (similarly to the already existing 'c++' one).
Co-authored-by: Nils-Christian Kempke <nils-christian.kempke@intel.com>
Many test cases had a few lines in the beginning that look like:
if { condition } {
continue
}
Where conditions varied, but were mostly in the form of ![runto_main] or
[skip_*_tests], making it quite clear that this code block was supposed
to finish the test if it entered the code block. This generates TCL
errors, as most of these tests are not inside loops. All cases on which
this was an obvious mistake are changed in this patch.
This commit fixes two regressions introduced by
891e4190ba.
Reason for the failures was, that on a 32 bit machine the maximum
array length as well as the maximum allocatable memory for arrays
(in bytes) both seem to be limited by the maximum value of a 4
byte (signed) Fortran integer. This lead to compiler errors/unexpected
behavior when compiling/running the test with the -m32 board. This
behavior is compiler dependent and can differ for different compiler
implementations, but generally, it seemed like a good idea to simply
avoid such situations.
The affected tests check for GDB's overflow behavior when using KIND
parameters with GDB implemented Fortran intrinsic functions. If these
KIND parameters are too small to fit the actual intrinsic function's
result, an overflow is expected. This was done for 1, 2, and 4
byte overflows. The last one caused problems, as it tried to allocate
arrays of length/byte-size bigger than the 4 byte signed integers which
would then be used with the LBOUND/UBOUND/SIZE intrinsics.
The tests were adapted to only execute the 4 byte overflow tests when
running on targets with 64 bit. For this, the compiled tests evaluate the
byte size of a C_NULL_PTR via C_SIZEOF, both defined in the ISO_C_BINDING
module. The ISO_C_BINDING constant C_NULL_PTR is a Fortran 2003, the
C_SIZEOF a Fortran 2008 extension. Both have been implemented in their
respective compilers for while (e.g. C_SIZEOF is available since
gfortran 4.6). If this byte size evaluates to less than 8 we skip the
4 byte overflow tests in the compiled tests of size.f90 and
lbound-ubound.f90. Similarly, in the lbound-ubound.exp testsfile we skip
the 4 byte overflow tests if the procedure is_64_target evaluates to false.
In size.f90, additionally, the to-be-allocated amount of bytes did not
fit into 4 byte signed integers for some of the arrays, as it was
approximately 4 times the maximum size of a 4 byte signed integer. We
adapted the dimensions of the arrays in question as the meaningfulness
of the test does not suffer from this.
With this patch both test run fine with the unix/-m32 board and
gcc/gfortran (9.4) as well as the standard board file.
We also thought about completely removing the affected test from the
testsuite. We decided against this as the 32 bit identification comes
with Fortran 2008 and removing tests would have decreased coverage.
A last change that happened with this patch was due to gfortran's and
ifx's type resolution when assigning big constants to Fortran Integer*8
variables. Before the above changes this happened in a parameter
statement. Here, both compilers happily accepted a line like
integer*8, parameter :: var = 2147483647 + 5.
After this change the assignment is not done as a parameter
anymore, as this triggered compile time overflow errors. Instead,
the assignment is done dynamically, depending on the kind of machine one
is on. Sadly, just changing this line to
integer*8 :: var
var = 2147483647 + 5
does not work with ifx (or flang for that matter, they behave similarly
here). It will create an integer overflow in the addition as ifx deduces
the type the additon is done in as Integer*4. So var will actually
contain the value -2147483644 after this. The lines
integer*8 :: var
var = 2147483652
on the other hand fail to compile with gfortran (9.4.0) as the compiler
identifies an Integer overflow here. Finally, to make this work with
all three compilers an additional parameter has been introduced
integer*8, parameter :: helper = 2147483647
integer*8 :: var
var = helper + 5.
This works on all 3 compilers as expected.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29053
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=29054
If a variable is passed to function in FORTRAN as an argument the
variable is treated as an array with rank zero. GDB currently does
not support the case for assumed rank 0. This patch provides support
for assumed rank 0 and updates the testcase as well.
Without patch:
Breakpoint 1, arank::sub1 (a=<error reading variable:
failed to resolve dynamic array rank>) at assumedrank.f90:11
11 PRINT *, RANK(a)
(gdb) p a
failed to resolve dynamic array rank
(gdb) p rank(a)
failed to resolve dynamic array rank
With patch:
Breakpoint 1, arank::sub1 (a=0) at assumedrank.f90:11
11 PRINT *, RANK(a)
(gdb) p a
$1 = 0
(gdb) p rank(a)
$2 = 0
The operators FLOOR, CEILING, CMPLX, LBOUND, UBOUND, and SIZE accept
(some only with Fortran 2003) the optional parameter KIND. This
parameter determines the kind of the associated return value. So far,
implementation of this kind parameter has been missing in GDB.
Additionally, the one argument overload for the CMPLX intrinsic function
was not yet available.
This patch adds overloads for all above mentioned functions to the
Fortran intrinsics handling in GDB.
It re-writes the intrinsic function handling section to use the helper
methods wrap_unop_intrinsic/wrap_binop_intrinsic/wrap_triop_intrinsic.
These methods define the action taken when a Fortran intrinsic function
is called with a certain amount of arguments (1/2/3). The helper methods
fortran_wrap2_kind and fortran_wrap3_kind have been added as equivalents
to the existing wrap and wrap2 methods.
After adding more overloads to the intrinsics handling, some of the
operation names were no longer accurate. E.g. UNOP_FORTRAN_CEILING
has been renamed to FORTRAN_CEILING as it is no longer a purely unary
intrinsic function. This patch also introduces intrinsic functions with
one, two, or three arguments to the Fortran parser and the
UNOP_OR_BINOP_OR_TERNOP_INTRINSIC token has been added.
Currently, when asking GDB to print the type of a Fortran default type
such as INTEGER or REAL, GDB will return the default name of that type,
e.g. "integer"/"real":
(gdb) ptype integer
type = integer
(gdb) ptype real
type = real
For LOGICAL and COMPLEX it would return the actual underlying types
(gdb) ptype logical
type = logical*4
(gdb) ptype complex
type = complex*4
Similarly, GDB would print the default integer type for the underlying
default type:
(gdb) ptype integer*4
type = integer
(gdb) ptype real*4
type = real
(gdb) ptype logical
type = logical*4
(gdb) ptype complex*4
type = complex*4
This is inconsistent and a bit confusing. Both options somehow indicate
what the internal underlying type for the default type is - but I think
the logical/complex version is a bit clearer.
Consider again:
(gdb) ptype integer
type = integer
This indicates to a user that the type of "integer" is Fortran's default
integer type. Without examining "ptype integer*4" I would expect, that
any variable declared integer in the actual code would also fit into a
GDB integer. But, since we cannot adapt out internal types to the
compiler flags used at compile time of a debugged binary, this might be
wrong. Consider debugging Fortran code compiled with GNU and e.g. the
"-fdefault-integer-8" flag. In this case the gfortran default integer
would be integer*8 while GDB internally still would use a builtin_integer,
so an integer of the size of an integer*4 type. On the other hand having
GDB print
(gdb) ptype integer
type = integer*4
makes this clearer. I would still be tempted to fit a variable declared
integer in the code into a GDB integer - but at least ptype would
directly tell me what is going on. Note, that when debugging a binary
compiled with "-fdefault-integer-8" a user will always see the actual
underlying type of any variable declared "integer" in the Fortran code.
So having the code
program test
integer :: a = 5
print *, a ! breakpt
end program test
will, when breaking at breakpt print
(gdb) ptype var
type = integer(kind=4)
or
(gdb) ptype var
type = integer(kind=8)
depending on the compiler flag.
This patch changes the outputs for the REAL and INTEGER default types to
actually print the internally used type over the default type name.
The new behavior for the above examples is:
(gdb) ptype integer
type = integer*4
(gdb) ptype integer*4
type = integer*4
Existing testcases have been adapted to reflect the new behavior.
The currently implemented intrinsic type handling for Fortran missed some
tokens and their parsing. While still not all Fortran type kinds are
implemented this patch at least makes the currently handled types
consistent. As an example for what this patch does, consider the
intrinsic type INTEGER. GDB implemented the handling of the
keywords "integer" and "integer_2" but missed "integer_4" and "integer_8"
even though their corresponding internal types were already available as
the Fortran builtin types builtin_integer and builtin_integer_s8.
Similar problems applied to LOGICAL, REAL, and COMPLEX. This patch adds
all missing tokens and their parsing. Whenever a section containing the
type handling was touched, it also was reordered to be in a more easy to
grasp order. All INTEGER/REAL/LOGICAL/COMPLEX types were grouped
together and ordered ascending in their size making a missing one more
easy to spot.
Before this change GDB would print the following when tyring to use the
INTEGER keywords:
(gdb) set language fortran
(gdb) ptype integer*1
unsupported kind 1 for type integer
(gdb) ptype integer_1
No symbol table is loaded. Use the "file" command.
(gdb) ptype integer*2
type = integer*2
(gdb) ptype integer_2
type = integer*2
(gdb) ptype integer*4
type = integer
(gdb) ptype integer_4
No symbol table is loaded. Use the "file" command.
(gdb) ptype integer*8
type = integer*8
(gdb) ptype integer_8
No symbol table is loaded. Use the "file" command.
(gdb) ptype integer
type = integer
With this patch all keywords are available and the GDB prints:
(gdb) set language fortran
(gdb) ptype integer*1
type = integer*1
(gdb) ptype integer_1
type = integer*1
(gdb) ptype integer*2
type = integer*2
(gdb) ptype integer_2
type = integer*2
(gdb) ptype integer*4
type = integer*4
(gdb) ptype integer_4
type = integer*4
(gdb) ptype integer*8
type = integer*8
(gdb) ptype integer_8
type = integer*8
(gdb) ptype integer
type = integer
The described changes have been applied to INTEGER, REAL, COMPLEX,
and LOGICAL. Existing testcases have been adapted to reflect the
new behavior. Tests for formerly missing types have been added.
According to the Fortran standard, logical is of the size of a
'single numeric storage unit' (just like real and integer). For
gfortran, flang and ifx/ifort this storage unit (or the default
logical type) is of size kind 4, actually occupying 4 bytes of
storage, and so the default type for logical expressions in
Fortran should probably also be Logical*4 and not Logical*2. I
adapted GDB's behavior to be in line with
gfortran/ifort/ifx/flang.
Before this patch things like
(gdb) ptype complex*8
complex*16
(gdb) ptype complex*4
complex*8
were possible in GDB, which seems confusing for a user. The reason
is a mixup in the implementation of the Fortran COMPLEX type. In
Fortran the "*X" after a type would normally (I don't think this
is language required) specify the type's size in memory. For the
COMPLEX type the kind parameters usually (at least for GNU, Intel, Flang)
specify not the size of the whole type but the size of the individual
two REALs used to form the COMPLEX. Thus, a COMPLEX*4 will usually
consist of two REAL*4s. Internally this type was represented by a
builtin_complex_s8 - but here I think the s8 actually meant the raw
size of the type. This is confusing and I renamed the types (e.g.
builting_complex_s8 became builtin_complex_s4 according to its most
common useage) and their printed names to their language equivalent.
Additionally, I added the default COMPLEX type "COMPLEX" being the same
as a COMPLEX*4 (as is normally the case) and removed the latter. I added
a few tests for this new behavior as well.
The new behavior is
(gdb) ptype complex*8
complex*8
(gdb) ptype complex*4
complex*4
Add the print of the base-class of an extended type to the output of
ptype. This requires the Fortran compiler to emit DW_AT_inheritance
for the extended type.
Co-authored-by: Nils-Christian Kempke <nils-christian.kempke@intel.com>
Fortran 2003 supports type extension. This patch allows access
to inherited members by using their fully qualified name as described
in the Fortran standard.
In doing so the patch also fixes a bug in GDB when trying to access the
members of a base class in a derived class via the derived class' base
class member.
This patch fixes PR22497 and PR26373 on GDB side.
Using the example Fortran program from PR22497
program mvce
implicit none
type :: my_type
integer :: my_int
end type my_type
type, extends(my_type) :: extended_type
end type extended_type
type(my_type) :: foo
type(extended_type) :: bar
foo%my_int = 0
bar%my_int = 1
print*, foo, bar
end program mvce
and running this with GDB and setting a BP at 17:
Before:
(gdb) p bar%my_type
A syntax error in expression, near `my_type'.
(gdb) p bar%my_int
There is no member named my_int.
(gdb) p bar%my_type%my_int
A syntax error in expression, near `my_type%my_int'.
(gdb) p bar
$1 = ( my_type = ( my_int = 1 ) )
After:
(gdb) p bar%my_type
$1 = ( my_int = 1 )
(gdb) p bar%my_int
$2 = 1 # this line requires DW_TAG_inheritance to work
(gdb) p bar%my_type%my_int
$3 = 1
(gdb) p bar
$4 = ( my_type = ( my_int = 1 ) )
In the above example "p bar%my_int" requires the compiler to emit
information about the inheritance relationship between extended_type
and my_type which gfortran and flang currently do not de. The
respective issue gcc/49475 has been put as kfail.
Co-authored-by: Nils-Christian Kempke <nils-christian.kempke@intel.com>
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=26373https://sourceware.org/bugzilla/show_bug.cgi?id=22497
Commit:
commit df7a7bdd97
Date: Thu Mar 17 18:56:23 2022 +0000
gdb: add support for Fortran's ASSUMED RANK arrays
Added support for Fortran assumed rank arrays. Unfortunately, this
commit contained a bug that means though GDB can correctly calculate
the rank of an assumed rank array, GDB can't fetch the contents of an
assumed rank array.
The history of this patch can be seen on the mailing list here:
https://sourceware.org/pipermail/gdb-patches/2022-January/185306.html
The patches that were finally committed can be found here:
https://sourceware.org/pipermail/gdb-patches/2022-March/186906.html
The original patches did support fetching the array contents, it was
only the later series that introduced the regression.
The problem is that when calculating the array rank the result is a
count of the number of ranks, i.e. this is a 1 based result, 1, 2, 3,
etc.
In contrast, when computing the details of any particular rank the
value passed to the DWARF expression evaluator should be a 0 based
rank offset, i.e. a 0 based number, 0, 1, 2, etc.
In the patches that were originally merged, this was not the case, and
we were passing the 1 based rank number to the expression evaluator,
e.g. passing 1 when we should pass 0, 2 when we should pass 1, etc.
As a result the DWARF expression evaluator was reading the
wrong (undefined) memory, and returning garbage results.
In this commit I have extended the test case to cover checking the
array contents, I've then ensured we make use of the correct rank
value, and extended some comments, and added or adjusted some asserts
as appropriate.
This patch adds a new dynamic property DYN_PROP_RANK, this property is
read from the DW_AT_rank attribute and stored within the type just
like other dynamic properties.
As arrays with dynamic ranks make use of a single
DW_TAG_generic_subrange to represent all ranks of the array, support
for this tag has been added to dwarf2/read.c.
The final piece of this puzzle is to add support in gdbtypes.c so that
we can resolve an array type with dynamic rank. To do this the
existing resolve_dynamic_array_or_string function is split into two,
there's a new resolve_dynamic_array_or_string_1 core that is
responsible for resolving each rank of the array, while the now outer
resolve_dynamic_array_or_string is responsible for figuring out the
array rank (which might require resolving a dynamic property) and then
calling the inner core.
The resolve_dynamic_range function now takes a rank, which is passed
on to the dwarf expression evaluator. This rank will only be used in
the case where the array itself has dynamic rank, but we now pass the
rank in all cases, this should be harmless if the rank is not needed.
The only small nit is that resolve_dynamic_type_internal actually
handles resolving dynamic ranges itself, which now obviously requires
us to pass a rank value. But what rank value to use? In the end I
just passed '1' through here as a sane default, my thinking is that if
we are in resolve_dynamic_type_internal to resolve a range, then the
range isn't part of an array with dynamic rank, and so the range
should actually be using the rank value at all.
An alternative approach would be to make the rank value a
gdb::optional, however, this ends up adding a bunch of complexity to
the code (e.g. having to conditionally build the array to pass to
dwarf2_evaluate_property, and handling the 'rank - 1' in
resolve_dynamic_array_or_string_1) so I haven't done that, but could,
if people think that would be a better approach.
Finally, support for assumed rank arrays was only fixed very recently
in gcc, so you'll need the latest gcc in order to run the tests for
this.
Here's an example test program:
PROGRAM arank
REAL :: a1(10)
CALL sub1(a1)
CONTAINS
SUBROUTINE sub1(a)
REAL :: a(..)
PRINT *, RANK(a)
END SUBROUTINE sub1
END PROGRAM arank
Compiler Version:
gcc (GCC) 12.0.0 20211122 (experimental)
Compilation command:
gfortran assumedrank.f90 -gdwarf-5 -o assumedrank
Without Patch:
gdb -q assumedrank
Reading symbols from assumedrank...
(gdb) break sub1
Breakpoint 1 at 0x4006ff: file assumedrank.f90, line 10.
(gdb) run
Starting program: /home/rupesh/STAGING-BUILD-2787/bin/assumedrank
Breakpoint 1, arank::sub1 (a=<unknown type in /home/rupesh/STAGING-BUILD-2787
/bin/assumedrank, CU 0x0, DIE 0xd5>) at assumedrank.f90:10
10 PRINT *, RANK(a)
(gdb) print RANK(a)
'a' has unknown type; cast it to its declared type
With patch:
gdb -q assumedrank
Reading symbols from assumedrank...
(gdb) break sub1
Breakpoint 1 at 0x4006ff: file assumedrank.f90, line 10.
(gdb) run
Starting program: /home/rupesh/STAGING-BUILD-2787/bin/assumedrank
Breakpoint 1, arank::sub1 (a=...) at assumedrank.f90:10
10 PRINT *, RANK(a)
(gdb) print RANK(a)
$1 = 1
(gdb) ptype a
type = real(kind=4) (10)
(gdb)
Co-Authored-By: Andrew Burgess <aburgess@redhat.com>
gdb.fortran/array-slices.exp and gdb.fortran/lbound-ubound.exp were
recently disabled unless testing with the native target, because they
rely on inferior I/O. However, when testing against gdbserver using
the native-gdbserver/native-extended-gdbserver boards, we do have
access to inferior I/O.
The right way to check whether the board can do I/O, is via checking
the gdb,noinferiorio board variable. Switch to using that.
And then, tweak the testcases to expect output to appear in
inferior_spawn_id, instead of gdb_spawn_id. When testing against the
native target, inferior_spawn_id is the same as gdb_spawn_id. When
testing against gdbserver, it maps to gdbserver_spawn_id.
This exposed a buglet in gdb.fortran/array-slices.f90's show_1d
subroutine -- it was missing printing newline at the end of the
"Expected GDB Output" text, leading to a test timeout. All other
subroutines end with advance=yes, except this one. Fix it by using
advance=yes here too.
Change-Id: I4640729f334431cfc24b0917e7d3977b677c6ca5
When running the gdb.fortran tests array-slices.exp and lbound-ubound.exp,
the test suite throws several ERRORs on native-gdbserver/-m{32,64},
and native-extended-gdbsever/-m{32,64}:
[on native-extended-gdbserver/-m64]
Running /home/keiths/work/gdb/branches/testsuite-errors/linux/gdb/testsuite/../../../src/gdb/testsuite/gdb.fortran/array-slices.exp ...
ERROR: failed to extract expected results
ERROR: failed to extract expected results
Running /home/keiths/work/gdb/branches/testsuite-errors/linux/gdb/testsuite/../../../src/gdb/testsuite/gdb.fortran/lbound-ubound.exp ...
ERROR: failed to extract expected results for lbound
This occurs because the tests require inferior I/O which we do not have
access to while using these targets.
This patch skips these tests when running on non-native targets.
Gfortran supports namelists (a Fortran feature); it emits
DW_TAG_namelist and DW_TAG_namelist_item dies. But gdb does not
process these dies and does not support 'print' or 'ptype' commands on
namelist variables.
An attempt to print namelist variables results in gdb bailing out with
the error message as shown below.
(gdb) print nml
No symbol "nml" in current context.
This commit is to make the print and ptype commands work for namelist
variables and its items. Sample output of these commands is shared
below, with fixed gdb.
(gdb) ptype nml
type = Type nml
integer(kind=4) :: a
integer(kind=4) :: b
End Type nml
(gdb) print nml
$1 = ( a = 10, b = 20 )
Info symbol is expected to print the symbol table name of a symbol, since
symbol lookup happens via the minimal symbol table. This name
corresponds to the linkage name in the full symbol table.
For gfortran (and maybe others) these names currently have the form
XXXX.NUMBER where XXXX is the symbol name and NUMBER a compiler
generated appendix for mangling.
An example taken from the modified nested-funcs-2.exp would be
~~~~
$ objdump -t ./outputs/gdb.fortran/nested-funcs-2/nested-funcs-2 | grep \
increment
00000000000014ab l F .text 0000000000000095 increment.3883
000000000000141c l F .text 000000000000008f increment_program_global.3881
~~~~
This mangled name gets recognized by the Ada demangler/decoder and decoded as
Ada to XXXX (setting the symbol language to Ada). This leads to output
of XXXX over XXXX.NUMBER for info symbol on gfortran symbols.
For ifort and ifx the generated linkage names have the form
SCOPEA_SCOPEB_XXXX_ which are not recognized by the Ada decoder (or any
other demangler for that matter) and thus printed as is.
The respective objdump in the above case looks like
~~~~
$ objdump -t ./outputs/gdb.fortran/nested-funcs-2/nested-funcs-2 | grep \
increment
0000000000403a44 l F .text 0000000000000074 contains_keyword_IP_increment_
0000000000403ab8 l F .text 0000000000000070
contains_keyword_IP_increment_program_global_
~~~~
In the unmodified testcase this results in 'fails' when ran with the intel
compilers:
~~~~
>> make check RUNTESTFLAGS="gdb.fortran/nested-funcs-2.exp \
GDBFLAGS='$GDBFLAGS' CC_FOR_TARGET='icpc' F90_FOR_TARGET='ifort'"
...
=== gdb Summary ===
\# of expected passes 80
\# of unexpected failures 14
~~~~
Note that there is no Fortran mangling standard. We keep the gfortran
behavior as is and modify the test to reflect ifx and ifort mangled
names which fixes above fails.
Signed-off-by: Nils-Christian Kempke <nils-christian.kempke@intel.com>
Add `set print array-indexes' handling for Fortran arrays. Currently
the setting is ignored and indices are never shown.
Keep track of the most recent index handled so that any outstanding
repeated elements printed when the limit set by `set print elements' is
hit have the correct index shown.
Output now looks like:
(gdb) set print array-indexes on
(gdb) print array_1d
$1 = ((-2) = 1, (-1) = 1, (0) = 1, (1) = 1, (2) = 1)
(gdb) set print repeats 4
(gdb) set print elements 12
(gdb) print array_2d
$2 = ((-2) = ((-2) = 2, <repeats 5 times>) (-1) = ((-2) = 2, <repeats 5 times>) (0) = ((-2) = 2, (-1) = 2, ...) ...)
(gdb)
for a 5-element vector and a 5 by 5 array filled with the value of 2.
Implement `set print repeats' handling for Fortran arrays. Currently
the setting is ignored and always treated as if no limit was set.
Unlike the generic array walker implemented decades ago the Fortran one
is a proper C++ class. Rather than trying to mimic the old walker then,
which turned out a bit of a challenge where interacting with the `set
print elements' setting, write it entirely from scratch, by adding an
extra specialization handler method for processing dimensions other than
the innermost one and letting the specialization class call the `walk_1'
method from the handler as it sees fit. This way repeats can be tracked
and the next inner dimension recursed into as a need arises only, or
unconditionally in the base class.
Keep track of the dimension number being handled in the class rather as
a parameter to the walker so that it does not have to be passed across
by the specialization class.
Use per-dimension element count tracking, needed to terminate processing
early when the limit set by `set print elements' is hit. This requires
extra care too where the limit triggers exactly where another element
that is a subarray begins. In that case rather than recursing we need
to terminate processing or lone `(...)' would be printed. Additionally
if the skipped element is the last one in the current dimension we need
to print `...' by hand, because `continue_walking' won't print it at the
upper level, because it can see the last element has already been taken
care of.
Preserve the existing semantics of `set print elements' where the total
count of the elements handled is matched against the trigger level which
is unlike with the C/C++ array printer where the per-dimension element
count is used instead.
Output now looks like:
(gdb) set print repeats 4
(gdb) print array_2d
$1 = ((2, <repeats 5 times>) <repeats 5 times>)
(gdb) set print elements 12
(gdb) print array_2d
$2 = ((2, <repeats 5 times>) (2, <repeats 5 times>) (2, 2, ...) ...)
(gdb)
for a 5 by 5 array filled with the value of 2.
Amend existing test cases accordingly that rely on the current incorrect
behavior and explicitly request that there be no limit for printing
repeated elements there.
Add suitable test cases as well covering sliced arrays in particular.
Co-Authored-By: Andrew Burgess <andrew.burgess@embecosm.com>
This commit brings all the changes made by running gdb/copyright.py
as per GDB's Start of New Year Procedure.
For the avoidance of doubt, all changes in this commits were
performed by the script.
When printing a variable x in a subroutine foo:
...
subroutine foo (x)
integer(4) :: x (*)
x(3) = 1
end subroutine foo
...
where x is an array with unknown bounds, we get:
...
$ gdb -q -batch outputs/gdb.fortran/array-no-bounds/array-no-bounds \
-ex "break foo" \
-ex run \
-ex "print x"
Breakpoint 1 at 0x4005cf: file array-no-bounds.f90, line 18.
Breakpoint 1, foo (x=...) at array-no-bounds.f90:18
18 x(3) = 1
$1 = <error reading variable>
...
Improve the error message by printing the details of the error, such that we
have instead:
...
$1 = <error reading variable: failed to get range bounds>
...
This is a change in gdb/valprint.c, and grepping through the sources reveals
that this is a common pattern.
Tested on x86_64-linux.
When running test-case gdb.fortran/call-no-debug.exp with target board
native-gdbserver, I run into:
...
(gdb) PASS: gdb.fortran/call-no-debug.exp: print string_func_ (&'abcdefg', 3)
call (integer) string_func_ (&'abcdefg', 3)^M
$2 = 0^M
(gdb) FAIL: gdb.fortran/call-no-debug.exp: call (integer) string_func_ (&'abcdefg', 3)
...
The problem is that gdb_test is used to match inferior output.
Fix this by using gdb_test_stdio.
Tested on x86_64-linux.
When running test-case gdb.mi/mi-var-child-f.exp on openSUSE Tumbleweed
(with glibc 2.34) I run into:
...
(gdb) ^M
PASS: gdb.mi/mi-var-child-f.exp: mi runto prog_array
Expecting: ^(-var-create array \* array[^M
]+)?(\^done,name="array",numchild="[0-9]+",value=".*",type=.*,has_more="0"[^M
]+[(]gdb[)] ^M
[ ]*)
-var-create array * array^M
&"Attempt to use a type name as an expression.\n"^M
^error,msg="-var-create: unable to create variable object"^M
(gdb) ^M
FAIL: gdb.mi/mi-var-child-f.exp: create local variable array (unexpected output)
...
The problem is that the name array is used both:
- as the name for a local variable
- as the name of a type in glibc, in file malloc/dynarray-skeleton.c, as included
by nss/nss_files/files-hosts.c.
Fix this by ignoring the shared lib symbols.
Likewise in a couple of other fortran tests.
Tested on x86_64-linux.
When running these test-cases:
- gdb.fortran/info-modules.exp
- gdb.fortran/module.exp
- gdb.mi/mi-fortran-modules.exp
in conjunction with:
...
$ stress -c $(($(cat /proc/cpuinfo | grep -c "^processor") + 1))
...
I run into timeouts.
Fix this by using:
- "set auto-solib-add off" to avoid symbols of shared libs
(which doesn't work for libc, now that libpthread_name_p has been
updated to match libc)
- "nosharedlibrary" to avoid symbols of libc
Tested on x86_64-linux.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=28133
As follow-up to this discussion:
https://sourceware.org/pipermail/gdb-patches/2020-August/171385.html
... make runto_main not pass no-message to runto. This means that if we
fail to run to main, for some reason, we'll emit a FAIL. This is the
behavior we want the majority of (if not all) the time.
Without this, we rely on tests logging a failure if runto_main fails,
otherwise. They do so in a very inconsisteny mannet, sometimes using
"fail", "unsupported" or "untested". The messages also vary widly.
This patch removes all these messages as well.
Also, remove a few "fail" where we call runto (and not runto_main). by
default (without an explicit no-message argument), runto prints a
failure already. In two places, gdb.multi/multi-re-run.exp and
gdb.python/py-pp-registration.exp, remove "message" passed to runto.
This removes a few PASSes that we don't care about (but FAILs will still
be printed if we fail to run to where we want to). This aligns their
behavior with the rest of the testsuite.
Change-Id: Ib763c98c5f4fb6898886b635210d7c34bd4b9023
Minimize gdb restarts, applying the following rules:
- don't use prepare_for_testing unless necessary
- don't use clean_restart unless necessary
Also, if possible, replace build_for_executable + clean_restart
with prepare_for_testing for brevity.
Touches 68 test-cases.
Tested on x86_64-linux.
On openSUSE Tumbleweed I ran into:
...
(gdb) ptype outstring_func.part^M
No symbol "outstring_func" in current context.^M
(gdb) FAIL: gdb.fortran/call-no-debug.exp: ptype outstring_func.part
...
while on openSUSE Leap 15.2 I have instead:
...
(gdb) ptype string_func_^M
type = <unknown return type> ()^M
(gdb) PASS: gdb.fortran/call-no-debug.exp: ptype string_func_
...
The difference is caused by the result for "info function string_func", which
is this for the latter:
...
(gdb) info function string_func^M
All functions matching regular expression "string_func":^M
^M
Non-debugging symbols:^M
0x000000000040089c string_func_^M
...
but this for the former:
...
(gdb) info function string_func^M
All functions matching regular expression "string_func":^M
^M
Non-debugging symbols:^M
0x00000000004012bb string_func_^M
0x00007ffff7bac5b0 outstring_func.part^M
0x00007ffff7bb1a00 outstring_func.part^M
...
The extra symbols are part of glibc:
...
$ nm /lib64/libc.so.6 | grep string_func
00000000000695b0 t outstring_func.part.0
000000000006ea00 t outstring_func.part.0
...
If glibc debug info is installed, we get instead:
...
(gdb) info function string_func^M
All functions matching regular expression "string_func":^M
^M
File /usr/src/debug/glibc-2.33-9.1.x86_64/stdio-common/vfprintf-internal.c:^M
236: static int outstring_func(int, size_t, const unsigned int *, FILE *);^M
^M
File vfprintf-internal.c:^M
236: static int outstring_func(int, size_t, const unsigned char *, FILE *);^M
^M
Non-debugging symbols:^M
0x00000000004012bb string_func_^M
...
and the FAIL doesn't trigger.
Fix this by calling "info function string_func" before starting the exec, such
that only symbols of the exec are taken into account.
Tested on x86_64-linux.
gdb/testsuite/ChangeLog:
2021-09-01 Tom de Vries <tdevries@suse.de>
* gdb.fortran/call-no-debug.exp: Avoid shared lib symbols for
find_mangled_name calls.
Since commit 05b8577206 "gdb/fortran: Add type info of formal parameter for
clang" I see:
...
(gdb) ptype say_string^M
type = void (character*(*), integer(kind=4))^M
(gdb) FAIL: gdb.fortran/ptype-on-functions.exp: ptype say_string
...
The part of the commit causing the fail is:
...
gdb_test "ptype say_string" \
- "type = void \\(character\\*\\(\\*\\), integer\\(kind=\\d+\\)\\)"
+ "type = void \\(character\[^,\]+, $integer8\\)"
...
which fails to take into account that for gcc-7 and before, the type for
string length of a string argument is int, not size_t.
Fix this by allowing both $integer8 and $integer4.
Tested on x86_64-linux, with gcc-7 and gcc-10.
gdb/testsuite/ChangeLog:
2021-07-05 Tom de Vries <tdevries@suse.de>
* gdb.fortran/ptype-on-functions.exp: Allow both $integer8 and
$integer4 for size of string length.
Additional compiler generated formal parameter exist with clang and type
information for the same is added accordingly. Also few kind parameter
printing are removed which is not default for clang.
Note: More details about this kind parameter omission while printing can
be found with similar patch
commit 0a709cba00
Author Alok Kumar Sharma (alokkumar.sharma@amd.com)
gdb/testsuite/ChangeLog:
* gdb.fortran/ptype-on-functions.exp: Add type info of formal
parameter for clang. Also removed the kind parameter for clang.
It's a common mistake of mine to do:
...
set l [list "foo" "bar"]
set re [multi_line $l]
...
and to get "foo bar" while I was expecting "foo\r\nbar", which I get after
doing instead:
...
set re [multi_line {*}$l]
...
Detect this type of mistake by erroring out in multi_line when only one
argument is passed.
Tested on x86_64-linux.
gdb/testsuite/ChangeLog:
2021-06-08 Tom de Vries <tdevries@suse.de>
* lib/gdb.exp (multi_line): Require more than one argument.
* gdb.base/gdbinit-history.exp: Update multi_line call.
* gdb.base/jit-reader.exp: Remove multi_line call.
* gdb.fortran/dynamic-ptype-whatis.exp: Same.
As mentioned in the test case itself, depending on the fortran compiler
used, class member names used in the print commands and also output of
these print commands varies. Existing print commands and its output are
suited for gfortran, hence they were failing with clang compiler and test
case was modified accordingly for clang compiler.
gdb/testsuite/ChangeLog:
* gdb.base/class-allocatable-array.exp: Modified test for clang.
Breakpoint location is modified to "return" statement which is
outside the DO loop. Because the label 100 of DO loop should get
executed for each iteration as shared in this external link:
http://www-pnp.physics.ox.ac.uk/~gronbech/intfor/node18.html.
flang compiler is following this fortran standard, whereas gfortran
compiler is not following, hence the test case is passing with
gfortran and failing with flang. but to correct this gfortran
behavior, bug has been filed in bugzilla
(https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99816). As reported in
the bug, with gfortran, label 100 of DO loop is reached only after
the completion of the entire DO loop. Hence at label 100, all the
array elements are set and printing of array element a(2) succeeds.
whereas with flang, when we are at label 100 for first time, array
element a(2) is not yet set, only a(1) is set, hence moving the
breakpoint location to outside the DO loop, so that once we are
outside the DO loop, we can print any of the array elements. This
change in test case is done irrespective of any fortran compiler.
gdb/testsuite/ChangeLog:
* gdb.fortran/array-element.exp: Breakpoint location is modified.
This commit replaces this patch:
https://sourceware.org/pipermail/gdb-patches/2021-January/174933.html
which was itself a replacement for this patch:
https://sourceware.org/pipermail/gdb-patches/2020-July/170335.html
The motivation behind the original patch can be seen in the new test,
which currently gives a GDB session like this:
(gdb) ptype var8
type = Type type6
PTR TO -> ( Type type2 :: ptr_1 )
PTR TO -> ( Type type2 :: ptr_2 )
End Type type6
(gdb) ptype var8%ptr_2
type = PTR TO -> ( Type type2
integer(kind=4) :: spacer
Type type1, allocatable :: t2_array(:) <------ Issue #1
End Type type2 )
(gdb) ptype var8%ptr_2%t2_array
Cannot access memory at address 0x38 <------ Issue #2
(gdb)
Issue #1: Here we see the abstract dynamic type, rather than the
resolved concrete type. Though in some cases the user might be
interested in the abstract dynamic type, I think that in most cases
showing the resolved concrete type will be of more use. Plus, the
user can always figure out the dynamic type (by source code inspection
if nothing else) given the concrete type, but it is much harder to
figure out the concrete type given only the dynamic type.
Issue #2: In this example, GDB evaluates the expression in
EVAL_AVOID_SIDE_EFFECTS mode (due to ptype). The value returned for
var8%ptr_2 will be a non-lazy, zero value of the correct dynamic
type. However, when GDB asks about the type of t2_array this requires
GDB to access the value of var8%ptr_2 in order to read the dynamic
properties. As this value was forced to zero (thanks to the use of
EVAL_AVOID_SIDE_EFFECTS) then GDB ends up accessing memory at a base
of zero plus some offset.
Both this patch, and my previous two attempts, have all tried to
resolve this problem by stopping EVAL_AVOID_SIDE_EFFECTS replacing the
result value with a zero value in some cases.
This new patch is influenced by how Ada handles its tagged typed.
There are plenty of examples in ada-lang.c, but one specific case is
ada_structop_operation::evaluate. When GDB spots that we are dealing
with a tagged (dynamic) type, and we're in EVAL_AVOID_SIDE_EFFECTS
mode, then GDB re-evaluates the child operation in EVAL_NORMAL mode.
This commit handles two cases like this specifically for Fortran, a
new fortran_structop_operation, and the already existing
fortran_undetermined, which is where we handle array accesses.
In these two locations we spot when we are dealing with a dynamic type
and re-evaluate the child operation in EVAL_NORMAL mode so that we
are able to access the dynamic properties of the type.
The rest of this commit message is my attempt to record why my
previous patches failed.
To understand my second patch, and why it failed lets consider two
expressions, this Fortran expression:
(gdb) ptype var8%ptr_2%t2_array --<A>
Operation: STRUCTOP_STRUCT --(1)
Operation: STRUCTOP_STRUCT --(2)
Operation: OP_VAR_VALUE --(3)
Symbol: var8
Block: 0x3980ac0
String: ptr_2
String: t2_array
And this C expression:
(gdb) ptype ptr && ptr->a == 3 --<B>
Operation: BINOP_LOGICAL_AND --(4)
Operation: OP_VAR_VALUE --(5)
Symbol: ptr
Block: 0x45a2a00
Operation: BINOP_EQUAL --(6)
Operation: STRUCTOP_PTR --(7)
Operation: OP_VAR_VALUE --(8)
Symbol: ptr
Block: 0x45a2a00
String: a
Operation: OP_LONG --(9)
Type: int
Constant: 0x0000000000000003
In expression <A> we should assume that t2_array is of dynamic type.
Nothing has dynamic type in expression <B>.
This is how GDB currently handles expression <A>, in all cases,
EVAL_AVOID_SIDE_EFFECTS or EVAL_NORMAL, an OP_VAR_VALUE operation
always returns the real value of the symbol, this is not forced to a
zero value even in EVAL_AVOID_SIDE_EFFECTS mode. This means that (3),
(5), and (8) will always return a real lazy value for the symbol.
However a STRUCTOP_STRUCT will always replace its result with a
non-lazy, zero value with the same type as its result. So (2) will
lookup the field ptr_2 and create a zero value with that type. In
this case the type is a pointer to a dynamic type.
Then, when we evaluate (1) to figure out the resolved type of
t2_array, we need to read the types dynamic properties. These
properties are stored in memory relative to the objects base address,
and the base address is in var8%ptr_2, which we already figured out
has the value zero. GDB then evaluates the DWARF expressions that
take the base address, add an offset and dereference. GDB then ends
up trying to access addresses like 0x16, 0x8, etc.
To fix this, I proposed changing STRUCTOP_STRUCT so that instead of
returning a zero value we instead returned the actual value
representing the structure's field in the target. My thinking was
that GDB would not try to access the value's contents unless it needed
it to resolve a dynamic type. This belief was incorrect.
Consider expression <B>. We already know that (5) and (8) will return
real values for the symbols being referenced. The BINOP_LOGICAL_AND,
operation (4) will evaluate both of its children in
EVAL_AVOID_SIDE_EFFECTS in order to get the types, this is required
for C++ operator lookup. This means that even if the value of (5)
would result in the BINOP_LOGICAL_AND returning false (say, ptr is
NULL), we still evaluate (6) in EVAL_AVOID_SIDE_EFFECTS mode.
Operation (6) will evaluate both children in EVAL_AVOID_SIDE_EFFECTS
mode, operation (9) is easy, it just returns a value with the constant
packed into it, but (7) is where the problem lies. Currently in GDB
this STRUCTOP_STRUCT will always return a non-lazy zero value of the
correct type.
When the results of (7) and (9) are back in the BINOP_LOGICAL_AND
operation (6), the two values are passed to value_equal which performs
the comparison and returns a result. Note, the two things compared
here are the immediate value (9), and a non-lazy zero value from (7).
However, with my proposed patch operation (7) no longer returns a zero
value, instead it returns a lazy value representing the actual value
in target memory. When we call value_equal in (6) this code causes
GDB to try and fetch the actual value from target memory. If `ptr` is
NULL then this will cause GDB to access some invalid address at an
offset from zero, this will most likely fail, and cause GDB to throw
an error instead of returning the expected type.
And so, we can now describe the problem that we're facing. The way
GDB's expression evaluator is currently written we assume, when in
EVAL_AVOID_SIDE_EFFECTS mode, that any value returned from a child
operation can safely have its content read without throwing an
error. If child operations start returning real values (instead of
the fake zero values), then this is simply not true.
If we wanted to work around this then we would need to rewrite almost
all operations (I would guess) so that EVAL_AVOID_SIDE_EFFECTS mode
does not cause evaluation of an operation to try and read the value of
a child operation. As an example, consider this current GDB code from
eval.c:
struct value *
eval_op_equal (struct type *expect_type, struct expression *exp,
enum noside noside, enum exp_opcode op,
struct value *arg1, struct value *arg2)
{
if (binop_user_defined_p (op, arg1, arg2))
{
return value_x_binop (arg1, arg2, op, OP_NULL, noside);
}
else
{
binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
int tem = value_equal (arg1, arg2);
struct type *type = language_bool_type (exp->language_defn,
exp->gdbarch);
return value_from_longest (type, (LONGEST) tem);
}
}
We could change this function to be this:
struct value *
eval_op_equal (struct type *expect_type, struct expression *exp,
enum noside noside, enum exp_opcode op,
struct value *arg1, struct value *arg2)
{
if (binop_user_defined_p (op, arg1, arg2))
{
return value_x_binop (arg1, arg2, op, OP_NULL, noside);
}
else
{
struct type *type = language_bool_type (exp->language_defn,
exp->gdbarch);
if (noside == EVAL_AVOID_SIDE_EFFECTS)
return value_zero (type, VALUE_LVAL (arg1));
else
{
binop_promote (exp->language_defn, exp->gdbarch, &arg1, &arg2);
int tem = value_equal (arg1, arg2);
return value_from_longest (type, (LONGEST) tem);
}
}
}
Now we don't call value_equal unless we really need to. However, we
would need to make the same, or similar change to almost all
operations, which would be a big task, and might not be a direction we
wanted to take GDB in.
So, for now, I'm proposing we go with the more targeted, Fortran
specific solution, that does the minimal required in order to
correctly resolve the dynamic types.
gdb/ChangeLog:
* f-exp.h (class fortran_structop_operation): New class.
* f-exp.y (exp): Create fortran_structop_operation instead of the
generic structop_operation.
* f-lang.c (fortran_undetermined::evaluate): Re-evaluate
expression as EVAL_NORMAL if the result type was dynamic so we can
extract the actual array bounds.
(fortran_structop_operation::evaluate): New function.
gdb/testsuite/ChangeLog:
* gdb.fortran/dynamic-ptype-whatis.exp: New file.
* gdb.fortran/dynamic-ptype-whatis.f90: New file.
LOC(X) returns the address of X as an integer:
https://gcc.gnu.org/onlinedocs/gfortran/LOC.html
Before:
(gdb) p LOC(r)
No symbol "LOC" in current context.
After:
(gdb) p LOC(r)
$1 = 0xffffdf48
gdb/ChangeLog:
2021-03-09 Felix Willgerodt <felix.willgerodt@intel.com>
* f-exp.h (eval_op_f_loc): Declare.
(expr::fortran_loc_operation): New typedef.
* f-exp.y (exp): Handle UNOP_FORTRAN_LOC after parsing an
UNOP_INTRINSIC.
(f77_keywords): Add LOC keyword.
* f-lang.c (eval_op_f_loc): New function.
* std-operator.def (UNOP_FORTRAN_LOC): New operator.
gdb/testsuite/ChangeLog:
2020-03-09 Felix Willgerodt <felix.willgerodt@intel.com>
* gdb.fortran/intrinsics.exp: Add LOC tests.
Add support for the SHAPE keyword to GDB's Fortran expression parser.
gdb/ChangeLog:
* f-exp.h (eval_op_f_array_shape): Declare.
(fortran_array_shape_operation): New type.
* f-exp.y (exp): Handle UNOP_FORTRAN_SHAPE after parsing
UNOP_INTRINSIC.
(f77_keywords): Add "shape" keyword.
* f-lang.c (fortran_array_shape): New function.
(eval_op_f_array_shape): New function.
* std-operator.def (UNOP_FORTRAN_SHAPE): New operator.
gdb/testsuite/ChangeLog:
* gdb.fortran/shape.exp: New file.
* gdb.fortran/shape.f90: New file.
Add support for the 'SIZE' keyword to the Fortran expression parser.
This returns the number of elements either in an entire array (passing
a single argument to SIZE), or in a particular dimension of an
array (passing two arguments to SIZE).
At this point I have not added support for the optional third argument
to SIZE, which controls the exact integer type of the result.
gdb/ChangeLog:
* f-exp.y (eval_op_f_array_size): Declare 1 and 2 argument forms
of this function.
(expr::fortran_array_size_1arg): New type.
(expr::fortran_array_size_2arg): Likewise.
* f-exp.y (exp): Handle FORTRAN_ARRAY_SIZE after parsing
UNOP_OR_BINOP_INTRINSIC.
(f77_keywords): Add "size" keyword.
* f-lang.c (fortran_array_size): New function.
(eval_op_f_array_size): New function, has a 1 arg and 2 arg form.
* std-operator.def (FORTRAN_ARRAY_SIZE): New operator.
gdb/testsuite/ChangeLog:
* gdb.fortran/size.exp: New file.
* gdb.fortran/size.f90: New file.
gfortran supports the RANK keyword, see:
https://gcc.gnu.org/onlinedocs/gfortran/RANK.html#RANK
this commit adds support for this keyword to GDB's Fortran expression
parser.
gdb/ChangeLog:
* f-exp.h (eval_op_f_rank): Declare.
(expr::fortran_rank_operation): New typedef.
* f-exp.y (exp): Handle UNOP_FORTRAN_RANK after parsing an
UNOP_INTRINSIC.
(f77_keywords): Add "rank" keyword.
* f-lang.c (eval_op_f_rank): New function.
* std-operator.def (UNOP_FORTRAN_RANK): New operator.
gdb/testsuite/ChangeLog:
* gdb.fortran/rank.exp: New file.
* gdb.fortran/rank.f90: New file.
This converts the Fortran parser to generate operations rather than
exp_elements. A couple of tests of expression debug dumping are
updated to follow the new output.
gdb/ChangeLog
2021-03-08 Tom Tromey <tom@tromey.com>
* f-exp.y: Create operations.
(f_language::parser): Update.
gdb/testsuite/ChangeLog
2021-03-08 Tom Tromey <tom@tromey.com>
* gdb.fortran/debug-expr.exp: Update tests.
In commit:
commit faeb9f13c1
Date: Wed Feb 24 12:50:00 2021 +0000
gdb/fortran: add support for ASSOCIATED builtin
A test was added that fails to process the trailing gdb prompt inside
a gdb_test_multiple call, this will cause a failure if the tests are
run with READ1=1, or randomly at other times depending on how the
expect buffers are read in.
Fixed by adding a -wrap argument.
gdb/testsuite/ChangeLog:
* gdb.fortran/associated.exp: Add missing '-wrap' argument.
When attempting to call a Fortran function for which there is no debug
information we currently trigger undefined behaviour in GDB by
accessing non-existent type fields.
The reason is that in order to prepare the arguments, for a call to a
Fortran function, we need to know the type of each argument. If the
function being called has no debug information then obviously GDB
doesn't know about the argument types and we should either give the
user an error or pick a suitable default. What we currently do is
just assume the field exist and access undefined memory, which is
clearly wrong.
The reason GDB needs to know the argument type is to tell if the
argument is artificial or not, artificial arguments will be passed by
value while non-artificial arguments will be passed by reference.
An ideal solution for this problem would be to allow the user to cast
the function to the correct type, we already do this to some degree
with the return value, for example:
(gdb) print some_func_ ()
'some_func_' has unknown return type; cast the call to its declared return type
(gdb) print (integer) some_func_ ()
$1 = 1
But if we could extend this to allow casting to the full function
type, GDB could figure out from the signature what are real
parameters, and what are artificial parameters. Maybe something like
this:
(gdb) print ((integer () (integer, double)) some_other_func_ (1, 2.3)
Alas, right now the Fortran expression parser doesn't seem to support
parsing function signatures, and we certainly don't have support for
figuring out real vs artificial arguments from a signature.
Still, I think we can prevent GDB from accessing undefined memory and
provide a reasonable default behaviour.
In this commit I:
- Only ask if the argument is artificial if the type of the argument
is actually known.
- Unknown arguments are assumed to be artificial and passed by
value (non-artificial arguments are pass by reference).
- If an artificial argument is prefixed with '&' by the user then we
treat the argument as pass-by-reference.
With these three changes we avoid undefined behaviour in GDB, and
allow the user, in most cases, to get a reasonably natural default
behaviour.
gdb/ChangeLog:
PR fortran/26155
* f-lang.c (fortran_argument_convert): Delete declaration.
(fortran_prepare_argument): New function.
(evaluate_subexp_f): Move logic to new function
fortran_prepare_argument.
gdb/testsuite/ChangeLog:
PR fortran/26155
* gdb.fortran/call-no-debug-func.f90: New file.
* gdb.fortran/call-no-debug-prog.f90: New file.
* gdb.fortran/call-no-debug.exp: New file.
This commit adds support for the ASSOCIATED builtin to the Fortran
expression evaluator. The ASSOCIATED builtin takes one or two
arguments.
When passed a single pointer argument GDB returns a boolean indicating
if the pointer is associated with anything.
When passed two arguments the second argument should either be some a
pointer could point at or a second pointer.
If the second argument is a pointer target, then the result from
associated indicates if the pointer is pointing at this target.
If the second argument is another pointer, then the result from
associated indicates if the two pointers are pointing at the same
thing.
gdb/ChangeLog:
* f-exp.y (f77_keywords): Add 'associated'.
* f-lang.c (fortran_associated): New function.
(evaluate_subexp_f): Handle FORTRAN_ASSOCIATED.
(operator_length_f): Likewise.
(print_unop_or_binop_subexp_f): New function.
(print_subexp_f): Make use of print_unop_or_binop_subexp_f for
FORTRAN_ASSOCIATED, FORTRAN_LBOUND, and FORTRAN_UBOUND.
(dump_subexp_body_f): Handle FORTRAN_ASSOCIATED.
(operator_check_f): Likewise.
* std-operator.def: Add FORTRAN_ASSOCIATED.
gdb/testsuite/ChangeLog:
* gdb.fortran/associated.exp: New file.
* gdb.fortran/associated.f90: New file.