binutils-gdb/gdb/f-lang.c

2041 lines
67 KiB
C
Raw Normal View History

/* Fortran language support routines for GDB, the GNU debugger.
Copyright (C) 1993-2024 Free Software Foundation, Inc.
Contributed by Motorola. Adapted from the C parser by Farooq Butt
(fmbutt@engage.sps.mot.com).
1999-07-08 04:19:36 +08:00
This file is part of GDB.
1999-07-08 04:19:36 +08:00
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
1999-07-08 04:19:36 +08:00
(at your option) any later version.
1999-07-08 04:19:36 +08:00
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.
1999-07-08 04:19:36 +08:00
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
Revert the header-sorting patch Andreas Schwab and John Baldwin pointed out some bugs in the header sorting patch; and I noticed that the output was not correct when limited to a subset of files (a bug in my script). So, I'm reverting the patch. I may try again after fixing the issues pointed out. gdb/ChangeLog 2019-04-05 Tom Tromey <tom@tromey.com> Revert the header-sorting patch. * ft32-tdep.c: Revert. * frv-tdep.c: Revert. * frv-linux-tdep.c: Revert. * frame.c: Revert. * frame-unwind.c: Revert. * frame-base.c: Revert. * fork-child.c: Revert. * findvar.c: Revert. * findcmd.c: Revert. * filesystem.c: Revert. * filename-seen-cache.h: Revert. * filename-seen-cache.c: Revert. * fbsd-tdep.c: Revert. * fbsd-nat.h: Revert. * fbsd-nat.c: Revert. * f-valprint.c: Revert. * f-typeprint.c: Revert. * f-lang.c: Revert. * extension.h: Revert. * extension.c: Revert. * extension-priv.h: Revert. * expprint.c: Revert. * exec.h: Revert. * exec.c: Revert. * exceptions.c: Revert. * event-top.c: Revert. * event-loop.c: Revert. * eval.c: Revert. * elfread.c: Revert. * dwarf2read.h: Revert. * dwarf2read.c: Revert. * dwarf2loc.c: Revert. * dwarf2expr.h: Revert. * dwarf2expr.c: Revert. * dwarf2-frame.c: Revert. * dwarf2-frame-tailcall.c: Revert. * dwarf-index-write.h: Revert. * dwarf-index-write.c: Revert. * dwarf-index-common.c: Revert. * dwarf-index-cache.h: Revert. * dwarf-index-cache.c: Revert. * dummy-frame.c: Revert. * dtrace-probe.c: Revert. * disasm.h: Revert. * disasm.c: Revert. * disasm-selftests.c: Revert. * dictionary.c: Revert. * dicos-tdep.c: Revert. * demangle.c: Revert. * dcache.h: Revert. * dcache.c: Revert. * darwin-nat.h: Revert. * darwin-nat.c: Revert. * darwin-nat-info.c: Revert. * d-valprint.c: Revert. * d-namespace.c: Revert. * d-lang.c: Revert. * ctf.c: Revert. * csky-tdep.c: Revert. * csky-linux-tdep.c: Revert. * cris-tdep.c: Revert. * cris-linux-tdep.c: Revert. * cp-valprint.c: Revert. * cp-support.c: Revert. * cp-namespace.c: Revert. * cp-abi.c: Revert. * corelow.c: Revert. * corefile.c: Revert. * continuations.c: Revert. * completer.h: Revert. * completer.c: Revert. * complaints.c: Revert. * coffread.c: Revert. * coff-pe-read.c: Revert. * cli-out.h: Revert. * cli-out.c: Revert. * charset.c: Revert. * c-varobj.c: Revert. * c-valprint.c: Revert. * c-typeprint.c: Revert. * c-lang.c: Revert. * buildsym.c: Revert. * buildsym-legacy.c: Revert. * build-id.h: Revert. * build-id.c: Revert. * btrace.c: Revert. * bsd-uthread.c: Revert. * breakpoint.h: Revert. * breakpoint.c: Revert. * break-catch-throw.c: Revert. * break-catch-syscall.c: Revert. * break-catch-sig.c: Revert. * blockframe.c: Revert. * block.c: Revert. * bfin-tdep.c: Revert. * bfin-linux-tdep.c: Revert. * bfd-target.c: Revert. * bcache.c: Revert. * ax-general.c: Revert. * ax-gdb.h: Revert. * ax-gdb.c: Revert. * avr-tdep.c: Revert. * auxv.c: Revert. * auto-load.c: Revert. * arm-wince-tdep.c: Revert. * arm-tdep.c: Revert. * arm-symbian-tdep.c: Revert. * arm-pikeos-tdep.c: Revert. * arm-obsd-tdep.c: Revert. * arm-nbsd-tdep.c: Revert. * arm-nbsd-nat.c: Revert. * arm-linux-tdep.c: Revert. * arm-linux-nat.c: Revert. * arm-fbsd-tdep.c: Revert. * arm-fbsd-nat.c: Revert. * arm-bsd-tdep.c: Revert. * arch-utils.c: Revert. * arc-tdep.c: Revert. * arc-newlib-tdep.c: Revert. * annotate.h: Revert. * annotate.c: Revert. * amd64-windows-tdep.c: Revert. * amd64-windows-nat.c: Revert. * amd64-tdep.c: Revert. * amd64-sol2-tdep.c: Revert. * amd64-obsd-tdep.c: Revert. * amd64-obsd-nat.c: Revert. * amd64-nbsd-tdep.c: Revert. * amd64-nbsd-nat.c: Revert. * amd64-nat.c: Revert. * amd64-linux-tdep.c: Revert. * amd64-linux-nat.c: Revert. * amd64-fbsd-tdep.c: Revert. * amd64-fbsd-nat.c: Revert. * amd64-dicos-tdep.c: Revert. * amd64-darwin-tdep.c: Revert. * amd64-bsd-nat.c: Revert. * alpha-tdep.c: Revert. * alpha-obsd-tdep.c: Revert. * alpha-nbsd-tdep.c: Revert. * alpha-mdebug-tdep.c: Revert. * alpha-linux-tdep.c: Revert. * alpha-linux-nat.c: Revert. * alpha-bsd-tdep.c: Revert. * alpha-bsd-nat.c: Revert. * aix-thread.c: Revert. * agent.c: Revert. * addrmap.c: Revert. * ada-varobj.c: Revert. * ada-valprint.c: Revert. * ada-typeprint.c: Revert. * ada-tasks.c: Revert. * ada-lang.c: Revert. * aarch64-tdep.c: Revert. * aarch64-ravenscar-thread.c: Revert. * aarch64-newlib-tdep.c: Revert. * aarch64-linux-tdep.c: Revert. * aarch64-linux-nat.c: Revert. * aarch64-fbsd-tdep.c: Revert. * aarch64-fbsd-nat.c: Revert. * aarch32-linux-nat.c: Revert.
2019-04-07 03:38:10 +08:00
#include "symtab.h"
Sort includes for files gdb/[a-f]*.[chyl]. This patch sorts the include files for the files [a-f]*.[chyl]. The patch was written by a script. Tested by the buildbot. I will follow up with patches to sort the remaining files, by sorting a subset, testing them, and then checking them in. gdb/ChangeLog 2019-04-05 Tom Tromey <tom@tromey.com> * ft32-tdep.c: Sort headers. * frv-tdep.c: Sort headers. * frv-linux-tdep.c: Sort headers. * frame.c: Sort headers. * frame-unwind.c: Sort headers. * frame-base.c: Sort headers. * fork-child.c: Sort headers. * findvar.c: Sort headers. * findcmd.c: Sort headers. * filesystem.c: Sort headers. * filename-seen-cache.h: Sort headers. * filename-seen-cache.c: Sort headers. * fbsd-tdep.c: Sort headers. * fbsd-nat.h: Sort headers. * fbsd-nat.c: Sort headers. * f-valprint.c: Sort headers. * f-typeprint.c: Sort headers. * f-lang.c: Sort headers. * extension.h: Sort headers. * extension.c: Sort headers. * extension-priv.h: Sort headers. * expprint.c: Sort headers. * exec.h: Sort headers. * exec.c: Sort headers. * exceptions.c: Sort headers. * event-top.c: Sort headers. * event-loop.c: Sort headers. * eval.c: Sort headers. * elfread.c: Sort headers. * dwarf2read.h: Sort headers. * dwarf2read.c: Sort headers. * dwarf2loc.c: Sort headers. * dwarf2expr.h: Sort headers. * dwarf2expr.c: Sort headers. * dwarf2-frame.c: Sort headers. * dwarf2-frame-tailcall.c: Sort headers. * dwarf-index-write.h: Sort headers. * dwarf-index-write.c: Sort headers. * dwarf-index-common.c: Sort headers. * dwarf-index-cache.h: Sort headers. * dwarf-index-cache.c: Sort headers. * dummy-frame.c: Sort headers. * dtrace-probe.c: Sort headers. * disasm.h: Sort headers. * disasm.c: Sort headers. * disasm-selftests.c: Sort headers. * dictionary.c: Sort headers. * dicos-tdep.c: Sort headers. * demangle.c: Sort headers. * dcache.h: Sort headers. * dcache.c: Sort headers. * darwin-nat.h: Sort headers. * darwin-nat.c: Sort headers. * darwin-nat-info.c: Sort headers. * d-valprint.c: Sort headers. * d-namespace.c: Sort headers. * d-lang.c: Sort headers. * ctf.c: Sort headers. * csky-tdep.c: Sort headers. * csky-linux-tdep.c: Sort headers. * cris-tdep.c: Sort headers. * cris-linux-tdep.c: Sort headers. * cp-valprint.c: Sort headers. * cp-support.c: Sort headers. * cp-namespace.c: Sort headers. * cp-abi.c: Sort headers. * corelow.c: Sort headers. * corefile.c: Sort headers. * continuations.c: Sort headers. * completer.h: Sort headers. * completer.c: Sort headers. * complaints.c: Sort headers. * coffread.c: Sort headers. * coff-pe-read.c: Sort headers. * cli-out.h: Sort headers. * cli-out.c: Sort headers. * charset.c: Sort headers. * c-varobj.c: Sort headers. * c-valprint.c: Sort headers. * c-typeprint.c: Sort headers. * c-lang.c: Sort headers. * buildsym.c: Sort headers. * buildsym-legacy.c: Sort headers. * build-id.h: Sort headers. * build-id.c: Sort headers. * btrace.c: Sort headers. * bsd-uthread.c: Sort headers. * breakpoint.h: Sort headers. * breakpoint.c: Sort headers. * break-catch-throw.c: Sort headers. * break-catch-syscall.c: Sort headers. * break-catch-sig.c: Sort headers. * blockframe.c: Sort headers. * block.c: Sort headers. * bfin-tdep.c: Sort headers. * bfin-linux-tdep.c: Sort headers. * bfd-target.c: Sort headers. * bcache.c: Sort headers. * ax-general.c: Sort headers. * ax-gdb.h: Sort headers. * ax-gdb.c: Sort headers. * avr-tdep.c: Sort headers. * auxv.c: Sort headers. * auto-load.c: Sort headers. * arm-wince-tdep.c: Sort headers. * arm-tdep.c: Sort headers. * arm-symbian-tdep.c: Sort headers. * arm-pikeos-tdep.c: Sort headers. * arm-obsd-tdep.c: Sort headers. * arm-nbsd-tdep.c: Sort headers. * arm-nbsd-nat.c: Sort headers. * arm-linux-tdep.c: Sort headers. * arm-linux-nat.c: Sort headers. * arm-fbsd-tdep.c: Sort headers. * arm-fbsd-nat.c: Sort headers. * arm-bsd-tdep.c: Sort headers. * arch-utils.c: Sort headers. * arc-tdep.c: Sort headers. * arc-newlib-tdep.c: Sort headers. * annotate.h: Sort headers. * annotate.c: Sort headers. * amd64-windows-tdep.c: Sort headers. * amd64-windows-nat.c: Sort headers. * amd64-tdep.c: Sort headers. * amd64-sol2-tdep.c: Sort headers. * amd64-obsd-tdep.c: Sort headers. * amd64-obsd-nat.c: Sort headers. * amd64-nbsd-tdep.c: Sort headers. * amd64-nbsd-nat.c: Sort headers. * amd64-nat.c: Sort headers. * amd64-linux-tdep.c: Sort headers. * amd64-linux-nat.c: Sort headers. * amd64-fbsd-tdep.c: Sort headers. * amd64-fbsd-nat.c: Sort headers. * amd64-dicos-tdep.c: Sort headers. * amd64-darwin-tdep.c: Sort headers. * amd64-bsd-nat.c: Sort headers. * alpha-tdep.c: Sort headers. * alpha-obsd-tdep.c: Sort headers. * alpha-nbsd-tdep.c: Sort headers. * alpha-mdebug-tdep.c: Sort headers. * alpha-linux-tdep.c: Sort headers. * alpha-linux-nat.c: Sort headers. * alpha-bsd-tdep.c: Sort headers. * alpha-bsd-nat.c: Sort headers. * aix-thread.c: Sort headers. * agent.c: Sort headers. * addrmap.c: Sort headers. * ada-varobj.c: Sort headers. * ada-valprint.c: Sort headers. * ada-typeprint.c: Sort headers. * ada-tasks.c: Sort headers. * ada-lang.c: Sort headers. * aarch64-tdep.c: Sort headers. * aarch64-ravenscar-thread.c: Sort headers. * aarch64-newlib-tdep.c: Sort headers. * aarch64-linux-tdep.c: Sort headers. * aarch64-linux-nat.c: Sort headers. * aarch64-fbsd-tdep.c: Sort headers. * aarch64-fbsd-nat.c: Sort headers. * aarch32-linux-nat.c: Sort headers.
2019-04-03 10:04:24 +08:00
#include "gdbtypes.h"
Revert the header-sorting patch Andreas Schwab and John Baldwin pointed out some bugs in the header sorting patch; and I noticed that the output was not correct when limited to a subset of files (a bug in my script). So, I'm reverting the patch. I may try again after fixing the issues pointed out. gdb/ChangeLog 2019-04-05 Tom Tromey <tom@tromey.com> Revert the header-sorting patch. * ft32-tdep.c: Revert. * frv-tdep.c: Revert. * frv-linux-tdep.c: Revert. * frame.c: Revert. * frame-unwind.c: Revert. * frame-base.c: Revert. * fork-child.c: Revert. * findvar.c: Revert. * findcmd.c: Revert. * filesystem.c: Revert. * filename-seen-cache.h: Revert. * filename-seen-cache.c: Revert. * fbsd-tdep.c: Revert. * fbsd-nat.h: Revert. * fbsd-nat.c: Revert. * f-valprint.c: Revert. * f-typeprint.c: Revert. * f-lang.c: Revert. * extension.h: Revert. * extension.c: Revert. * extension-priv.h: Revert. * expprint.c: Revert. * exec.h: Revert. * exec.c: Revert. * exceptions.c: Revert. * event-top.c: Revert. * event-loop.c: Revert. * eval.c: Revert. * elfread.c: Revert. * dwarf2read.h: Revert. * dwarf2read.c: Revert. * dwarf2loc.c: Revert. * dwarf2expr.h: Revert. * dwarf2expr.c: Revert. * dwarf2-frame.c: Revert. * dwarf2-frame-tailcall.c: Revert. * dwarf-index-write.h: Revert. * dwarf-index-write.c: Revert. * dwarf-index-common.c: Revert. * dwarf-index-cache.h: Revert. * dwarf-index-cache.c: Revert. * dummy-frame.c: Revert. * dtrace-probe.c: Revert. * disasm.h: Revert. * disasm.c: Revert. * disasm-selftests.c: Revert. * dictionary.c: Revert. * dicos-tdep.c: Revert. * demangle.c: Revert. * dcache.h: Revert. * dcache.c: Revert. * darwin-nat.h: Revert. * darwin-nat.c: Revert. * darwin-nat-info.c: Revert. * d-valprint.c: Revert. * d-namespace.c: Revert. * d-lang.c: Revert. * ctf.c: Revert. * csky-tdep.c: Revert. * csky-linux-tdep.c: Revert. * cris-tdep.c: Revert. * cris-linux-tdep.c: Revert. * cp-valprint.c: Revert. * cp-support.c: Revert. * cp-namespace.c: Revert. * cp-abi.c: Revert. * corelow.c: Revert. * corefile.c: Revert. * continuations.c: Revert. * completer.h: Revert. * completer.c: Revert. * complaints.c: Revert. * coffread.c: Revert. * coff-pe-read.c: Revert. * cli-out.h: Revert. * cli-out.c: Revert. * charset.c: Revert. * c-varobj.c: Revert. * c-valprint.c: Revert. * c-typeprint.c: Revert. * c-lang.c: Revert. * buildsym.c: Revert. * buildsym-legacy.c: Revert. * build-id.h: Revert. * build-id.c: Revert. * btrace.c: Revert. * bsd-uthread.c: Revert. * breakpoint.h: Revert. * breakpoint.c: Revert. * break-catch-throw.c: Revert. * break-catch-syscall.c: Revert. * break-catch-sig.c: Revert. * blockframe.c: Revert. * block.c: Revert. * bfin-tdep.c: Revert. * bfin-linux-tdep.c: Revert. * bfd-target.c: Revert. * bcache.c: Revert. * ax-general.c: Revert. * ax-gdb.h: Revert. * ax-gdb.c: Revert. * avr-tdep.c: Revert. * auxv.c: Revert. * auto-load.c: Revert. * arm-wince-tdep.c: Revert. * arm-tdep.c: Revert. * arm-symbian-tdep.c: Revert. * arm-pikeos-tdep.c: Revert. * arm-obsd-tdep.c: Revert. * arm-nbsd-tdep.c: Revert. * arm-nbsd-nat.c: Revert. * arm-linux-tdep.c: Revert. * arm-linux-nat.c: Revert. * arm-fbsd-tdep.c: Revert. * arm-fbsd-nat.c: Revert. * arm-bsd-tdep.c: Revert. * arch-utils.c: Revert. * arc-tdep.c: Revert. * arc-newlib-tdep.c: Revert. * annotate.h: Revert. * annotate.c: Revert. * amd64-windows-tdep.c: Revert. * amd64-windows-nat.c: Revert. * amd64-tdep.c: Revert. * amd64-sol2-tdep.c: Revert. * amd64-obsd-tdep.c: Revert. * amd64-obsd-nat.c: Revert. * amd64-nbsd-tdep.c: Revert. * amd64-nbsd-nat.c: Revert. * amd64-nat.c: Revert. * amd64-linux-tdep.c: Revert. * amd64-linux-nat.c: Revert. * amd64-fbsd-tdep.c: Revert. * amd64-fbsd-nat.c: Revert. * amd64-dicos-tdep.c: Revert. * amd64-darwin-tdep.c: Revert. * amd64-bsd-nat.c: Revert. * alpha-tdep.c: Revert. * alpha-obsd-tdep.c: Revert. * alpha-nbsd-tdep.c: Revert. * alpha-mdebug-tdep.c: Revert. * alpha-linux-tdep.c: Revert. * alpha-linux-nat.c: Revert. * alpha-bsd-tdep.c: Revert. * alpha-bsd-nat.c: Revert. * aix-thread.c: Revert. * agent.c: Revert. * addrmap.c: Revert. * ada-varobj.c: Revert. * ada-valprint.c: Revert. * ada-typeprint.c: Revert. * ada-tasks.c: Revert. * ada-lang.c: Revert. * aarch64-tdep.c: Revert. * aarch64-ravenscar-thread.c: Revert. * aarch64-newlib-tdep.c: Revert. * aarch64-linux-tdep.c: Revert. * aarch64-linux-nat.c: Revert. * aarch64-fbsd-tdep.c: Revert. * aarch64-fbsd-nat.c: Revert. * aarch32-linux-nat.c: Revert.
2019-04-07 03:38:10 +08:00
#include "expression.h"
Sort includes for files gdb/[a-f]*.[chyl]. This patch sorts the include files for the files [a-f]*.[chyl]. The patch was written by a script. Tested by the buildbot. I will follow up with patches to sort the remaining files, by sorting a subset, testing them, and then checking them in. gdb/ChangeLog 2019-04-05 Tom Tromey <tom@tromey.com> * ft32-tdep.c: Sort headers. * frv-tdep.c: Sort headers. * frv-linux-tdep.c: Sort headers. * frame.c: Sort headers. * frame-unwind.c: Sort headers. * frame-base.c: Sort headers. * fork-child.c: Sort headers. * findvar.c: Sort headers. * findcmd.c: Sort headers. * filesystem.c: Sort headers. * filename-seen-cache.h: Sort headers. * filename-seen-cache.c: Sort headers. * fbsd-tdep.c: Sort headers. * fbsd-nat.h: Sort headers. * fbsd-nat.c: Sort headers. * f-valprint.c: Sort headers. * f-typeprint.c: Sort headers. * f-lang.c: Sort headers. * extension.h: Sort headers. * extension.c: Sort headers. * extension-priv.h: Sort headers. * expprint.c: Sort headers. * exec.h: Sort headers. * exec.c: Sort headers. * exceptions.c: Sort headers. * event-top.c: Sort headers. * event-loop.c: Sort headers. * eval.c: Sort headers. * elfread.c: Sort headers. * dwarf2read.h: Sort headers. * dwarf2read.c: Sort headers. * dwarf2loc.c: Sort headers. * dwarf2expr.h: Sort headers. * dwarf2expr.c: Sort headers. * dwarf2-frame.c: Sort headers. * dwarf2-frame-tailcall.c: Sort headers. * dwarf-index-write.h: Sort headers. * dwarf-index-write.c: Sort headers. * dwarf-index-common.c: Sort headers. * dwarf-index-cache.h: Sort headers. * dwarf-index-cache.c: Sort headers. * dummy-frame.c: Sort headers. * dtrace-probe.c: Sort headers. * disasm.h: Sort headers. * disasm.c: Sort headers. * disasm-selftests.c: Sort headers. * dictionary.c: Sort headers. * dicos-tdep.c: Sort headers. * demangle.c: Sort headers. * dcache.h: Sort headers. * dcache.c: Sort headers. * darwin-nat.h: Sort headers. * darwin-nat.c: Sort headers. * darwin-nat-info.c: Sort headers. * d-valprint.c: Sort headers. * d-namespace.c: Sort headers. * d-lang.c: Sort headers. * ctf.c: Sort headers. * csky-tdep.c: Sort headers. * csky-linux-tdep.c: Sort headers. * cris-tdep.c: Sort headers. * cris-linux-tdep.c: Sort headers. * cp-valprint.c: Sort headers. * cp-support.c: Sort headers. * cp-namespace.c: Sort headers. * cp-abi.c: Sort headers. * corelow.c: Sort headers. * corefile.c: Sort headers. * continuations.c: Sort headers. * completer.h: Sort headers. * completer.c: Sort headers. * complaints.c: Sort headers. * coffread.c: Sort headers. * coff-pe-read.c: Sort headers. * cli-out.h: Sort headers. * cli-out.c: Sort headers. * charset.c: Sort headers. * c-varobj.c: Sort headers. * c-valprint.c: Sort headers. * c-typeprint.c: Sort headers. * c-lang.c: Sort headers. * buildsym.c: Sort headers. * buildsym-legacy.c: Sort headers. * build-id.h: Sort headers. * build-id.c: Sort headers. * btrace.c: Sort headers. * bsd-uthread.c: Sort headers. * breakpoint.h: Sort headers. * breakpoint.c: Sort headers. * break-catch-throw.c: Sort headers. * break-catch-syscall.c: Sort headers. * break-catch-sig.c: Sort headers. * blockframe.c: Sort headers. * block.c: Sort headers. * bfin-tdep.c: Sort headers. * bfin-linux-tdep.c: Sort headers. * bfd-target.c: Sort headers. * bcache.c: Sort headers. * ax-general.c: Sort headers. * ax-gdb.h: Sort headers. * ax-gdb.c: Sort headers. * avr-tdep.c: Sort headers. * auxv.c: Sort headers. * auto-load.c: Sort headers. * arm-wince-tdep.c: Sort headers. * arm-tdep.c: Sort headers. * arm-symbian-tdep.c: Sort headers. * arm-pikeos-tdep.c: Sort headers. * arm-obsd-tdep.c: Sort headers. * arm-nbsd-tdep.c: Sort headers. * arm-nbsd-nat.c: Sort headers. * arm-linux-tdep.c: Sort headers. * arm-linux-nat.c: Sort headers. * arm-fbsd-tdep.c: Sort headers. * arm-fbsd-nat.c: Sort headers. * arm-bsd-tdep.c: Sort headers. * arch-utils.c: Sort headers. * arc-tdep.c: Sort headers. * arc-newlib-tdep.c: Sort headers. * annotate.h: Sort headers. * annotate.c: Sort headers. * amd64-windows-tdep.c: Sort headers. * amd64-windows-nat.c: Sort headers. * amd64-tdep.c: Sort headers. * amd64-sol2-tdep.c: Sort headers. * amd64-obsd-tdep.c: Sort headers. * amd64-obsd-nat.c: Sort headers. * amd64-nbsd-tdep.c: Sort headers. * amd64-nbsd-nat.c: Sort headers. * amd64-nat.c: Sort headers. * amd64-linux-tdep.c: Sort headers. * amd64-linux-nat.c: Sort headers. * amd64-fbsd-tdep.c: Sort headers. * amd64-fbsd-nat.c: Sort headers. * amd64-dicos-tdep.c: Sort headers. * amd64-darwin-tdep.c: Sort headers. * amd64-bsd-nat.c: Sort headers. * alpha-tdep.c: Sort headers. * alpha-obsd-tdep.c: Sort headers. * alpha-nbsd-tdep.c: Sort headers. * alpha-mdebug-tdep.c: Sort headers. * alpha-linux-tdep.c: Sort headers. * alpha-linux-nat.c: Sort headers. * alpha-bsd-tdep.c: Sort headers. * alpha-bsd-nat.c: Sort headers. * aix-thread.c: Sort headers. * agent.c: Sort headers. * addrmap.c: Sort headers. * ada-varobj.c: Sort headers. * ada-valprint.c: Sort headers. * ada-typeprint.c: Sort headers. * ada-tasks.c: Sort headers. * ada-lang.c: Sort headers. * aarch64-tdep.c: Sort headers. * aarch64-ravenscar-thread.c: Sort headers. * aarch64-newlib-tdep.c: Sort headers. * aarch64-linux-tdep.c: Sort headers. * aarch64-linux-nat.c: Sort headers. * aarch64-fbsd-tdep.c: Sort headers. * aarch64-fbsd-nat.c: Sort headers. * aarch32-linux-nat.c: Sort headers.
2019-04-03 10:04:24 +08:00
#include "parser-defs.h"
Revert the header-sorting patch Andreas Schwab and John Baldwin pointed out some bugs in the header sorting patch; and I noticed that the output was not correct when limited to a subset of files (a bug in my script). So, I'm reverting the patch. I may try again after fixing the issues pointed out. gdb/ChangeLog 2019-04-05 Tom Tromey <tom@tromey.com> Revert the header-sorting patch. * ft32-tdep.c: Revert. * frv-tdep.c: Revert. * frv-linux-tdep.c: Revert. * frame.c: Revert. * frame-unwind.c: Revert. * frame-base.c: Revert. * fork-child.c: Revert. * findvar.c: Revert. * findcmd.c: Revert. * filesystem.c: Revert. * filename-seen-cache.h: Revert. * filename-seen-cache.c: Revert. * fbsd-tdep.c: Revert. * fbsd-nat.h: Revert. * fbsd-nat.c: Revert. * f-valprint.c: Revert. * f-typeprint.c: Revert. * f-lang.c: Revert. * extension.h: Revert. * extension.c: Revert. * extension-priv.h: Revert. * expprint.c: Revert. * exec.h: Revert. * exec.c: Revert. * exceptions.c: Revert. * event-top.c: Revert. * event-loop.c: Revert. * eval.c: Revert. * elfread.c: Revert. * dwarf2read.h: Revert. * dwarf2read.c: Revert. * dwarf2loc.c: Revert. * dwarf2expr.h: Revert. * dwarf2expr.c: Revert. * dwarf2-frame.c: Revert. * dwarf2-frame-tailcall.c: Revert. * dwarf-index-write.h: Revert. * dwarf-index-write.c: Revert. * dwarf-index-common.c: Revert. * dwarf-index-cache.h: Revert. * dwarf-index-cache.c: Revert. * dummy-frame.c: Revert. * dtrace-probe.c: Revert. * disasm.h: Revert. * disasm.c: Revert. * disasm-selftests.c: Revert. * dictionary.c: Revert. * dicos-tdep.c: Revert. * demangle.c: Revert. * dcache.h: Revert. * dcache.c: Revert. * darwin-nat.h: Revert. * darwin-nat.c: Revert. * darwin-nat-info.c: Revert. * d-valprint.c: Revert. * d-namespace.c: Revert. * d-lang.c: Revert. * ctf.c: Revert. * csky-tdep.c: Revert. * csky-linux-tdep.c: Revert. * cris-tdep.c: Revert. * cris-linux-tdep.c: Revert. * cp-valprint.c: Revert. * cp-support.c: Revert. * cp-namespace.c: Revert. * cp-abi.c: Revert. * corelow.c: Revert. * corefile.c: Revert. * continuations.c: Revert. * completer.h: Revert. * completer.c: Revert. * complaints.c: Revert. * coffread.c: Revert. * coff-pe-read.c: Revert. * cli-out.h: Revert. * cli-out.c: Revert. * charset.c: Revert. * c-varobj.c: Revert. * c-valprint.c: Revert. * c-typeprint.c: Revert. * c-lang.c: Revert. * buildsym.c: Revert. * buildsym-legacy.c: Revert. * build-id.h: Revert. * build-id.c: Revert. * btrace.c: Revert. * bsd-uthread.c: Revert. * breakpoint.h: Revert. * breakpoint.c: Revert. * break-catch-throw.c: Revert. * break-catch-syscall.c: Revert. * break-catch-sig.c: Revert. * blockframe.c: Revert. * block.c: Revert. * bfin-tdep.c: Revert. * bfin-linux-tdep.c: Revert. * bfd-target.c: Revert. * bcache.c: Revert. * ax-general.c: Revert. * ax-gdb.h: Revert. * ax-gdb.c: Revert. * avr-tdep.c: Revert. * auxv.c: Revert. * auto-load.c: Revert. * arm-wince-tdep.c: Revert. * arm-tdep.c: Revert. * arm-symbian-tdep.c: Revert. * arm-pikeos-tdep.c: Revert. * arm-obsd-tdep.c: Revert. * arm-nbsd-tdep.c: Revert. * arm-nbsd-nat.c: Revert. * arm-linux-tdep.c: Revert. * arm-linux-nat.c: Revert. * arm-fbsd-tdep.c: Revert. * arm-fbsd-nat.c: Revert. * arm-bsd-tdep.c: Revert. * arch-utils.c: Revert. * arc-tdep.c: Revert. * arc-newlib-tdep.c: Revert. * annotate.h: Revert. * annotate.c: Revert. * amd64-windows-tdep.c: Revert. * amd64-windows-nat.c: Revert. * amd64-tdep.c: Revert. * amd64-sol2-tdep.c: Revert. * amd64-obsd-tdep.c: Revert. * amd64-obsd-nat.c: Revert. * amd64-nbsd-tdep.c: Revert. * amd64-nbsd-nat.c: Revert. * amd64-nat.c: Revert. * amd64-linux-tdep.c: Revert. * amd64-linux-nat.c: Revert. * amd64-fbsd-tdep.c: Revert. * amd64-fbsd-nat.c: Revert. * amd64-dicos-tdep.c: Revert. * amd64-darwin-tdep.c: Revert. * amd64-bsd-nat.c: Revert. * alpha-tdep.c: Revert. * alpha-obsd-tdep.c: Revert. * alpha-nbsd-tdep.c: Revert. * alpha-mdebug-tdep.c: Revert. * alpha-linux-tdep.c: Revert. * alpha-linux-nat.c: Revert. * alpha-bsd-tdep.c: Revert. * alpha-bsd-nat.c: Revert. * aix-thread.c: Revert. * agent.c: Revert. * addrmap.c: Revert. * ada-varobj.c: Revert. * ada-valprint.c: Revert. * ada-typeprint.c: Revert. * ada-tasks.c: Revert. * ada-lang.c: Revert. * aarch64-tdep.c: Revert. * aarch64-ravenscar-thread.c: Revert. * aarch64-newlib-tdep.c: Revert. * aarch64-linux-tdep.c: Revert. * aarch64-linux-nat.c: Revert. * aarch64-fbsd-tdep.c: Revert. * aarch64-fbsd-nat.c: Revert. * aarch32-linux-nat.c: Revert.
2019-04-07 03:38:10 +08:00
#include "language.h"
#include "varobj.h"
#include "gdbcore.h"
#include "f-lang.h"
#include "valprint.h"
#include "value.h"
Revert the header-sorting patch Andreas Schwab and John Baldwin pointed out some bugs in the header sorting patch; and I noticed that the output was not correct when limited to a subset of files (a bug in my script). So, I'm reverting the patch. I may try again after fixing the issues pointed out. gdb/ChangeLog 2019-04-05 Tom Tromey <tom@tromey.com> Revert the header-sorting patch. * ft32-tdep.c: Revert. * frv-tdep.c: Revert. * frv-linux-tdep.c: Revert. * frame.c: Revert. * frame-unwind.c: Revert. * frame-base.c: Revert. * fork-child.c: Revert. * findvar.c: Revert. * findcmd.c: Revert. * filesystem.c: Revert. * filename-seen-cache.h: Revert. * filename-seen-cache.c: Revert. * fbsd-tdep.c: Revert. * fbsd-nat.h: Revert. * fbsd-nat.c: Revert. * f-valprint.c: Revert. * f-typeprint.c: Revert. * f-lang.c: Revert. * extension.h: Revert. * extension.c: Revert. * extension-priv.h: Revert. * expprint.c: Revert. * exec.h: Revert. * exec.c: Revert. * exceptions.c: Revert. * event-top.c: Revert. * event-loop.c: Revert. * eval.c: Revert. * elfread.c: Revert. * dwarf2read.h: Revert. * dwarf2read.c: Revert. * dwarf2loc.c: Revert. * dwarf2expr.h: Revert. * dwarf2expr.c: Revert. * dwarf2-frame.c: Revert. * dwarf2-frame-tailcall.c: Revert. * dwarf-index-write.h: Revert. * dwarf-index-write.c: Revert. * dwarf-index-common.c: Revert. * dwarf-index-cache.h: Revert. * dwarf-index-cache.c: Revert. * dummy-frame.c: Revert. * dtrace-probe.c: Revert. * disasm.h: Revert. * disasm.c: Revert. * disasm-selftests.c: Revert. * dictionary.c: Revert. * dicos-tdep.c: Revert. * demangle.c: Revert. * dcache.h: Revert. * dcache.c: Revert. * darwin-nat.h: Revert. * darwin-nat.c: Revert. * darwin-nat-info.c: Revert. * d-valprint.c: Revert. * d-namespace.c: Revert. * d-lang.c: Revert. * ctf.c: Revert. * csky-tdep.c: Revert. * csky-linux-tdep.c: Revert. * cris-tdep.c: Revert. * cris-linux-tdep.c: Revert. * cp-valprint.c: Revert. * cp-support.c: Revert. * cp-namespace.c: Revert. * cp-abi.c: Revert. * corelow.c: Revert. * corefile.c: Revert. * continuations.c: Revert. * completer.h: Revert. * completer.c: Revert. * complaints.c: Revert. * coffread.c: Revert. * coff-pe-read.c: Revert. * cli-out.h: Revert. * cli-out.c: Revert. * charset.c: Revert. * c-varobj.c: Revert. * c-valprint.c: Revert. * c-typeprint.c: Revert. * c-lang.c: Revert. * buildsym.c: Revert. * buildsym-legacy.c: Revert. * build-id.h: Revert. * build-id.c: Revert. * btrace.c: Revert. * bsd-uthread.c: Revert. * breakpoint.h: Revert. * breakpoint.c: Revert. * break-catch-throw.c: Revert. * break-catch-syscall.c: Revert. * break-catch-sig.c: Revert. * blockframe.c: Revert. * block.c: Revert. * bfin-tdep.c: Revert. * bfin-linux-tdep.c: Revert. * bfd-target.c: Revert. * bcache.c: Revert. * ax-general.c: Revert. * ax-gdb.h: Revert. * ax-gdb.c: Revert. * avr-tdep.c: Revert. * auxv.c: Revert. * auto-load.c: Revert. * arm-wince-tdep.c: Revert. * arm-tdep.c: Revert. * arm-symbian-tdep.c: Revert. * arm-pikeos-tdep.c: Revert. * arm-obsd-tdep.c: Revert. * arm-nbsd-tdep.c: Revert. * arm-nbsd-nat.c: Revert. * arm-linux-tdep.c: Revert. * arm-linux-nat.c: Revert. * arm-fbsd-tdep.c: Revert. * arm-fbsd-nat.c: Revert. * arm-bsd-tdep.c: Revert. * arch-utils.c: Revert. * arc-tdep.c: Revert. * arc-newlib-tdep.c: Revert. * annotate.h: Revert. * annotate.c: Revert. * amd64-windows-tdep.c: Revert. * amd64-windows-nat.c: Revert. * amd64-tdep.c: Revert. * amd64-sol2-tdep.c: Revert. * amd64-obsd-tdep.c: Revert. * amd64-obsd-nat.c: Revert. * amd64-nbsd-tdep.c: Revert. * amd64-nbsd-nat.c: Revert. * amd64-nat.c: Revert. * amd64-linux-tdep.c: Revert. * amd64-linux-nat.c: Revert. * amd64-fbsd-tdep.c: Revert. * amd64-fbsd-nat.c: Revert. * amd64-dicos-tdep.c: Revert. * amd64-darwin-tdep.c: Revert. * amd64-bsd-nat.c: Revert. * alpha-tdep.c: Revert. * alpha-obsd-tdep.c: Revert. * alpha-nbsd-tdep.c: Revert. * alpha-mdebug-tdep.c: Revert. * alpha-linux-tdep.c: Revert. * alpha-linux-nat.c: Revert. * alpha-bsd-tdep.c: Revert. * alpha-bsd-nat.c: Revert. * aix-thread.c: Revert. * agent.c: Revert. * addrmap.c: Revert. * ada-varobj.c: Revert. * ada-valprint.c: Revert. * ada-typeprint.c: Revert. * ada-tasks.c: Revert. * ada-lang.c: Revert. * aarch64-tdep.c: Revert. * aarch64-ravenscar-thread.c: Revert. * aarch64-newlib-tdep.c: Revert. * aarch64-linux-tdep.c: Revert. * aarch64-linux-nat.c: Revert. * aarch64-fbsd-tdep.c: Revert. * aarch64-fbsd-nat.c: Revert. * aarch32-linux-nat.c: Revert.
2019-04-07 03:38:10 +08:00
#include "cp-support.h"
#include "charset.h"
#include "c-lang.h"
#include "target-float.h"
Don't include gdbarch.h from defs.h I touched symtab.h and was surprised to see how many files were rebuilt. I looked into it a bit, and found that defs.h includes gdbarch.h, which in turn includes many things. gdbarch.h is only needed by a minority ofthe files in gdb, so this patch removes the include from defs.h and updates the fallout. I did "wc -l" on the files in build/gdb/.deps; this patch reduces the line count from 139935 to 137030; so there are definitely future build-time savings here. Note that while I configured with --enable-targets=all, it's possible that some *-nat.c file needs an update. I could not test all of these. The buildbot caught a few problems along these lines. gdb/ChangeLog 2019-07-10 Tom Tromey <tom@tromey.com> * defs.h: Don't include gdbarch.h. * aarch64-ravenscar-thread.c, aarch64-tdep.c, alpha-bsd-tdep.h, alpha-linux-tdep.c, alpha-mdebug-tdep.c, arch-utils.h, arm-tdep.h, ax-general.c, btrace.c, buildsym-legacy.c, buildsym.h, c-lang.c, cli/cli-decode.h, cli/cli-dump.c, cli/cli-script.h, cli/cli-style.h, coff-pe-read.h, compile/compile-c-support.c, compile/compile-cplus.h, compile/compile-loc2c.c, corefile.c, cp-valprint.c, cris-linux-tdep.c, ctf.c, d-lang.c, d-namespace.c, dcache.c, dicos-tdep.c, dictionary.c, disasm-selftests.c, dummy-frame.c, dummy-frame.h, dwarf2-frame-tailcall.c, dwarf2expr.c, expression.h, f-lang.c, frame-base.c, frame-unwind.c, frv-linux-tdep.c, gdbarch-selftests.c, gdbtypes.h, go-lang.c, hppa-nbsd-tdep.c, hppa-obsd-tdep.c, i386-dicos-tdep.c, i386-tdep.h, ia64-vms-tdep.c, interps.h, language.c, linux-record.c, location.h, m2-lang.c, m32r-linux-tdep.c, mem-break.c, memattr.c, mn10300-linux-tdep.c, nios2-linux-tdep.c, objfiles.h, opencl-lang.c, or1k-linux-tdep.c, p-lang.c, parser-defs.h, ppc-tdep.h, probe.h, python/py-record-btrace.c, record-btrace.c, record.h, regcache-dump.c, regcache.h, riscv-fbsd-tdep.c, riscv-linux-tdep.c, rust-exp.y, sh-linux-tdep.c, sh-nbsd-tdep.c, source-cache.c, sparc-nbsd-tdep.c, sparc-obsd-tdep.c, sparc-ravenscar-thread.c, sparc64-fbsd-tdep.c, std-regs.c, target-descriptions.h, target-float.c, tic6x-linux-tdep.c, tilegx-linux-tdep.c, top.c, tracefile.c, trad-frame.c, type-stack.h, ui-style.c, utils.c, utils.h, valarith.c, valprint.c, varobj.c, x86-tdep.c, xml-support.h, xtensa-linux-tdep.c, cli/cli-cmds.h: Update. * s390-linux-nat.c, procfs.c, inf-ptrace.c: Likewise.
2019-06-10 05:21:02 +08:00
#include "gdbarch.h"
#include "cli/cli-cmds.h"
gdb/fortran: Add support for Fortran array slices at the GDB prompt This commit brings array slice support to GDB. WARNING: This patch contains a rather big hack which is limited to Fortran arrays, this can be seen in gdbtypes.c and f-lang.c. More details on this below. This patch rewrites two areas of GDB's Fortran support, the code to extract an array slice, and the code to print an array. After this commit a user can, from the GDB prompt, ask for a slice of a Fortran array and should get the correct result back. Slices can (optionally) have the lower bound, upper bound, and a stride specified. Slices can also have a negative stride. Fortran has the concept of repacking array slices. Within a compiled Fortran program if a user passes a non-contiguous array slice to a function then the compiler may have to repack the slice, this involves copying the elements of the slice to a new area of memory before the call, and copying the elements back to the original array after the call. Whether repacking occurs will depend on which version of Fortran is being used, and what type of function is being called. This commit adds support for both packed, and unpacked array slicing, with the default being unpacked. With an unpacked array slice, when the user asks for a slice of an array GDB creates a new type that accurately describes where the elements of the slice can be found within the original array, a value of this type is then returned to the user. The address of an element within the slice will be equal to the address of an element within the original array. A user can choose to select packed array slices instead using: (gdb) set fortran repack-array-slices on|off (gdb) show fortran repack-array-slices With packed array slices GDB creates a new type that reflects how the elements of the slice would look if they were laid out in contiguous memory, allocates a value of this type, and then fetches the elements from the original array and places then into the contents buffer of the new value. One benefit of using packed slices over unpacked slices is the memory usage, taking a small slice of N elements from a large array will require (in GDB) N * ELEMENT_SIZE bytes of memory, while an unpacked array will also include all of the "padding" between the non-contiguous elements. There are new tests added that highlight this difference. There is also a new debugging flag added with this commit that introduces these commands: (gdb) set debug fortran-array-slicing on|off (gdb) show debug fortran-array-slicing This prints information about how the array slices are being built. As both the repacking, and the array printing requires GDB to walk through a multi-dimensional Fortran array visiting each element, this commit adds the file f-array-walk.h, which introduces some infrastructure to support this process. This means the array printing code in f-valprint.c is significantly reduced. The only slight issue with this commit is the "rather big hack" that I mentioned above. This hack allows us to handle one specific case, array slices with negative strides. This is something that I don't believe the current GDB value contents model will allow us to correctly handle, and rather than rewrite the value contents code right now, I'm hoping to slip this hack in as a work around. The problem is that, as I see it, the current value contents model assumes that an object base address will be the lowest address within that object, and that the contents of the object start at this base address and occupy the TYPE_LENGTH bytes after that. ( We do have the embedded_offset, which is used for C++ sub-classes, such that an object can start at some offset from the content buffer, however, the assumption that the object then occupies the next TYPE_LENGTH bytes is still true within GDB. ) The problem is that Fortran arrays with a negative stride don't follow this pattern. In this case the base address of the object points to the element with the highest address, the contents of the array then start at some offset _before_ the base address, and proceed for one element _past_ the base address. As the stride for such an array would be negative then, in theory the TYPE_LENGTH for this type would also be negative. However, in many places a value in GDB will degrade to a pointer + length, and the length almost always comes from the TYPE_LENGTH. It is my belief that in order to correctly model this case the value content handling of GDB will need to be reworked to split apart the value's content buffer (which is a block of memory with a length), and the object's in memory base address and length, which could be negative. Things are further complicated because arrays with negative strides like this are always dynamic types. When a value has a dynamic type and its base address needs resolving we actually store the address of the object within the resolved dynamic type, not within the value object itself. In short I don't currently see an easy path to cleanly support this situation within GDB. And so I believe that leaves two options, either add a work around, or catch cases where the user tries to make use of a negative stride, or access an array with a negative stride, and throw an error. This patch currently goes with adding a work around, which is that when we resolve a dynamic Fortran array type, if the stride is negative, then we adjust the base address to point to the lowest address required by the array. The printing and slicing code is aware of this adjustment and will correctly slice and print Fortran arrays. Where this hack will show through to the user is if they ask for the address of an array in their program with a negative array stride, the address they get from GDB will not match the address that would be computed within the Fortran program. gdb/ChangeLog: * Makefile.in (HFILES_NO_SRCDIR): Add f-array-walker.h. * NEWS: Mention new options. * f-array-walker.h: New file. * f-lang.c: Include 'gdbcmd.h' and 'f-array-walker.h'. (repack_array_slices): New static global. (show_repack_array_slices): New function. (fortran_array_slicing_debug): New static global. (show_fortran_array_slicing_debug): New function. (value_f90_subarray): Delete. (skip_undetermined_arglist): Delete. (class fortran_array_repacker_base_impl): New class. (class fortran_lazy_array_repacker_impl): New class. (class fortran_array_repacker_impl): New class. (fortran_value_subarray): Complete rewrite. (set_fortran_list): New static global. (show_fortran_list): Likewise. (_initialize_f_language): Register new commands. (fortran_adjust_dynamic_array_base_address_hack): New function. * f-lang.h (fortran_adjust_dynamic_array_base_address_hack): Declare. * f-valprint.c: Include 'f-array-walker.h'. (class fortran_array_printer_impl): New class. (f77_print_array_1): Delete. (f77_print_array): Delete. (fortran_print_array): New. (f_value_print_inner): Update to call fortran_print_array. * gdbtypes.c: Include 'f-lang.h'. (resolve_dynamic_type_internal): Call fortran_adjust_dynamic_array_base_address_hack. gdb/testsuite/ChangeLog: * gdb.fortran/array-slices-bad.exp: New file. * gdb.fortran/array-slices-bad.f90: New file. * gdb.fortran/array-slices-sub-slices.exp: New file. * gdb.fortran/array-slices-sub-slices.f90: New file. * gdb.fortran/array-slices.exp: Rewrite tests. * gdb.fortran/array-slices.f90: Rewrite tests. * gdb.fortran/vla-sizeof.exp: Correct expected results. gdb/doc/ChangeLog: * gdb.texinfo (Debugging Output): Document 'set/show debug fortran-array-slicing'. (Special Fortran Commands): Document 'set/show fortran repack-array-slices'.
2020-10-08 23:45:59 +08:00
#include "f-array-walker.h"
#include "f-exp.h"
Revert the header-sorting patch Andreas Schwab and John Baldwin pointed out some bugs in the header sorting patch; and I noticed that the output was not correct when limited to a subset of files (a bug in my script). So, I'm reverting the patch. I may try again after fixing the issues pointed out. gdb/ChangeLog 2019-04-05 Tom Tromey <tom@tromey.com> Revert the header-sorting patch. * ft32-tdep.c: Revert. * frv-tdep.c: Revert. * frv-linux-tdep.c: Revert. * frame.c: Revert. * frame-unwind.c: Revert. * frame-base.c: Revert. * fork-child.c: Revert. * findvar.c: Revert. * findcmd.c: Revert. * filesystem.c: Revert. * filename-seen-cache.h: Revert. * filename-seen-cache.c: Revert. * fbsd-tdep.c: Revert. * fbsd-nat.h: Revert. * fbsd-nat.c: Revert. * f-valprint.c: Revert. * f-typeprint.c: Revert. * f-lang.c: Revert. * extension.h: Revert. * extension.c: Revert. * extension-priv.h: Revert. * expprint.c: Revert. * exec.h: Revert. * exec.c: Revert. * exceptions.c: Revert. * event-top.c: Revert. * event-loop.c: Revert. * eval.c: Revert. * elfread.c: Revert. * dwarf2read.h: Revert. * dwarf2read.c: Revert. * dwarf2loc.c: Revert. * dwarf2expr.h: Revert. * dwarf2expr.c: Revert. * dwarf2-frame.c: Revert. * dwarf2-frame-tailcall.c: Revert. * dwarf-index-write.h: Revert. * dwarf-index-write.c: Revert. * dwarf-index-common.c: Revert. * dwarf-index-cache.h: Revert. * dwarf-index-cache.c: Revert. * dummy-frame.c: Revert. * dtrace-probe.c: Revert. * disasm.h: Revert. * disasm.c: Revert. * disasm-selftests.c: Revert. * dictionary.c: Revert. * dicos-tdep.c: Revert. * demangle.c: Revert. * dcache.h: Revert. * dcache.c: Revert. * darwin-nat.h: Revert. * darwin-nat.c: Revert. * darwin-nat-info.c: Revert. * d-valprint.c: Revert. * d-namespace.c: Revert. * d-lang.c: Revert. * ctf.c: Revert. * csky-tdep.c: Revert. * csky-linux-tdep.c: Revert. * cris-tdep.c: Revert. * cris-linux-tdep.c: Revert. * cp-valprint.c: Revert. * cp-support.c: Revert. * cp-namespace.c: Revert. * cp-abi.c: Revert. * corelow.c: Revert. * corefile.c: Revert. * continuations.c: Revert. * completer.h: Revert. * completer.c: Revert. * complaints.c: Revert. * coffread.c: Revert. * coff-pe-read.c: Revert. * cli-out.h: Revert. * cli-out.c: Revert. * charset.c: Revert. * c-varobj.c: Revert. * c-valprint.c: Revert. * c-typeprint.c: Revert. * c-lang.c: Revert. * buildsym.c: Revert. * buildsym-legacy.c: Revert. * build-id.h: Revert. * build-id.c: Revert. * btrace.c: Revert. * bsd-uthread.c: Revert. * breakpoint.h: Revert. * breakpoint.c: Revert. * break-catch-throw.c: Revert. * break-catch-syscall.c: Revert. * break-catch-sig.c: Revert. * blockframe.c: Revert. * block.c: Revert. * bfin-tdep.c: Revert. * bfin-linux-tdep.c: Revert. * bfd-target.c: Revert. * bcache.c: Revert. * ax-general.c: Revert. * ax-gdb.h: Revert. * ax-gdb.c: Revert. * avr-tdep.c: Revert. * auxv.c: Revert. * auto-load.c: Revert. * arm-wince-tdep.c: Revert. * arm-tdep.c: Revert. * arm-symbian-tdep.c: Revert. * arm-pikeos-tdep.c: Revert. * arm-obsd-tdep.c: Revert. * arm-nbsd-tdep.c: Revert. * arm-nbsd-nat.c: Revert. * arm-linux-tdep.c: Revert. * arm-linux-nat.c: Revert. * arm-fbsd-tdep.c: Revert. * arm-fbsd-nat.c: Revert. * arm-bsd-tdep.c: Revert. * arch-utils.c: Revert. * arc-tdep.c: Revert. * arc-newlib-tdep.c: Revert. * annotate.h: Revert. * annotate.c: Revert. * amd64-windows-tdep.c: Revert. * amd64-windows-nat.c: Revert. * amd64-tdep.c: Revert. * amd64-sol2-tdep.c: Revert. * amd64-obsd-tdep.c: Revert. * amd64-obsd-nat.c: Revert. * amd64-nbsd-tdep.c: Revert. * amd64-nbsd-nat.c: Revert. * amd64-nat.c: Revert. * amd64-linux-tdep.c: Revert. * amd64-linux-nat.c: Revert. * amd64-fbsd-tdep.c: Revert. * amd64-fbsd-nat.c: Revert. * amd64-dicos-tdep.c: Revert. * amd64-darwin-tdep.c: Revert. * amd64-bsd-nat.c: Revert. * alpha-tdep.c: Revert. * alpha-obsd-tdep.c: Revert. * alpha-nbsd-tdep.c: Revert. * alpha-mdebug-tdep.c: Revert. * alpha-linux-tdep.c: Revert. * alpha-linux-nat.c: Revert. * alpha-bsd-tdep.c: Revert. * alpha-bsd-nat.c: Revert. * aix-thread.c: Revert. * agent.c: Revert. * addrmap.c: Revert. * ada-varobj.c: Revert. * ada-valprint.c: Revert. * ada-typeprint.c: Revert. * ada-tasks.c: Revert. * ada-lang.c: Revert. * aarch64-tdep.c: Revert. * aarch64-ravenscar-thread.c: Revert. * aarch64-newlib-tdep.c: Revert. * aarch64-linux-tdep.c: Revert. * aarch64-linux-nat.c: Revert. * aarch64-fbsd-tdep.c: Revert. * aarch64-fbsd-nat.c: Revert. * aarch32-linux-nat.c: Revert.
2019-04-07 03:38:10 +08:00
#include <math.h>
gdb/fortran: Add support for Fortran array slices at the GDB prompt This commit brings array slice support to GDB. WARNING: This patch contains a rather big hack which is limited to Fortran arrays, this can be seen in gdbtypes.c and f-lang.c. More details on this below. This patch rewrites two areas of GDB's Fortran support, the code to extract an array slice, and the code to print an array. After this commit a user can, from the GDB prompt, ask for a slice of a Fortran array and should get the correct result back. Slices can (optionally) have the lower bound, upper bound, and a stride specified. Slices can also have a negative stride. Fortran has the concept of repacking array slices. Within a compiled Fortran program if a user passes a non-contiguous array slice to a function then the compiler may have to repack the slice, this involves copying the elements of the slice to a new area of memory before the call, and copying the elements back to the original array after the call. Whether repacking occurs will depend on which version of Fortran is being used, and what type of function is being called. This commit adds support for both packed, and unpacked array slicing, with the default being unpacked. With an unpacked array slice, when the user asks for a slice of an array GDB creates a new type that accurately describes where the elements of the slice can be found within the original array, a value of this type is then returned to the user. The address of an element within the slice will be equal to the address of an element within the original array. A user can choose to select packed array slices instead using: (gdb) set fortran repack-array-slices on|off (gdb) show fortran repack-array-slices With packed array slices GDB creates a new type that reflects how the elements of the slice would look if they were laid out in contiguous memory, allocates a value of this type, and then fetches the elements from the original array and places then into the contents buffer of the new value. One benefit of using packed slices over unpacked slices is the memory usage, taking a small slice of N elements from a large array will require (in GDB) N * ELEMENT_SIZE bytes of memory, while an unpacked array will also include all of the "padding" between the non-contiguous elements. There are new tests added that highlight this difference. There is also a new debugging flag added with this commit that introduces these commands: (gdb) set debug fortran-array-slicing on|off (gdb) show debug fortran-array-slicing This prints information about how the array slices are being built. As both the repacking, and the array printing requires GDB to walk through a multi-dimensional Fortran array visiting each element, this commit adds the file f-array-walk.h, which introduces some infrastructure to support this process. This means the array printing code in f-valprint.c is significantly reduced. The only slight issue with this commit is the "rather big hack" that I mentioned above. This hack allows us to handle one specific case, array slices with negative strides. This is something that I don't believe the current GDB value contents model will allow us to correctly handle, and rather than rewrite the value contents code right now, I'm hoping to slip this hack in as a work around. The problem is that, as I see it, the current value contents model assumes that an object base address will be the lowest address within that object, and that the contents of the object start at this base address and occupy the TYPE_LENGTH bytes after that. ( We do have the embedded_offset, which is used for C++ sub-classes, such that an object can start at some offset from the content buffer, however, the assumption that the object then occupies the next TYPE_LENGTH bytes is still true within GDB. ) The problem is that Fortran arrays with a negative stride don't follow this pattern. In this case the base address of the object points to the element with the highest address, the contents of the array then start at some offset _before_ the base address, and proceed for one element _past_ the base address. As the stride for such an array would be negative then, in theory the TYPE_LENGTH for this type would also be negative. However, in many places a value in GDB will degrade to a pointer + length, and the length almost always comes from the TYPE_LENGTH. It is my belief that in order to correctly model this case the value content handling of GDB will need to be reworked to split apart the value's content buffer (which is a block of memory with a length), and the object's in memory base address and length, which could be negative. Things are further complicated because arrays with negative strides like this are always dynamic types. When a value has a dynamic type and its base address needs resolving we actually store the address of the object within the resolved dynamic type, not within the value object itself. In short I don't currently see an easy path to cleanly support this situation within GDB. And so I believe that leaves two options, either add a work around, or catch cases where the user tries to make use of a negative stride, or access an array with a negative stride, and throw an error. This patch currently goes with adding a work around, which is that when we resolve a dynamic Fortran array type, if the stride is negative, then we adjust the base address to point to the lowest address required by the array. The printing and slicing code is aware of this adjustment and will correctly slice and print Fortran arrays. Where this hack will show through to the user is if they ask for the address of an array in their program with a negative array stride, the address they get from GDB will not match the address that would be computed within the Fortran program. gdb/ChangeLog: * Makefile.in (HFILES_NO_SRCDIR): Add f-array-walker.h. * NEWS: Mention new options. * f-array-walker.h: New file. * f-lang.c: Include 'gdbcmd.h' and 'f-array-walker.h'. (repack_array_slices): New static global. (show_repack_array_slices): New function. (fortran_array_slicing_debug): New static global. (show_fortran_array_slicing_debug): New function. (value_f90_subarray): Delete. (skip_undetermined_arglist): Delete. (class fortran_array_repacker_base_impl): New class. (class fortran_lazy_array_repacker_impl): New class. (class fortran_array_repacker_impl): New class. (fortran_value_subarray): Complete rewrite. (set_fortran_list): New static global. (show_fortran_list): Likewise. (_initialize_f_language): Register new commands. (fortran_adjust_dynamic_array_base_address_hack): New function. * f-lang.h (fortran_adjust_dynamic_array_base_address_hack): Declare. * f-valprint.c: Include 'f-array-walker.h'. (class fortran_array_printer_impl): New class. (f77_print_array_1): Delete. (f77_print_array): Delete. (fortran_print_array): New. (f_value_print_inner): Update to call fortran_print_array. * gdbtypes.c: Include 'f-lang.h'. (resolve_dynamic_type_internal): Call fortran_adjust_dynamic_array_base_address_hack. gdb/testsuite/ChangeLog: * gdb.fortran/array-slices-bad.exp: New file. * gdb.fortran/array-slices-bad.f90: New file. * gdb.fortran/array-slices-sub-slices.exp: New file. * gdb.fortran/array-slices-sub-slices.f90: New file. * gdb.fortran/array-slices.exp: Rewrite tests. * gdb.fortran/array-slices.f90: Rewrite tests. * gdb.fortran/vla-sizeof.exp: Correct expected results. gdb/doc/ChangeLog: * gdb.texinfo (Debugging Output): Document 'set/show debug fortran-array-slicing'. (Special Fortran Commands): Document 'set/show fortran repack-array-slices'.
2020-10-08 23:45:59 +08:00
/* Whether GDB should repack array slices created by the user. */
static bool repack_array_slices = false;
/* Implement 'show fortran repack-array-slices'. */
static void
show_repack_array_slices (struct ui_file *file, int from_tty,
struct cmd_list_element *c, const char *value)
{
gdb_printf (file, _("Repacking of Fortran array slices is %s.\n"),
value);
gdb/fortran: Add support for Fortran array slices at the GDB prompt This commit brings array slice support to GDB. WARNING: This patch contains a rather big hack which is limited to Fortran arrays, this can be seen in gdbtypes.c and f-lang.c. More details on this below. This patch rewrites two areas of GDB's Fortran support, the code to extract an array slice, and the code to print an array. After this commit a user can, from the GDB prompt, ask for a slice of a Fortran array and should get the correct result back. Slices can (optionally) have the lower bound, upper bound, and a stride specified. Slices can also have a negative stride. Fortran has the concept of repacking array slices. Within a compiled Fortran program if a user passes a non-contiguous array slice to a function then the compiler may have to repack the slice, this involves copying the elements of the slice to a new area of memory before the call, and copying the elements back to the original array after the call. Whether repacking occurs will depend on which version of Fortran is being used, and what type of function is being called. This commit adds support for both packed, and unpacked array slicing, with the default being unpacked. With an unpacked array slice, when the user asks for a slice of an array GDB creates a new type that accurately describes where the elements of the slice can be found within the original array, a value of this type is then returned to the user. The address of an element within the slice will be equal to the address of an element within the original array. A user can choose to select packed array slices instead using: (gdb) set fortran repack-array-slices on|off (gdb) show fortran repack-array-slices With packed array slices GDB creates a new type that reflects how the elements of the slice would look if they were laid out in contiguous memory, allocates a value of this type, and then fetches the elements from the original array and places then into the contents buffer of the new value. One benefit of using packed slices over unpacked slices is the memory usage, taking a small slice of N elements from a large array will require (in GDB) N * ELEMENT_SIZE bytes of memory, while an unpacked array will also include all of the "padding" between the non-contiguous elements. There are new tests added that highlight this difference. There is also a new debugging flag added with this commit that introduces these commands: (gdb) set debug fortran-array-slicing on|off (gdb) show debug fortran-array-slicing This prints information about how the array slices are being built. As both the repacking, and the array printing requires GDB to walk through a multi-dimensional Fortran array visiting each element, this commit adds the file f-array-walk.h, which introduces some infrastructure to support this process. This means the array printing code in f-valprint.c is significantly reduced. The only slight issue with this commit is the "rather big hack" that I mentioned above. This hack allows us to handle one specific case, array slices with negative strides. This is something that I don't believe the current GDB value contents model will allow us to correctly handle, and rather than rewrite the value contents code right now, I'm hoping to slip this hack in as a work around. The problem is that, as I see it, the current value contents model assumes that an object base address will be the lowest address within that object, and that the contents of the object start at this base address and occupy the TYPE_LENGTH bytes after that. ( We do have the embedded_offset, which is used for C++ sub-classes, such that an object can start at some offset from the content buffer, however, the assumption that the object then occupies the next TYPE_LENGTH bytes is still true within GDB. ) The problem is that Fortran arrays with a negative stride don't follow this pattern. In this case the base address of the object points to the element with the highest address, the contents of the array then start at some offset _before_ the base address, and proceed for one element _past_ the base address. As the stride for such an array would be negative then, in theory the TYPE_LENGTH for this type would also be negative. However, in many places a value in GDB will degrade to a pointer + length, and the length almost always comes from the TYPE_LENGTH. It is my belief that in order to correctly model this case the value content handling of GDB will need to be reworked to split apart the value's content buffer (which is a block of memory with a length), and the object's in memory base address and length, which could be negative. Things are further complicated because arrays with negative strides like this are always dynamic types. When a value has a dynamic type and its base address needs resolving we actually store the address of the object within the resolved dynamic type, not within the value object itself. In short I don't currently see an easy path to cleanly support this situation within GDB. And so I believe that leaves two options, either add a work around, or catch cases where the user tries to make use of a negative stride, or access an array with a negative stride, and throw an error. This patch currently goes with adding a work around, which is that when we resolve a dynamic Fortran array type, if the stride is negative, then we adjust the base address to point to the lowest address required by the array. The printing and slicing code is aware of this adjustment and will correctly slice and print Fortran arrays. Where this hack will show through to the user is if they ask for the address of an array in their program with a negative array stride, the address they get from GDB will not match the address that would be computed within the Fortran program. gdb/ChangeLog: * Makefile.in (HFILES_NO_SRCDIR): Add f-array-walker.h. * NEWS: Mention new options. * f-array-walker.h: New file. * f-lang.c: Include 'gdbcmd.h' and 'f-array-walker.h'. (repack_array_slices): New static global. (show_repack_array_slices): New function. (fortran_array_slicing_debug): New static global. (show_fortran_array_slicing_debug): New function. (value_f90_subarray): Delete. (skip_undetermined_arglist): Delete. (class fortran_array_repacker_base_impl): New class. (class fortran_lazy_array_repacker_impl): New class. (class fortran_array_repacker_impl): New class. (fortran_value_subarray): Complete rewrite. (set_fortran_list): New static global. (show_fortran_list): Likewise. (_initialize_f_language): Register new commands. (fortran_adjust_dynamic_array_base_address_hack): New function. * f-lang.h (fortran_adjust_dynamic_array_base_address_hack): Declare. * f-valprint.c: Include 'f-array-walker.h'. (class fortran_array_printer_impl): New class. (f77_print_array_1): Delete. (f77_print_array): Delete. (fortran_print_array): New. (f_value_print_inner): Update to call fortran_print_array. * gdbtypes.c: Include 'f-lang.h'. (resolve_dynamic_type_internal): Call fortran_adjust_dynamic_array_base_address_hack. gdb/testsuite/ChangeLog: * gdb.fortran/array-slices-bad.exp: New file. * gdb.fortran/array-slices-bad.f90: New file. * gdb.fortran/array-slices-sub-slices.exp: New file. * gdb.fortran/array-slices-sub-slices.f90: New file. * gdb.fortran/array-slices.exp: Rewrite tests. * gdb.fortran/array-slices.f90: Rewrite tests. * gdb.fortran/vla-sizeof.exp: Correct expected results. gdb/doc/ChangeLog: * gdb.texinfo (Debugging Output): Document 'set/show debug fortran-array-slicing'. (Special Fortran Commands): Document 'set/show fortran repack-array-slices'.
2020-10-08 23:45:59 +08:00
}
/* Debugging of Fortran's array slicing. */
static bool fortran_array_slicing_debug = false;
/* Implement 'show debug fortran-array-slicing'. */
static void
show_fortran_array_slicing_debug (struct ui_file *file, int from_tty,
struct cmd_list_element *c,
const char *value)
{
gdb_printf (file, _("Debugging of Fortran array slicing is %s.\n"),
value);
gdb/fortran: Add support for Fortran array slices at the GDB prompt This commit brings array slice support to GDB. WARNING: This patch contains a rather big hack which is limited to Fortran arrays, this can be seen in gdbtypes.c and f-lang.c. More details on this below. This patch rewrites two areas of GDB's Fortran support, the code to extract an array slice, and the code to print an array. After this commit a user can, from the GDB prompt, ask for a slice of a Fortran array and should get the correct result back. Slices can (optionally) have the lower bound, upper bound, and a stride specified. Slices can also have a negative stride. Fortran has the concept of repacking array slices. Within a compiled Fortran program if a user passes a non-contiguous array slice to a function then the compiler may have to repack the slice, this involves copying the elements of the slice to a new area of memory before the call, and copying the elements back to the original array after the call. Whether repacking occurs will depend on which version of Fortran is being used, and what type of function is being called. This commit adds support for both packed, and unpacked array slicing, with the default being unpacked. With an unpacked array slice, when the user asks for a slice of an array GDB creates a new type that accurately describes where the elements of the slice can be found within the original array, a value of this type is then returned to the user. The address of an element within the slice will be equal to the address of an element within the original array. A user can choose to select packed array slices instead using: (gdb) set fortran repack-array-slices on|off (gdb) show fortran repack-array-slices With packed array slices GDB creates a new type that reflects how the elements of the slice would look if they were laid out in contiguous memory, allocates a value of this type, and then fetches the elements from the original array and places then into the contents buffer of the new value. One benefit of using packed slices over unpacked slices is the memory usage, taking a small slice of N elements from a large array will require (in GDB) N * ELEMENT_SIZE bytes of memory, while an unpacked array will also include all of the "padding" between the non-contiguous elements. There are new tests added that highlight this difference. There is also a new debugging flag added with this commit that introduces these commands: (gdb) set debug fortran-array-slicing on|off (gdb) show debug fortran-array-slicing This prints information about how the array slices are being built. As both the repacking, and the array printing requires GDB to walk through a multi-dimensional Fortran array visiting each element, this commit adds the file f-array-walk.h, which introduces some infrastructure to support this process. This means the array printing code in f-valprint.c is significantly reduced. The only slight issue with this commit is the "rather big hack" that I mentioned above. This hack allows us to handle one specific case, array slices with negative strides. This is something that I don't believe the current GDB value contents model will allow us to correctly handle, and rather than rewrite the value contents code right now, I'm hoping to slip this hack in as a work around. The problem is that, as I see it, the current value contents model assumes that an object base address will be the lowest address within that object, and that the contents of the object start at this base address and occupy the TYPE_LENGTH bytes after that. ( We do have the embedded_offset, which is used for C++ sub-classes, such that an object can start at some offset from the content buffer, however, the assumption that the object then occupies the next TYPE_LENGTH bytes is still true within GDB. ) The problem is that Fortran arrays with a negative stride don't follow this pattern. In this case the base address of the object points to the element with the highest address, the contents of the array then start at some offset _before_ the base address, and proceed for one element _past_ the base address. As the stride for such an array would be negative then, in theory the TYPE_LENGTH for this type would also be negative. However, in many places a value in GDB will degrade to a pointer + length, and the length almost always comes from the TYPE_LENGTH. It is my belief that in order to correctly model this case the value content handling of GDB will need to be reworked to split apart the value's content buffer (which is a block of memory with a length), and the object's in memory base address and length, which could be negative. Things are further complicated because arrays with negative strides like this are always dynamic types. When a value has a dynamic type and its base address needs resolving we actually store the address of the object within the resolved dynamic type, not within the value object itself. In short I don't currently see an easy path to cleanly support this situation within GDB. And so I believe that leaves two options, either add a work around, or catch cases where the user tries to make use of a negative stride, or access an array with a negative stride, and throw an error. This patch currently goes with adding a work around, which is that when we resolve a dynamic Fortran array type, if the stride is negative, then we adjust the base address to point to the lowest address required by the array. The printing and slicing code is aware of this adjustment and will correctly slice and print Fortran arrays. Where this hack will show through to the user is if they ask for the address of an array in their program with a negative array stride, the address they get from GDB will not match the address that would be computed within the Fortran program. gdb/ChangeLog: * Makefile.in (HFILES_NO_SRCDIR): Add f-array-walker.h. * NEWS: Mention new options. * f-array-walker.h: New file. * f-lang.c: Include 'gdbcmd.h' and 'f-array-walker.h'. (repack_array_slices): New static global. (show_repack_array_slices): New function. (fortran_array_slicing_debug): New static global. (show_fortran_array_slicing_debug): New function. (value_f90_subarray): Delete. (skip_undetermined_arglist): Delete. (class fortran_array_repacker_base_impl): New class. (class fortran_lazy_array_repacker_impl): New class. (class fortran_array_repacker_impl): New class. (fortran_value_subarray): Complete rewrite. (set_fortran_list): New static global. (show_fortran_list): Likewise. (_initialize_f_language): Register new commands. (fortran_adjust_dynamic_array_base_address_hack): New function. * f-lang.h (fortran_adjust_dynamic_array_base_address_hack): Declare. * f-valprint.c: Include 'f-array-walker.h'. (class fortran_array_printer_impl): New class. (f77_print_array_1): Delete. (f77_print_array): Delete. (fortran_print_array): New. (f_value_print_inner): Update to call fortran_print_array. * gdbtypes.c: Include 'f-lang.h'. (resolve_dynamic_type_internal): Call fortran_adjust_dynamic_array_base_address_hack. gdb/testsuite/ChangeLog: * gdb.fortran/array-slices-bad.exp: New file. * gdb.fortran/array-slices-bad.f90: New file. * gdb.fortran/array-slices-sub-slices.exp: New file. * gdb.fortran/array-slices-sub-slices.f90: New file. * gdb.fortran/array-slices.exp: Rewrite tests. * gdb.fortran/array-slices.f90: Rewrite tests. * gdb.fortran/vla-sizeof.exp: Correct expected results. gdb/doc/ChangeLog: * gdb.texinfo (Debugging Output): Document 'set/show debug fortran-array-slicing'. (Special Fortran Commands): Document 'set/show fortran repack-array-slices'.
2020-10-08 23:45:59 +08:00
}
/* Local functions */
static value *fortran_prepare_argument (struct expression *exp,
expr::operation *subexp,
int arg_num, bool is_internal_call_p,
struct type *func_type, enum noside noside);
/* Return the encoding that should be used for the character type
TYPE. */
gdb: move f_language class into a header file Moves the f_language class from f-lang.c into f-lang.h. The benefit of this is that functions declared in other f-*.c files can become member functions without having to go through a level of indirection. Some additional support functions have now become private member functions of the f_language class, these are mostly functions that then called some other function that was itself a member of the language_defn class hierarchy. There should be no user visible changes after this commit. gdb/ChangeLog: * f-exp.y (f_parse): Rename to... (f_language::parser): ...this. * f-lang.c (f_get_encoding): Rename to... (f_language::get_encoding): ...this. (f_op_print_tab): Rename to... (f_language::op_print_tab): ...this. (exp_descriptor_f): Rename to... (f_language::exp_descriptor_tab): ...this. (class f_language): Moved to f-lang.h. (f_language::language_arch_info): New function, moved out of class declaration. (f_language::search_name_hash): Likewise. (f_language::lookup_symbol_nonlocal): Likewise. (f_language::get_symbol_name_matcher_inner): Likewise. * f-lang.h: Add 'valprint.h' include. (class f_language): Moved here from f-lang.c. * f-typeprint.c (f_type_print_args): Delete commented out declaration. (f_print_typedef): Rename to... (f_language::print_typedef): ...this. (f_print_type): Rename to... (f_language::print_type): ...this. (f_type_print_varspec_prefix): Delete declaration and rename to... (f_language::f_type_print_varspec_prefix): ...this. (f_type_print_varspec_suffix): Delete declaration and rename to... (f_language::f_type_print_varspec_suffix): ...this. (f_type_print_base): Delete declaration and rename to... (f_language::f_type_print_base): ...this. * f-valprint.c (f_value_print_inner): Rename to... (f_language::value_print_inner): ...this. * parse.c: Delete 'f-lang.h' include.
2020-09-16 23:27:30 +08:00
const char *
f_language::get_encoding (struct type *type)
{
const char *encoding;
switch (type->length ())
{
case 1:
encoding = target_charset (type->arch ());
break;
case 4:
Adjust byte order variable display/change if DW_AT_endianity is present. - Rationale: It is possible for compilers to indicate the desired byte order interpretation of scalar variables using the DWARF attribute: DW_AT_endianity A type flagged with this variable would typically use one of: DW_END_big DW_END_little which instructs the debugger what the desired byte order interpretation of the variable should be. The GCC compiler (as of V6) has a mechanism for setting the desired byte ordering of the fields within a structure or union. For, example, on a little endian target, a structure declared as: struct big { int v; short a[4]; } __attribute__( ( scalar_storage_order( "big-endian" ) ) ); could be used to ensure all the structure members have a big-endian interpretation (the compiler would automatically insert byte swap instructions before and after respective store and load instructions). - To reproduce GCC V8 is required to correctly emit DW_AT_endianity DWARF attributes in all situations when the scalar_storage_order attribute is used. A fix for (dwarf endianity instrumentation) for GCC V6-V7 can be found in the URL field of the following PR: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82509 - Test-case: A new test case (testsuite/gdb.base/endianity.*) is included with this patch. Manual testing for mixed endianity code has also been done with GCC V8. See: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82509#c4 - Observed vs. expected: Without this change, using scalar_storage_order that doesn't match the target, such as struct otherendian { int v; } __attribute__( ( scalar_storage_order( "big-endian" ) ) ); would behave like the following on a little endian target: Breakpoint 1 at 0x401135: file endianity.c, line 41. (gdb) run Starting program: /home/pjoot/freeware/t/a.out Missing separate debuginfos, use: debuginfo-install glibc-2.17-292.el7.x86_64 Breakpoint 1, main () at endianity.c:41 41 struct otherendian o = {3}; (gdb) n 43 do_nothing (&o); /* START */ (gdb) p o $1 = {v = 50331648} (gdb) p /x $2 = {v = 0x3000000} whereas with this gdb enhancement we can access the variable with the user specified endianity: Breakpoint 1, main () at endianity.c:41 41 struct otherendian o = {3}; (gdb) p o $1 = {v = 0} (gdb) n 43 do_nothing (&o); /* START */ (gdb) p o $2 = {v = 3} (gdb) p o.v = 4 $3 = 4 (gdb) p o.v $4 = 4 (gdb) x/4xb &o.v 0x7fffffffd90c: 0x00 0x00 0x00 0x04 (observe that the 4 byte int variable has a big endian representation in the hex dump.) gdb/ChangeLog 2019-11-21 Peeter Joot <peeter.joot@lzlabs.com> Byte reverse display of variables with DW_END_big, DW_END_little (DW_AT_endianity) dwarf attributes if different than the native byte order. * ada-lang.c (ada_value_binop): Use type_byte_order instead of gdbarch_byte_order. * ada-valprint.c (printstr): (ada_val_print_string): * ada-lang.c (value_pointer): (ada_value_binop): Use type_byte_order instead of gdbarch_byte_order. * c-lang.c (c_get_string): Use type_byte_order instead of gdbarch_byte_order. * c-valprint.c (c_val_print_array): Use type_byte_order instead of gdbarch_byte_order. * cp-valprint.c (cp_print_class_member): Use type_byte_order instead of gdbarch_byte_order. * dwarf2loc.c (rw_pieced_value): Use type_byte_order instead of gdbarch_byte_order. * dwarf2read.c (read_base_type): Handle DW_END_big, DW_END_little * f-lang.c (f_get_encoding): Use type_byte_order instead of gdbarch_byte_order. * findvar.c (default_read_var_value): Use type_byte_order instead of gdbarch_byte_order. * gdbtypes.c (check_types_equal): Require matching TYPE_ENDIANITY_NOT_DEFAULT if set. (recursive_dump_type): Print TYPE_ENDIANITY_BIG, and TYPE_ENDIANITY_LITTLE if set. (type_byte_order): new function. * gdbtypes.h (TYPE_ENDIANITY_NOT_DEFAULT): New macro. (struct main_type) <flag_endianity_not_default>: New field. (type_byte_order): New function. * infcmd.c (default_print_one_register_info): Use type_byte_order instead of gdbarch_byte_order. * p-lang.c (pascal_printstr): Use type_byte_order instead of gdbarch_byte_order. * p-valprint.c (pascal_val_print): Use type_byte_order instead of gdbarch_byte_order. * printcmd.c (print_scalar_formatted): Use type_byte_order instead of gdbarch_byte_order. * solib-darwin.c (darwin_current_sos): Use type_byte_order instead of gdbarch_byte_order. * solib-svr4.c (solib_svr4_r_ldsomap): Use type_byte_order instead of gdbarch_byte_order. * stap-probe.c (stap_modify_semaphore): Use type_byte_order instead of gdbarch_byte_order. * target-float.c (target_float_same_format_p): Use type_byte_order instead of gdbarch_byte_order. * valarith.c (scalar_binop): (value_bit_index): Use type_byte_order instead of gdbarch_byte_order. * valops.c (value_cast): Use type_byte_order instead of gdbarch_byte_order. * valprint.c (generic_emit_char): (generic_printstr): (val_print_string): Use type_byte_order instead of gdbarch_byte_order. * value.c (unpack_long): (unpack_bits_as_long): (unpack_value_bitfield): (modify_field): (pack_long): (pack_unsigned_long): Use type_byte_order instead of gdbarch_byte_order. * findvar.c (unsigned_pointer_to_address): (signed_pointer_to_address): (unsigned_address_to_pointer): (address_to_signed_pointer): (default_read_var_value): (default_value_from_register): Use type_byte_order instead of gdbarch_byte_order. * gnu-v3-abi.c (gnuv3_make_method_ptr): Use type_byte_order instead of gdbarch_byte_order. * riscv-tdep.c (riscv_print_one_register_info): Use type_byte_order instead of gdbarch_byte_order. gdb/testsuite/ChangeLog 2019-11-21 Peeter Joot <peeter.joot@lzlabs.com> * gdb.base/endianity.c: New test. * gdb.base/endianity.exp: New file. Change-Id: I4bd98c1b4508c2d7c5a5dbb15d7b7b1cb4e667e2
2017-10-07 04:13:04 +08:00
if (type_byte_order (type) == BFD_ENDIAN_BIG)
encoding = "UTF-32BE";
else
encoding = "UTF-32LE";
break;
default:
error (_("unrecognized character type"));
}
return encoding;
}
gdb: building inferior strings from within GDB History Of This Patch ===================== This commit aims to address PR gdb/21699. There have now been a couple of attempts to fix this issue. Simon originally posted two patches back in 2021: https://sourceware.org/pipermail/gdb-patches/2021-July/180894.html https://sourceware.org/pipermail/gdb-patches/2021-July/180896.html Before Pedro then posted a version of his own: https://sourceware.org/pipermail/gdb-patches/2021-July/180970.html After this the conversation halted. Then in 2023 I (Andrew) also took a look at this bug and posted two versions: https://sourceware.org/pipermail/gdb-patches/2023-April/198570.html https://sourceware.org/pipermail/gdb-patches/2023-April/198680.html The approach taken in my first patch was pretty similar to what Simon originally posted back in 2021. My second attempt was only a slight variation on the first. Pedro then pointed out his older patch, and so we arrive at this patch. The GDB changes here are mostly Pedro's work, but updated by me (Andrew), any mistakes are mine. The tests here are a combinations of everyone's work, and the commit message is new, but copies bits from everyone's earlier work. Problem Description =================== Bug PR gdb/21699 makes the observation that using $_as_string with GDB's printf can cause GDB to print unexpected data from the inferior. The reproducer is pretty simple: #include <stddef.h> static char arena[100]; /* Override malloc() so value_coerce_to_target() gets a known pointer, and we know we"ll see an error if $_as_string() gives a string that isn't null terminated. */ void *malloc (size_t size) { memset (arena, 'x', sizeof (arena)); if (size > sizeof (arena)) return NULL; return arena; } int main () { return 0; } And then in a GDB session: $ gdb -q test Reading symbols from /tmp/test... (gdb) start Temporary breakpoint 1 at 0x4004c8: file test.c, line 17. Starting program: /tmp/test Temporary breakpoint 1, main () at test.c:17 17 return 0; (gdb) printf "%s\n", $_as_string("hello") "hello"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx (gdb) quit The problem above is caused by how value_cstring is used within py-value.c, but once we understand the issue then it turns out that value_cstring is used in an unexpected way in many places within GDB. Within py-value.c we have a null-terminated C-style string. We then pass a pointer to this string, along with the length of this string (so not including the null-character) to value_cstring. In value_cstring GDB allocates an array value of the given character type, and copies in requested number of characters. However value_cstring does not add a null-character of its own. This means that the value created by calling value_cstring is only null-terminated if the null-character is included in the passed in length. In py-value.c this is not the case, and indeed, in most uses of value_cstring, this is not the case. When GDB tries to print one of these strings the value contents are pushed to the inferior, and then read back as a C-style string, that is, GDB reads inferior memory until it finds a null-terminator. For the py-value.c case, no null-terminator is pushed into the inferior, so GDB will continue reading inferior memory until a null-terminator is found, with unpredictable results. Patch Description ================= The first thing this patch does is better define what the arguments for the two function value_cstring and value_string should represent. The comments in the header file are updated to describe whether the length argument should, or should not, include a null-character. Also, the data argument is changed to type gdb_byte. The functions as they currently exist will handle wide-characters, in which case more than one 'char' would be needed for each character. As such using gdb_byte seems to make more sense. To avoid adding casts throughout GDB, I've also added an overload that still takes a 'char *', but asserts that the character type being used is of size '1'. The value_cstring function is now responsible for adding a null character at the end of the string value it creates. However, once we start looking at how value_cstring is used, we realise there's another, related, problem. Not every language's strings are null terminated. Fortran and Ada strings, for example, are just an array of characters, GDB already has the function value_string which can be used to create such values. Consider this example using current GDB: (gdb) set language ada (gdb) p $_gdb_setting("arch") $1 = (97, 117, 116, 111) (gdb) ptype $ type = array (1 .. 4) of char (gdb) p $_gdb_maint_setting("test-settings string") $2 = (0) (gdb) ptype $ type = array (1 .. 1) of char This shows two problems, first, the $_gdb_setting and $_gdb_maint_setting functions are calling value_cstring using the builtin_char character, rather than a language appropriate type. In the first call, the 'arch' case, the value_cstring call doesn't include the null character, so the returned array only contains the expected characters. But, in the $_gdb_maint_setting example we do end up including the null-character, even though this is not expected for Ada strings. This commit adds a new language method language_defn::value_string, this function takes a pointer and length and creates a language appropriate value that represents the string. For C, C++, etc this will be a null-terminated string (by calling value_cstring), and for Fortran and Ada this can be a bounded array of characters with no null terminator. Additionally, this new language_defn::value_string function is responsible for selecting a language appropriate character type. After this commit the only calls to value_cstring are from the C expression evaluator and from the default language_defn::value_string. And the only calls to value_string are from Fortan, Ada, and ObjectC related code. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=21699 Co-Authored-By: Simon Marchi <simon.marchi@efficios.com> Co-Authored-By: Andrew Burgess <aburgess@redhat.com> Co-Authored-By: Pedro Alves <pedro@palves.net> Approved-By: Simon Marchi <simon.marchi@efficios.com>
2021-07-14 02:44:27 +08:00
/* See language.h. */
struct value *
f_language::value_string (struct gdbarch *gdbarch,
const char *ptr, ssize_t len) const
{
struct type *type = language_string_char_type (this, gdbarch);
return ::value_string (ptr, len, type);
}
/* A helper function for the "bound" intrinsics that checks that TYPE
is an array. LBOUND_P is true for lower bound; this is used for
the error message, if any. */
static void
fortran_require_array (struct type *type, bool lbound_p)
{
type = check_typedef (type);
if (type->code () != TYPE_CODE_ARRAY)
{
if (lbound_p)
error (_("LBOUND can only be applied to arrays"));
else
error (_("UBOUND can only be applied to arrays"));
}
}
/* Create an array containing the lower bounds (when LBOUND_P is true) or
the upper bounds (when LBOUND_P is false) of ARRAY (which must be of
array type). GDBARCH is the current architecture. */
static struct value *
fortran_bounds_all_dims (bool lbound_p,
struct gdbarch *gdbarch,
struct value *array)
{
type *array_type = check_typedef (array->type ());
int ndimensions = calc_f77_array_dims (array_type);
/* Allocate a result value of the correct type. */
type_allocator alloc (gdbarch);
struct type *range
= create_static_range_type (alloc,
builtin_f_type (gdbarch)->builtin_integer,
1, ndimensions);
struct type *elm_type = builtin_f_type (gdbarch)->builtin_integer;
struct type *result_type = create_array_type (alloc, elm_type, range);
struct value *result = value::allocate (result_type);
/* Walk the array dimensions backwards due to the way the array will be
laid out in memory, the first dimension will be the most inner. */
LONGEST elm_len = elm_type->length ();
for (LONGEST dst_offset = elm_len * (ndimensions - 1);
dst_offset >= 0;
dst_offset -= elm_len)
{
LONGEST b;
/* Grab the required bound. */
if (lbound_p)
b = f77_get_lowerbound (array_type);
else
b = f77_get_upperbound (array_type);
/* And copy the value into the result value. */
struct value *v = value_from_longest (elm_type, b);
gdb_assert (dst_offset + v->type ()->length ()
<= result->type ()->length ());
gdb_assert (v->type ()->length () == elm_len);
v->contents_copy (result, dst_offset, 0, elm_len);
/* Peel another dimension of the array. */
array_type = array_type->target_type ();
}
return result;
}
/* Return the lower bound (when LBOUND_P is true) or the upper bound (when
LBOUND_P is false) for dimension DIM_VAL (which must be an integer) of
ARRAY (which must be an array). RESULT_TYPE corresponds to the type kind
the function should be evaluated in. */
static value *
fortran_bounds_for_dimension (bool lbound_p, value *array, value *dim_val,
type* result_type)
{
/* Check the requested dimension is valid for this array. */
type *array_type = check_typedef (array->type ());
int ndimensions = calc_f77_array_dims (array_type);
long dim = value_as_long (dim_val);
if (dim < 1 || dim > ndimensions)
{
if (lbound_p)
error (_("LBOUND dimension must be from 1 to %d"), ndimensions);
else
error (_("UBOUND dimension must be from 1 to %d"), ndimensions);
}
/* Walk the dimensions backwards, due to the ordering in which arrays are
laid out the first dimension is the most inner. */
for (int i = ndimensions - 1; i >= 0; --i)
{
/* If this is the requested dimension then we're done. Grab the
bounds and return. */
if (i == dim - 1)
{
LONGEST b;
if (lbound_p)
b = f77_get_lowerbound (array_type);
else
b = f77_get_upperbound (array_type);
return value_from_longest (result_type, b);
}
/* Peel off another dimension of the array. */
array_type = array_type->target_type ();
}
gdb_assert_not_reached ("failed to find matching dimension");
}
gdb/fortran: Move Fortran expression handling into f-lang.c The Fortran specific OP_F77_UNDETERMINED_ARGLIST is currently handled in the generic expression handling code. There's no reason why this should be the case, so this commit moves handling of this into Fortran specific files. There should be no user visible changes after this commit. gdb/ChangeLog: * eval.c: Remove 'f-lang.h' include. (value_f90_subarray): Moved to f-lang.c. (eval_call): Renamed to... (evaluate_subexp_do_call): ...this, is no longer static, header comment moved into header file. (evaluate_funcall): Update call to eval_call. (skip_undetermined_arglist): Moved to f-lang.c. (fortran_value_subarray): Likewise. (evaluate_subexp_standard): OP_F77_UNDETERMINED_ARGLIST handling moved to evaluate_subexp_f. (calc_f77_array_dims): Moved to f-lang.c * expprint.c (print_subexp_funcall): New function. (print_subexp_standard): OP_F77_UNDETERMINED_ARGLIST handling moved to print_subexp_f, OP_FUNCALL uses new function. (dump_subexp_body_funcall): New function. (dump_subexp_body_standard): OP_F77_UNDETERMINED_ARGLIST handling moved to dump_subexp_f, OP_FUNCALL uses new function. * expression.h (evaluate_subexp_do_call): Declare. * f-lang.c (value_f90_subarray): Moved from eval.c. (skip_undetermined_arglist): Likewise. (calc_f77_array_dims): Likewise. (fortran_value_subarray): Likewise. (evaluate_subexp_f): Add OP_F77_UNDETERMINED_ARGLIST support. (operator_length_f): Likewise. (print_subexp_f): Likewise. (dump_subexp_body_f): Likewise. * fortran-operator.def (OP_F77_UNDETERMINED_ARGLIST): Move declaration of this operation to here. * parse.c (operator_length_standard): OP_F77_UNDETERMINED_ARGLIST support moved to operator_length_f. * parser-defs.h (dump_subexp_body_funcall): Declare. (print_subexp_funcall): Declare. * std-operator.def (OP_F77_UNDETERMINED_ARGLIST): Moved to fortran-operator.def.
2020-05-07 23:27:16 +08:00
/* Return the number of dimensions for a Fortran array or string. */
int
calc_f77_array_dims (struct type *array_type)
{
int ndimen = 1;
struct type *tmp_type;
if ((array_type->code () == TYPE_CODE_STRING))
return 1;
if ((array_type->code () != TYPE_CODE_ARRAY))
error (_("Can't get dimensions for a non-array type"));
tmp_type = array_type;
while ((tmp_type = tmp_type->target_type ()))
gdb/fortran: Move Fortran expression handling into f-lang.c The Fortran specific OP_F77_UNDETERMINED_ARGLIST is currently handled in the generic expression handling code. There's no reason why this should be the case, so this commit moves handling of this into Fortran specific files. There should be no user visible changes after this commit. gdb/ChangeLog: * eval.c: Remove 'f-lang.h' include. (value_f90_subarray): Moved to f-lang.c. (eval_call): Renamed to... (evaluate_subexp_do_call): ...this, is no longer static, header comment moved into header file. (evaluate_funcall): Update call to eval_call. (skip_undetermined_arglist): Moved to f-lang.c. (fortran_value_subarray): Likewise. (evaluate_subexp_standard): OP_F77_UNDETERMINED_ARGLIST handling moved to evaluate_subexp_f. (calc_f77_array_dims): Moved to f-lang.c * expprint.c (print_subexp_funcall): New function. (print_subexp_standard): OP_F77_UNDETERMINED_ARGLIST handling moved to print_subexp_f, OP_FUNCALL uses new function. (dump_subexp_body_funcall): New function. (dump_subexp_body_standard): OP_F77_UNDETERMINED_ARGLIST handling moved to dump_subexp_f, OP_FUNCALL uses new function. * expression.h (evaluate_subexp_do_call): Declare. * f-lang.c (value_f90_subarray): Moved from eval.c. (skip_undetermined_arglist): Likewise. (calc_f77_array_dims): Likewise. (fortran_value_subarray): Likewise. (evaluate_subexp_f): Add OP_F77_UNDETERMINED_ARGLIST support. (operator_length_f): Likewise. (print_subexp_f): Likewise. (dump_subexp_body_f): Likewise. * fortran-operator.def (OP_F77_UNDETERMINED_ARGLIST): Move declaration of this operation to here. * parse.c (operator_length_standard): OP_F77_UNDETERMINED_ARGLIST support moved to operator_length_f. * parser-defs.h (dump_subexp_body_funcall): Declare. (print_subexp_funcall): Declare. * std-operator.def (OP_F77_UNDETERMINED_ARGLIST): Moved to fortran-operator.def.
2020-05-07 23:27:16 +08:00
{
if (tmp_type->code () == TYPE_CODE_ARRAY)
++ndimen;
}
return ndimen;
}
gdb/fortran: Add support for Fortran array slices at the GDB prompt This commit brings array slice support to GDB. WARNING: This patch contains a rather big hack which is limited to Fortran arrays, this can be seen in gdbtypes.c and f-lang.c. More details on this below. This patch rewrites two areas of GDB's Fortran support, the code to extract an array slice, and the code to print an array. After this commit a user can, from the GDB prompt, ask for a slice of a Fortran array and should get the correct result back. Slices can (optionally) have the lower bound, upper bound, and a stride specified. Slices can also have a negative stride. Fortran has the concept of repacking array slices. Within a compiled Fortran program if a user passes a non-contiguous array slice to a function then the compiler may have to repack the slice, this involves copying the elements of the slice to a new area of memory before the call, and copying the elements back to the original array after the call. Whether repacking occurs will depend on which version of Fortran is being used, and what type of function is being called. This commit adds support for both packed, and unpacked array slicing, with the default being unpacked. With an unpacked array slice, when the user asks for a slice of an array GDB creates a new type that accurately describes where the elements of the slice can be found within the original array, a value of this type is then returned to the user. The address of an element within the slice will be equal to the address of an element within the original array. A user can choose to select packed array slices instead using: (gdb) set fortran repack-array-slices on|off (gdb) show fortran repack-array-slices With packed array slices GDB creates a new type that reflects how the elements of the slice would look if they were laid out in contiguous memory, allocates a value of this type, and then fetches the elements from the original array and places then into the contents buffer of the new value. One benefit of using packed slices over unpacked slices is the memory usage, taking a small slice of N elements from a large array will require (in GDB) N * ELEMENT_SIZE bytes of memory, while an unpacked array will also include all of the "padding" between the non-contiguous elements. There are new tests added that highlight this difference. There is also a new debugging flag added with this commit that introduces these commands: (gdb) set debug fortran-array-slicing on|off (gdb) show debug fortran-array-slicing This prints information about how the array slices are being built. As both the repacking, and the array printing requires GDB to walk through a multi-dimensional Fortran array visiting each element, this commit adds the file f-array-walk.h, which introduces some infrastructure to support this process. This means the array printing code in f-valprint.c is significantly reduced. The only slight issue with this commit is the "rather big hack" that I mentioned above. This hack allows us to handle one specific case, array slices with negative strides. This is something that I don't believe the current GDB value contents model will allow us to correctly handle, and rather than rewrite the value contents code right now, I'm hoping to slip this hack in as a work around. The problem is that, as I see it, the current value contents model assumes that an object base address will be the lowest address within that object, and that the contents of the object start at this base address and occupy the TYPE_LENGTH bytes after that. ( We do have the embedded_offset, which is used for C++ sub-classes, such that an object can start at some offset from the content buffer, however, the assumption that the object then occupies the next TYPE_LENGTH bytes is still true within GDB. ) The problem is that Fortran arrays with a negative stride don't follow this pattern. In this case the base address of the object points to the element with the highest address, the contents of the array then start at some offset _before_ the base address, and proceed for one element _past_ the base address. As the stride for such an array would be negative then, in theory the TYPE_LENGTH for this type would also be negative. However, in many places a value in GDB will degrade to a pointer + length, and the length almost always comes from the TYPE_LENGTH. It is my belief that in order to correctly model this case the value content handling of GDB will need to be reworked to split apart the value's content buffer (which is a block of memory with a length), and the object's in memory base address and length, which could be negative. Things are further complicated because arrays with negative strides like this are always dynamic types. When a value has a dynamic type and its base address needs resolving we actually store the address of the object within the resolved dynamic type, not within the value object itself. In short I don't currently see an easy path to cleanly support this situation within GDB. And so I believe that leaves two options, either add a work around, or catch cases where the user tries to make use of a negative stride, or access an array with a negative stride, and throw an error. This patch currently goes with adding a work around, which is that when we resolve a dynamic Fortran array type, if the stride is negative, then we adjust the base address to point to the lowest address required by the array. The printing and slicing code is aware of this adjustment and will correctly slice and print Fortran arrays. Where this hack will show through to the user is if they ask for the address of an array in their program with a negative array stride, the address they get from GDB will not match the address that would be computed within the Fortran program. gdb/ChangeLog: * Makefile.in (HFILES_NO_SRCDIR): Add f-array-walker.h. * NEWS: Mention new options. * f-array-walker.h: New file. * f-lang.c: Include 'gdbcmd.h' and 'f-array-walker.h'. (repack_array_slices): New static global. (show_repack_array_slices): New function. (fortran_array_slicing_debug): New static global. (show_fortran_array_slicing_debug): New function. (value_f90_subarray): Delete. (skip_undetermined_arglist): Delete. (class fortran_array_repacker_base_impl): New class. (class fortran_lazy_array_repacker_impl): New class. (class fortran_array_repacker_impl): New class. (fortran_value_subarray): Complete rewrite. (set_fortran_list): New static global. (show_fortran_list): Likewise. (_initialize_f_language): Register new commands. (fortran_adjust_dynamic_array_base_address_hack): New function. * f-lang.h (fortran_adjust_dynamic_array_base_address_hack): Declare. * f-valprint.c: Include 'f-array-walker.h'. (class fortran_array_printer_impl): New class. (f77_print_array_1): Delete. (f77_print_array): Delete. (fortran_print_array): New. (f_value_print_inner): Update to call fortran_print_array. * gdbtypes.c: Include 'f-lang.h'. (resolve_dynamic_type_internal): Call fortran_adjust_dynamic_array_base_address_hack. gdb/testsuite/ChangeLog: * gdb.fortran/array-slices-bad.exp: New file. * gdb.fortran/array-slices-bad.f90: New file. * gdb.fortran/array-slices-sub-slices.exp: New file. * gdb.fortran/array-slices-sub-slices.f90: New file. * gdb.fortran/array-slices.exp: Rewrite tests. * gdb.fortran/array-slices.f90: Rewrite tests. * gdb.fortran/vla-sizeof.exp: Correct expected results. gdb/doc/ChangeLog: * gdb.texinfo (Debugging Output): Document 'set/show debug fortran-array-slicing'. (Special Fortran Commands): Document 'set/show fortran repack-array-slices'.
2020-10-08 23:45:59 +08:00
/* A class used by FORTRAN_VALUE_SUBARRAY when repacking Fortran array
slices. This is a base class for two alternative repacking mechanisms,
one for when repacking from a lazy value, and one for repacking from a
non-lazy (already loaded) value. */
class fortran_array_repacker_base_impl
: public fortran_array_walker_base_impl
{
public:
/* Constructor, DEST is the value we are repacking into. */
fortran_array_repacker_base_impl (struct value *dest)
: m_dest (dest),
m_dest_offset (0)
{ /* Nothing. */ }
/* When we start processing the inner most dimension, this is where we
will be creating values for each element as we load them and then copy
them into the M_DEST value. Set a value mark so we can free these
temporary values. */
void start_dimension (struct type *index_type, LONGEST nelts, bool inner_p)
gdb/fortran: Add support for Fortran array slices at the GDB prompt This commit brings array slice support to GDB. WARNING: This patch contains a rather big hack which is limited to Fortran arrays, this can be seen in gdbtypes.c and f-lang.c. More details on this below. This patch rewrites two areas of GDB's Fortran support, the code to extract an array slice, and the code to print an array. After this commit a user can, from the GDB prompt, ask for a slice of a Fortran array and should get the correct result back. Slices can (optionally) have the lower bound, upper bound, and a stride specified. Slices can also have a negative stride. Fortran has the concept of repacking array slices. Within a compiled Fortran program if a user passes a non-contiguous array slice to a function then the compiler may have to repack the slice, this involves copying the elements of the slice to a new area of memory before the call, and copying the elements back to the original array after the call. Whether repacking occurs will depend on which version of Fortran is being used, and what type of function is being called. This commit adds support for both packed, and unpacked array slicing, with the default being unpacked. With an unpacked array slice, when the user asks for a slice of an array GDB creates a new type that accurately describes where the elements of the slice can be found within the original array, a value of this type is then returned to the user. The address of an element within the slice will be equal to the address of an element within the original array. A user can choose to select packed array slices instead using: (gdb) set fortran repack-array-slices on|off (gdb) show fortran repack-array-slices With packed array slices GDB creates a new type that reflects how the elements of the slice would look if they were laid out in contiguous memory, allocates a value of this type, and then fetches the elements from the original array and places then into the contents buffer of the new value. One benefit of using packed slices over unpacked slices is the memory usage, taking a small slice of N elements from a large array will require (in GDB) N * ELEMENT_SIZE bytes of memory, while an unpacked array will also include all of the "padding" between the non-contiguous elements. There are new tests added that highlight this difference. There is also a new debugging flag added with this commit that introduces these commands: (gdb) set debug fortran-array-slicing on|off (gdb) show debug fortran-array-slicing This prints information about how the array slices are being built. As both the repacking, and the array printing requires GDB to walk through a multi-dimensional Fortran array visiting each element, this commit adds the file f-array-walk.h, which introduces some infrastructure to support this process. This means the array printing code in f-valprint.c is significantly reduced. The only slight issue with this commit is the "rather big hack" that I mentioned above. This hack allows us to handle one specific case, array slices with negative strides. This is something that I don't believe the current GDB value contents model will allow us to correctly handle, and rather than rewrite the value contents code right now, I'm hoping to slip this hack in as a work around. The problem is that, as I see it, the current value contents model assumes that an object base address will be the lowest address within that object, and that the contents of the object start at this base address and occupy the TYPE_LENGTH bytes after that. ( We do have the embedded_offset, which is used for C++ sub-classes, such that an object can start at some offset from the content buffer, however, the assumption that the object then occupies the next TYPE_LENGTH bytes is still true within GDB. ) The problem is that Fortran arrays with a negative stride don't follow this pattern. In this case the base address of the object points to the element with the highest address, the contents of the array then start at some offset _before_ the base address, and proceed for one element _past_ the base address. As the stride for such an array would be negative then, in theory the TYPE_LENGTH for this type would also be negative. However, in many places a value in GDB will degrade to a pointer + length, and the length almost always comes from the TYPE_LENGTH. It is my belief that in order to correctly model this case the value content handling of GDB will need to be reworked to split apart the value's content buffer (which is a block of memory with a length), and the object's in memory base address and length, which could be negative. Things are further complicated because arrays with negative strides like this are always dynamic types. When a value has a dynamic type and its base address needs resolving we actually store the address of the object within the resolved dynamic type, not within the value object itself. In short I don't currently see an easy path to cleanly support this situation within GDB. And so I believe that leaves two options, either add a work around, or catch cases where the user tries to make use of a negative stride, or access an array with a negative stride, and throw an error. This patch currently goes with adding a work around, which is that when we resolve a dynamic Fortran array type, if the stride is negative, then we adjust the base address to point to the lowest address required by the array. The printing and slicing code is aware of this adjustment and will correctly slice and print Fortran arrays. Where this hack will show through to the user is if they ask for the address of an array in their program with a negative array stride, the address they get from GDB will not match the address that would be computed within the Fortran program. gdb/ChangeLog: * Makefile.in (HFILES_NO_SRCDIR): Add f-array-walker.h. * NEWS: Mention new options. * f-array-walker.h: New file. * f-lang.c: Include 'gdbcmd.h' and 'f-array-walker.h'. (repack_array_slices): New static global. (show_repack_array_slices): New function. (fortran_array_slicing_debug): New static global. (show_fortran_array_slicing_debug): New function. (value_f90_subarray): Delete. (skip_undetermined_arglist): Delete. (class fortran_array_repacker_base_impl): New class. (class fortran_lazy_array_repacker_impl): New class. (class fortran_array_repacker_impl): New class. (fortran_value_subarray): Complete rewrite. (set_fortran_list): New static global. (show_fortran_list): Likewise. (_initialize_f_language): Register new commands. (fortran_adjust_dynamic_array_base_address_hack): New function. * f-lang.h (fortran_adjust_dynamic_array_base_address_hack): Declare. * f-valprint.c: Include 'f-array-walker.h'. (class fortran_array_printer_impl): New class. (f77_print_array_1): Delete. (f77_print_array): Delete. (fortran_print_array): New. (f_value_print_inner): Update to call fortran_print_array. * gdbtypes.c: Include 'f-lang.h'. (resolve_dynamic_type_internal): Call fortran_adjust_dynamic_array_base_address_hack. gdb/testsuite/ChangeLog: * gdb.fortran/array-slices-bad.exp: New file. * gdb.fortran/array-slices-bad.f90: New file. * gdb.fortran/array-slices-sub-slices.exp: New file. * gdb.fortran/array-slices-sub-slices.f90: New file. * gdb.fortran/array-slices.exp: Rewrite tests. * gdb.fortran/array-slices.f90: Rewrite tests. * gdb.fortran/vla-sizeof.exp: Correct expected results. gdb/doc/ChangeLog: * gdb.texinfo (Debugging Output): Document 'set/show debug fortran-array-slicing'. (Special Fortran Commands): Document 'set/show fortran repack-array-slices'.
2020-10-08 23:45:59 +08:00
{
if (inner_p)
{
gdb_assert (!m_mark.has_value ());
m_mark.emplace ();
gdb/fortran: Add support for Fortran array slices at the GDB prompt This commit brings array slice support to GDB. WARNING: This patch contains a rather big hack which is limited to Fortran arrays, this can be seen in gdbtypes.c and f-lang.c. More details on this below. This patch rewrites two areas of GDB's Fortran support, the code to extract an array slice, and the code to print an array. After this commit a user can, from the GDB prompt, ask for a slice of a Fortran array and should get the correct result back. Slices can (optionally) have the lower bound, upper bound, and a stride specified. Slices can also have a negative stride. Fortran has the concept of repacking array slices. Within a compiled Fortran program if a user passes a non-contiguous array slice to a function then the compiler may have to repack the slice, this involves copying the elements of the slice to a new area of memory before the call, and copying the elements back to the original array after the call. Whether repacking occurs will depend on which version of Fortran is being used, and what type of function is being called. This commit adds support for both packed, and unpacked array slicing, with the default being unpacked. With an unpacked array slice, when the user asks for a slice of an array GDB creates a new type that accurately describes where the elements of the slice can be found within the original array, a value of this type is then returned to the user. The address of an element within the slice will be equal to the address of an element within the original array. A user can choose to select packed array slices instead using: (gdb) set fortran repack-array-slices on|off (gdb) show fortran repack-array-slices With packed array slices GDB creates a new type that reflects how the elements of the slice would look if they were laid out in contiguous memory, allocates a value of this type, and then fetches the elements from the original array and places then into the contents buffer of the new value. One benefit of using packed slices over unpacked slices is the memory usage, taking a small slice of N elements from a large array will require (in GDB) N * ELEMENT_SIZE bytes of memory, while an unpacked array will also include all of the "padding" between the non-contiguous elements. There are new tests added that highlight this difference. There is also a new debugging flag added with this commit that introduces these commands: (gdb) set debug fortran-array-slicing on|off (gdb) show debug fortran-array-slicing This prints information about how the array slices are being built. As both the repacking, and the array printing requires GDB to walk through a multi-dimensional Fortran array visiting each element, this commit adds the file f-array-walk.h, which introduces some infrastructure to support this process. This means the array printing code in f-valprint.c is significantly reduced. The only slight issue with this commit is the "rather big hack" that I mentioned above. This hack allows us to handle one specific case, array slices with negative strides. This is something that I don't believe the current GDB value contents model will allow us to correctly handle, and rather than rewrite the value contents code right now, I'm hoping to slip this hack in as a work around. The problem is that, as I see it, the current value contents model assumes that an object base address will be the lowest address within that object, and that the contents of the object start at this base address and occupy the TYPE_LENGTH bytes after that. ( We do have the embedded_offset, which is used for C++ sub-classes, such that an object can start at some offset from the content buffer, however, the assumption that the object then occupies the next TYPE_LENGTH bytes is still true within GDB. ) The problem is that Fortran arrays with a negative stride don't follow this pattern. In this case the base address of the object points to the element with the highest address, the contents of the array then start at some offset _before_ the base address, and proceed for one element _past_ the base address. As the stride for such an array would be negative then, in theory the TYPE_LENGTH for this type would also be negative. However, in many places a value in GDB will degrade to a pointer + length, and the length almost always comes from the TYPE_LENGTH. It is my belief that in order to correctly model this case the value content handling of GDB will need to be reworked to split apart the value's content buffer (which is a block of memory with a length), and the object's in memory base address and length, which could be negative. Things are further complicated because arrays with negative strides like this are always dynamic types. When a value has a dynamic type and its base address needs resolving we actually store the address of the object within the resolved dynamic type, not within the value object itself. In short I don't currently see an easy path to cleanly support this situation within GDB. And so I believe that leaves two options, either add a work around, or catch cases where the user tries to make use of a negative stride, or access an array with a negative stride, and throw an error. This patch currently goes with adding a work around, which is that when we resolve a dynamic Fortran array type, if the stride is negative, then we adjust the base address to point to the lowest address required by the array. The printing and slicing code is aware of this adjustment and will correctly slice and print Fortran arrays. Where this hack will show through to the user is if they ask for the address of an array in their program with a negative array stride, the address they get from GDB will not match the address that would be computed within the Fortran program. gdb/ChangeLog: * Makefile.in (HFILES_NO_SRCDIR): Add f-array-walker.h. * NEWS: Mention new options. * f-array-walker.h: New file. * f-lang.c: Include 'gdbcmd.h' and 'f-array-walker.h'. (repack_array_slices): New static global. (show_repack_array_slices): New function. (fortran_array_slicing_debug): New static global. (show_fortran_array_slicing_debug): New function. (value_f90_subarray): Delete. (skip_undetermined_arglist): Delete. (class fortran_array_repacker_base_impl): New class. (class fortran_lazy_array_repacker_impl): New class. (class fortran_array_repacker_impl): New class. (fortran_value_subarray): Complete rewrite. (set_fortran_list): New static global. (show_fortran_list): Likewise. (_initialize_f_language): Register new commands. (fortran_adjust_dynamic_array_base_address_hack): New function. * f-lang.h (fortran_adjust_dynamic_array_base_address_hack): Declare. * f-valprint.c: Include 'f-array-walker.h'. (class fortran_array_printer_impl): New class. (f77_print_array_1): Delete. (f77_print_array): Delete. (fortran_print_array): New. (f_value_print_inner): Update to call fortran_print_array. * gdbtypes.c: Include 'f-lang.h'. (resolve_dynamic_type_internal): Call fortran_adjust_dynamic_array_base_address_hack. gdb/testsuite/ChangeLog: * gdb.fortran/array-slices-bad.exp: New file. * gdb.fortran/array-slices-bad.f90: New file. * gdb.fortran/array-slices-sub-slices.exp: New file. * gdb.fortran/array-slices-sub-slices.f90: New file. * gdb.fortran/array-slices.exp: Rewrite tests. * gdb.fortran/array-slices.f90: Rewrite tests. * gdb.fortran/vla-sizeof.exp: Correct expected results. gdb/doc/ChangeLog: * gdb.texinfo (Debugging Output): Document 'set/show debug fortran-array-slicing'. (Special Fortran Commands): Document 'set/show fortran repack-array-slices'.
2020-10-08 23:45:59 +08:00
}
}
/* When we finish processing the inner most dimension free all temporary
value that were created. */
void finish_dimension (bool inner_p, bool last_p)
{
if (inner_p)
{
gdb_assert (m_mark.has_value ());
m_mark.reset ();
gdb/fortran: Add support for Fortran array slices at the GDB prompt This commit brings array slice support to GDB. WARNING: This patch contains a rather big hack which is limited to Fortran arrays, this can be seen in gdbtypes.c and f-lang.c. More details on this below. This patch rewrites two areas of GDB's Fortran support, the code to extract an array slice, and the code to print an array. After this commit a user can, from the GDB prompt, ask for a slice of a Fortran array and should get the correct result back. Slices can (optionally) have the lower bound, upper bound, and a stride specified. Slices can also have a negative stride. Fortran has the concept of repacking array slices. Within a compiled Fortran program if a user passes a non-contiguous array slice to a function then the compiler may have to repack the slice, this involves copying the elements of the slice to a new area of memory before the call, and copying the elements back to the original array after the call. Whether repacking occurs will depend on which version of Fortran is being used, and what type of function is being called. This commit adds support for both packed, and unpacked array slicing, with the default being unpacked. With an unpacked array slice, when the user asks for a slice of an array GDB creates a new type that accurately describes where the elements of the slice can be found within the original array, a value of this type is then returned to the user. The address of an element within the slice will be equal to the address of an element within the original array. A user can choose to select packed array slices instead using: (gdb) set fortran repack-array-slices on|off (gdb) show fortran repack-array-slices With packed array slices GDB creates a new type that reflects how the elements of the slice would look if they were laid out in contiguous memory, allocates a value of this type, and then fetches the elements from the original array and places then into the contents buffer of the new value. One benefit of using packed slices over unpacked slices is the memory usage, taking a small slice of N elements from a large array will require (in GDB) N * ELEMENT_SIZE bytes of memory, while an unpacked array will also include all of the "padding" between the non-contiguous elements. There are new tests added that highlight this difference. There is also a new debugging flag added with this commit that introduces these commands: (gdb) set debug fortran-array-slicing on|off (gdb) show debug fortran-array-slicing This prints information about how the array slices are being built. As both the repacking, and the array printing requires GDB to walk through a multi-dimensional Fortran array visiting each element, this commit adds the file f-array-walk.h, which introduces some infrastructure to support this process. This means the array printing code in f-valprint.c is significantly reduced. The only slight issue with this commit is the "rather big hack" that I mentioned above. This hack allows us to handle one specific case, array slices with negative strides. This is something that I don't believe the current GDB value contents model will allow us to correctly handle, and rather than rewrite the value contents code right now, I'm hoping to slip this hack in as a work around. The problem is that, as I see it, the current value contents model assumes that an object base address will be the lowest address within that object, and that the contents of the object start at this base address and occupy the TYPE_LENGTH bytes after that. ( We do have the embedded_offset, which is used for C++ sub-classes, such that an object can start at some offset from the content buffer, however, the assumption that the object then occupies the next TYPE_LENGTH bytes is still true within GDB. ) The problem is that Fortran arrays with a negative stride don't follow this pattern. In this case the base address of the object points to the element with the highest address, the contents of the array then start at some offset _before_ the base address, and proceed for one element _past_ the base address. As the stride for such an array would be negative then, in theory the TYPE_LENGTH for this type would also be negative. However, in many places a value in GDB will degrade to a pointer + length, and the length almost always comes from the TYPE_LENGTH. It is my belief that in order to correctly model this case the value content handling of GDB will need to be reworked to split apart the value's content buffer (which is a block of memory with a length), and the object's in memory base address and length, which could be negative. Things are further complicated because arrays with negative strides like this are always dynamic types. When a value has a dynamic type and its base address needs resolving we actually store the address of the object within the resolved dynamic type, not within the value object itself. In short I don't currently see an easy path to cleanly support this situation within GDB. And so I believe that leaves two options, either add a work around, or catch cases where the user tries to make use of a negative stride, or access an array with a negative stride, and throw an error. This patch currently goes with adding a work around, which is that when we resolve a dynamic Fortran array type, if the stride is negative, then we adjust the base address to point to the lowest address required by the array. The printing and slicing code is aware of this adjustment and will correctly slice and print Fortran arrays. Where this hack will show through to the user is if they ask for the address of an array in their program with a negative array stride, the address they get from GDB will not match the address that would be computed within the Fortran program. gdb/ChangeLog: * Makefile.in (HFILES_NO_SRCDIR): Add f-array-walker.h. * NEWS: Mention new options. * f-array-walker.h: New file. * f-lang.c: Include 'gdbcmd.h' and 'f-array-walker.h'. (repack_array_slices): New static global. (show_repack_array_slices): New function. (fortran_array_slicing_debug): New static global. (show_fortran_array_slicing_debug): New function. (value_f90_subarray): Delete. (skip_undetermined_arglist): Delete. (class fortran_array_repacker_base_impl): New class. (class fortran_lazy_array_repacker_impl): New class. (class fortran_array_repacker_impl): New class. (fortran_value_subarray): Complete rewrite. (set_fortran_list): New static global. (show_fortran_list): Likewise. (_initialize_f_language): Register new commands. (fortran_adjust_dynamic_array_base_address_hack): New function. * f-lang.h (fortran_adjust_dynamic_array_base_address_hack): Declare. * f-valprint.c: Include 'f-array-walker.h'. (class fortran_array_printer_impl): New class. (f77_print_array_1): Delete. (f77_print_array): Delete. (fortran_print_array): New. (f_value_print_inner): Update to call fortran_print_array. * gdbtypes.c: Include 'f-lang.h'. (resolve_dynamic_type_internal): Call fortran_adjust_dynamic_array_base_address_hack. gdb/testsuite/ChangeLog: * gdb.fortran/array-slices-bad.exp: New file. * gdb.fortran/array-slices-bad.f90: New file. * gdb.fortran/array-slices-sub-slices.exp: New file. * gdb.fortran/array-slices-sub-slices.f90: New file. * gdb.fortran/array-slices.exp: Rewrite tests. * gdb.fortran/array-slices.f90: Rewrite tests. * gdb.fortran/vla-sizeof.exp: Correct expected results. gdb/doc/ChangeLog: * gdb.texinfo (Debugging Output): Document 'set/show debug fortran-array-slicing'. (Special Fortran Commands): Document 'set/show fortran repack-array-slices'.
2020-10-08 23:45:59 +08:00
}
}
protected:
/* Copy the contents of array element ELT into M_DEST at the next
available offset. */
void copy_element_to_dest (struct value *elt)
{
elt->contents_copy (m_dest, m_dest_offset, 0,
elt->type ()->length ());
m_dest_offset += elt->type ()->length ();
gdb/fortran: Add support for Fortran array slices at the GDB prompt This commit brings array slice support to GDB. WARNING: This patch contains a rather big hack which is limited to Fortran arrays, this can be seen in gdbtypes.c and f-lang.c. More details on this below. This patch rewrites two areas of GDB's Fortran support, the code to extract an array slice, and the code to print an array. After this commit a user can, from the GDB prompt, ask for a slice of a Fortran array and should get the correct result back. Slices can (optionally) have the lower bound, upper bound, and a stride specified. Slices can also have a negative stride. Fortran has the concept of repacking array slices. Within a compiled Fortran program if a user passes a non-contiguous array slice to a function then the compiler may have to repack the slice, this involves copying the elements of the slice to a new area of memory before the call, and copying the elements back to the original array after the call. Whether repacking occurs will depend on which version of Fortran is being used, and what type of function is being called. This commit adds support for both packed, and unpacked array slicing, with the default being unpacked. With an unpacked array slice, when the user asks for a slice of an array GDB creates a new type that accurately describes where the elements of the slice can be found within the original array, a value of this type is then returned to the user. The address of an element within the slice will be equal to the address of an element within the original array. A user can choose to select packed array slices instead using: (gdb) set fortran repack-array-slices on|off (gdb) show fortran repack-array-slices With packed array slices GDB creates a new type that reflects how the elements of the slice would look if they were laid out in contiguous memory, allocates a value of this type, and then fetches the elements from the original array and places then into the contents buffer of the new value. One benefit of using packed slices over unpacked slices is the memory usage, taking a small slice of N elements from a large array will require (in GDB) N * ELEMENT_SIZE bytes of memory, while an unpacked array will also include all of the "padding" between the non-contiguous elements. There are new tests added that highlight this difference. There is also a new debugging flag added with this commit that introduces these commands: (gdb) set debug fortran-array-slicing on|off (gdb) show debug fortran-array-slicing This prints information about how the array slices are being built. As both the repacking, and the array printing requires GDB to walk through a multi-dimensional Fortran array visiting each element, this commit adds the file f-array-walk.h, which introduces some infrastructure to support this process. This means the array printing code in f-valprint.c is significantly reduced. The only slight issue with this commit is the "rather big hack" that I mentioned above. This hack allows us to handle one specific case, array slices with negative strides. This is something that I don't believe the current GDB value contents model will allow us to correctly handle, and rather than rewrite the value contents code right now, I'm hoping to slip this hack in as a work around. The problem is that, as I see it, the current value contents model assumes that an object base address will be the lowest address within that object, and that the contents of the object start at this base address and occupy the TYPE_LENGTH bytes after that. ( We do have the embedded_offset, which is used for C++ sub-classes, such that an object can start at some offset from the content buffer, however, the assumption that the object then occupies the next TYPE_LENGTH bytes is still true within GDB. ) The problem is that Fortran arrays with a negative stride don't follow this pattern. In this case the base address of the object points to the element with the highest address, the contents of the array then start at some offset _before_ the base address, and proceed for one element _past_ the base address. As the stride for such an array would be negative then, in theory the TYPE_LENGTH for this type would also be negative. However, in many places a value in GDB will degrade to a pointer + length, and the length almost always comes from the TYPE_LENGTH. It is my belief that in order to correctly model this case the value content handling of GDB will need to be reworked to split apart the value's content buffer (which is a block of memory with a length), and the object's in memory base address and length, which could be negative. Things are further complicated because arrays with negative strides like this are always dynamic types. When a value has a dynamic type and its base address needs resolving we actually store the address of the object within the resolved dynamic type, not within the value object itself. In short I don't currently see an easy path to cleanly support this situation within GDB. And so I believe that leaves two options, either add a work around, or catch cases where the user tries to make use of a negative stride, or access an array with a negative stride, and throw an error. This patch currently goes with adding a work around, which is that when we resolve a dynamic Fortran array type, if the stride is negative, then we adjust the base address to point to the lowest address required by the array. The printing and slicing code is aware of this adjustment and will correctly slice and print Fortran arrays. Where this hack will show through to the user is if they ask for the address of an array in their program with a negative array stride, the address they get from GDB will not match the address that would be computed within the Fortran program. gdb/ChangeLog: * Makefile.in (HFILES_NO_SRCDIR): Add f-array-walker.h. * NEWS: Mention new options. * f-array-walker.h: New file. * f-lang.c: Include 'gdbcmd.h' and 'f-array-walker.h'. (repack_array_slices): New static global. (show_repack_array_slices): New function. (fortran_array_slicing_debug): New static global. (show_fortran_array_slicing_debug): New function. (value_f90_subarray): Delete. (skip_undetermined_arglist): Delete. (class fortran_array_repacker_base_impl): New class. (class fortran_lazy_array_repacker_impl): New class. (class fortran_array_repacker_impl): New class. (fortran_value_subarray): Complete rewrite. (set_fortran_list): New static global. (show_fortran_list): Likewise. (_initialize_f_language): Register new commands. (fortran_adjust_dynamic_array_base_address_hack): New function. * f-lang.h (fortran_adjust_dynamic_array_base_address_hack): Declare. * f-valprint.c: Include 'f-array-walker.h'. (class fortran_array_printer_impl): New class. (f77_print_array_1): Delete. (f77_print_array): Delete. (fortran_print_array): New. (f_value_print_inner): Update to call fortran_print_array. * gdbtypes.c: Include 'f-lang.h'. (resolve_dynamic_type_internal): Call fortran_adjust_dynamic_array_base_address_hack. gdb/testsuite/ChangeLog: * gdb.fortran/array-slices-bad.exp: New file. * gdb.fortran/array-slices-bad.f90: New file. * gdb.fortran/array-slices-sub-slices.exp: New file. * gdb.fortran/array-slices-sub-slices.f90: New file. * gdb.fortran/array-slices.exp: Rewrite tests. * gdb.fortran/array-slices.f90: Rewrite tests. * gdb.fortran/vla-sizeof.exp: Correct expected results. gdb/doc/ChangeLog: * gdb.texinfo (Debugging Output): Document 'set/show debug fortran-array-slicing'. (Special Fortran Commands): Document 'set/show fortran repack-array-slices'.
2020-10-08 23:45:59 +08:00
}
/* The value being written to. */
struct value *m_dest;
/* The byte offset in M_DEST at which the next element should be
written. */
LONGEST m_dest_offset;
/* Set and reset to handle removing intermediate values from the
value chain. */
std::optional<scoped_value_mark> m_mark;
gdb/fortran: Add support for Fortran array slices at the GDB prompt This commit brings array slice support to GDB. WARNING: This patch contains a rather big hack which is limited to Fortran arrays, this can be seen in gdbtypes.c and f-lang.c. More details on this below. This patch rewrites two areas of GDB's Fortran support, the code to extract an array slice, and the code to print an array. After this commit a user can, from the GDB prompt, ask for a slice of a Fortran array and should get the correct result back. Slices can (optionally) have the lower bound, upper bound, and a stride specified. Slices can also have a negative stride. Fortran has the concept of repacking array slices. Within a compiled Fortran program if a user passes a non-contiguous array slice to a function then the compiler may have to repack the slice, this involves copying the elements of the slice to a new area of memory before the call, and copying the elements back to the original array after the call. Whether repacking occurs will depend on which version of Fortran is being used, and what type of function is being called. This commit adds support for both packed, and unpacked array slicing, with the default being unpacked. With an unpacked array slice, when the user asks for a slice of an array GDB creates a new type that accurately describes where the elements of the slice can be found within the original array, a value of this type is then returned to the user. The address of an element within the slice will be equal to the address of an element within the original array. A user can choose to select packed array slices instead using: (gdb) set fortran repack-array-slices on|off (gdb) show fortran repack-array-slices With packed array slices GDB creates a new type that reflects how the elements of the slice would look if they were laid out in contiguous memory, allocates a value of this type, and then fetches the elements from the original array and places then into the contents buffer of the new value. One benefit of using packed slices over unpacked slices is the memory usage, taking a small slice of N elements from a large array will require (in GDB) N * ELEMENT_SIZE bytes of memory, while an unpacked array will also include all of the "padding" between the non-contiguous elements. There are new tests added that highlight this difference. There is also a new debugging flag added with this commit that introduces these commands: (gdb) set debug fortran-array-slicing on|off (gdb) show debug fortran-array-slicing This prints information about how the array slices are being built. As both the repacking, and the array printing requires GDB to walk through a multi-dimensional Fortran array visiting each element, this commit adds the file f-array-walk.h, which introduces some infrastructure to support this process. This means the array printing code in f-valprint.c is significantly reduced. The only slight issue with this commit is the "rather big hack" that I mentioned above. This hack allows us to handle one specific case, array slices with negative strides. This is something that I don't believe the current GDB value contents model will allow us to correctly handle, and rather than rewrite the value contents code right now, I'm hoping to slip this hack in as a work around. The problem is that, as I see it, the current value contents model assumes that an object base address will be the lowest address within that object, and that the contents of the object start at this base address and occupy the TYPE_LENGTH bytes after that. ( We do have the embedded_offset, which is used for C++ sub-classes, such that an object can start at some offset from the content buffer, however, the assumption that the object then occupies the next TYPE_LENGTH bytes is still true within GDB. ) The problem is that Fortran arrays with a negative stride don't follow this pattern. In this case the base address of the object points to the element with the highest address, the contents of the array then start at some offset _before_ the base address, and proceed for one element _past_ the base address. As the stride for such an array would be negative then, in theory the TYPE_LENGTH for this type would also be negative. However, in many places a value in GDB will degrade to a pointer + length, and the length almost always comes from the TYPE_LENGTH. It is my belief that in order to correctly model this case the value content handling of GDB will need to be reworked to split apart the value's content buffer (which is a block of memory with a length), and the object's in memory base address and length, which could be negative. Things are further complicated because arrays with negative strides like this are always dynamic types. When a value has a dynamic type and its base address needs resolving we actually store the address of the object within the resolved dynamic type, not within the value object itself. In short I don't currently see an easy path to cleanly support this situation within GDB. And so I believe that leaves two options, either add a work around, or catch cases where the user tries to make use of a negative stride, or access an array with a negative stride, and throw an error. This patch currently goes with adding a work around, which is that when we resolve a dynamic Fortran array type, if the stride is negative, then we adjust the base address to point to the lowest address required by the array. The printing and slicing code is aware of this adjustment and will correctly slice and print Fortran arrays. Where this hack will show through to the user is if they ask for the address of an array in their program with a negative array stride, the address they get from GDB will not match the address that would be computed within the Fortran program. gdb/ChangeLog: * Makefile.in (HFILES_NO_SRCDIR): Add f-array-walker.h. * NEWS: Mention new options. * f-array-walker.h: New file. * f-lang.c: Include 'gdbcmd.h' and 'f-array-walker.h'. (repack_array_slices): New static global. (show_repack_array_slices): New function. (fortran_array_slicing_debug): New static global. (show_fortran_array_slicing_debug): New function. (value_f90_subarray): Delete. (skip_undetermined_arglist): Delete. (class fortran_array_repacker_base_impl): New class. (class fortran_lazy_array_repacker_impl): New class. (class fortran_array_repacker_impl): New class. (fortran_value_subarray): Complete rewrite. (set_fortran_list): New static global. (show_fortran_list): Likewise. (_initialize_f_language): Register new commands. (fortran_adjust_dynamic_array_base_address_hack): New function. * f-lang.h (fortran_adjust_dynamic_array_base_address_hack): Declare. * f-valprint.c: Include 'f-array-walker.h'. (class fortran_array_printer_impl): New class. (f77_print_array_1): Delete. (f77_print_array): Delete. (fortran_print_array): New. (f_value_print_inner): Update to call fortran_print_array. * gdbtypes.c: Include 'f-lang.h'. (resolve_dynamic_type_internal): Call fortran_adjust_dynamic_array_base_address_hack. gdb/testsuite/ChangeLog: * gdb.fortran/array-slices-bad.exp: New file. * gdb.fortran/array-slices-bad.f90: New file. * gdb.fortran/array-slices-sub-slices.exp: New file. * gdb.fortran/array-slices-sub-slices.f90: New file. * gdb.fortran/array-slices.exp: Rewrite tests. * gdb.fortran/array-slices.f90: Rewrite tests. * gdb.fortran/vla-sizeof.exp: Correct expected results. gdb/doc/ChangeLog: * gdb.texinfo (Debugging Output): Document 'set/show debug fortran-array-slicing'. (Special Fortran Commands): Document 'set/show fortran repack-array-slices'.
2020-10-08 23:45:59 +08:00
};
/* A class used by FORTRAN_VALUE_SUBARRAY when repacking Fortran array
slices. This class is specialised for repacking an array slice from a
lazy array value, as such it does not require the parent array value to
be loaded into GDB's memory; the parent value could be huge, while the
slice could be tiny. */
class fortran_lazy_array_repacker_impl
: public fortran_array_repacker_base_impl
{
public:
/* Constructor. TYPE is the type of the slice being loaded from the
parent value, so this type will correctly reflect the strides required
to find all of the elements from the parent value. ADDRESS is the
address in target memory of value matching TYPE, and DEST is the value
we are repacking into. */
explicit fortran_lazy_array_repacker_impl (struct type *type,
CORE_ADDR address,
struct value *dest)
: fortran_array_repacker_base_impl (dest),
m_addr (address)
{ /* Nothing. */ }
/* Create a lazy value in target memory representing a single element,
then load the element into GDB's memory and copy the contents into the
destination value. */
void process_element (struct type *elt_type, LONGEST elt_off,
LONGEST index, bool last_p)
gdb/fortran: Add support for Fortran array slices at the GDB prompt This commit brings array slice support to GDB. WARNING: This patch contains a rather big hack which is limited to Fortran arrays, this can be seen in gdbtypes.c and f-lang.c. More details on this below. This patch rewrites two areas of GDB's Fortran support, the code to extract an array slice, and the code to print an array. After this commit a user can, from the GDB prompt, ask for a slice of a Fortran array and should get the correct result back. Slices can (optionally) have the lower bound, upper bound, and a stride specified. Slices can also have a negative stride. Fortran has the concept of repacking array slices. Within a compiled Fortran program if a user passes a non-contiguous array slice to a function then the compiler may have to repack the slice, this involves copying the elements of the slice to a new area of memory before the call, and copying the elements back to the original array after the call. Whether repacking occurs will depend on which version of Fortran is being used, and what type of function is being called. This commit adds support for both packed, and unpacked array slicing, with the default being unpacked. With an unpacked array slice, when the user asks for a slice of an array GDB creates a new type that accurately describes where the elements of the slice can be found within the original array, a value of this type is then returned to the user. The address of an element within the slice will be equal to the address of an element within the original array. A user can choose to select packed array slices instead using: (gdb) set fortran repack-array-slices on|off (gdb) show fortran repack-array-slices With packed array slices GDB creates a new type that reflects how the elements of the slice would look if they were laid out in contiguous memory, allocates a value of this type, and then fetches the elements from the original array and places then into the contents buffer of the new value. One benefit of using packed slices over unpacked slices is the memory usage, taking a small slice of N elements from a large array will require (in GDB) N * ELEMENT_SIZE bytes of memory, while an unpacked array will also include all of the "padding" between the non-contiguous elements. There are new tests added that highlight this difference. There is also a new debugging flag added with this commit that introduces these commands: (gdb) set debug fortran-array-slicing on|off (gdb) show debug fortran-array-slicing This prints information about how the array slices are being built. As both the repacking, and the array printing requires GDB to walk through a multi-dimensional Fortran array visiting each element, this commit adds the file f-array-walk.h, which introduces some infrastructure to support this process. This means the array printing code in f-valprint.c is significantly reduced. The only slight issue with this commit is the "rather big hack" that I mentioned above. This hack allows us to handle one specific case, array slices with negative strides. This is something that I don't believe the current GDB value contents model will allow us to correctly handle, and rather than rewrite the value contents code right now, I'm hoping to slip this hack in as a work around. The problem is that, as I see it, the current value contents model assumes that an object base address will be the lowest address within that object, and that the contents of the object start at this base address and occupy the TYPE_LENGTH bytes after that. ( We do have the embedded_offset, which is used for C++ sub-classes, such that an object can start at some offset from the content buffer, however, the assumption that the object then occupies the next TYPE_LENGTH bytes is still true within GDB. ) The problem is that Fortran arrays with a negative stride don't follow this pattern. In this case the base address of the object points to the element with the highest address, the contents of the array then start at some offset _before_ the base address, and proceed for one element _past_ the base address. As the stride for such an array would be negative then, in theory the TYPE_LENGTH for this type would also be negative. However, in many places a value in GDB will degrade to a pointer + length, and the length almost always comes from the TYPE_LENGTH. It is my belief that in order to correctly model this case the value content handling of GDB will need to be reworked to split apart the value's content buffer (which is a block of memory with a length), and the object's in memory base address and length, which could be negative. Things are further complicated because arrays with negative strides like this are always dynamic types. When a value has a dynamic type and its base address needs resolving we actually store the address of the object within the resolved dynamic type, not within the value object itself. In short I don't currently see an easy path to cleanly support this situation within GDB. And so I believe that leaves two options, either add a work around, or catch cases where the user tries to make use of a negative stride, or access an array with a negative stride, and throw an error. This patch currently goes with adding a work around, which is that when we resolve a dynamic Fortran array type, if the stride is negative, then we adjust the base address to point to the lowest address required by the array. The printing and slicing code is aware of this adjustment and will correctly slice and print Fortran arrays. Where this hack will show through to the user is if they ask for the address of an array in their program with a negative array stride, the address they get from GDB will not match the address that would be computed within the Fortran program. gdb/ChangeLog: * Makefile.in (HFILES_NO_SRCDIR): Add f-array-walker.h. * NEWS: Mention new options. * f-array-walker.h: New file. * f-lang.c: Include 'gdbcmd.h' and 'f-array-walker.h'. (repack_array_slices): New static global. (show_repack_array_slices): New function. (fortran_array_slicing_debug): New static global. (show_fortran_array_slicing_debug): New function. (value_f90_subarray): Delete. (skip_undetermined_arglist): Delete. (class fortran_array_repacker_base_impl): New class. (class fortran_lazy_array_repacker_impl): New class. (class fortran_array_repacker_impl): New class. (fortran_value_subarray): Complete rewrite. (set_fortran_list): New static global. (show_fortran_list): Likewise. (_initialize_f_language): Register new commands. (fortran_adjust_dynamic_array_base_address_hack): New function. * f-lang.h (fortran_adjust_dynamic_array_base_address_hack): Declare. * f-valprint.c: Include 'f-array-walker.h'. (class fortran_array_printer_impl): New class. (f77_print_array_1): Delete. (f77_print_array): Delete. (fortran_print_array): New. (f_value_print_inner): Update to call fortran_print_array. * gdbtypes.c: Include 'f-lang.h'. (resolve_dynamic_type_internal): Call fortran_adjust_dynamic_array_base_address_hack. gdb/testsuite/ChangeLog: * gdb.fortran/array-slices-bad.exp: New file. * gdb.fortran/array-slices-bad.f90: New file. * gdb.fortran/array-slices-sub-slices.exp: New file. * gdb.fortran/array-slices-sub-slices.f90: New file. * gdb.fortran/array-slices.exp: Rewrite tests. * gdb.fortran/array-slices.f90: Rewrite tests. * gdb.fortran/vla-sizeof.exp: Correct expected results. gdb/doc/ChangeLog: * gdb.texinfo (Debugging Output): Document 'set/show debug fortran-array-slicing'. (Special Fortran Commands): Document 'set/show fortran repack-array-slices'.
2020-10-08 23:45:59 +08:00
{
copy_element_to_dest (value_at_lazy (elt_type, m_addr + elt_off));
}
private:
/* The address in target memory where the parent value starts. */
CORE_ADDR m_addr;
};
gdb/fortran: Move Fortran expression handling into f-lang.c The Fortran specific OP_F77_UNDETERMINED_ARGLIST is currently handled in the generic expression handling code. There's no reason why this should be the case, so this commit moves handling of this into Fortran specific files. There should be no user visible changes after this commit. gdb/ChangeLog: * eval.c: Remove 'f-lang.h' include. (value_f90_subarray): Moved to f-lang.c. (eval_call): Renamed to... (evaluate_subexp_do_call): ...this, is no longer static, header comment moved into header file. (evaluate_funcall): Update call to eval_call. (skip_undetermined_arglist): Moved to f-lang.c. (fortran_value_subarray): Likewise. (evaluate_subexp_standard): OP_F77_UNDETERMINED_ARGLIST handling moved to evaluate_subexp_f. (calc_f77_array_dims): Moved to f-lang.c * expprint.c (print_subexp_funcall): New function. (print_subexp_standard): OP_F77_UNDETERMINED_ARGLIST handling moved to print_subexp_f, OP_FUNCALL uses new function. (dump_subexp_body_funcall): New function. (dump_subexp_body_standard): OP_F77_UNDETERMINED_ARGLIST handling moved to dump_subexp_f, OP_FUNCALL uses new function. * expression.h (evaluate_subexp_do_call): Declare. * f-lang.c (value_f90_subarray): Moved from eval.c. (skip_undetermined_arglist): Likewise. (calc_f77_array_dims): Likewise. (fortran_value_subarray): Likewise. (evaluate_subexp_f): Add OP_F77_UNDETERMINED_ARGLIST support. (operator_length_f): Likewise. (print_subexp_f): Likewise. (dump_subexp_body_f): Likewise. * fortran-operator.def (OP_F77_UNDETERMINED_ARGLIST): Move declaration of this operation to here. * parse.c (operator_length_standard): OP_F77_UNDETERMINED_ARGLIST support moved to operator_length_f. * parser-defs.h (dump_subexp_body_funcall): Declare. (print_subexp_funcall): Declare. * std-operator.def (OP_F77_UNDETERMINED_ARGLIST): Moved to fortran-operator.def.
2020-05-07 23:27:16 +08:00
/* A class used by FORTRAN_VALUE_SUBARRAY when repacking Fortran array
slices. This class is specialised for repacking an array slice from a
previously loaded (non-lazy) array value, as such it fetches the
element values from the contents of the parent value. */
class fortran_array_repacker_impl
: public fortran_array_repacker_base_impl
{
public:
/* Constructor. TYPE is the type for the array slice within the parent
value, as such it has stride values as required to find the elements
within the original parent value. ADDRESS is the address in target
memory of the value matching TYPE. BASE_OFFSET is the offset from
the start of VAL's content buffer to the start of the object of TYPE,
VAL is the parent object from which we are loading the value, and
DEST is the value into which we are repacking. */
explicit fortran_array_repacker_impl (struct type *type, CORE_ADDR address,
LONGEST base_offset,
struct value *val, struct value *dest)
: fortran_array_repacker_base_impl (dest),
m_base_offset (base_offset),
m_val (val)
{
gdb_assert (!val->lazy ());
}
gdb/fortran: Add support for Fortran array slices at the GDB prompt This commit brings array slice support to GDB. WARNING: This patch contains a rather big hack which is limited to Fortran arrays, this can be seen in gdbtypes.c and f-lang.c. More details on this below. This patch rewrites two areas of GDB's Fortran support, the code to extract an array slice, and the code to print an array. After this commit a user can, from the GDB prompt, ask for a slice of a Fortran array and should get the correct result back. Slices can (optionally) have the lower bound, upper bound, and a stride specified. Slices can also have a negative stride. Fortran has the concept of repacking array slices. Within a compiled Fortran program if a user passes a non-contiguous array slice to a function then the compiler may have to repack the slice, this involves copying the elements of the slice to a new area of memory before the call, and copying the elements back to the original array after the call. Whether repacking occurs will depend on which version of Fortran is being used, and what type of function is being called. This commit adds support for both packed, and unpacked array slicing, with the default being unpacked. With an unpacked array slice, when the user asks for a slice of an array GDB creates a new type that accurately describes where the elements of the slice can be found within the original array, a value of this type is then returned to the user. The address of an element within the slice will be equal to the address of an element within the original array. A user can choose to select packed array slices instead using: (gdb) set fortran repack-array-slices on|off (gdb) show fortran repack-array-slices With packed array slices GDB creates a new type that reflects how the elements of the slice would look if they were laid out in contiguous memory, allocates a value of this type, and then fetches the elements from the original array and places then into the contents buffer of the new value. One benefit of using packed slices over unpacked slices is the memory usage, taking a small slice of N elements from a large array will require (in GDB) N * ELEMENT_SIZE bytes of memory, while an unpacked array will also include all of the "padding" between the non-contiguous elements. There are new tests added that highlight this difference. There is also a new debugging flag added with this commit that introduces these commands: (gdb) set debug fortran-array-slicing on|off (gdb) show debug fortran-array-slicing This prints information about how the array slices are being built. As both the repacking, and the array printing requires GDB to walk through a multi-dimensional Fortran array visiting each element, this commit adds the file f-array-walk.h, which introduces some infrastructure to support this process. This means the array printing code in f-valprint.c is significantly reduced. The only slight issue with this commit is the "rather big hack" that I mentioned above. This hack allows us to handle one specific case, array slices with negative strides. This is something that I don't believe the current GDB value contents model will allow us to correctly handle, and rather than rewrite the value contents code right now, I'm hoping to slip this hack in as a work around. The problem is that, as I see it, the current value contents model assumes that an object base address will be the lowest address within that object, and that the contents of the object start at this base address and occupy the TYPE_LENGTH bytes after that. ( We do have the embedded_offset, which is used for C++ sub-classes, such that an object can start at some offset from the content buffer, however, the assumption that the object then occupies the next TYPE_LENGTH bytes is still true within GDB. ) The problem is that Fortran arrays with a negative stride don't follow this pattern. In this case the base address of the object points to the element with the highest address, the contents of the array then start at some offset _before_ the base address, and proceed for one element _past_ the base address. As the stride for such an array would be negative then, in theory the TYPE_LENGTH for this type would also be negative. However, in many places a value in GDB will degrade to a pointer + length, and the length almost always comes from the TYPE_LENGTH. It is my belief that in order to correctly model this case the value content handling of GDB will need to be reworked to split apart the value's content buffer (which is a block of memory with a length), and the object's in memory base address and length, which could be negative. Things are further complicated because arrays with negative strides like this are always dynamic types. When a value has a dynamic type and its base address needs resolving we actually store the address of the object within the resolved dynamic type, not within the value object itself. In short I don't currently see an easy path to cleanly support this situation within GDB. And so I believe that leaves two options, either add a work around, or catch cases where the user tries to make use of a negative stride, or access an array with a negative stride, and throw an error. This patch currently goes with adding a work around, which is that when we resolve a dynamic Fortran array type, if the stride is negative, then we adjust the base address to point to the lowest address required by the array. The printing and slicing code is aware of this adjustment and will correctly slice and print Fortran arrays. Where this hack will show through to the user is if they ask for the address of an array in their program with a negative array stride, the address they get from GDB will not match the address that would be computed within the Fortran program. gdb/ChangeLog: * Makefile.in (HFILES_NO_SRCDIR): Add f-array-walker.h. * NEWS: Mention new options. * f-array-walker.h: New file. * f-lang.c: Include 'gdbcmd.h' and 'f-array-walker.h'. (repack_array_slices): New static global. (show_repack_array_slices): New function. (fortran_array_slicing_debug): New static global. (show_fortran_array_slicing_debug): New function. (value_f90_subarray): Delete. (skip_undetermined_arglist): Delete. (class fortran_array_repacker_base_impl): New class. (class fortran_lazy_array_repacker_impl): New class. (class fortran_array_repacker_impl): New class. (fortran_value_subarray): Complete rewrite. (set_fortran_list): New static global. (show_fortran_list): Likewise. (_initialize_f_language): Register new commands. (fortran_adjust_dynamic_array_base_address_hack): New function. * f-lang.h (fortran_adjust_dynamic_array_base_address_hack): Declare. * f-valprint.c: Include 'f-array-walker.h'. (class fortran_array_printer_impl): New class. (f77_print_array_1): Delete. (f77_print_array): Delete. (fortran_print_array): New. (f_value_print_inner): Update to call fortran_print_array. * gdbtypes.c: Include 'f-lang.h'. (resolve_dynamic_type_internal): Call fortran_adjust_dynamic_array_base_address_hack. gdb/testsuite/ChangeLog: * gdb.fortran/array-slices-bad.exp: New file. * gdb.fortran/array-slices-bad.f90: New file. * gdb.fortran/array-slices-sub-slices.exp: New file. * gdb.fortran/array-slices-sub-slices.f90: New file. * gdb.fortran/array-slices.exp: Rewrite tests. * gdb.fortran/array-slices.f90: Rewrite tests. * gdb.fortran/vla-sizeof.exp: Correct expected results. gdb/doc/ChangeLog: * gdb.texinfo (Debugging Output): Document 'set/show debug fortran-array-slicing'. (Special Fortran Commands): Document 'set/show fortran repack-array-slices'.
2020-10-08 23:45:59 +08:00
/* Extract an element of ELT_TYPE at offset (M_BASE_OFFSET + ELT_OFF)
from the content buffer of M_VAL then copy this extracted value into
the repacked destination value. */
void process_element (struct type *elt_type, LONGEST elt_off,
LONGEST index, bool last_p)
{
struct value *elt
= value_from_component (m_val, elt_type, (elt_off + m_base_offset));
copy_element_to_dest (elt);
}
gdb/fortran: Add support for Fortran array slices at the GDB prompt This commit brings array slice support to GDB. WARNING: This patch contains a rather big hack which is limited to Fortran arrays, this can be seen in gdbtypes.c and f-lang.c. More details on this below. This patch rewrites two areas of GDB's Fortran support, the code to extract an array slice, and the code to print an array. After this commit a user can, from the GDB prompt, ask for a slice of a Fortran array and should get the correct result back. Slices can (optionally) have the lower bound, upper bound, and a stride specified. Slices can also have a negative stride. Fortran has the concept of repacking array slices. Within a compiled Fortran program if a user passes a non-contiguous array slice to a function then the compiler may have to repack the slice, this involves copying the elements of the slice to a new area of memory before the call, and copying the elements back to the original array after the call. Whether repacking occurs will depend on which version of Fortran is being used, and what type of function is being called. This commit adds support for both packed, and unpacked array slicing, with the default being unpacked. With an unpacked array slice, when the user asks for a slice of an array GDB creates a new type that accurately describes where the elements of the slice can be found within the original array, a value of this type is then returned to the user. The address of an element within the slice will be equal to the address of an element within the original array. A user can choose to select packed array slices instead using: (gdb) set fortran repack-array-slices on|off (gdb) show fortran repack-array-slices With packed array slices GDB creates a new type that reflects how the elements of the slice would look if they were laid out in contiguous memory, allocates a value of this type, and then fetches the elements from the original array and places then into the contents buffer of the new value. One benefit of using packed slices over unpacked slices is the memory usage, taking a small slice of N elements from a large array will require (in GDB) N * ELEMENT_SIZE bytes of memory, while an unpacked array will also include all of the "padding" between the non-contiguous elements. There are new tests added that highlight this difference. There is also a new debugging flag added with this commit that introduces these commands: (gdb) set debug fortran-array-slicing on|off (gdb) show debug fortran-array-slicing This prints information about how the array slices are being built. As both the repacking, and the array printing requires GDB to walk through a multi-dimensional Fortran array visiting each element, this commit adds the file f-array-walk.h, which introduces some infrastructure to support this process. This means the array printing code in f-valprint.c is significantly reduced. The only slight issue with this commit is the "rather big hack" that I mentioned above. This hack allows us to handle one specific case, array slices with negative strides. This is something that I don't believe the current GDB value contents model will allow us to correctly handle, and rather than rewrite the value contents code right now, I'm hoping to slip this hack in as a work around. The problem is that, as I see it, the current value contents model assumes that an object base address will be the lowest address within that object, and that the contents of the object start at this base address and occupy the TYPE_LENGTH bytes after that. ( We do have the embedded_offset, which is used for C++ sub-classes, such that an object can start at some offset from the content buffer, however, the assumption that the object then occupies the next TYPE_LENGTH bytes is still true within GDB. ) The problem is that Fortran arrays with a negative stride don't follow this pattern. In this case the base address of the object points to the element with the highest address, the contents of the array then start at some offset _before_ the base address, and proceed for one element _past_ the base address. As the stride for such an array would be negative then, in theory the TYPE_LENGTH for this type would also be negative. However, in many places a value in GDB will degrade to a pointer + length, and the length almost always comes from the TYPE_LENGTH. It is my belief that in order to correctly model this case the value content handling of GDB will need to be reworked to split apart the value's content buffer (which is a block of memory with a length), and the object's in memory base address and length, which could be negative. Things are further complicated because arrays with negative strides like this are always dynamic types. When a value has a dynamic type and its base address needs resolving we actually store the address of the object within the resolved dynamic type, not within the value object itself. In short I don't currently see an easy path to cleanly support this situation within GDB. And so I believe that leaves two options, either add a work around, or catch cases where the user tries to make use of a negative stride, or access an array with a negative stride, and throw an error. This patch currently goes with adding a work around, which is that when we resolve a dynamic Fortran array type, if the stride is negative, then we adjust the base address to point to the lowest address required by the array. The printing and slicing code is aware of this adjustment and will correctly slice and print Fortran arrays. Where this hack will show through to the user is if they ask for the address of an array in their program with a negative array stride, the address they get from GDB will not match the address that would be computed within the Fortran program. gdb/ChangeLog: * Makefile.in (HFILES_NO_SRCDIR): Add f-array-walker.h. * NEWS: Mention new options. * f-array-walker.h: New file. * f-lang.c: Include 'gdbcmd.h' and 'f-array-walker.h'. (repack_array_slices): New static global. (show_repack_array_slices): New function. (fortran_array_slicing_debug): New static global. (show_fortran_array_slicing_debug): New function. (value_f90_subarray): Delete. (skip_undetermined_arglist): Delete. (class fortran_array_repacker_base_impl): New class. (class fortran_lazy_array_repacker_impl): New class. (class fortran_array_repacker_impl): New class. (fortran_value_subarray): Complete rewrite. (set_fortran_list): New static global. (show_fortran_list): Likewise. (_initialize_f_language): Register new commands. (fortran_adjust_dynamic_array_base_address_hack): New function. * f-lang.h (fortran_adjust_dynamic_array_base_address_hack): Declare. * f-valprint.c: Include 'f-array-walker.h'. (class fortran_array_printer_impl): New class. (f77_print_array_1): Delete. (f77_print_array): Delete. (fortran_print_array): New. (f_value_print_inner): Update to call fortran_print_array. * gdbtypes.c: Include 'f-lang.h'. (resolve_dynamic_type_internal): Call fortran_adjust_dynamic_array_base_address_hack. gdb/testsuite/ChangeLog: * gdb.fortran/array-slices-bad.exp: New file. * gdb.fortran/array-slices-bad.f90: New file. * gdb.fortran/array-slices-sub-slices.exp: New file. * gdb.fortran/array-slices-sub-slices.f90: New file. * gdb.fortran/array-slices.exp: Rewrite tests. * gdb.fortran/array-slices.f90: Rewrite tests. * gdb.fortran/vla-sizeof.exp: Correct expected results. gdb/doc/ChangeLog: * gdb.texinfo (Debugging Output): Document 'set/show debug fortran-array-slicing'. (Special Fortran Commands): Document 'set/show fortran repack-array-slices'.
2020-10-08 23:45:59 +08:00
private:
/* The offset into the content buffer of M_VAL to the start of the slice
being extracted. */
LONGEST m_base_offset;
gdb/fortran: Move Fortran expression handling into f-lang.c The Fortran specific OP_F77_UNDETERMINED_ARGLIST is currently handled in the generic expression handling code. There's no reason why this should be the case, so this commit moves handling of this into Fortran specific files. There should be no user visible changes after this commit. gdb/ChangeLog: * eval.c: Remove 'f-lang.h' include. (value_f90_subarray): Moved to f-lang.c. (eval_call): Renamed to... (evaluate_subexp_do_call): ...this, is no longer static, header comment moved into header file. (evaluate_funcall): Update call to eval_call. (skip_undetermined_arglist): Moved to f-lang.c. (fortran_value_subarray): Likewise. (evaluate_subexp_standard): OP_F77_UNDETERMINED_ARGLIST handling moved to evaluate_subexp_f. (calc_f77_array_dims): Moved to f-lang.c * expprint.c (print_subexp_funcall): New function. (print_subexp_standard): OP_F77_UNDETERMINED_ARGLIST handling moved to print_subexp_f, OP_FUNCALL uses new function. (dump_subexp_body_funcall): New function. (dump_subexp_body_standard): OP_F77_UNDETERMINED_ARGLIST handling moved to dump_subexp_f, OP_FUNCALL uses new function. * expression.h (evaluate_subexp_do_call): Declare. * f-lang.c (value_f90_subarray): Moved from eval.c. (skip_undetermined_arglist): Likewise. (calc_f77_array_dims): Likewise. (fortran_value_subarray): Likewise. (evaluate_subexp_f): Add OP_F77_UNDETERMINED_ARGLIST support. (operator_length_f): Likewise. (print_subexp_f): Likewise. (dump_subexp_body_f): Likewise. * fortran-operator.def (OP_F77_UNDETERMINED_ARGLIST): Move declaration of this operation to here. * parse.c (operator_length_standard): OP_F77_UNDETERMINED_ARGLIST support moved to operator_length_f. * parser-defs.h (dump_subexp_body_funcall): Declare. (print_subexp_funcall): Declare. * std-operator.def (OP_F77_UNDETERMINED_ARGLIST): Moved to fortran-operator.def.
2020-05-07 23:27:16 +08:00
/* The parent value from which we are extracting a slice. */
struct value *m_val;
};
gdb/fortran: Move Fortran expression handling into f-lang.c The Fortran specific OP_F77_UNDETERMINED_ARGLIST is currently handled in the generic expression handling code. There's no reason why this should be the case, so this commit moves handling of this into Fortran specific files. There should be no user visible changes after this commit. gdb/ChangeLog: * eval.c: Remove 'f-lang.h' include. (value_f90_subarray): Moved to f-lang.c. (eval_call): Renamed to... (evaluate_subexp_do_call): ...this, is no longer static, header comment moved into header file. (evaluate_funcall): Update call to eval_call. (skip_undetermined_arglist): Moved to f-lang.c. (fortran_value_subarray): Likewise. (evaluate_subexp_standard): OP_F77_UNDETERMINED_ARGLIST handling moved to evaluate_subexp_f. (calc_f77_array_dims): Moved to f-lang.c * expprint.c (print_subexp_funcall): New function. (print_subexp_standard): OP_F77_UNDETERMINED_ARGLIST handling moved to print_subexp_f, OP_FUNCALL uses new function. (dump_subexp_body_funcall): New function. (dump_subexp_body_standard): OP_F77_UNDETERMINED_ARGLIST handling moved to dump_subexp_f, OP_FUNCALL uses new function. * expression.h (evaluate_subexp_do_call): Declare. * f-lang.c (value_f90_subarray): Moved from eval.c. (skip_undetermined_arglist): Likewise. (calc_f77_array_dims): Likewise. (fortran_value_subarray): Likewise. (evaluate_subexp_f): Add OP_F77_UNDETERMINED_ARGLIST support. (operator_length_f): Likewise. (print_subexp_f): Likewise. (dump_subexp_body_f): Likewise. * fortran-operator.def (OP_F77_UNDETERMINED_ARGLIST): Move declaration of this operation to here. * parse.c (operator_length_standard): OP_F77_UNDETERMINED_ARGLIST support moved to operator_length_f. * parser-defs.h (dump_subexp_body_funcall): Declare. (print_subexp_funcall): Declare. * std-operator.def (OP_F77_UNDETERMINED_ARGLIST): Moved to fortran-operator.def.
2020-05-07 23:27:16 +08:00
/* Evaluate FORTRAN_ASSOCIATED expressions. Both GDBARCH and LANG are
extracted from the expression being evaluated. POINTER is the required
first argument to the 'associated' keyword, and TARGET is the optional
second argument, this will be nullptr if the user only passed one
argument to their use of 'associated'. */
static struct value *
fortran_associated (struct gdbarch *gdbarch, const language_defn *lang,
struct value *pointer, struct value *target = nullptr)
{
struct type *result_type = language_bool_type (lang, gdbarch);
/* All Fortran pointers should have the associated property, this is
how we know the pointer is pointing at something or not. */
struct type *pointer_type = check_typedef (pointer->type ());
if (TYPE_ASSOCIATED_PROP (pointer_type) == nullptr
&& pointer_type->code () != TYPE_CODE_PTR)
error (_("ASSOCIATED can only be applied to pointers"));
/* Get an address from POINTER. Fortran (or at least gfortran) models
array pointers as arrays with a dynamic data address, so we need to
use two approaches here, for real pointers we take the contents of the
pointer as an address. For non-pointers we take the address of the
content. */
CORE_ADDR pointer_addr;
if (pointer_type->code () == TYPE_CODE_PTR)
pointer_addr = value_as_address (pointer);
else
pointer_addr = pointer->address ();
/* The single argument case, is POINTER associated with anything? */
if (target == nullptr)
{
bool is_associated = false;
/* If POINTER is an actual pointer and doesn't have an associated
property then we need to figure out whether this pointer is
associated by looking at the value of the pointer itself. We make
the assumption that a non-associated pointer will be set to 0.
This is probably true for most targets, but might not be true for
everyone. */
if (pointer_type->code () == TYPE_CODE_PTR
&& TYPE_ASSOCIATED_PROP (pointer_type) == nullptr)
is_associated = (pointer_addr != 0);
else
is_associated = !type_not_associated (pointer_type);
return value_from_longest (result_type, is_associated ? 1 : 0);
}
/* The two argument case, is POINTER associated with TARGET? */
struct type *target_type = check_typedef (target->type ());
struct type *pointer_target_type;
if (pointer_type->code () == TYPE_CODE_PTR)
pointer_target_type = pointer_type->target_type ();
else
pointer_target_type = pointer_type;
struct type *target_target_type;
if (target_type->code () == TYPE_CODE_PTR)
target_target_type = target_type->target_type ();
else
target_target_type = target_type;
if (pointer_target_type->code () != target_target_type->code ()
|| (pointer_target_type->code () != TYPE_CODE_ARRAY
&& (pointer_target_type->length ()
!= target_target_type->length ())))
error (_("arguments to associated must be of same type and kind"));
/* If TARGET is not in memory, or the original pointer is specifically
known to be not associated with anything, then the answer is obviously
false. Alternatively, if POINTER is an actual pointer and has no
associated property, then we have to check if its associated by
looking the value of the pointer itself. We make the assumption that
a non-associated pointer will be set to 0. This is probably true for
most targets, but might not be true for everyone. */
if (target->lval () != lval_memory
|| type_not_associated (pointer_type)
|| (TYPE_ASSOCIATED_PROP (pointer_type) == nullptr
&& pointer_type->code () == TYPE_CODE_PTR
&& pointer_addr == 0))
return value_from_longest (result_type, 0);
/* See the comment for POINTER_ADDR above. */
CORE_ADDR target_addr;
if (target_type->code () == TYPE_CODE_PTR)
target_addr = value_as_address (target);
else
target_addr = target->address ();
/* Wrap the following checks inside a do { ... } while (false) loop so
that we can use `break' to jump out of the loop. */
bool is_associated = false;
do
{
/* If the addresses are different then POINTER is definitely not
pointing at TARGET. */
if (pointer_addr != target_addr)
break;
/* If POINTER is a real pointer (i.e. not an array pointer, which are
implemented as arrays with a dynamic content address), then this
is all the checking that is needed. */
if (pointer_type->code () == TYPE_CODE_PTR)
{
is_associated = true;
break;
}
/* We have an array pointer. Check the number of dimensions. */
int pointer_dims = calc_f77_array_dims (pointer_type);
int target_dims = calc_f77_array_dims (target_type);
if (pointer_dims != target_dims)
break;
/* Now check that every dimension has the same upper bound, lower
bound, and stride value. */
int dim = 0;
while (dim < pointer_dims)
{
LONGEST pointer_lowerbound, pointer_upperbound, pointer_stride;
LONGEST target_lowerbound, target_upperbound, target_stride;
pointer_type = check_typedef (pointer_type);
target_type = check_typedef (target_type);
struct type *pointer_range = pointer_type->index_type ();
struct type *target_range = target_type->index_type ();
if (!get_discrete_bounds (pointer_range, &pointer_lowerbound,
&pointer_upperbound))
break;
if (!get_discrete_bounds (target_range, &target_lowerbound,
&target_upperbound))
break;
if (pointer_lowerbound != target_lowerbound
|| pointer_upperbound != target_upperbound)
break;
/* Figure out the stride (in bits) for both pointer and target.
If either doesn't have a stride then we take the element size,
but we need to convert to bits (hence the * 8). */
pointer_stride = pointer_range->bounds ()->bit_stride ();
if (pointer_stride == 0)
pointer_stride
= type_length_units (check_typedef
(pointer_type->target_type ())) * 8;
target_stride = target_range->bounds ()->bit_stride ();
if (target_stride == 0)
target_stride
= type_length_units (check_typedef
(target_type->target_type ())) * 8;
if (pointer_stride != target_stride)
break;
++dim;
}
if (dim < pointer_dims)
break;
is_associated = true;
}
while (false);
return value_from_longest (result_type, is_associated ? 1 : 0);
}
struct value *
eval_op_f_associated (struct type *expect_type,
struct expression *exp,
enum noside noside,
enum exp_opcode opcode,
struct value *arg1)
{
return fortran_associated (exp->gdbarch, exp->language_defn, arg1);
}
struct value *
eval_op_f_associated (struct type *expect_type,
struct expression *exp,
enum noside noside,
enum exp_opcode opcode,
struct value *arg1,
struct value *arg2)
{
return fortran_associated (exp->gdbarch, exp->language_defn, arg1, arg2);
}
/* Implement FORTRAN_ARRAY_SIZE expression, this corresponds to the 'SIZE'
keyword. RESULT_TYPE corresponds to the type kind the function should be
evaluated in, ARRAY is the value that should be an array, though this will
not have been checked before calling this function. DIM is optional, if
present then it should be an integer identifying a dimension of the
array to ask about. As with ARRAY the validity of DIM is not checked
before calling this function.
Return either the total number of elements in ARRAY (when DIM is
nullptr), or the number of elements in dimension DIM. */
static value *
fortran_array_size (value *array, value *dim_val, type *result_type)
{
/* Check that ARRAY is the correct type. */
struct type *array_type = check_typedef (array->type ());
if (array_type->code () != TYPE_CODE_ARRAY)
error (_("SIZE can only be applied to arrays"));
if (type_not_allocated (array_type) || type_not_associated (array_type))
error (_("SIZE can only be used on allocated/associated arrays"));
int ndimensions = calc_f77_array_dims (array_type);
int dim = -1;
LONGEST result = 0;
if (dim_val != nullptr)
{
if (check_typedef (dim_val->type ())->code () != TYPE_CODE_INT)
error (_("DIM argument to SIZE must be an integer"));
dim = (int) value_as_long (dim_val);
if (dim < 1 || dim > ndimensions)
error (_("DIM argument to SIZE must be between 1 and %d"),
ndimensions);
}
/* Now walk over all the dimensions of the array totalling up the
elements in each dimension. */
for (int i = ndimensions - 1; i >= 0; --i)
{
/* If this is the requested dimension then we're done. Grab the
bounds and return. */
if (i == dim - 1 || dim == -1)
{
LONGEST lbound, ubound;
struct type *range = array_type->index_type ();
if (!get_discrete_bounds (range, &lbound, &ubound))
error (_("failed to find array bounds"));
LONGEST dim_size = (ubound - lbound + 1);
if (result == 0)
result = dim_size;
else
result *= dim_size;
if (dim != -1)
break;
}
/* Peel off another dimension of the array. */
array_type = array_type->target_type ();
}
return value_from_longest (result_type, result);
}
/* See f-exp.h. */
struct value *
eval_op_f_array_size (struct type *expect_type,
struct expression *exp,
enum noside noside,
enum exp_opcode opcode,
struct value *arg1)
{
gdb_assert (opcode == FORTRAN_ARRAY_SIZE);
type *result_type = builtin_f_type (exp->gdbarch)->builtin_integer;
return fortran_array_size (arg1, nullptr, result_type);
}
/* See f-exp.h. */
struct value *
eval_op_f_array_size (struct type *expect_type,
struct expression *exp,
enum noside noside,
enum exp_opcode opcode,
struct value *arg1,
struct value *arg2)
{
gdb_assert (opcode == FORTRAN_ARRAY_SIZE);
type *result_type = builtin_f_type (exp->gdbarch)->builtin_integer;
return fortran_array_size (arg1, arg2, result_type);
}
/* See f-exp.h. */
value *eval_op_f_array_size (type *expect_type, expression *exp, noside noside,
exp_opcode opcode, value *arg1, value *arg2,
type *kind_arg)
{
gdb_assert (opcode == FORTRAN_ARRAY_SIZE);
gdb_assert (kind_arg->code () == TYPE_CODE_INT);
return fortran_array_size (arg1, arg2, kind_arg);
}
/* Implement UNOP_FORTRAN_SHAPE expression. Both GDBARCH and LANG are
extracted from the expression being evaluated. VAL is the value on
which 'shape' was used, this can be any type.
Return an array of integers. If VAL is not an array then the returned
array should have zero elements. If VAL is an array then the returned
array should have one element per dimension, with the element
containing the extent of that dimension from VAL. */
static struct value *
fortran_array_shape (struct gdbarch *gdbarch, const language_defn *lang,
struct value *val)
{
struct type *val_type = check_typedef (val->type ());
/* If we are passed an array that is either not allocated, or not
associated, then this is explicitly not allowed according to the
Fortran specification. */
if (val_type->code () == TYPE_CODE_ARRAY
&& (type_not_associated (val_type) || type_not_allocated (val_type)))
error (_("The array passed to SHAPE must be allocated or associated"));
/* The Fortran specification allows non-array types to be passed to this
function, in which case we get back an empty array.
Calculate the number of dimensions for the resulting array. */
int ndimensions = 0;
if (val_type->code () == TYPE_CODE_ARRAY)
ndimensions = calc_f77_array_dims (val_type);
/* Allocate a result value of the correct type. */
type_allocator alloc (gdbarch);
struct type *range
= create_static_range_type (alloc,
builtin_type (gdbarch)->builtin_int,
1, ndimensions);
struct type *elm_type = builtin_f_type (gdbarch)->builtin_integer;
struct type *result_type = create_array_type (alloc, elm_type, range);
struct value *result = value::allocate (result_type);
LONGEST elm_len = elm_type->length ();
/* Walk the array dimensions backwards due to the way the array will be
laid out in memory, the first dimension will be the most inner.
If VAL was not an array then ndimensions will be 0, in which case we
will never go around this loop. */
for (LONGEST dst_offset = elm_len * (ndimensions - 1);
dst_offset >= 0;
dst_offset -= elm_len)
{
LONGEST lbound, ubound;
if (!get_discrete_bounds (val_type->index_type (), &lbound, &ubound))
error (_("failed to find array bounds"));
LONGEST dim_size = (ubound - lbound + 1);
/* And copy the value into the result value. */
struct value *v = value_from_longest (elm_type, dim_size);
gdb_assert (dst_offset + v->type ()->length ()
<= result->type ()->length ());
gdb_assert (v->type ()->length () == elm_len);
v->contents_copy (result, dst_offset, 0, elm_len);
/* Peel another dimension of the array. */
val_type = val_type->target_type ();
}
return result;
}
/* See f-exp.h. */
struct value *
eval_op_f_array_shape (struct type *expect_type, struct expression *exp,
enum noside noside, enum exp_opcode opcode,
struct value *arg1)
{
gdb_assert (opcode == UNOP_FORTRAN_SHAPE);
return fortran_array_shape (exp->gdbarch, exp->language_defn, arg1);
}
/* A helper function for UNOP_ABS. */
struct value *
eval_op_f_abs (struct type *expect_type, struct expression *exp,
enum noside noside,
enum exp_opcode opcode,
struct value *arg1)
{
struct type *type = arg1->type ();
switch (type->code ())
{
case TYPE_CODE_FLT:
{
double d
= fabs (target_float_to_host_double (arg1->contents ().data (),
arg1->type ()));
return value_from_host_double (type, d);
}
case TYPE_CODE_INT:
{
LONGEST l = value_as_long (arg1);
l = llabs (l);
return value_from_longest (type, l);
}
}
error (_("ABS of type %s not supported"), TYPE_SAFE_NAME (type));
}
/* A helper function for BINOP_MOD. */
struct value *
eval_op_f_mod (struct type *expect_type, struct expression *exp,
enum noside noside,
enum exp_opcode opcode,
struct value *arg1, struct value *arg2)
{
struct type *type = arg1->type ();
if (type->code () != arg2->type ()->code ())
error (_("non-matching types for parameters to MOD ()"));
switch (type->code ())
{
case TYPE_CODE_FLT:
{
double d1
= target_float_to_host_double (arg1->contents ().data (),
arg1->type ());
double d2
= target_float_to_host_double (arg2->contents ().data (),
arg2->type ());
double d3 = fmod (d1, d2);
return value_from_host_double (type, d3);
}
case TYPE_CODE_INT:
{
LONGEST v1 = value_as_long (arg1);
LONGEST v2 = value_as_long (arg2);
if (v2 == 0)
error (_("calling MOD (N, 0) is undefined"));
LONGEST v3 = v1 - (v1 / v2) * v2;
return value_from_longest (arg1->type (), v3);
}
}
error (_("MOD of type %s not supported"), TYPE_SAFE_NAME (type));
}
/* A helper function for the different FORTRAN_CEILING overloads. Calculates
CEILING for ARG1 (a float type) and returns it in the requested kind type
RESULT_TYPE. */
static value *
fortran_ceil_operation (value *arg1, type *result_type)
{
if (arg1->type ()->code () != TYPE_CODE_FLT)
error (_("argument to CEILING must be of type float"));
double val = target_float_to_host_double (arg1->contents ().data (),
arg1->type ());
val = ceil (val);
return value_from_longest (result_type, val);
}
/* A helper function for FORTRAN_CEILING. */
struct value *
eval_op_f_ceil (struct type *expect_type, struct expression *exp,
enum noside noside,
enum exp_opcode opcode,
struct value *arg1)
{
gdb_assert (opcode == FORTRAN_CEILING);
type *result_type = builtin_f_type (exp->gdbarch)->builtin_integer;
return fortran_ceil_operation (arg1, result_type);
}
/* A helper function for FORTRAN_CEILING. */
value *
eval_op_f_ceil (type *expect_type, expression *exp, noside noside,
exp_opcode opcode, value *arg1, type *kind_arg)
{
gdb_assert (opcode == FORTRAN_CEILING);
gdb_assert (kind_arg->code () == TYPE_CODE_INT);
return fortran_ceil_operation (arg1, kind_arg);
}
/* A helper function for the different FORTRAN_FLOOR overloads. Calculates
FLOOR for ARG1 (a float type) and returns it in the requested kind type
RESULT_TYPE. */
static value *
fortran_floor_operation (value *arg1, type *result_type)
{
if (arg1->type ()->code () != TYPE_CODE_FLT)
error (_("argument to FLOOR must be of type float"));
double val = target_float_to_host_double (arg1->contents ().data (),
arg1->type ());
val = floor (val);
return value_from_longest (result_type, val);
}
/* A helper function for FORTRAN_FLOOR. */
struct value *
eval_op_f_floor (struct type *expect_type, struct expression *exp,
enum noside noside,
enum exp_opcode opcode,
struct value *arg1)
{
gdb_assert (opcode == FORTRAN_FLOOR);
type *result_type = builtin_f_type (exp->gdbarch)->builtin_integer;
return fortran_floor_operation (arg1, result_type);
}
/* A helper function for FORTRAN_FLOOR. */
struct value *
eval_op_f_floor (type *expect_type, expression *exp, noside noside,
exp_opcode opcode, value *arg1, type *kind_arg)
{
gdb_assert (opcode == FORTRAN_FLOOR);
gdb_assert (kind_arg->code () == TYPE_CODE_INT);
return fortran_floor_operation (arg1, kind_arg);
}
/* A helper function for BINOP_FORTRAN_MODULO. */
struct value *
eval_op_f_modulo (struct type *expect_type, struct expression *exp,
enum noside noside,
enum exp_opcode opcode,
struct value *arg1, struct value *arg2)
{
struct type *type = arg1->type ();
if (type->code () != arg2->type ()->code ())
error (_("non-matching types for parameters to MODULO ()"));
/* MODULO(A, P) = A - FLOOR (A / P) * P */
switch (type->code ())
{
case TYPE_CODE_INT:
{
LONGEST a = value_as_long (arg1);
LONGEST p = value_as_long (arg2);
LONGEST result = a - (a / p) * p;
if (result != 0 && (a < 0) != (p < 0))
result += p;
return value_from_longest (arg1->type (), result);
}
case TYPE_CODE_FLT:
{
double a
= target_float_to_host_double (arg1->contents ().data (),
arg1->type ());
double p
= target_float_to_host_double (arg2->contents ().data (),
arg2->type ());
double result = fmod (a, p);
if (result != 0 && (a < 0.0) != (p < 0.0))
result += p;
return value_from_host_double (type, result);
}
}
error (_("MODULO of type %s not supported"), TYPE_SAFE_NAME (type));
}
/* A helper function for FORTRAN_CMPLX. */
value *
eval_op_f_cmplx (type *expect_type, expression *exp, noside noside,
exp_opcode opcode, value *arg1)
{
gdb_assert (opcode == FORTRAN_CMPLX);
type *result_type = builtin_f_type (exp->gdbarch)->builtin_complex;
if (arg1->type ()->code () == TYPE_CODE_COMPLEX)
return value_cast (result_type, arg1);
else
return value_literal_complex (arg1,
value::zero (arg1->type (), not_lval),
result_type);
}
/* A helper function for FORTRAN_CMPLX. */
struct value *
eval_op_f_cmplx (struct type *expect_type, struct expression *exp,
enum noside noside,
enum exp_opcode opcode,
struct value *arg1, struct value *arg2)
{
if (arg1->type ()->code () == TYPE_CODE_COMPLEX
|| arg2->type ()->code () == TYPE_CODE_COMPLEX)
error (_("Types of arguments for CMPLX called with more then one argument "
"must be REAL or INTEGER"));
type *result_type = builtin_f_type (exp->gdbarch)->builtin_complex;
return value_literal_complex (arg1, arg2, result_type);
}
/* A helper function for FORTRAN_CMPLX. */
value *
eval_op_f_cmplx (type *expect_type, expression *exp, noside noside,
exp_opcode opcode, value *arg1, value *arg2, type *kind_arg)
{
gdb_assert (kind_arg->code () == TYPE_CODE_COMPLEX);
if (arg1->type ()->code () == TYPE_CODE_COMPLEX
|| arg2->type ()->code () == TYPE_CODE_COMPLEX)
error (_("Types of arguments for CMPLX called with more then one argument "
"must be REAL or INTEGER"));
return value_literal_complex (arg1, arg2, kind_arg);
}
/* A helper function for UNOP_FORTRAN_KIND. */
struct value *
eval_op_f_kind (struct type *expect_type, struct expression *exp,
enum noside noside,
enum exp_opcode opcode,
struct value *arg1)
{
struct type *type = arg1->type ();
switch (type->code ())
{
case TYPE_CODE_STRUCT:
case TYPE_CODE_UNION:
case TYPE_CODE_MODULE:
case TYPE_CODE_FUNC:
error (_("argument to kind must be an intrinsic type"));
}
if (!type->target_type ())
return value_from_longest (builtin_type (exp->gdbarch)->builtin_int,
type->length ());
return value_from_longest (builtin_type (exp->gdbarch)->builtin_int,
type->target_type ()->length ());
}
/* A helper function for UNOP_FORTRAN_ALLOCATED. */
struct value *
eval_op_f_allocated (struct type *expect_type, struct expression *exp,
enum noside noside, enum exp_opcode op,
struct value *arg1)
{
struct type *type = check_typedef (arg1->type ());
if (type->code () != TYPE_CODE_ARRAY)
error (_("ALLOCATED can only be applied to arrays"));
struct type *result_type
= builtin_f_type (exp->gdbarch)->builtin_logical;
LONGEST result_value = type_not_allocated (type) ? 0 : 1;
return value_from_longest (result_type, result_value);
}
/* See f-exp.h. */
struct value *
eval_op_f_rank (struct type *expect_type,
struct expression *exp,
enum noside noside,
enum exp_opcode op,
struct value *arg1)
{
gdb_assert (op == UNOP_FORTRAN_RANK);
struct type *result_type
= builtin_f_type (exp->gdbarch)->builtin_integer;
struct type *type = check_typedef (arg1->type ());
if (type->code () != TYPE_CODE_ARRAY)
return value_from_longest (result_type, 0);
LONGEST ndim = calc_f77_array_dims (type);
return value_from_longest (result_type, ndim);
}
/* A helper function for UNOP_FORTRAN_LOC. */
struct value *
eval_op_f_loc (struct type *expect_type, struct expression *exp,
enum noside noside, enum exp_opcode op,
struct value *arg1)
{
struct type *result_type;
if (gdbarch_ptr_bit (exp->gdbarch) == 16)
result_type = builtin_f_type (exp->gdbarch)->builtin_integer_s2;
else if (gdbarch_ptr_bit (exp->gdbarch) == 32)
result_type = builtin_f_type (exp->gdbarch)->builtin_integer;
else
result_type = builtin_f_type (exp->gdbarch)->builtin_integer_s8;
LONGEST result_value = arg1->address ();
return value_from_longest (result_type, result_value);
}
namespace expr
{
/* Called from evaluate to perform array indexing, and sub-range
extraction, for Fortran. As well as arrays this function also
handles strings as they can be treated like arrays of characters.
ARRAY is the array or string being accessed. EXP and NOSIDE are as
for evaluate. */
value *
fortran_undetermined::value_subarray (value *array,
struct expression *exp,
enum noside noside)
{
type *original_array_type = check_typedef (array->type ());
bool is_string_p = original_array_type->code () == TYPE_CODE_STRING;
const std::vector<operation_up> &ops = std::get<1> (m_storage);
int nargs = ops.size ();
/* Perform checks for ARRAY not being available. The somewhat overly
complex logic here is just to keep backward compatibility with the
errors that we used to get before FORTRAN_VALUE_SUBARRAY was
rewritten. Maybe a future task would streamline the error messages we
get here, and update all the expected test results. */
if (ops[0]->opcode () != OP_RANGE)
{
if (type_not_associated (original_array_type))
error (_("no such vector element (vector not associated)"));
else if (type_not_allocated (original_array_type))
error (_("no such vector element (vector not allocated)"));
}
else
{
if (type_not_associated (original_array_type))
error (_("array not associated"));
else if (type_not_allocated (original_array_type))
error (_("array not allocated"));
}
/* First check that the number of dimensions in the type we are slicing
matches the number of arguments we were passed. */
int ndimensions = calc_f77_array_dims (original_array_type);
if (nargs != ndimensions)
error (_("Wrong number of subscripts"));
/* This will be initialised below with the type of the elements held in
ARRAY. */
struct type *inner_element_type;
/* Extract the types of each array dimension from the original array
type. We need these available so we can fill in the default upper and
lower bounds if the user requested slice doesn't provide that
information. Additionally unpacking the dimensions like this gives us
the inner element type. */
std::vector<struct type *> dim_types;
{
dim_types.reserve (ndimensions);
struct type *type = original_array_type;
for (int i = 0; i < ndimensions; ++i)
{
dim_types.push_back (type);
type = type->target_type ();
}
/* TYPE is now the inner element type of the array, we start the new
array slice off as this type, then as we process the requested slice
(from the user) we wrap new types around this to build up the final
slice type. */
inner_element_type = type;
}
/* As we analyse the new slice type we need to understand if the data
being referenced is contiguous. Do decide this we must track the size
of an element at each dimension of the new slice array. Initially the
elements of the inner most dimension of the array are the same inner
most elements as the original ARRAY. */
LONGEST slice_element_size = inner_element_type->length ();
/* Start off assuming all data is contiguous, this will be set to false
if access to any dimension results in non-contiguous data. */
bool is_all_contiguous = true;
/* The TOTAL_OFFSET is the distance in bytes from the start of the
original ARRAY to the start of the new slice. This is calculated as
we process the information from the user. */
LONGEST total_offset = 0;
/* A structure representing information about each dimension of the
resulting slice. */
struct slice_dim
{
/* Constructor. */
slice_dim (LONGEST l, LONGEST h, LONGEST s, struct type *idx)
: low (l),
high (h),
stride (s),
index (idx)
{ /* Nothing. */ }
/* The low bound for this dimension of the slice. */
LONGEST low;
/* The high bound for this dimension of the slice. */
LONGEST high;
/* The byte stride for this dimension of the slice. */
LONGEST stride;
struct type *index;
};
/* The dimensions of the resulting slice. */
std::vector<slice_dim> slice_dims;
/* Process the incoming arguments. These arguments are in the reverse
order to the array dimensions, that is the first argument refers to
the last array dimension. */
if (fortran_array_slicing_debug)
debug_printf ("Processing array access:\n");
for (int i = 0; i < nargs; ++i)
{
/* For each dimension of the array the user will have either provided
a ranged access with optional lower bound, upper bound, and
stride, or the user will have supplied a single index. */
struct type *dim_type = dim_types[ndimensions - (i + 1)];
fortran_range_operation *range_op
= dynamic_cast<fortran_range_operation *> (ops[i].get ());
if (range_op != nullptr)
{
enum range_flag range_flag = range_op->get_flags ();
LONGEST low, high, stride;
low = high = stride = 0;
if ((range_flag & RANGE_LOW_BOUND_DEFAULT) == 0)
low = value_as_long (range_op->evaluate0 (exp, noside));
else
low = f77_get_lowerbound (dim_type);
if ((range_flag & RANGE_HIGH_BOUND_DEFAULT) == 0)
high = value_as_long (range_op->evaluate1 (exp, noside));
else
high = f77_get_upperbound (dim_type);
if ((range_flag & RANGE_HAS_STRIDE) == RANGE_HAS_STRIDE)
stride = value_as_long (range_op->evaluate2 (exp, noside));
else
stride = 1;
if (stride == 0)
error (_("stride must not be 0"));
/* Get information about this dimension in the original ARRAY. */
struct type *target_type = dim_type->target_type ();
struct type *index_type = dim_type->index_type ();
LONGEST lb = f77_get_lowerbound (dim_type);
LONGEST ub = f77_get_upperbound (dim_type);
LONGEST sd = index_type->bit_stride ();
if (sd == 0)
sd = target_type->length () * 8;
if (fortran_array_slicing_debug)
{
debug_printf ("|-> Range access\n");
std::string str = type_to_string (dim_type);
debug_printf ("| |-> Type: %s\n", str.c_str ());
debug_printf ("| |-> Array:\n");
debug_printf ("| | |-> Low bound: %s\n", plongest (lb));
debug_printf ("| | |-> High bound: %s\n", plongest (ub));
debug_printf ("| | |-> Bit stride: %s\n", plongest (sd));
debug_printf ("| | |-> Byte stride: %s\n", plongest (sd / 8));
debug_printf ("| | |-> Type size: %s\n",
pulongest (dim_type->length ()));
debug_printf ("| | '-> Target type size: %s\n",
pulongest (target_type->length ()));
debug_printf ("| |-> Accessing:\n");
debug_printf ("| | |-> Low bound: %s\n",
plongest (low));
debug_printf ("| | |-> High bound: %s\n",
plongest (high));
debug_printf ("| | '-> Element stride: %s\n",
plongest (stride));
}
/* Check the user hasn't asked for something invalid. */
if (high > ub || low < lb)
error (_("array subscript out of bounds"));
/* Calculate what this dimension of the new slice array will look
like. OFFSET is the byte offset from the start of the
previous (more outer) dimension to the start of this
dimension. E_COUNT is the number of elements in this
dimension. REMAINDER is the number of elements remaining
between the last included element and the upper bound. For
example an access '1:6:2' will include elements 1, 3, 5 and
have a remainder of 1 (element #6). */
LONGEST lowest = std::min (low, high);
LONGEST offset = (sd / 8) * (lowest - lb);
LONGEST e_count = std::abs (high - low) + 1;
e_count = (e_count + (std::abs (stride) - 1)) / std::abs (stride);
LONGEST new_low = 1;
LONGEST new_high = new_low + e_count - 1;
LONGEST new_stride = (sd * stride) / 8;
LONGEST last_elem = low + ((e_count - 1) * stride);
LONGEST remainder = high - last_elem;
if (low > high)
{
offset += std::abs (remainder) * target_type->length ();
if (stride > 0)
error (_("incorrect stride and boundary combination"));
}
else if (stride < 0)
error (_("incorrect stride and boundary combination"));
/* Is the data within this dimension contiguous? It is if the
newly computed stride is the same size as a single element of
this dimension. */
bool is_dim_contiguous = (new_stride == slice_element_size);
is_all_contiguous &= is_dim_contiguous;
if (fortran_array_slicing_debug)
{
debug_printf ("| '-> Results:\n");
debug_printf ("| |-> Offset = %s\n", plongest (offset));
debug_printf ("| |-> Elements = %s\n", plongest (e_count));
debug_printf ("| |-> Low bound = %s\n", plongest (new_low));
debug_printf ("| |-> High bound = %s\n",
plongest (new_high));
debug_printf ("| |-> Byte stride = %s\n",
plongest (new_stride));
debug_printf ("| |-> Last element = %s\n",
plongest (last_elem));
debug_printf ("| |-> Remainder = %s\n",
plongest (remainder));
debug_printf ("| '-> Contiguous = %s\n",
(is_dim_contiguous ? "Yes" : "No"));
}
/* Figure out how big (in bytes) an element of this dimension of
the new array slice will be. */
slice_element_size = std::abs (new_stride * e_count);
slice_dims.emplace_back (new_low, new_high, new_stride,
index_type);
/* Update the total offset. */
total_offset += offset;
}
else
{
/* There is a single index for this dimension. */
LONGEST index
= value_as_long (ops[i]->evaluate_with_coercion (exp, noside));
/* Get information about this dimension in the original ARRAY. */
struct type *target_type = dim_type->target_type ();
struct type *index_type = dim_type->index_type ();
LONGEST lb = f77_get_lowerbound (dim_type);
LONGEST ub = f77_get_upperbound (dim_type);
LONGEST sd = index_type->bit_stride () / 8;
if (sd == 0)
sd = target_type->length ();
if (fortran_array_slicing_debug)
{
debug_printf ("|-> Index access\n");
std::string str = type_to_string (dim_type);
debug_printf ("| |-> Type: %s\n", str.c_str ());
debug_printf ("| |-> Array:\n");
debug_printf ("| | |-> Low bound: %s\n", plongest (lb));
debug_printf ("| | |-> High bound: %s\n", plongest (ub));
debug_printf ("| | |-> Byte stride: %s\n", plongest (sd));
debug_printf ("| | |-> Type size: %s\n",
pulongest (dim_type->length ()));
debug_printf ("| | '-> Target type size: %s\n",
pulongest (target_type->length ()));
debug_printf ("| '-> Accessing:\n");
debug_printf ("| '-> Index: %s\n",
plongest (index));
}
/* If the array has actual content then check the index is in
bounds. An array without content (an unbound array) doesn't
have a known upper bound, so don't error check in that
situation. */
if (index < lb
|| (dim_type->index_type ()->bounds ()->high.is_available ()
&& index > ub)
|| (array->lval () != lval_memory
&& dim_type->index_type ()->bounds ()->high.kind () == PROP_UNDEFINED))
{
if (type_not_associated (dim_type))
error (_("no such vector element (vector not associated)"));
else if (type_not_allocated (dim_type))
error (_("no such vector element (vector not allocated)"));
else
error (_("no such vector element"));
}
/* Calculate using the type stride, not the target type size. */
LONGEST offset = sd * (index - lb);
total_offset += offset;
}
}
/* Build a type that represents the new array slice in the target memory
of the original ARRAY, this type makes use of strides to correctly
find only those elements that are part of the new slice. */
struct type *array_slice_type = inner_element_type;
for (const auto &d : slice_dims)
{
/* Create the range. */
dynamic_prop p_low, p_high, p_stride;
p_low.set_const_val (d.low);
p_high.set_const_val (d.high);
p_stride.set_const_val (d.stride);
type_allocator alloc (d.index->target_type ());
struct type *new_range
= create_range_type_with_stride (alloc,
d.index->target_type (),
&p_low, &p_high, 0, &p_stride,
true);
array_slice_type
= create_array_type (alloc, array_slice_type, new_range);
}
if (fortran_array_slicing_debug)
{
debug_printf ("'-> Final result:\n");
debug_printf (" |-> Type: %s\n",
type_to_string (array_slice_type).c_str ());
debug_printf (" |-> Total offset: %s\n",
plongest (total_offset));
debug_printf (" |-> Base address: %s\n",
core_addr_to_string (array->address ()));
debug_printf (" '-> Contiguous = %s\n",
(is_all_contiguous ? "Yes" : "No"));
}
/* Should we repack this array slice? */
if (!is_all_contiguous && (repack_array_slices || is_string_p))
{
/* Build a type for the repacked slice. */
struct type *repacked_array_type = inner_element_type;
for (const auto &d : slice_dims)
{
/* Create the range. */
dynamic_prop p_low, p_high, p_stride;
p_low.set_const_val (d.low);
p_high.set_const_val (d.high);
p_stride.set_const_val (repacked_array_type->length ());
type_allocator alloc (d.index->target_type ());
struct type *new_range
= create_range_type_with_stride (alloc,
d.index->target_type (),
&p_low, &p_high, 0, &p_stride,
true);
repacked_array_type
= create_array_type (alloc, repacked_array_type, new_range);
}
/* Now copy the elements from the original ARRAY into the packed
array value DEST. */
struct value *dest = value::allocate (repacked_array_type);
if (array->lazy ()
|| (total_offset + array_slice_type->length ()
> check_typedef (array->type ())->length ()))
{
fortran_array_walker<fortran_lazy_array_repacker_impl> p
(array_slice_type, array->address () + total_offset, dest);
p.walk ();
}
else
{
fortran_array_walker<fortran_array_repacker_impl> p
(array_slice_type, array->address () + total_offset,
total_offset, array, dest);
p.walk ();
}
array = dest;
}
else
{
if (array->lval () == lval_memory)
{
/* If the value we're taking a slice from is not yet loaded, or
the requested slice is outside the values content range then
just create a new lazy value pointing at the memory where the
contents we're looking for exist. */
if (array->lazy ()
|| (total_offset + array_slice_type->length ()
> check_typedef (array->type ())->length ()))
array = value_at_lazy (array_slice_type,
array->address () + total_offset);
else
array = value_from_contents_and_address
(array_slice_type, array->contents ().data () + total_offset,
array->address () + total_offset);
}
else if (!array->lazy ())
array = value_from_component (array, array_slice_type, total_offset);
else
error (_("cannot subscript arrays that are not in memory"));
}
return array;
}
value *
fortran_undetermined::evaluate (struct type *expect_type,
struct expression *exp,
enum noside noside)
{
value *callee = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
gdb/fortran: handle dynamic types within arrays and structures 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.
2021-01-08 21:07:32 +08:00
if (noside == EVAL_AVOID_SIDE_EFFECTS
&& is_dynamic_type (callee->type ()))
gdb/fortran: handle dynamic types within arrays and structures 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.
2021-01-08 21:07:32 +08:00
callee = std::get<0> (m_storage)->evaluate (nullptr, exp, EVAL_NORMAL);
struct type *type = check_typedef (callee->type ());
enum type_code code = type->code ();
if (code == TYPE_CODE_PTR)
{
/* Fortran always passes variable to subroutines as pointer.
So we need to look into its target type to see if it is
array, string or function. If it is, we need to switch
to the target value the original one points to. */
struct type *target_type = check_typedef (type->target_type ());
if (target_type->code () == TYPE_CODE_ARRAY
|| target_type->code () == TYPE_CODE_STRING
|| target_type->code () == TYPE_CODE_FUNC)
{
callee = value_ind (callee);
type = check_typedef (callee->type ());
code = type->code ();
}
}
switch (code)
{
case TYPE_CODE_ARRAY:
case TYPE_CODE_STRING:
return value_subarray (callee, exp, noside);
case TYPE_CODE_PTR:
case TYPE_CODE_FUNC:
case TYPE_CODE_INTERNAL_FUNCTION:
{
/* It's a function call. Allocate arg vector, including
space for the function to be called in argvec[0] and a
termination NULL. */
const std::vector<operation_up> &actual (std::get<1> (m_storage));
std::vector<value *> argvec (actual.size ());
bool is_internal_func = (code == TYPE_CODE_INTERNAL_FUNCTION);
for (int tem = 0; tem < argvec.size (); tem++)
argvec[tem] = fortran_prepare_argument (exp, actual[tem].get (),
tem, is_internal_func,
callee->type (),
noside);
return evaluate_subexp_do_call (exp, noside, callee, argvec,
nullptr, expect_type);
}
default:
error (_("Cannot perform substring on this type"));
}
}
value *
fortran_bound_1arg::evaluate (struct type *expect_type,
struct expression *exp,
enum noside noside)
{
bool lbound_p = std::get<0> (m_storage) == FORTRAN_LBOUND;
value *arg1 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
fortran_require_array (arg1->type (), lbound_p);
return fortran_bounds_all_dims (lbound_p, exp->gdbarch, arg1);
}
value *
fortran_bound_2arg::evaluate (struct type *expect_type,
struct expression *exp,
enum noside noside)
{
bool lbound_p = std::get<0> (m_storage) == FORTRAN_LBOUND;
value *arg1 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
fortran_require_array (arg1->type (), lbound_p);
/* User asked for the bounds of a specific dimension of the array. */
value *arg2 = std::get<2> (m_storage)->evaluate (nullptr, exp, noside);
type *type_arg2 = check_typedef (arg2->type ());
if (type_arg2->code () != TYPE_CODE_INT)
{
if (lbound_p)
error (_("LBOUND second argument should be an integer"));
else
error (_("UBOUND second argument should be an integer"));
}
type *result_type = builtin_f_type (exp->gdbarch)->builtin_integer;
return fortran_bounds_for_dimension (lbound_p, arg1, arg2, result_type);
}
value *
fortran_bound_3arg::evaluate (type *expect_type,
expression *exp,
noside noside)
{
const bool lbound_p = std::get<0> (m_storage) == FORTRAN_LBOUND;
value *arg1 = std::get<1> (m_storage)->evaluate (nullptr, exp, noside);
fortran_require_array (arg1->type (), lbound_p);
/* User asked for the bounds of a specific dimension of the array. */
value *arg2 = std::get<2> (m_storage)->evaluate (nullptr, exp, noside);
type *type_arg2 = check_typedef (arg2->type ());
if (type_arg2->code () != TYPE_CODE_INT)
{
if (lbound_p)
error (_("LBOUND second argument should be an integer"));
else
error (_("UBOUND second argument should be an integer"));
}
type *kind_arg = std::get<3> (m_storage);
gdb_assert (kind_arg->code () == TYPE_CODE_INT);
return fortran_bounds_for_dimension (lbound_p, arg1, arg2, kind_arg);
}
gdb/fortran: handle dynamic types within arrays and structures 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.
2021-01-08 21:07:32 +08:00
/* Implement STRUCTOP_STRUCT for Fortran. See operation::evaluate in
expression.h for argument descriptions. */
value *
fortran_structop_operation::evaluate (struct type *expect_type,
struct expression *exp,
enum noside noside)
{
value *arg1 = std::get<0> (m_storage)->evaluate (nullptr, exp, noside);
const char *str = std::get<1> (m_storage).c_str ();
if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
struct type *type = lookup_struct_elt_type (arg1->type (), str, 1);
gdb/fortran: handle dynamic types within arrays and structures 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.
2021-01-08 21:07:32 +08:00
if (type != nullptr && is_dynamic_type (type))
arg1 = std::get<0> (m_storage)->evaluate (nullptr, exp, EVAL_NORMAL);
}
gdb: use gdb::optional instead of passing a pointer to gdb::array_view Following on from the previous commit, this commit changes the API of value_struct_elt to take gdb::optional<gdb::array_view<value *>> instead of a pointer to the gdb::array_view. This makes the optional nature of the array_view parameter explicit. This commit is purely a refactoring commit, there should be no user visible change after this commit. I have deliberately kept this refactor separate from the previous two commits as this is a more extensive change, and I'm not 100% sure that using gdb::optional for the parameter type, instead of a pointer, is going to be to everyone's taste. If there's push back on this patch then this one can be dropped from the series. gdb/ChangeLog: * ada-lang.c (desc_bounds): Use '{}' instead of NULL to indicate an empty gdb::optional when calling value_struct_elt. (desc_data): Likewise. (desc_one_bound): Likewise. * eval.c (structop_base_operation::evaluate_funcall): Pass gdb::array_view, not a gdb::array_view* to value_struct_elt. (eval_op_structop_struct): Use '{}' instead of NULL to indicate an empty gdb::optional when calling value_struct_elt. (eval_op_structop_ptr): Likewise. * f-lang.c (fortran_structop_operation::evaluate): Likewise. * guile/scm-value.c (gdbscm_value_field): Likewise. * m2-lang.c (eval_op_m2_high): Likewise. (eval_op_m2_subscript): Likewise. * opencl-lang.c (opencl_structop_operation::evaluate): Likewise. * python/py-value.c (valpy_getitem): Likewise. * rust-lang.c (rust_val_print_str): Likewise. (rust_range): Likewise. (rust_subscript): Likewise. (eval_op_rust_structop): Likewise. (rust_aggregate_operation::evaluate): Likewise. * valarith.c (value_user_defined_op): Likewise. * valops.c (search_struct_method): Change parameter type, update function body accordingly, and update header comment. (value_struct_elt): Change parameter type, update function body accordingly. * value.h (value_struct_elt): Update declaration.
2021-06-23 02:27:53 +08:00
value *elt = value_struct_elt (&arg1, {}, str, NULL, "structure");
gdb/fortran: handle dynamic types within arrays and structures 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.
2021-01-08 21:07:32 +08:00
if (noside == EVAL_AVOID_SIDE_EFFECTS)
{
struct type *elt_type = elt->type ();
gdb/fortran: handle dynamic types within arrays and structures 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.
2021-01-08 21:07:32 +08:00
if (is_dynamic_type (elt_type))
{
const gdb_byte *valaddr = elt->contents_for_printing ().data ();
CORE_ADDR address = elt->address ();
gdb/fortran: handle dynamic types within arrays and structures 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.
2021-01-08 21:07:32 +08:00
gdb::array_view<const gdb_byte> view
= gdb::make_array_view (valaddr, elt_type->length ());
gdb/fortran: handle dynamic types within arrays and structures 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.
2021-01-08 21:07:32 +08:00
elt_type = resolve_dynamic_type (elt_type, view, address);
}
elt = value::zero (elt_type, elt->lval ());
gdb/fortran: handle dynamic types within arrays and structures 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.
2021-01-08 21:07:32 +08:00
}
return elt;
}
} /* namespace expr */
gdb: move f_language class into a header file Moves the f_language class from f-lang.c into f-lang.h. The benefit of this is that functions declared in other f-*.c files can become member functions without having to go through a level of indirection. Some additional support functions have now become private member functions of the f_language class, these are mostly functions that then called some other function that was itself a member of the language_defn class hierarchy. There should be no user visible changes after this commit. gdb/ChangeLog: * f-exp.y (f_parse): Rename to... (f_language::parser): ...this. * f-lang.c (f_get_encoding): Rename to... (f_language::get_encoding): ...this. (f_op_print_tab): Rename to... (f_language::op_print_tab): ...this. (exp_descriptor_f): Rename to... (f_language::exp_descriptor_tab): ...this. (class f_language): Moved to f-lang.h. (f_language::language_arch_info): New function, moved out of class declaration. (f_language::search_name_hash): Likewise. (f_language::lookup_symbol_nonlocal): Likewise. (f_language::get_symbol_name_matcher_inner): Likewise. * f-lang.h: Add 'valprint.h' include. (class f_language): Moved here from f-lang.c. * f-typeprint.c (f_type_print_args): Delete commented out declaration. (f_print_typedef): Rename to... (f_language::print_typedef): ...this. (f_print_type): Rename to... (f_language::print_type): ...this. (f_type_print_varspec_prefix): Delete declaration and rename to... (f_language::f_type_print_varspec_prefix): ...this. (f_type_print_varspec_suffix): Delete declaration and rename to... (f_language::f_type_print_varspec_suffix): ...this. (f_type_print_base): Delete declaration and rename to... (f_language::f_type_print_base): ...this. * f-valprint.c (f_value_print_inner): Rename to... (f_language::value_print_inner): ...this. * parse.c: Delete 'f-lang.h' include.
2020-09-16 23:27:30 +08:00
/* See language.h. */
gdb: Represent all languages as sub-classes of language_defn This commit converts all languages to sub-classes of a language_defn base class. The motivation for this change is to make it easier to add new methods onto languages without having to update all of the individual language structures. In the future it might be possible to move more things, like expression parsing, into the language class(es) for better encapsulation, however I have no plans to tackle this in the short term. This commit sets up a strategy for transitioning from the current language system, where each language is an instance of the language_defn structure, to the class hierarchy system. The plan is to rename the existing language_defn into language_data, and make this a base class for the new language_defn class, something like this: struct language_data { ... old language_defn fields here ... }; struct language_defn : public language_data { language_defn (const language_data d) : language_data (d) { .... } }; Then each existing language, for example ada_language_defn can be converted into an instance of language_data, and passed into the constructor of a new language class, something like this: language_data ada_language_data = { ... old ada_language_defn values here ... }; struct ada_language : public language_defn { ada_language (ada_language_data) { .... } }; What this means is that immediately after the conversion nothing much changes. Every language is now its own class, but all the old language fields still exist and can be accessed in the same way. In later commits I will convert function pointers from the old language_defn structure into real class methods on language_defn, with overrides on sub-classes where needed. At this point I imagine that those fields of the old language_defn structure that contained only data will probably remain as data fields within the new language_data base structure, it is only the methods that I plan to change initially. I tweaked how we manage the list of languages a bit, each language is now registered as it is created, and this resulted in a small number of changes in language.c. Most of the changes in the *-lang.c files are identical. There should be no user visible changes after this commit. gdb/ChangeLog: * gdb/ada-lang.c (ada_language_defn): Convert to... (ada_language_data): ...this. (class ada_language): New class. (ada_language_defn): New static global. * gdb/c-lang.c (c_language_defn): Convert to... (c_language_data): ...this. (class c_language): New class. (c_language_defn): New static global. (cplus_language_defn): Convert to... (cplus_language_data): ...this. (class cplus_language): New class. (cplus_language_defn): New static global. (asm_language_defn): Convert to... (asm_language_data): ...this. (class asm_language): New class. (asm_language_defn): New static global. (minimal_language_defn): Convert to... (minimal_language_data): ...this. (class minimal_language): New class. (minimal_language_defn): New static global. * gdb/d-lang.c (d_language_defn): Convert to... (d_language_data): ...this. (class d_language): New class. (d_language_defn): New static global. * gdb/f-lang.c (f_language_defn): Convert to... (f_language_data): ...this. (class f_language): New class. (f_language_defn): New static global. * gdb/go-lang.c (go_language_defn): Convert to... (go_language_data): ...this. (class go_language): New class. (go_language_defn): New static global. * gdb/language.c (unknown_language_defn): Remove declaration. (current_language): Initialize to nullptr, real initialization is moved to _initialize_language. (languages): Delete global. (language_defn::languages): Define. (set_language_command): Use language_defn::languages. (set_language): Likewise. (range_error): Likewise. (language_enum): Likewise. (language_def): Likewise. (add_set_language_command): Use language_def::languages for the language list, and language_def to lookup language pointers. (skip_language_trampoline): Use language_defn::languages. (unknown_language_defn): Convert to... (unknown_language_data): ...this. (class unknown_language): New class. (unknown_language_defn): New static global. (auto_language_defn): Convert to... (auto_language_data): ...this. (class auto_language): New class. (auto_language_defn): New static global. (language_gdbarch_post_init): Use language_defn::languages. (_initialize_language): Initialize current_language. * gdb/language.h (struct language_defn): Rename to... (struct language_data): ...this. (struct language_defn): New. (auto_language_defn): Delete. (unknown_language_defn): Delete. (minimal_language_defn): Delete. (ada_language_defn): Delete. (asm_language_defn): Delete. (c_language_defn): Delete. (cplus_language_defn): Delete. (d_language_defn): Delete. (f_language_defn): Delete. (go_language_defn): Delete. (m2_language_defn): Delete. (objc_language_defn): Delete. (opencl_language_defn): Delete. (pascal_language_defn): Delete. (rust_language_defn): Delete. * gdb/m2-lang.c (m2_language_defn): Convert to... (m2_language_data): ...this. (class m2_language): New class. (m2_language_defn): New static global. * gdb/objc-lang.c (objc_language_defn): Convert to... (objc_language_data): ...this. (class objc_language): New class. (objc_language_defn): New static global. * gdb/opencl-lang.c (opencl_language_defn): Convert to... (opencl_language_data): ...this. (class opencl_language): New class. (opencl_language_defn): New static global. * gdb/p-lang.c (pascal_language_defn): Convert to... (pascal_language_data): ...this. (class pascal_language): New class. (pascal_language_defn): New static global. * gdb/rust-exp.y (rust_lex_tests): Use language_def to find language pointer, update comment format. * gdb/rust-lang.c (rust_language_defn): Convert to... (rust_language_data): ...this. (class rust_language): New class. (rust_language_defn): New static global.
2020-05-01 19:16:58 +08:00
void
f_language::print_array_index (struct type *index_type, LONGEST index,
struct ui_file *stream,
const value_print_options *options) const
{
struct value *index_value = value_from_longest (index_type, index);
gdb_printf (stream, "(");
value_print (index_value, stream, options);
gdb_printf (stream, ") = ");
}
/* See language.h. */
gdb: move f_language class into a header file Moves the f_language class from f-lang.c into f-lang.h. The benefit of this is that functions declared in other f-*.c files can become member functions without having to go through a level of indirection. Some additional support functions have now become private member functions of the f_language class, these are mostly functions that then called some other function that was itself a member of the language_defn class hierarchy. There should be no user visible changes after this commit. gdb/ChangeLog: * f-exp.y (f_parse): Rename to... (f_language::parser): ...this. * f-lang.c (f_get_encoding): Rename to... (f_language::get_encoding): ...this. (f_op_print_tab): Rename to... (f_language::op_print_tab): ...this. (exp_descriptor_f): Rename to... (f_language::exp_descriptor_tab): ...this. (class f_language): Moved to f-lang.h. (f_language::language_arch_info): New function, moved out of class declaration. (f_language::search_name_hash): Likewise. (f_language::lookup_symbol_nonlocal): Likewise. (f_language::get_symbol_name_matcher_inner): Likewise. * f-lang.h: Add 'valprint.h' include. (class f_language): Moved here from f-lang.c. * f-typeprint.c (f_type_print_args): Delete commented out declaration. (f_print_typedef): Rename to... (f_language::print_typedef): ...this. (f_print_type): Rename to... (f_language::print_type): ...this. (f_type_print_varspec_prefix): Delete declaration and rename to... (f_language::f_type_print_varspec_prefix): ...this. (f_type_print_varspec_suffix): Delete declaration and rename to... (f_language::f_type_print_varspec_suffix): ...this. (f_type_print_base): Delete declaration and rename to... (f_language::f_type_print_base): ...this. * f-valprint.c (f_value_print_inner): Rename to... (f_language::value_print_inner): ...this. * parse.c: Delete 'f-lang.h' include.
2020-09-16 23:27:30 +08:00
void
f_language::language_arch_info (struct gdbarch *gdbarch,
struct language_arch_info *lai) const
gdb: Represent all languages as sub-classes of language_defn This commit converts all languages to sub-classes of a language_defn base class. The motivation for this change is to make it easier to add new methods onto languages without having to update all of the individual language structures. In the future it might be possible to move more things, like expression parsing, into the language class(es) for better encapsulation, however I have no plans to tackle this in the short term. This commit sets up a strategy for transitioning from the current language system, where each language is an instance of the language_defn structure, to the class hierarchy system. The plan is to rename the existing language_defn into language_data, and make this a base class for the new language_defn class, something like this: struct language_data { ... old language_defn fields here ... }; struct language_defn : public language_data { language_defn (const language_data d) : language_data (d) { .... } }; Then each existing language, for example ada_language_defn can be converted into an instance of language_data, and passed into the constructor of a new language class, something like this: language_data ada_language_data = { ... old ada_language_defn values here ... }; struct ada_language : public language_defn { ada_language (ada_language_data) { .... } }; What this means is that immediately after the conversion nothing much changes. Every language is now its own class, but all the old language fields still exist and can be accessed in the same way. In later commits I will convert function pointers from the old language_defn structure into real class methods on language_defn, with overrides on sub-classes where needed. At this point I imagine that those fields of the old language_defn structure that contained only data will probably remain as data fields within the new language_data base structure, it is only the methods that I plan to change initially. I tweaked how we manage the list of languages a bit, each language is now registered as it is created, and this resulted in a small number of changes in language.c. Most of the changes in the *-lang.c files are identical. There should be no user visible changes after this commit. gdb/ChangeLog: * gdb/ada-lang.c (ada_language_defn): Convert to... (ada_language_data): ...this. (class ada_language): New class. (ada_language_defn): New static global. * gdb/c-lang.c (c_language_defn): Convert to... (c_language_data): ...this. (class c_language): New class. (c_language_defn): New static global. (cplus_language_defn): Convert to... (cplus_language_data): ...this. (class cplus_language): New class. (cplus_language_defn): New static global. (asm_language_defn): Convert to... (asm_language_data): ...this. (class asm_language): New class. (asm_language_defn): New static global. (minimal_language_defn): Convert to... (minimal_language_data): ...this. (class minimal_language): New class. (minimal_language_defn): New static global. * gdb/d-lang.c (d_language_defn): Convert to... (d_language_data): ...this. (class d_language): New class. (d_language_defn): New static global. * gdb/f-lang.c (f_language_defn): Convert to... (f_language_data): ...this. (class f_language): New class. (f_language_defn): New static global. * gdb/go-lang.c (go_language_defn): Convert to... (go_language_data): ...this. (class go_language): New class. (go_language_defn): New static global. * gdb/language.c (unknown_language_defn): Remove declaration. (current_language): Initialize to nullptr, real initialization is moved to _initialize_language. (languages): Delete global. (language_defn::languages): Define. (set_language_command): Use language_defn::languages. (set_language): Likewise. (range_error): Likewise. (language_enum): Likewise. (language_def): Likewise. (add_set_language_command): Use language_def::languages for the language list, and language_def to lookup language pointers. (skip_language_trampoline): Use language_defn::languages. (unknown_language_defn): Convert to... (unknown_language_data): ...this. (class unknown_language): New class. (unknown_language_defn): New static global. (auto_language_defn): Convert to... (auto_language_data): ...this. (class auto_language): New class. (auto_language_defn): New static global. (language_gdbarch_post_init): Use language_defn::languages. (_initialize_language): Initialize current_language. * gdb/language.h (struct language_defn): Rename to... (struct language_data): ...this. (struct language_defn): New. (auto_language_defn): Delete. (unknown_language_defn): Delete. (minimal_language_defn): Delete. (ada_language_defn): Delete. (asm_language_defn): Delete. (c_language_defn): Delete. (cplus_language_defn): Delete. (d_language_defn): Delete. (f_language_defn): Delete. (go_language_defn): Delete. (m2_language_defn): Delete. (objc_language_defn): Delete. (opencl_language_defn): Delete. (pascal_language_defn): Delete. (rust_language_defn): Delete. * gdb/m2-lang.c (m2_language_defn): Convert to... (m2_language_data): ...this. (class m2_language): New class. (m2_language_defn): New static global. * gdb/objc-lang.c (objc_language_defn): Convert to... (objc_language_data): ...this. (class objc_language): New class. (objc_language_defn): New static global. * gdb/opencl-lang.c (opencl_language_defn): Convert to... (opencl_language_data): ...this. (class opencl_language): New class. (opencl_language_defn): New static global. * gdb/p-lang.c (pascal_language_defn): Convert to... (pascal_language_data): ...this. (class pascal_language): New class. (pascal_language_defn): New static global. * gdb/rust-exp.y (rust_lex_tests): Use language_def to find language pointer, update comment format. * gdb/rust-lang.c (rust_language_defn): Convert to... (rust_language_data): ...this. (class rust_language): New class. (rust_language_defn): New static global.
2020-05-01 19:16:58 +08:00
{
gdb: move f_language class into a header file Moves the f_language class from f-lang.c into f-lang.h. The benefit of this is that functions declared in other f-*.c files can become member functions without having to go through a level of indirection. Some additional support functions have now become private member functions of the f_language class, these are mostly functions that then called some other function that was itself a member of the language_defn class hierarchy. There should be no user visible changes after this commit. gdb/ChangeLog: * f-exp.y (f_parse): Rename to... (f_language::parser): ...this. * f-lang.c (f_get_encoding): Rename to... (f_language::get_encoding): ...this. (f_op_print_tab): Rename to... (f_language::op_print_tab): ...this. (exp_descriptor_f): Rename to... (f_language::exp_descriptor_tab): ...this. (class f_language): Moved to f-lang.h. (f_language::language_arch_info): New function, moved out of class declaration. (f_language::search_name_hash): Likewise. (f_language::lookup_symbol_nonlocal): Likewise. (f_language::get_symbol_name_matcher_inner): Likewise. * f-lang.h: Add 'valprint.h' include. (class f_language): Moved here from f-lang.c. * f-typeprint.c (f_type_print_args): Delete commented out declaration. (f_print_typedef): Rename to... (f_language::print_typedef): ...this. (f_print_type): Rename to... (f_language::print_type): ...this. (f_type_print_varspec_prefix): Delete declaration and rename to... (f_language::f_type_print_varspec_prefix): ...this. (f_type_print_varspec_suffix): Delete declaration and rename to... (f_language::f_type_print_varspec_suffix): ...this. (f_type_print_base): Delete declaration and rename to... (f_language::f_type_print_base): ...this. * f-valprint.c (f_value_print_inner): Rename to... (f_language::value_print_inner): ...this. * parse.c: Delete 'f-lang.h' include.
2020-09-16 23:27:30 +08:00
const struct builtin_f_type *builtin = builtin_f_type (gdbarch);
gdb: rewrite how per language primitive types are managed Consider the following GDB session: $ gdb (gdb) set language c (gdb) ptype void type = void (gdb) set language fortran (gdb) ptype void No symbol table is loaded. Use the "file" command. (gdb) With no symbol file loaded GDB and the language set to C GDB knows about the type void, while when the language is set to Fortran GDB doesn't know about the void, why is that? In f-lang.c, f_language::language_arch_info, we do have this line: lai->primitive_type_vector [f_primitive_type_void] = builtin->builtin_void; where we add the void type to the list of primitive types that GDB should always know about, so what's going wrong? It turns out that the primitive types are stored in a C style array, indexed by an enum, so Fortran uses `enum f_primitive_types'. The array is allocated and populated in each languages language_arch_info member function. The array is allocated with an extra entry at the end which is left as a NULL value, and this indicates the end of the array of types. Unfortunately for Fortran, a type is not assigned for each element in the enum. As a result the final populated array has gaps in it, gaps which are initialised to NULL, and so every time we iterate over the list (for Fortran) we stop early, and never reach the void type. This has been the case since 2007 when this functionality was added to GDB in commit cad351d11d6c3f6487cd. Obviously I could just fix Fortran by ensuring that either the enum is trimmed, or we create types for the missing types. However, I think a better approach would be to move to C++ data structures and removed the fixed enum indexing into the array approach. After this commit the primitive types are pushed into a vector, and GDB just iterates over the vector in the obvious way when it needs to hunt for a type. After this commit all the currently defined primitive types can be found when the language is set to Fortran, for example: $ gdb (gdb) set language fortran (gdb) ptype void type = void (gdb) A new test checks this functionality. I didn't see any other languages with similar issues, but I could have missed something. gdb/ChangeLog: * ada-exp.y (find_primitive_type): Make parameter const. * ada-lang.c (enum ada_primitive_types): Delete. (ada_language::language_arch_info): Update. * c-lang.c (enum c_primitive_types): Delete. (c_language_arch_info): Update. (enum cplus_primitive_types): Delete. (cplus_language::language_arch_info): Update. * d-lang.c (enum d_primitive_types): Delete. (d_language::language_arch_info): Update. * f-lang.c (enum f_primitive_types): Delete. (f_language::language_arch_info): Update. * go-lang.c (enum go_primitive_types): Delete. (go_language::language_arch_info): Update. * language.c (auto_or_unknown_language::language_arch_info): Update. (language_gdbarch_post_init): Use obstack_new, use array indexing. (language_string_char_type): Add header comment, call function in language_arch_info. (language_bool_type): Likewise (language_arch_info::bool_type): Define. (language_lookup_primitive_type_1): Delete. (language_lookup_primitive_type): Rewrite as a templated function to call function in language_arch_info, then instantiate twice. (language_arch_info::type_and_symbol::alloc_type_symbol): Define. (language_arch_info::lookup_primitive_type_and_symbol): Define. (language_arch_info::lookup_primitive_type): Define twice with different signatures. (language_arch_info::lookup_primitive_type_as_symbol): Define. (language_lookup_primitive_type_as_symbol): Rewrite to call a member function in language_arch_info. * language.h (language_arch_info): Complete rewrite. (language_lookup_primitive_type): Make templated. * m2-lang.c (enum m2_primitive_types): Delete. (m2_language::language_arch_info): Update. * opencl-lang.c (OCL_P_TYPE): Delete. (enum opencl_primitive_types): Delete. (opencl_type_data): Delete. (builtin_opencl_type): Delete. (lookup_opencl_vector_type): Update. (opencl_language::language_arch_info): Update, lots of content moved from... (build_opencl_types): ...here. This function is now deleted. (_initialize_opencl_language): Delete. * p-lang.c (enum pascal_primitive_types): Delete. (pascal_language::language_arch_info): Update. * rust-lang.c (enum rust_primitive_types): Delete. (rust_language::language_arch_info): Update. gdb/testsuite/ChangeLog: * gdb.fortran/types.exp: Add more tests.
2020-10-31 04:40:59 +08:00
/* Helper function to allow shorter lines below. */
auto add = [&] (struct type * t)
{
lai->add_primitive_type (t);
};
add (builtin->builtin_character);
add (builtin->builtin_logical);
add (builtin->builtin_logical_s1);
add (builtin->builtin_logical_s2);
add (builtin->builtin_logical_s8);
add (builtin->builtin_real);
add (builtin->builtin_real_s8);
add (builtin->builtin_real_s16);
add (builtin->builtin_complex);
gdb: rewrite how per language primitive types are managed Consider the following GDB session: $ gdb (gdb) set language c (gdb) ptype void type = void (gdb) set language fortran (gdb) ptype void No symbol table is loaded. Use the "file" command. (gdb) With no symbol file loaded GDB and the language set to C GDB knows about the type void, while when the language is set to Fortran GDB doesn't know about the void, why is that? In f-lang.c, f_language::language_arch_info, we do have this line: lai->primitive_type_vector [f_primitive_type_void] = builtin->builtin_void; where we add the void type to the list of primitive types that GDB should always know about, so what's going wrong? It turns out that the primitive types are stored in a C style array, indexed by an enum, so Fortran uses `enum f_primitive_types'. The array is allocated and populated in each languages language_arch_info member function. The array is allocated with an extra entry at the end which is left as a NULL value, and this indicates the end of the array of types. Unfortunately for Fortran, a type is not assigned for each element in the enum. As a result the final populated array has gaps in it, gaps which are initialised to NULL, and so every time we iterate over the list (for Fortran) we stop early, and never reach the void type. This has been the case since 2007 when this functionality was added to GDB in commit cad351d11d6c3f6487cd. Obviously I could just fix Fortran by ensuring that either the enum is trimmed, or we create types for the missing types. However, I think a better approach would be to move to C++ data structures and removed the fixed enum indexing into the array approach. After this commit the primitive types are pushed into a vector, and GDB just iterates over the vector in the obvious way when it needs to hunt for a type. After this commit all the currently defined primitive types can be found when the language is set to Fortran, for example: $ gdb (gdb) set language fortran (gdb) ptype void type = void (gdb) A new test checks this functionality. I didn't see any other languages with similar issues, but I could have missed something. gdb/ChangeLog: * ada-exp.y (find_primitive_type): Make parameter const. * ada-lang.c (enum ada_primitive_types): Delete. (ada_language::language_arch_info): Update. * c-lang.c (enum c_primitive_types): Delete. (c_language_arch_info): Update. (enum cplus_primitive_types): Delete. (cplus_language::language_arch_info): Update. * d-lang.c (enum d_primitive_types): Delete. (d_language::language_arch_info): Update. * f-lang.c (enum f_primitive_types): Delete. (f_language::language_arch_info): Update. * go-lang.c (enum go_primitive_types): Delete. (go_language::language_arch_info): Update. * language.c (auto_or_unknown_language::language_arch_info): Update. (language_gdbarch_post_init): Use obstack_new, use array indexing. (language_string_char_type): Add header comment, call function in language_arch_info. (language_bool_type): Likewise (language_arch_info::bool_type): Define. (language_lookup_primitive_type_1): Delete. (language_lookup_primitive_type): Rewrite as a templated function to call function in language_arch_info, then instantiate twice. (language_arch_info::type_and_symbol::alloc_type_symbol): Define. (language_arch_info::lookup_primitive_type_and_symbol): Define. (language_arch_info::lookup_primitive_type): Define twice with different signatures. (language_arch_info::lookup_primitive_type_as_symbol): Define. (language_lookup_primitive_type_as_symbol): Rewrite to call a member function in language_arch_info. * language.h (language_arch_info): Complete rewrite. (language_lookup_primitive_type): Make templated. * m2-lang.c (enum m2_primitive_types): Delete. (m2_language::language_arch_info): Update. * opencl-lang.c (OCL_P_TYPE): Delete. (enum opencl_primitive_types): Delete. (opencl_type_data): Delete. (builtin_opencl_type): Delete. (lookup_opencl_vector_type): Update. (opencl_language::language_arch_info): Update, lots of content moved from... (build_opencl_types): ...here. This function is now deleted. (_initialize_opencl_language): Delete. * p-lang.c (enum pascal_primitive_types): Delete. (pascal_language::language_arch_info): Update. * rust-lang.c (enum rust_primitive_types): Delete. (rust_language::language_arch_info): Update. gdb/testsuite/ChangeLog: * gdb.fortran/types.exp: Add more tests.
2020-10-31 04:40:59 +08:00
add (builtin->builtin_complex_s8);
add (builtin->builtin_void);
lai->set_string_char_type (builtin->builtin_character);
lai->set_bool_type (builtin->builtin_logical, "logical");
gdb: move f_language class into a header file Moves the f_language class from f-lang.c into f-lang.h. The benefit of this is that functions declared in other f-*.c files can become member functions without having to go through a level of indirection. Some additional support functions have now become private member functions of the f_language class, these are mostly functions that then called some other function that was itself a member of the language_defn class hierarchy. There should be no user visible changes after this commit. gdb/ChangeLog: * f-exp.y (f_parse): Rename to... (f_language::parser): ...this. * f-lang.c (f_get_encoding): Rename to... (f_language::get_encoding): ...this. (f_op_print_tab): Rename to... (f_language::op_print_tab): ...this. (exp_descriptor_f): Rename to... (f_language::exp_descriptor_tab): ...this. (class f_language): Moved to f-lang.h. (f_language::language_arch_info): New function, moved out of class declaration. (f_language::search_name_hash): Likewise. (f_language::lookup_symbol_nonlocal): Likewise. (f_language::get_symbol_name_matcher_inner): Likewise. * f-lang.h: Add 'valprint.h' include. (class f_language): Moved here from f-lang.c. * f-typeprint.c (f_type_print_args): Delete commented out declaration. (f_print_typedef): Rename to... (f_language::print_typedef): ...this. (f_print_type): Rename to... (f_language::print_type): ...this. (f_type_print_varspec_prefix): Delete declaration and rename to... (f_language::f_type_print_varspec_prefix): ...this. (f_type_print_varspec_suffix): Delete declaration and rename to... (f_language::f_type_print_varspec_suffix): ...this. (f_type_print_base): Delete declaration and rename to... (f_language::f_type_print_base): ...this. * f-valprint.c (f_value_print_inner): Rename to... (f_language::value_print_inner): ...this. * parse.c: Delete 'f-lang.h' include.
2020-09-16 23:27:30 +08:00
}
gdb: Convert language_data::la_exp_desc to a method Convert language_data::la_exp_desc member variable to a virtual method language_defn::expression_ops. The change of names brings this method more into line with the existing varobj_ops method, that also returns a table of function pointers. There should be no user visible changes after this commit. gdb/ChangeLog: * ada-lang.c (ada_language_data): Remove la_exp_desc initializer. (ada_language::expression_ops): New member function. * c-lang.c (c_language_data): Remove la_exp_desc initializer. (c_language::expression_ops): New member function. (cplus_language_data): Remove la_exp_desc initializer. (cplus_language::expression_ops): New member function. (asm_language_data): Remove la_exp_desc initializer. (asm_language::expression_ops): New member function. (minimal_language_data): Remove la_exp_desc initializer. (minimal_language::expression_ops): New member function. * d-lang.c (d_language_data): Remove la_exp_desc initializer. (d_language::expression_ops): New member function. * eval.c (evaluate_subexp): Update call to expression_ops. * expprint.c (print_subexp): Likewise. (op_name): Likewise. (dump_subexp_body): Likewise. * f-lang.c (f_language_data): Remove la_exp_desc initializer. (f_language::expression_ops): New member function. * go-lang.c (go_language_data): Remove la_exp_desc initializer. (go_language::expression_ops): New member function. * language.c (language_defn::expression_ops): New function. (unknown_language_data): Remove la_exp_desc initializer. (auto_language_data): Likewise. * language.h (language_data): Remove la_exp_desc field. (language_defn::expression_ops): Declare new member function. * m2-lang.c (m2_language_data): Remove la_exp_desc initializer. (m2_language::expression_ops): New member function. * objc-lang.c (objc_language_data): Remove la_exp_desc initializer. * opencl-lang.c (opencl_language_data): Remove la_exp_desc initializer. (opencl_language::expression_ops): New member function. * p-lang.c (pascal_language_data): Remove la_exp_desc initializer. * parse.c (operator_length): Update call to expression_ops. (exp_iterate): Likewise. * rust-lang.c (rust_language_data): Remove la_exp_desc initializer. (ruse_language::expression_ops): New member function.
2020-08-04 23:31:56 +08:00
gdb: move f_language class into a header file Moves the f_language class from f-lang.c into f-lang.h. The benefit of this is that functions declared in other f-*.c files can become member functions without having to go through a level of indirection. Some additional support functions have now become private member functions of the f_language class, these are mostly functions that then called some other function that was itself a member of the language_defn class hierarchy. There should be no user visible changes after this commit. gdb/ChangeLog: * f-exp.y (f_parse): Rename to... (f_language::parser): ...this. * f-lang.c (f_get_encoding): Rename to... (f_language::get_encoding): ...this. (f_op_print_tab): Rename to... (f_language::op_print_tab): ...this. (exp_descriptor_f): Rename to... (f_language::exp_descriptor_tab): ...this. (class f_language): Moved to f-lang.h. (f_language::language_arch_info): New function, moved out of class declaration. (f_language::search_name_hash): Likewise. (f_language::lookup_symbol_nonlocal): Likewise. (f_language::get_symbol_name_matcher_inner): Likewise. * f-lang.h: Add 'valprint.h' include. (class f_language): Moved here from f-lang.c. * f-typeprint.c (f_type_print_args): Delete commented out declaration. (f_print_typedef): Rename to... (f_language::print_typedef): ...this. (f_print_type): Rename to... (f_language::print_type): ...this. (f_type_print_varspec_prefix): Delete declaration and rename to... (f_language::f_type_print_varspec_prefix): ...this. (f_type_print_varspec_suffix): Delete declaration and rename to... (f_language::f_type_print_varspec_suffix): ...this. (f_type_print_base): Delete declaration and rename to... (f_language::f_type_print_base): ...this. * f-valprint.c (f_value_print_inner): Rename to... (f_language::value_print_inner): ...this. * parse.c: Delete 'f-lang.h' include.
2020-09-16 23:27:30 +08:00
/* See language.h. */
gdb: Convert language_data::la_exp_desc to a method Convert language_data::la_exp_desc member variable to a virtual method language_defn::expression_ops. The change of names brings this method more into line with the existing varobj_ops method, that also returns a table of function pointers. There should be no user visible changes after this commit. gdb/ChangeLog: * ada-lang.c (ada_language_data): Remove la_exp_desc initializer. (ada_language::expression_ops): New member function. * c-lang.c (c_language_data): Remove la_exp_desc initializer. (c_language::expression_ops): New member function. (cplus_language_data): Remove la_exp_desc initializer. (cplus_language::expression_ops): New member function. (asm_language_data): Remove la_exp_desc initializer. (asm_language::expression_ops): New member function. (minimal_language_data): Remove la_exp_desc initializer. (minimal_language::expression_ops): New member function. * d-lang.c (d_language_data): Remove la_exp_desc initializer. (d_language::expression_ops): New member function. * eval.c (evaluate_subexp): Update call to expression_ops. * expprint.c (print_subexp): Likewise. (op_name): Likewise. (dump_subexp_body): Likewise. * f-lang.c (f_language_data): Remove la_exp_desc initializer. (f_language::expression_ops): New member function. * go-lang.c (go_language_data): Remove la_exp_desc initializer. (go_language::expression_ops): New member function. * language.c (language_defn::expression_ops): New function. (unknown_language_data): Remove la_exp_desc initializer. (auto_language_data): Likewise. * language.h (language_data): Remove la_exp_desc field. (language_defn::expression_ops): Declare new member function. * m2-lang.c (m2_language_data): Remove la_exp_desc initializer. (m2_language::expression_ops): New member function. * objc-lang.c (objc_language_data): Remove la_exp_desc initializer. * opencl-lang.c (opencl_language_data): Remove la_exp_desc initializer. (opencl_language::expression_ops): New member function. * p-lang.c (pascal_language_data): Remove la_exp_desc initializer. * parse.c (operator_length): Update call to expression_ops. (exp_iterate): Likewise. * rust-lang.c (rust_language_data): Remove la_exp_desc initializer. (ruse_language::expression_ops): New member function.
2020-08-04 23:31:56 +08:00
gdb: move f_language class into a header file Moves the f_language class from f-lang.c into f-lang.h. The benefit of this is that functions declared in other f-*.c files can become member functions without having to go through a level of indirection. Some additional support functions have now become private member functions of the f_language class, these are mostly functions that then called some other function that was itself a member of the language_defn class hierarchy. There should be no user visible changes after this commit. gdb/ChangeLog: * f-exp.y (f_parse): Rename to... (f_language::parser): ...this. * f-lang.c (f_get_encoding): Rename to... (f_language::get_encoding): ...this. (f_op_print_tab): Rename to... (f_language::op_print_tab): ...this. (exp_descriptor_f): Rename to... (f_language::exp_descriptor_tab): ...this. (class f_language): Moved to f-lang.h. (f_language::language_arch_info): New function, moved out of class declaration. (f_language::search_name_hash): Likewise. (f_language::lookup_symbol_nonlocal): Likewise. (f_language::get_symbol_name_matcher_inner): Likewise. * f-lang.h: Add 'valprint.h' include. (class f_language): Moved here from f-lang.c. * f-typeprint.c (f_type_print_args): Delete commented out declaration. (f_print_typedef): Rename to... (f_language::print_typedef): ...this. (f_print_type): Rename to... (f_language::print_type): ...this. (f_type_print_varspec_prefix): Delete declaration and rename to... (f_language::f_type_print_varspec_prefix): ...this. (f_type_print_varspec_suffix): Delete declaration and rename to... (f_language::f_type_print_varspec_suffix): ...this. (f_type_print_base): Delete declaration and rename to... (f_language::f_type_print_base): ...this. * f-valprint.c (f_value_print_inner): Rename to... (f_language::value_print_inner): ...this. * parse.c: Delete 'f-lang.h' include.
2020-09-16 23:27:30 +08:00
unsigned int
f_language::search_name_hash (const char *name) const
{
return cp_search_name_hash (name);
}
gdb: Convert language_data::la_op_print_tab to a method Convert language_data::la_op_print_tab member variable to a virtual method language_defn::opcode_print_table. I changed the name in order to make it clearer (I hope) what the method does. There should be no user visible changes after this commit. gdb/ChangeLog: * ada-lang.c (ada_language_data): Remove la_op_print_tab initializer. (ada_language::opcode_print_table): New member function. * c-lang.c (c_language_data): Remove la_op_print_tab initializer. (c_language::opcode_print_table): New member function. (cplus_language_data): Remove la_op_print_tab initializer. (cplus_language::opcode_print_table): New member function. (asm_language_data): Remove la_op_print_tab initializer. (asm_language::opcode_print_table): New member function. (minimal_language_data): Remove la_op_print_tab initializer. (minimal_language::opcode_print_table): New member function. * d-lang.c (d_language_data): Remove la_op_print_tab initializer. (d_language::opcode_print_table): New member function. * expprint.c (print_subexp_standard): Update call to opcode_print_table. (op_string): Likewise. * f-lang.c (f_language_data): Remove la_op_print_tab initializer. (f_language::opcode_print_table): New member function. * go-lang.c (go_language_data): Remove la_op_print_tab initializer. (go_language::opcode_print_table): New member function. * language.c (unknown_language_data): Remove la_op_print_tab initializer. (unknown_language::opcode_print_table): New member function. (auto_language_data): Remove la_op_print_tab initializer. (auto_language::opcode_print_table): New member function. * language.h (language_data): Remove la_op_print_tab field. (language_defn::opcode_print_table): Declare new member function. * m2-lang.c (m2_language_data): Remove la_op_print_tab initializer. (m2_language::opcode_print_table): New member function. * objc-lang.c (objc_language_data): Remove la_op_print_tab initializer. (objc_language::opcode_print_table): New member function. * opencl-lang.c (opencl_language_data): Remove la_op_print_tab initializer. (opencl_language::opcode_print_table): New member function. * p-lang.c (pascal_language_data): Remove la_op_print_tab initializer. (pascal_language::opcode_print_table): New member function. * rust-lang.c (rust_language_data): Remove la_op_print_tab initializer. (rust_language::opcode_print_table): New member function.
2020-08-05 00:07:59 +08:00
gdb: move f_language class into a header file Moves the f_language class from f-lang.c into f-lang.h. The benefit of this is that functions declared in other f-*.c files can become member functions without having to go through a level of indirection. Some additional support functions have now become private member functions of the f_language class, these are mostly functions that then called some other function that was itself a member of the language_defn class hierarchy. There should be no user visible changes after this commit. gdb/ChangeLog: * f-exp.y (f_parse): Rename to... (f_language::parser): ...this. * f-lang.c (f_get_encoding): Rename to... (f_language::get_encoding): ...this. (f_op_print_tab): Rename to... (f_language::op_print_tab): ...this. (exp_descriptor_f): Rename to... (f_language::exp_descriptor_tab): ...this. (class f_language): Moved to f-lang.h. (f_language::language_arch_info): New function, moved out of class declaration. (f_language::search_name_hash): Likewise. (f_language::lookup_symbol_nonlocal): Likewise. (f_language::get_symbol_name_matcher_inner): Likewise. * f-lang.h: Add 'valprint.h' include. (class f_language): Moved here from f-lang.c. * f-typeprint.c (f_type_print_args): Delete commented out declaration. (f_print_typedef): Rename to... (f_language::print_typedef): ...this. (f_print_type): Rename to... (f_language::print_type): ...this. (f_type_print_varspec_prefix): Delete declaration and rename to... (f_language::f_type_print_varspec_prefix): ...this. (f_type_print_varspec_suffix): Delete declaration and rename to... (f_language::f_type_print_varspec_suffix): ...this. (f_type_print_base): Delete declaration and rename to... (f_language::f_type_print_base): ...this. * f-valprint.c (f_value_print_inner): Rename to... (f_language::value_print_inner): ...this. * parse.c: Delete 'f-lang.h' include.
2020-09-16 23:27:30 +08:00
/* See language.h. */
gdb: Convert language_data::la_op_print_tab to a method Convert language_data::la_op_print_tab member variable to a virtual method language_defn::opcode_print_table. I changed the name in order to make it clearer (I hope) what the method does. There should be no user visible changes after this commit. gdb/ChangeLog: * ada-lang.c (ada_language_data): Remove la_op_print_tab initializer. (ada_language::opcode_print_table): New member function. * c-lang.c (c_language_data): Remove la_op_print_tab initializer. (c_language::opcode_print_table): New member function. (cplus_language_data): Remove la_op_print_tab initializer. (cplus_language::opcode_print_table): New member function. (asm_language_data): Remove la_op_print_tab initializer. (asm_language::opcode_print_table): New member function. (minimal_language_data): Remove la_op_print_tab initializer. (minimal_language::opcode_print_table): New member function. * d-lang.c (d_language_data): Remove la_op_print_tab initializer. (d_language::opcode_print_table): New member function. * expprint.c (print_subexp_standard): Update call to opcode_print_table. (op_string): Likewise. * f-lang.c (f_language_data): Remove la_op_print_tab initializer. (f_language::opcode_print_table): New member function. * go-lang.c (go_language_data): Remove la_op_print_tab initializer. (go_language::opcode_print_table): New member function. * language.c (unknown_language_data): Remove la_op_print_tab initializer. (unknown_language::opcode_print_table): New member function. (auto_language_data): Remove la_op_print_tab initializer. (auto_language::opcode_print_table): New member function. * language.h (language_data): Remove la_op_print_tab field. (language_defn::opcode_print_table): Declare new member function. * m2-lang.c (m2_language_data): Remove la_op_print_tab initializer. (m2_language::opcode_print_table): New member function. * objc-lang.c (objc_language_data): Remove la_op_print_tab initializer. (objc_language::opcode_print_table): New member function. * opencl-lang.c (opencl_language_data): Remove la_op_print_tab initializer. (opencl_language::opcode_print_table): New member function. * p-lang.c (pascal_language_data): Remove la_op_print_tab initializer. (pascal_language::opcode_print_table): New member function. * rust-lang.c (rust_language_data): Remove la_op_print_tab initializer. (rust_language::opcode_print_table): New member function.
2020-08-05 00:07:59 +08:00
struct block_symbol
f_language::lookup_symbol_local (const char *scope,
const char *name,
const struct block *block,
const domain_search_flags domain) const
{
return cp_lookup_symbol_imports (scope, name, block, domain);
}
/* See language.h. */
gdb: move f_language class into a header file Moves the f_language class from f-lang.c into f-lang.h. The benefit of this is that functions declared in other f-*.c files can become member functions without having to go through a level of indirection. Some additional support functions have now become private member functions of the f_language class, these are mostly functions that then called some other function that was itself a member of the language_defn class hierarchy. There should be no user visible changes after this commit. gdb/ChangeLog: * f-exp.y (f_parse): Rename to... (f_language::parser): ...this. * f-lang.c (f_get_encoding): Rename to... (f_language::get_encoding): ...this. (f_op_print_tab): Rename to... (f_language::op_print_tab): ...this. (exp_descriptor_f): Rename to... (f_language::exp_descriptor_tab): ...this. (class f_language): Moved to f-lang.h. (f_language::language_arch_info): New function, moved out of class declaration. (f_language::search_name_hash): Likewise. (f_language::lookup_symbol_nonlocal): Likewise. (f_language::get_symbol_name_matcher_inner): Likewise. * f-lang.h: Add 'valprint.h' include. (class f_language): Moved here from f-lang.c. * f-typeprint.c (f_type_print_args): Delete commented out declaration. (f_print_typedef): Rename to... (f_language::print_typedef): ...this. (f_print_type): Rename to... (f_language::print_type): ...this. (f_type_print_varspec_prefix): Delete declaration and rename to... (f_language::f_type_print_varspec_prefix): ...this. (f_type_print_varspec_suffix): Delete declaration and rename to... (f_language::f_type_print_varspec_suffix): ...this. (f_type_print_base): Delete declaration and rename to... (f_language::f_type_print_base): ...this. * f-valprint.c (f_value_print_inner): Rename to... (f_language::value_print_inner): ...this. * parse.c: Delete 'f-lang.h' include.
2020-09-16 23:27:30 +08:00
struct block_symbol
f_language::lookup_symbol_nonlocal (const char *name,
const struct block *block,
const domain_search_flags domain) const
gdb: move f_language class into a header file Moves the f_language class from f-lang.c into f-lang.h. The benefit of this is that functions declared in other f-*.c files can become member functions without having to go through a level of indirection. Some additional support functions have now become private member functions of the f_language class, these are mostly functions that then called some other function that was itself a member of the language_defn class hierarchy. There should be no user visible changes after this commit. gdb/ChangeLog: * f-exp.y (f_parse): Rename to... (f_language::parser): ...this. * f-lang.c (f_get_encoding): Rename to... (f_language::get_encoding): ...this. (f_op_print_tab): Rename to... (f_language::op_print_tab): ...this. (exp_descriptor_f): Rename to... (f_language::exp_descriptor_tab): ...this. (class f_language): Moved to f-lang.h. (f_language::language_arch_info): New function, moved out of class declaration. (f_language::search_name_hash): Likewise. (f_language::lookup_symbol_nonlocal): Likewise. (f_language::get_symbol_name_matcher_inner): Likewise. * f-lang.h: Add 'valprint.h' include. (class f_language): Moved here from f-lang.c. * f-typeprint.c (f_type_print_args): Delete commented out declaration. (f_print_typedef): Rename to... (f_language::print_typedef): ...this. (f_print_type): Rename to... (f_language::print_type): ...this. (f_type_print_varspec_prefix): Delete declaration and rename to... (f_language::f_type_print_varspec_prefix): ...this. (f_type_print_varspec_suffix): Delete declaration and rename to... (f_language::f_type_print_varspec_suffix): ...this. (f_type_print_base): Delete declaration and rename to... (f_language::f_type_print_base): ...this. * f-valprint.c (f_value_print_inner): Rename to... (f_language::value_print_inner): ...this. * parse.c: Delete 'f-lang.h' include.
2020-09-16 23:27:30 +08:00
{
return cp_lookup_symbol_nonlocal (this, name, block, domain);
}
gdb: Convert language la_get_symbol_name_matcher field to a method This commit changes the language_data::la_get_symbol_name_matcher function pointer member variable into a member function of language_defn. There should be no user visible changes after this commit. Before this commit access to the la_get_symbol_name_matcher function pointer was through the get_symbol_name_matcher function, which looked something like this (is pseudo-code): <return-type> get_symbol_name_matcher (language_defn *lang, <other args>) { if (current_language == ada) current_language->la_get_symbol_name_matcher (<other args>); else lang->la_get_symbol_name_matcher (<other args>); } In this commit I moved the get_symbol_name_matcher as a non-virtual function in the language_defn base class, I then add a new virtual method that is only used from within get_symbol_name_matcher, this can then be overridden by specific languages as needed. So we now have: class language_defn { <return-type> get_symbol_name_matcher (<args>) { if (current_language == ada) return current_language->get_symbol_name_matcher_inner (<args>); else return this->get_symbol_name_matcher_inner (<args>); } virtual <return-type> get_symbol_name_matcher_inner (<args>) { .... } } gdb/ChangeLog: * ada-lang.c (ada_get_symbol_name_matcher): Update header comment. (ada_language_data): Delete la_get_symbol_name_matcher initializer. (language_defn::get_symbol_name_matcher_inner): New member function. * c-lang.c (c_language_data): Delete la_get_symbol_name_matcher initializer. (cplus_language_data): Likewise. (cplus_language::get_symbol_name_matcher_inner): New member function. (asm_language_data): Delete la_get_symbol_name_matcher initializer. (minimal_language_data): Likewise. * cp-support.h (cp_get_symbol_name_matcher): Update header comment. * d-lang.c (d_language_data): Delete la_get_symbol_name_matcher initializer. * dictionary.c (iter_match_first_hashed): Update call to get_symbol_name_matcher. (iter_match_next_hashed): Likewise. (iter_match_next_linear): Likewise. * dwarf2/read.c (dw2_expand_symtabs_matching_symbol): Likewise. * f-lang.c (f_language_data): Delete la_get_symbol_name_matcher initializer. (f_language::get_symbol_name_matcher_inner): New member function. * go-lang.c (go_language_data): Delete la_get_symbol_name_matcher initializer. * language.c (default_symbol_name_matcher): Update header comment, make static. (language_defn::get_symbol_name_matcher): New definition. (language_defn::get_symbol_name_matcher_inner): Likewise. (get_symbol_name_matcher): Delete. (unknown_language_data): Delete la_get_symbol_name_matcher initializer. (auto_language_data): Likewise. * language.h (language_data): Delete la_get_symbol_name_matcher field. (language_defn::get_symbol_name_matcher): New member function. (language_defn::get_symbol_name_matcher_inner): Likewise. (default_symbol_name_matcher): Delete declaration. * linespec.c (find_methods): Update call to get_symbol_name_matcher. * m2-lang.c (m2_language_data): Delete la_get_symbol_name_matcher initializer. * minsyms.c (lookup_minimal_symbol): Update call to get_symbol_name_matcher. (iterate_over_minimal_symbols): Likewise. * objc-lang.c (objc_language_data): Delete la_get_symbol_name_matcher initializer. * opencl-lang.c (opencl_language_data): Likewise. * p-lang.c (pascal_language_data): Likewise. * psymtab.c (psymbol_name_matches): Update call to get_symbol_name_matcher. * rust-lang.c (rust_language_data): Delete la_get_symbol_name_matcher initializer. * symtab.c (symbol_matches_search_name): Update call to get_symbol_name_matcher. (compare_symbol_name): Likewise.
2020-06-01 18:46:54 +08:00
gdb: move f_language class into a header file Moves the f_language class from f-lang.c into f-lang.h. The benefit of this is that functions declared in other f-*.c files can become member functions without having to go through a level of indirection. Some additional support functions have now become private member functions of the f_language class, these are mostly functions that then called some other function that was itself a member of the language_defn class hierarchy. There should be no user visible changes after this commit. gdb/ChangeLog: * f-exp.y (f_parse): Rename to... (f_language::parser): ...this. * f-lang.c (f_get_encoding): Rename to... (f_language::get_encoding): ...this. (f_op_print_tab): Rename to... (f_language::op_print_tab): ...this. (exp_descriptor_f): Rename to... (f_language::exp_descriptor_tab): ...this. (class f_language): Moved to f-lang.h. (f_language::language_arch_info): New function, moved out of class declaration. (f_language::search_name_hash): Likewise. (f_language::lookup_symbol_nonlocal): Likewise. (f_language::get_symbol_name_matcher_inner): Likewise. * f-lang.h: Add 'valprint.h' include. (class f_language): Moved here from f-lang.c. * f-typeprint.c (f_type_print_args): Delete commented out declaration. (f_print_typedef): Rename to... (f_language::print_typedef): ...this. (f_print_type): Rename to... (f_language::print_type): ...this. (f_type_print_varspec_prefix): Delete declaration and rename to... (f_language::f_type_print_varspec_prefix): ...this. (f_type_print_varspec_suffix): Delete declaration and rename to... (f_language::f_type_print_varspec_suffix): ...this. (f_type_print_base): Delete declaration and rename to... (f_language::f_type_print_base): ...this. * f-valprint.c (f_value_print_inner): Rename to... (f_language::value_print_inner): ...this. * parse.c: Delete 'f-lang.h' include.
2020-09-16 23:27:30 +08:00
/* See language.h. */
gdb: Convert language la_get_symbol_name_matcher field to a method This commit changes the language_data::la_get_symbol_name_matcher function pointer member variable into a member function of language_defn. There should be no user visible changes after this commit. Before this commit access to the la_get_symbol_name_matcher function pointer was through the get_symbol_name_matcher function, which looked something like this (is pseudo-code): <return-type> get_symbol_name_matcher (language_defn *lang, <other args>) { if (current_language == ada) current_language->la_get_symbol_name_matcher (<other args>); else lang->la_get_symbol_name_matcher (<other args>); } In this commit I moved the get_symbol_name_matcher as a non-virtual function in the language_defn base class, I then add a new virtual method that is only used from within get_symbol_name_matcher, this can then be overridden by specific languages as needed. So we now have: class language_defn { <return-type> get_symbol_name_matcher (<args>) { if (current_language == ada) return current_language->get_symbol_name_matcher_inner (<args>); else return this->get_symbol_name_matcher_inner (<args>); } virtual <return-type> get_symbol_name_matcher_inner (<args>) { .... } } gdb/ChangeLog: * ada-lang.c (ada_get_symbol_name_matcher): Update header comment. (ada_language_data): Delete la_get_symbol_name_matcher initializer. (language_defn::get_symbol_name_matcher_inner): New member function. * c-lang.c (c_language_data): Delete la_get_symbol_name_matcher initializer. (cplus_language_data): Likewise. (cplus_language::get_symbol_name_matcher_inner): New member function. (asm_language_data): Delete la_get_symbol_name_matcher initializer. (minimal_language_data): Likewise. * cp-support.h (cp_get_symbol_name_matcher): Update header comment. * d-lang.c (d_language_data): Delete la_get_symbol_name_matcher initializer. * dictionary.c (iter_match_first_hashed): Update call to get_symbol_name_matcher. (iter_match_next_hashed): Likewise. (iter_match_next_linear): Likewise. * dwarf2/read.c (dw2_expand_symtabs_matching_symbol): Likewise. * f-lang.c (f_language_data): Delete la_get_symbol_name_matcher initializer. (f_language::get_symbol_name_matcher_inner): New member function. * go-lang.c (go_language_data): Delete la_get_symbol_name_matcher initializer. * language.c (default_symbol_name_matcher): Update header comment, make static. (language_defn::get_symbol_name_matcher): New definition. (language_defn::get_symbol_name_matcher_inner): Likewise. (get_symbol_name_matcher): Delete. (unknown_language_data): Delete la_get_symbol_name_matcher initializer. (auto_language_data): Likewise. * language.h (language_data): Delete la_get_symbol_name_matcher field. (language_defn::get_symbol_name_matcher): New member function. (language_defn::get_symbol_name_matcher_inner): Likewise. (default_symbol_name_matcher): Delete declaration. * linespec.c (find_methods): Update call to get_symbol_name_matcher. * m2-lang.c (m2_language_data): Delete la_get_symbol_name_matcher initializer. * minsyms.c (lookup_minimal_symbol): Update call to get_symbol_name_matcher. (iterate_over_minimal_symbols): Likewise. * objc-lang.c (objc_language_data): Delete la_get_symbol_name_matcher initializer. * opencl-lang.c (opencl_language_data): Likewise. * p-lang.c (pascal_language_data): Likewise. * psymtab.c (psymbol_name_matches): Update call to get_symbol_name_matcher. * rust-lang.c (rust_language_data): Delete la_get_symbol_name_matcher initializer. * symtab.c (symbol_matches_search_name): Update call to get_symbol_name_matcher. (compare_symbol_name): Likewise.
2020-06-01 18:46:54 +08:00
gdb: move f_language class into a header file Moves the f_language class from f-lang.c into f-lang.h. The benefit of this is that functions declared in other f-*.c files can become member functions without having to go through a level of indirection. Some additional support functions have now become private member functions of the f_language class, these are mostly functions that then called some other function that was itself a member of the language_defn class hierarchy. There should be no user visible changes after this commit. gdb/ChangeLog: * f-exp.y (f_parse): Rename to... (f_language::parser): ...this. * f-lang.c (f_get_encoding): Rename to... (f_language::get_encoding): ...this. (f_op_print_tab): Rename to... (f_language::op_print_tab): ...this. (exp_descriptor_f): Rename to... (f_language::exp_descriptor_tab): ...this. (class f_language): Moved to f-lang.h. (f_language::language_arch_info): New function, moved out of class declaration. (f_language::search_name_hash): Likewise. (f_language::lookup_symbol_nonlocal): Likewise. (f_language::get_symbol_name_matcher_inner): Likewise. * f-lang.h: Add 'valprint.h' include. (class f_language): Moved here from f-lang.c. * f-typeprint.c (f_type_print_args): Delete commented out declaration. (f_print_typedef): Rename to... (f_language::print_typedef): ...this. (f_print_type): Rename to... (f_language::print_type): ...this. (f_type_print_varspec_prefix): Delete declaration and rename to... (f_language::f_type_print_varspec_prefix): ...this. (f_type_print_varspec_suffix): Delete declaration and rename to... (f_language::f_type_print_varspec_suffix): ...this. (f_type_print_base): Delete declaration and rename to... (f_language::f_type_print_base): ...this. * f-valprint.c (f_value_print_inner): Rename to... (f_language::value_print_inner): ...this. * parse.c: Delete 'f-lang.h' include.
2020-09-16 23:27:30 +08:00
symbol_name_matcher_ftype *
f_language::get_symbol_name_matcher_inner
(const lookup_name_info &lookup_name) const
{
return cp_get_symbol_name_matcher (lookup_name);
}
gdb: Represent all languages as sub-classes of language_defn This commit converts all languages to sub-classes of a language_defn base class. The motivation for this change is to make it easier to add new methods onto languages without having to update all of the individual language structures. In the future it might be possible to move more things, like expression parsing, into the language class(es) for better encapsulation, however I have no plans to tackle this in the short term. This commit sets up a strategy for transitioning from the current language system, where each language is an instance of the language_defn structure, to the class hierarchy system. The plan is to rename the existing language_defn into language_data, and make this a base class for the new language_defn class, something like this: struct language_data { ... old language_defn fields here ... }; struct language_defn : public language_data { language_defn (const language_data d) : language_data (d) { .... } }; Then each existing language, for example ada_language_defn can be converted into an instance of language_data, and passed into the constructor of a new language class, something like this: language_data ada_language_data = { ... old ada_language_defn values here ... }; struct ada_language : public language_defn { ada_language (ada_language_data) { .... } }; What this means is that immediately after the conversion nothing much changes. Every language is now its own class, but all the old language fields still exist and can be accessed in the same way. In later commits I will convert function pointers from the old language_defn structure into real class methods on language_defn, with overrides on sub-classes where needed. At this point I imagine that those fields of the old language_defn structure that contained only data will probably remain as data fields within the new language_data base structure, it is only the methods that I plan to change initially. I tweaked how we manage the list of languages a bit, each language is now registered as it is created, and this resulted in a small number of changes in language.c. Most of the changes in the *-lang.c files are identical. There should be no user visible changes after this commit. gdb/ChangeLog: * gdb/ada-lang.c (ada_language_defn): Convert to... (ada_language_data): ...this. (class ada_language): New class. (ada_language_defn): New static global. * gdb/c-lang.c (c_language_defn): Convert to... (c_language_data): ...this. (class c_language): New class. (c_language_defn): New static global. (cplus_language_defn): Convert to... (cplus_language_data): ...this. (class cplus_language): New class. (cplus_language_defn): New static global. (asm_language_defn): Convert to... (asm_language_data): ...this. (class asm_language): New class. (asm_language_defn): New static global. (minimal_language_defn): Convert to... (minimal_language_data): ...this. (class minimal_language): New class. (minimal_language_defn): New static global. * gdb/d-lang.c (d_language_defn): Convert to... (d_language_data): ...this. (class d_language): New class. (d_language_defn): New static global. * gdb/f-lang.c (f_language_defn): Convert to... (f_language_data): ...this. (class f_language): New class. (f_language_defn): New static global. * gdb/go-lang.c (go_language_defn): Convert to... (go_language_data): ...this. (class go_language): New class. (go_language_defn): New static global. * gdb/language.c (unknown_language_defn): Remove declaration. (current_language): Initialize to nullptr, real initialization is moved to _initialize_language. (languages): Delete global. (language_defn::languages): Define. (set_language_command): Use language_defn::languages. (set_language): Likewise. (range_error): Likewise. (language_enum): Likewise. (language_def): Likewise. (add_set_language_command): Use language_def::languages for the language list, and language_def to lookup language pointers. (skip_language_trampoline): Use language_defn::languages. (unknown_language_defn): Convert to... (unknown_language_data): ...this. (class unknown_language): New class. (unknown_language_defn): New static global. (auto_language_defn): Convert to... (auto_language_data): ...this. (class auto_language): New class. (auto_language_defn): New static global. (language_gdbarch_post_init): Use language_defn::languages. (_initialize_language): Initialize current_language. * gdb/language.h (struct language_defn): Rename to... (struct language_data): ...this. (struct language_defn): New. (auto_language_defn): Delete. (unknown_language_defn): Delete. (minimal_language_defn): Delete. (ada_language_defn): Delete. (asm_language_defn): Delete. (c_language_defn): Delete. (cplus_language_defn): Delete. (d_language_defn): Delete. (f_language_defn): Delete. (go_language_defn): Delete. (m2_language_defn): Delete. (objc_language_defn): Delete. (opencl_language_defn): Delete. (pascal_language_defn): Delete. (rust_language_defn): Delete. * gdb/m2-lang.c (m2_language_defn): Convert to... (m2_language_data): ...this. (class m2_language): New class. (m2_language_defn): New static global. * gdb/objc-lang.c (objc_language_defn): Convert to... (objc_language_data): ...this. (class objc_language): New class. (objc_language_defn): New static global. * gdb/opencl-lang.c (opencl_language_defn): Convert to... (opencl_language_data): ...this. (class opencl_language): New class. (opencl_language_defn): New static global. * gdb/p-lang.c (pascal_language_defn): Convert to... (pascal_language_data): ...this. (class pascal_language): New class. (pascal_language_defn): New static global. * gdb/rust-exp.y (rust_lex_tests): Use language_def to find language pointer, update comment format. * gdb/rust-lang.c (rust_language_defn): Convert to... (rust_language_data): ...this. (class rust_language): New class. (rust_language_defn): New static global.
2020-05-01 19:16:58 +08:00
/* Single instance of the Fortran language class. */
static f_language f_language_defn;
static struct builtin_f_type *
build_fortran_types (struct gdbarch *gdbarch)
{
struct builtin_f_type *builtin_f_type = new struct builtin_f_type;
builtin_f_type->builtin_void = builtin_type (gdbarch)->builtin_void;
* gdbtypes.h (TYPE_OBJFILE_OWNED, TYPE_OWNER): New macros. (TYPE_OBJFILE, TYPE_ALLOC, TYPE_ZALLOC): Reimplement. (alloc_type_arch): Add prototype. (alloc_type_copy): Likewise. (get_type_arch): Likewise. (arch_type): Likewise. (arch_integer_type): Likewise. (arch_character_type): Likewise. (arch_boolean_type): Likewise. (init_float_type): Remove, replace by ... (arch_float_type): ... this. (init_complex_type): Remove, replace by ... (arch_complex_type): ... this. (init_flags_type): Remove, replace by ... (arch_flags_type): ... this. (init_composite_type): Remove, replace by ... (arch_composite_type): ... this. * gdbtypes.c (alloc_type): No longer support NULL objfile. (init_type): Likewise. (alloc_type_arch): New function. (alloc_type_copy): New function. (get_type_arch): New function. (smash_type): Preserve type ownership information. (make_pointer_type, make_reference_type, make_function_type, smash_to_memberptr_type, smash_to_method_type): No longer preserve OBJFILE across smash_type calls. (make_pointer_type, make_reference_type, make_function_type, lookup_memberptr_type, lookup_methodptr_type, allocate_stub_method, create_range_type, create_array_type, create_set_type, copy_type): Use alloc_type_copy when allocating types. (check_typedef): Use alloc_type_arch. (copy_type_recursive): Likewise. Preserve type ownership data after copying type. (recursive_dump_type): Dump type ownership data. (alloc_type_instance): Update type ownership check. (copy_type, copy_type_recursive): Likewise. (arch_type): New function. (arch_integer_type): Likewise. (arch_character_type): Likewise. (arch_boolean_type): Likewise. (init_float_type): Remove, replace by ... (arch_float_type): ... this. (init_complex_type): Remove, replace by ... (arch_complex_type): ... this. (init_flags_type): Remove, replace by ... (arch_flags_type): ... this. (append_flags_type_flag): Move down. (init_composite_type): Remove, replace by ... (arch_composite_type): ... this. (append_composite_type_field_aligned, append_composite_type_field): Move down. * gdbarch.c (gdbtypes_post_init): Allocate all types using per-architecture routines. * ada-lang.c (ada_language_arch_info): Likewise. * f-lang.c (build_fortran_types): Likewise. * jv-lang.c (build_java_types): Likewise. * m2-lang.c (build_m2_types): Likewise. * scm-lang.c (build_scm_types): Likewise. * ada-lang.c (ada_type_of_array): Use alloc_type_copy. (packed_array_type): Likewise. (ada_template_to_fixed_record_type_1): Likewise. (template_to_static_fixed_type): Likewise. (to_record_with_fixed_variant_part): Likewise. (to_fixed_variant_branch_type): Likewise. (to_fixed_array_type): Likewise. (to_fixed_range_type): Likewise. (empty_record): Use type instead of objfile argument. Use alloc_type_copy. (to_fixed_variant_branch_type): Update call to empty_record. * jv-lang.c (type_from_class): Use alloc_type_arch. * arm-tdep.c (arm_ext_type): Allocate per-architecture type. * i386-tdep.c (i386_eflags_type, i386_mxcsr_type, i387_ext_type, i386_mmx_type, i386_sse_type): Likewise. * ia64-tdep.c (ia64_ext_type): Likewise. * m32c-tdep.c (make_types): Likewise. * m68k-tdep.c (m68k_ps_type, m68881_ext_type): Likewise. * rs6000-tdep.c (rs6000_builtin_type_vec64, rs6000_builtin_type_vec128): Likewise. * sparc-tdep.c (sparc_psr_type, sparc_fsr_type): Likewise. * sparc64-tdep.c (sparc64_pstate_type, sparc64_fsr_type, sparc64_fprs_type): Likewise. * spu-tdep.c (spu_builtin_type_vec128): Likewise. * xtensa-tdep.c (xtensa_register_type): Likewise. * linux-tdep.c (linux_get_siginfo_type): Likewise. * target-descriptions.c (tdesc_gdb_type): Likewise. * gnu-v3-abi.c (build_gdb_vtable_type): Likewise.
2009-07-02 20:55:30 +08:00
type_allocator alloc (gdbarch);
* gdbtypes.h (TYPE_OBJFILE_OWNED, TYPE_OWNER): New macros. (TYPE_OBJFILE, TYPE_ALLOC, TYPE_ZALLOC): Reimplement. (alloc_type_arch): Add prototype. (alloc_type_copy): Likewise. (get_type_arch): Likewise. (arch_type): Likewise. (arch_integer_type): Likewise. (arch_character_type): Likewise. (arch_boolean_type): Likewise. (init_float_type): Remove, replace by ... (arch_float_type): ... this. (init_complex_type): Remove, replace by ... (arch_complex_type): ... this. (init_flags_type): Remove, replace by ... (arch_flags_type): ... this. (init_composite_type): Remove, replace by ... (arch_composite_type): ... this. * gdbtypes.c (alloc_type): No longer support NULL objfile. (init_type): Likewise. (alloc_type_arch): New function. (alloc_type_copy): New function. (get_type_arch): New function. (smash_type): Preserve type ownership information. (make_pointer_type, make_reference_type, make_function_type, smash_to_memberptr_type, smash_to_method_type): No longer preserve OBJFILE across smash_type calls. (make_pointer_type, make_reference_type, make_function_type, lookup_memberptr_type, lookup_methodptr_type, allocate_stub_method, create_range_type, create_array_type, create_set_type, copy_type): Use alloc_type_copy when allocating types. (check_typedef): Use alloc_type_arch. (copy_type_recursive): Likewise. Preserve type ownership data after copying type. (recursive_dump_type): Dump type ownership data. (alloc_type_instance): Update type ownership check. (copy_type, copy_type_recursive): Likewise. (arch_type): New function. (arch_integer_type): Likewise. (arch_character_type): Likewise. (arch_boolean_type): Likewise. (init_float_type): Remove, replace by ... (arch_float_type): ... this. (init_complex_type): Remove, replace by ... (arch_complex_type): ... this. (init_flags_type): Remove, replace by ... (arch_flags_type): ... this. (append_flags_type_flag): Move down. (init_composite_type): Remove, replace by ... (arch_composite_type): ... this. (append_composite_type_field_aligned, append_composite_type_field): Move down. * gdbarch.c (gdbtypes_post_init): Allocate all types using per-architecture routines. * ada-lang.c (ada_language_arch_info): Likewise. * f-lang.c (build_fortran_types): Likewise. * jv-lang.c (build_java_types): Likewise. * m2-lang.c (build_m2_types): Likewise. * scm-lang.c (build_scm_types): Likewise. * ada-lang.c (ada_type_of_array): Use alloc_type_copy. (packed_array_type): Likewise. (ada_template_to_fixed_record_type_1): Likewise. (template_to_static_fixed_type): Likewise. (to_record_with_fixed_variant_part): Likewise. (to_fixed_variant_branch_type): Likewise. (to_fixed_array_type): Likewise. (to_fixed_range_type): Likewise. (empty_record): Use type instead of objfile argument. Use alloc_type_copy. (to_fixed_variant_branch_type): Update call to empty_record. * jv-lang.c (type_from_class): Use alloc_type_arch. * arm-tdep.c (arm_ext_type): Allocate per-architecture type. * i386-tdep.c (i386_eflags_type, i386_mxcsr_type, i387_ext_type, i386_mmx_type, i386_sse_type): Likewise. * ia64-tdep.c (ia64_ext_type): Likewise. * m32c-tdep.c (make_types): Likewise. * m68k-tdep.c (m68k_ps_type, m68881_ext_type): Likewise. * rs6000-tdep.c (rs6000_builtin_type_vec64, rs6000_builtin_type_vec128): Likewise. * sparc-tdep.c (sparc_psr_type, sparc_fsr_type): Likewise. * sparc64-tdep.c (sparc64_pstate_type, sparc64_fsr_type, sparc64_fprs_type): Likewise. * spu-tdep.c (spu_builtin_type_vec128): Likewise. * xtensa-tdep.c (xtensa_register_type): Likewise. * linux-tdep.c (linux_get_siginfo_type): Likewise. * target-descriptions.c (tdesc_gdb_type): Likewise. * gnu-v3-abi.c (build_gdb_vtable_type): Likewise.
2009-07-02 20:55:30 +08:00
builtin_f_type->builtin_character
= alloc.new_type (TYPE_CODE_CHAR, TARGET_CHAR_BIT, "character");
* gdbtypes.h (TYPE_OBJFILE_OWNED, TYPE_OWNER): New macros. (TYPE_OBJFILE, TYPE_ALLOC, TYPE_ZALLOC): Reimplement. (alloc_type_arch): Add prototype. (alloc_type_copy): Likewise. (get_type_arch): Likewise. (arch_type): Likewise. (arch_integer_type): Likewise. (arch_character_type): Likewise. (arch_boolean_type): Likewise. (init_float_type): Remove, replace by ... (arch_float_type): ... this. (init_complex_type): Remove, replace by ... (arch_complex_type): ... this. (init_flags_type): Remove, replace by ... (arch_flags_type): ... this. (init_composite_type): Remove, replace by ... (arch_composite_type): ... this. * gdbtypes.c (alloc_type): No longer support NULL objfile. (init_type): Likewise. (alloc_type_arch): New function. (alloc_type_copy): New function. (get_type_arch): New function. (smash_type): Preserve type ownership information. (make_pointer_type, make_reference_type, make_function_type, smash_to_memberptr_type, smash_to_method_type): No longer preserve OBJFILE across smash_type calls. (make_pointer_type, make_reference_type, make_function_type, lookup_memberptr_type, lookup_methodptr_type, allocate_stub_method, create_range_type, create_array_type, create_set_type, copy_type): Use alloc_type_copy when allocating types. (check_typedef): Use alloc_type_arch. (copy_type_recursive): Likewise. Preserve type ownership data after copying type. (recursive_dump_type): Dump type ownership data. (alloc_type_instance): Update type ownership check. (copy_type, copy_type_recursive): Likewise. (arch_type): New function. (arch_integer_type): Likewise. (arch_character_type): Likewise. (arch_boolean_type): Likewise. (init_float_type): Remove, replace by ... (arch_float_type): ... this. (init_complex_type): Remove, replace by ... (arch_complex_type): ... this. (init_flags_type): Remove, replace by ... (arch_flags_type): ... this. (append_flags_type_flag): Move down. (init_composite_type): Remove, replace by ... (arch_composite_type): ... this. (append_composite_type_field_aligned, append_composite_type_field): Move down. * gdbarch.c (gdbtypes_post_init): Allocate all types using per-architecture routines. * ada-lang.c (ada_language_arch_info): Likewise. * f-lang.c (build_fortran_types): Likewise. * jv-lang.c (build_java_types): Likewise. * m2-lang.c (build_m2_types): Likewise. * scm-lang.c (build_scm_types): Likewise. * ada-lang.c (ada_type_of_array): Use alloc_type_copy. (packed_array_type): Likewise. (ada_template_to_fixed_record_type_1): Likewise. (template_to_static_fixed_type): Likewise. (to_record_with_fixed_variant_part): Likewise. (to_fixed_variant_branch_type): Likewise. (to_fixed_array_type): Likewise. (to_fixed_range_type): Likewise. (empty_record): Use type instead of objfile argument. Use alloc_type_copy. (to_fixed_variant_branch_type): Update call to empty_record. * jv-lang.c (type_from_class): Use alloc_type_arch. * arm-tdep.c (arm_ext_type): Allocate per-architecture type. * i386-tdep.c (i386_eflags_type, i386_mxcsr_type, i387_ext_type, i386_mmx_type, i386_sse_type): Likewise. * ia64-tdep.c (ia64_ext_type): Likewise. * m32c-tdep.c (make_types): Likewise. * m68k-tdep.c (m68k_ps_type, m68881_ext_type): Likewise. * rs6000-tdep.c (rs6000_builtin_type_vec64, rs6000_builtin_type_vec128): Likewise. * sparc-tdep.c (sparc_psr_type, sparc_fsr_type): Likewise. * sparc64-tdep.c (sparc64_pstate_type, sparc64_fsr_type, sparc64_fprs_type): Likewise. * spu-tdep.c (spu_builtin_type_vec128): Likewise. * xtensa-tdep.c (xtensa_register_type): Likewise. * linux-tdep.c (linux_get_siginfo_type): Likewise. * target-descriptions.c (tdesc_gdb_type): Likewise. * gnu-v3-abi.c (build_gdb_vtable_type): Likewise.
2009-07-02 20:55:30 +08:00
builtin_f_type->builtin_logical_s1
= init_boolean_type (alloc, TARGET_CHAR_BIT, 1, "logical*1");
* gdbtypes.h (TYPE_OBJFILE_OWNED, TYPE_OWNER): New macros. (TYPE_OBJFILE, TYPE_ALLOC, TYPE_ZALLOC): Reimplement. (alloc_type_arch): Add prototype. (alloc_type_copy): Likewise. (get_type_arch): Likewise. (arch_type): Likewise. (arch_integer_type): Likewise. (arch_character_type): Likewise. (arch_boolean_type): Likewise. (init_float_type): Remove, replace by ... (arch_float_type): ... this. (init_complex_type): Remove, replace by ... (arch_complex_type): ... this. (init_flags_type): Remove, replace by ... (arch_flags_type): ... this. (init_composite_type): Remove, replace by ... (arch_composite_type): ... this. * gdbtypes.c (alloc_type): No longer support NULL objfile. (init_type): Likewise. (alloc_type_arch): New function. (alloc_type_copy): New function. (get_type_arch): New function. (smash_type): Preserve type ownership information. (make_pointer_type, make_reference_type, make_function_type, smash_to_memberptr_type, smash_to_method_type): No longer preserve OBJFILE across smash_type calls. (make_pointer_type, make_reference_type, make_function_type, lookup_memberptr_type, lookup_methodptr_type, allocate_stub_method, create_range_type, create_array_type, create_set_type, copy_type): Use alloc_type_copy when allocating types. (check_typedef): Use alloc_type_arch. (copy_type_recursive): Likewise. Preserve type ownership data after copying type. (recursive_dump_type): Dump type ownership data. (alloc_type_instance): Update type ownership check. (copy_type, copy_type_recursive): Likewise. (arch_type): New function. (arch_integer_type): Likewise. (arch_character_type): Likewise. (arch_boolean_type): Likewise. (init_float_type): Remove, replace by ... (arch_float_type): ... this. (init_complex_type): Remove, replace by ... (arch_complex_type): ... this. (init_flags_type): Remove, replace by ... (arch_flags_type): ... this. (append_flags_type_flag): Move down. (init_composite_type): Remove, replace by ... (arch_composite_type): ... this. (append_composite_type_field_aligned, append_composite_type_field): Move down. * gdbarch.c (gdbtypes_post_init): Allocate all types using per-architecture routines. * ada-lang.c (ada_language_arch_info): Likewise. * f-lang.c (build_fortran_types): Likewise. * jv-lang.c (build_java_types): Likewise. * m2-lang.c (build_m2_types): Likewise. * scm-lang.c (build_scm_types): Likewise. * ada-lang.c (ada_type_of_array): Use alloc_type_copy. (packed_array_type): Likewise. (ada_template_to_fixed_record_type_1): Likewise. (template_to_static_fixed_type): Likewise. (to_record_with_fixed_variant_part): Likewise. (to_fixed_variant_branch_type): Likewise. (to_fixed_array_type): Likewise. (to_fixed_range_type): Likewise. (empty_record): Use type instead of objfile argument. Use alloc_type_copy. (to_fixed_variant_branch_type): Update call to empty_record. * jv-lang.c (type_from_class): Use alloc_type_arch. * arm-tdep.c (arm_ext_type): Allocate per-architecture type. * i386-tdep.c (i386_eflags_type, i386_mxcsr_type, i387_ext_type, i386_mmx_type, i386_sse_type): Likewise. * ia64-tdep.c (ia64_ext_type): Likewise. * m32c-tdep.c (make_types): Likewise. * m68k-tdep.c (m68k_ps_type, m68881_ext_type): Likewise. * rs6000-tdep.c (rs6000_builtin_type_vec64, rs6000_builtin_type_vec128): Likewise. * sparc-tdep.c (sparc_psr_type, sparc_fsr_type): Likewise. * sparc64-tdep.c (sparc64_pstate_type, sparc64_fsr_type, sparc64_fprs_type): Likewise. * spu-tdep.c (spu_builtin_type_vec128): Likewise. * xtensa-tdep.c (xtensa_register_type): Likewise. * linux-tdep.c (linux_get_siginfo_type): Likewise. * target-descriptions.c (tdesc_gdb_type): Likewise. * gnu-v3-abi.c (build_gdb_vtable_type): Likewise.
2009-07-02 20:55:30 +08:00
builtin_f_type->builtin_logical_s2
= init_boolean_type (alloc, gdbarch_short_bit (gdbarch), 1, "logical*2");
* gdbtypes.h (TYPE_OBJFILE_OWNED, TYPE_OWNER): New macros. (TYPE_OBJFILE, TYPE_ALLOC, TYPE_ZALLOC): Reimplement. (alloc_type_arch): Add prototype. (alloc_type_copy): Likewise. (get_type_arch): Likewise. (arch_type): Likewise. (arch_integer_type): Likewise. (arch_character_type): Likewise. (arch_boolean_type): Likewise. (init_float_type): Remove, replace by ... (arch_float_type): ... this. (init_complex_type): Remove, replace by ... (arch_complex_type): ... this. (init_flags_type): Remove, replace by ... (arch_flags_type): ... this. (init_composite_type): Remove, replace by ... (arch_composite_type): ... this. * gdbtypes.c (alloc_type): No longer support NULL objfile. (init_type): Likewise. (alloc_type_arch): New function. (alloc_type_copy): New function. (get_type_arch): New function. (smash_type): Preserve type ownership information. (make_pointer_type, make_reference_type, make_function_type, smash_to_memberptr_type, smash_to_method_type): No longer preserve OBJFILE across smash_type calls. (make_pointer_type, make_reference_type, make_function_type, lookup_memberptr_type, lookup_methodptr_type, allocate_stub_method, create_range_type, create_array_type, create_set_type, copy_type): Use alloc_type_copy when allocating types. (check_typedef): Use alloc_type_arch. (copy_type_recursive): Likewise. Preserve type ownership data after copying type. (recursive_dump_type): Dump type ownership data. (alloc_type_instance): Update type ownership check. (copy_type, copy_type_recursive): Likewise. (arch_type): New function. (arch_integer_type): Likewise. (arch_character_type): Likewise. (arch_boolean_type): Likewise. (init_float_type): Remove, replace by ... (arch_float_type): ... this. (init_complex_type): Remove, replace by ... (arch_complex_type): ... this. (init_flags_type): Remove, replace by ... (arch_flags_type): ... this. (append_flags_type_flag): Move down. (init_composite_type): Remove, replace by ... (arch_composite_type): ... this. (append_composite_type_field_aligned, append_composite_type_field): Move down. * gdbarch.c (gdbtypes_post_init): Allocate all types using per-architecture routines. * ada-lang.c (ada_language_arch_info): Likewise. * f-lang.c (build_fortran_types): Likewise. * jv-lang.c (build_java_types): Likewise. * m2-lang.c (build_m2_types): Likewise. * scm-lang.c (build_scm_types): Likewise. * ada-lang.c (ada_type_of_array): Use alloc_type_copy. (packed_array_type): Likewise. (ada_template_to_fixed_record_type_1): Likewise. (template_to_static_fixed_type): Likewise. (to_record_with_fixed_variant_part): Likewise. (to_fixed_variant_branch_type): Likewise. (to_fixed_array_type): Likewise. (to_fixed_range_type): Likewise. (empty_record): Use type instead of objfile argument. Use alloc_type_copy. (to_fixed_variant_branch_type): Update call to empty_record. * jv-lang.c (type_from_class): Use alloc_type_arch. * arm-tdep.c (arm_ext_type): Allocate per-architecture type. * i386-tdep.c (i386_eflags_type, i386_mxcsr_type, i387_ext_type, i386_mmx_type, i386_sse_type): Likewise. * ia64-tdep.c (ia64_ext_type): Likewise. * m32c-tdep.c (make_types): Likewise. * m68k-tdep.c (m68k_ps_type, m68881_ext_type): Likewise. * rs6000-tdep.c (rs6000_builtin_type_vec64, rs6000_builtin_type_vec128): Likewise. * sparc-tdep.c (sparc_psr_type, sparc_fsr_type): Likewise. * sparc64-tdep.c (sparc64_pstate_type, sparc64_fsr_type, sparc64_fprs_type): Likewise. * spu-tdep.c (spu_builtin_type_vec128): Likewise. * xtensa-tdep.c (xtensa_register_type): Likewise. * linux-tdep.c (linux_get_siginfo_type): Likewise. * target-descriptions.c (tdesc_gdb_type): Likewise. * gnu-v3-abi.c (build_gdb_vtable_type): Likewise.
2009-07-02 20:55:30 +08:00
gdb/fortran: clean-up Fortran intrinsic types 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.
2022-04-11 20:06:56 +08:00
builtin_f_type->builtin_logical
= init_boolean_type (alloc, gdbarch_int_bit (gdbarch), 1, "logical*4");
gdb/fortran: clean-up Fortran intrinsic types 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.
2022-04-11 20:06:56 +08:00
builtin_f_type->builtin_logical_s8
= init_boolean_type (alloc, gdbarch_long_long_bit (gdbarch), 1,
"logical*8");
gdb/fortran: clean-up Fortran intrinsic types 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.
2022-04-11 20:06:56 +08:00
builtin_f_type->builtin_integer_s1
= init_integer_type (alloc, TARGET_CHAR_BIT, 0, "integer*1");
gdb/fortran: clean-up Fortran intrinsic types 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.
2022-04-11 20:06:56 +08:00
builtin_f_type->builtin_integer_s2
= init_integer_type (alloc, gdbarch_short_bit (gdbarch), 0, "integer*2");
gdb/fortran: clean-up Fortran intrinsic types 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.
2022-04-11 20:06:56 +08:00
* gdbtypes.h (TYPE_OBJFILE_OWNED, TYPE_OWNER): New macros. (TYPE_OBJFILE, TYPE_ALLOC, TYPE_ZALLOC): Reimplement. (alloc_type_arch): Add prototype. (alloc_type_copy): Likewise. (get_type_arch): Likewise. (arch_type): Likewise. (arch_integer_type): Likewise. (arch_character_type): Likewise. (arch_boolean_type): Likewise. (init_float_type): Remove, replace by ... (arch_float_type): ... this. (init_complex_type): Remove, replace by ... (arch_complex_type): ... this. (init_flags_type): Remove, replace by ... (arch_flags_type): ... this. (init_composite_type): Remove, replace by ... (arch_composite_type): ... this. * gdbtypes.c (alloc_type): No longer support NULL objfile. (init_type): Likewise. (alloc_type_arch): New function. (alloc_type_copy): New function. (get_type_arch): New function. (smash_type): Preserve type ownership information. (make_pointer_type, make_reference_type, make_function_type, smash_to_memberptr_type, smash_to_method_type): No longer preserve OBJFILE across smash_type calls. (make_pointer_type, make_reference_type, make_function_type, lookup_memberptr_type, lookup_methodptr_type, allocate_stub_method, create_range_type, create_array_type, create_set_type, copy_type): Use alloc_type_copy when allocating types. (check_typedef): Use alloc_type_arch. (copy_type_recursive): Likewise. Preserve type ownership data after copying type. (recursive_dump_type): Dump type ownership data. (alloc_type_instance): Update type ownership check. (copy_type, copy_type_recursive): Likewise. (arch_type): New function. (arch_integer_type): Likewise. (arch_character_type): Likewise. (arch_boolean_type): Likewise. (init_float_type): Remove, replace by ... (arch_float_type): ... this. (init_complex_type): Remove, replace by ... (arch_complex_type): ... this. (init_flags_type): Remove, replace by ... (arch_flags_type): ... this. (append_flags_type_flag): Move down. (init_composite_type): Remove, replace by ... (arch_composite_type): ... this. (append_composite_type_field_aligned, append_composite_type_field): Move down. * gdbarch.c (gdbtypes_post_init): Allocate all types using per-architecture routines. * ada-lang.c (ada_language_arch_info): Likewise. * f-lang.c (build_fortran_types): Likewise. * jv-lang.c (build_java_types): Likewise. * m2-lang.c (build_m2_types): Likewise. * scm-lang.c (build_scm_types): Likewise. * ada-lang.c (ada_type_of_array): Use alloc_type_copy. (packed_array_type): Likewise. (ada_template_to_fixed_record_type_1): Likewise. (template_to_static_fixed_type): Likewise. (to_record_with_fixed_variant_part): Likewise. (to_fixed_variant_branch_type): Likewise. (to_fixed_array_type): Likewise. (to_fixed_range_type): Likewise. (empty_record): Use type instead of objfile argument. Use alloc_type_copy. (to_fixed_variant_branch_type): Update call to empty_record. * jv-lang.c (type_from_class): Use alloc_type_arch. * arm-tdep.c (arm_ext_type): Allocate per-architecture type. * i386-tdep.c (i386_eflags_type, i386_mxcsr_type, i387_ext_type, i386_mmx_type, i386_sse_type): Likewise. * ia64-tdep.c (ia64_ext_type): Likewise. * m32c-tdep.c (make_types): Likewise. * m68k-tdep.c (m68k_ps_type, m68881_ext_type): Likewise. * rs6000-tdep.c (rs6000_builtin_type_vec64, rs6000_builtin_type_vec128): Likewise. * sparc-tdep.c (sparc_psr_type, sparc_fsr_type): Likewise. * sparc64-tdep.c (sparc64_pstate_type, sparc64_fsr_type, sparc64_fprs_type): Likewise. * spu-tdep.c (spu_builtin_type_vec128): Likewise. * xtensa-tdep.c (xtensa_register_type): Likewise. * linux-tdep.c (linux_get_siginfo_type): Likewise. * target-descriptions.c (tdesc_gdb_type): Likewise. * gnu-v3-abi.c (build_gdb_vtable_type): Likewise.
2009-07-02 20:55:30 +08:00
builtin_f_type->builtin_integer
= init_integer_type (alloc, gdbarch_int_bit (gdbarch), 0, "integer*4");
* gdbtypes.h (TYPE_OBJFILE_OWNED, TYPE_OWNER): New macros. (TYPE_OBJFILE, TYPE_ALLOC, TYPE_ZALLOC): Reimplement. (alloc_type_arch): Add prototype. (alloc_type_copy): Likewise. (get_type_arch): Likewise. (arch_type): Likewise. (arch_integer_type): Likewise. (arch_character_type): Likewise. (arch_boolean_type): Likewise. (init_float_type): Remove, replace by ... (arch_float_type): ... this. (init_complex_type): Remove, replace by ... (arch_complex_type): ... this. (init_flags_type): Remove, replace by ... (arch_flags_type): ... this. (init_composite_type): Remove, replace by ... (arch_composite_type): ... this. * gdbtypes.c (alloc_type): No longer support NULL objfile. (init_type): Likewise. (alloc_type_arch): New function. (alloc_type_copy): New function. (get_type_arch): New function. (smash_type): Preserve type ownership information. (make_pointer_type, make_reference_type, make_function_type, smash_to_memberptr_type, smash_to_method_type): No longer preserve OBJFILE across smash_type calls. (make_pointer_type, make_reference_type, make_function_type, lookup_memberptr_type, lookup_methodptr_type, allocate_stub_method, create_range_type, create_array_type, create_set_type, copy_type): Use alloc_type_copy when allocating types. (check_typedef): Use alloc_type_arch. (copy_type_recursive): Likewise. Preserve type ownership data after copying type. (recursive_dump_type): Dump type ownership data. (alloc_type_instance): Update type ownership check. (copy_type, copy_type_recursive): Likewise. (arch_type): New function. (arch_integer_type): Likewise. (arch_character_type): Likewise. (arch_boolean_type): Likewise. (init_float_type): Remove, replace by ... (arch_float_type): ... this. (init_complex_type): Remove, replace by ... (arch_complex_type): ... this. (init_flags_type): Remove, replace by ... (arch_flags_type): ... this. (append_flags_type_flag): Move down. (init_composite_type): Remove, replace by ... (arch_composite_type): ... this. (append_composite_type_field_aligned, append_composite_type_field): Move down. * gdbarch.c (gdbtypes_post_init): Allocate all types using per-architecture routines. * ada-lang.c (ada_language_arch_info): Likewise. * f-lang.c (build_fortran_types): Likewise. * jv-lang.c (build_java_types): Likewise. * m2-lang.c (build_m2_types): Likewise. * scm-lang.c (build_scm_types): Likewise. * ada-lang.c (ada_type_of_array): Use alloc_type_copy. (packed_array_type): Likewise. (ada_template_to_fixed_record_type_1): Likewise. (template_to_static_fixed_type): Likewise. (to_record_with_fixed_variant_part): Likewise. (to_fixed_variant_branch_type): Likewise. (to_fixed_array_type): Likewise. (to_fixed_range_type): Likewise. (empty_record): Use type instead of objfile argument. Use alloc_type_copy. (to_fixed_variant_branch_type): Update call to empty_record. * jv-lang.c (type_from_class): Use alloc_type_arch. * arm-tdep.c (arm_ext_type): Allocate per-architecture type. * i386-tdep.c (i386_eflags_type, i386_mxcsr_type, i387_ext_type, i386_mmx_type, i386_sse_type): Likewise. * ia64-tdep.c (ia64_ext_type): Likewise. * m32c-tdep.c (make_types): Likewise. * m68k-tdep.c (m68k_ps_type, m68881_ext_type): Likewise. * rs6000-tdep.c (rs6000_builtin_type_vec64, rs6000_builtin_type_vec128): Likewise. * sparc-tdep.c (sparc_psr_type, sparc_fsr_type): Likewise. * sparc64-tdep.c (sparc64_pstate_type, sparc64_fsr_type, sparc64_fprs_type): Likewise. * spu-tdep.c (spu_builtin_type_vec128): Likewise. * xtensa-tdep.c (xtensa_register_type): Likewise. * linux-tdep.c (linux_get_siginfo_type): Likewise. * target-descriptions.c (tdesc_gdb_type): Likewise. * gnu-v3-abi.c (build_gdb_vtable_type): Likewise.
2009-07-02 20:55:30 +08:00
gdb/fortran: clean-up Fortran intrinsic types 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.
2022-04-11 20:06:56 +08:00
builtin_f_type->builtin_integer_s8
= init_integer_type (alloc, gdbarch_long_long_bit (gdbarch), 0,
gdb/fortran: clean-up Fortran intrinsic types 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.
2022-04-11 20:06:56 +08:00
"integer*8");
* gdbtypes.h (TYPE_OBJFILE_OWNED, TYPE_OWNER): New macros. (TYPE_OBJFILE, TYPE_ALLOC, TYPE_ZALLOC): Reimplement. (alloc_type_arch): Add prototype. (alloc_type_copy): Likewise. (get_type_arch): Likewise. (arch_type): Likewise. (arch_integer_type): Likewise. (arch_character_type): Likewise. (arch_boolean_type): Likewise. (init_float_type): Remove, replace by ... (arch_float_type): ... this. (init_complex_type): Remove, replace by ... (arch_complex_type): ... this. (init_flags_type): Remove, replace by ... (arch_flags_type): ... this. (init_composite_type): Remove, replace by ... (arch_composite_type): ... this. * gdbtypes.c (alloc_type): No longer support NULL objfile. (init_type): Likewise. (alloc_type_arch): New function. (alloc_type_copy): New function. (get_type_arch): New function. (smash_type): Preserve type ownership information. (make_pointer_type, make_reference_type, make_function_type, smash_to_memberptr_type, smash_to_method_type): No longer preserve OBJFILE across smash_type calls. (make_pointer_type, make_reference_type, make_function_type, lookup_memberptr_type, lookup_methodptr_type, allocate_stub_method, create_range_type, create_array_type, create_set_type, copy_type): Use alloc_type_copy when allocating types. (check_typedef): Use alloc_type_arch. (copy_type_recursive): Likewise. Preserve type ownership data after copying type. (recursive_dump_type): Dump type ownership data. (alloc_type_instance): Update type ownership check. (copy_type, copy_type_recursive): Likewise. (arch_type): New function. (arch_integer_type): Likewise. (arch_character_type): Likewise. (arch_boolean_type): Likewise. (init_float_type): Remove, replace by ... (arch_float_type): ... this. (init_complex_type): Remove, replace by ... (arch_complex_type): ... this. (init_flags_type): Remove, replace by ... (arch_flags_type): ... this. (append_flags_type_flag): Move down. (init_composite_type): Remove, replace by ... (arch_composite_type): ... this. (append_composite_type_field_aligned, append_composite_type_field): Move down. * gdbarch.c (gdbtypes_post_init): Allocate all types using per-architecture routines. * ada-lang.c (ada_language_arch_info): Likewise. * f-lang.c (build_fortran_types): Likewise. * jv-lang.c (build_java_types): Likewise. * m2-lang.c (build_m2_types): Likewise. * scm-lang.c (build_scm_types): Likewise. * ada-lang.c (ada_type_of_array): Use alloc_type_copy. (packed_array_type): Likewise. (ada_template_to_fixed_record_type_1): Likewise. (template_to_static_fixed_type): Likewise. (to_record_with_fixed_variant_part): Likewise. (to_fixed_variant_branch_type): Likewise. (to_fixed_array_type): Likewise. (to_fixed_range_type): Likewise. (empty_record): Use type instead of objfile argument. Use alloc_type_copy. (to_fixed_variant_branch_type): Update call to empty_record. * jv-lang.c (type_from_class): Use alloc_type_arch. * arm-tdep.c (arm_ext_type): Allocate per-architecture type. * i386-tdep.c (i386_eflags_type, i386_mxcsr_type, i387_ext_type, i386_mmx_type, i386_sse_type): Likewise. * ia64-tdep.c (ia64_ext_type): Likewise. * m32c-tdep.c (make_types): Likewise. * m68k-tdep.c (m68k_ps_type, m68881_ext_type): Likewise. * rs6000-tdep.c (rs6000_builtin_type_vec64, rs6000_builtin_type_vec128): Likewise. * sparc-tdep.c (sparc_psr_type, sparc_fsr_type): Likewise. * sparc64-tdep.c (sparc64_pstate_type, sparc64_fsr_type, sparc64_fprs_type): Likewise. * spu-tdep.c (spu_builtin_type_vec128): Likewise. * xtensa-tdep.c (xtensa_register_type): Likewise. * linux-tdep.c (linux_get_siginfo_type): Likewise. * target-descriptions.c (tdesc_gdb_type): Likewise. * gnu-v3-abi.c (build_gdb_vtable_type): Likewise.
2009-07-02 20:55:30 +08:00
builtin_f_type->builtin_real
= init_float_type (alloc, gdbarch_float_bit (gdbarch),
gdb/fortran: Change GDB print for fortran default types 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.
2022-04-11 20:06:56 +08:00
"real*4", gdbarch_float_format (gdbarch));
* gdbtypes.h (TYPE_OBJFILE_OWNED, TYPE_OWNER): New macros. (TYPE_OBJFILE, TYPE_ALLOC, TYPE_ZALLOC): Reimplement. (alloc_type_arch): Add prototype. (alloc_type_copy): Likewise. (get_type_arch): Likewise. (arch_type): Likewise. (arch_integer_type): Likewise. (arch_character_type): Likewise. (arch_boolean_type): Likewise. (init_float_type): Remove, replace by ... (arch_float_type): ... this. (init_complex_type): Remove, replace by ... (arch_complex_type): ... this. (init_flags_type): Remove, replace by ... (arch_flags_type): ... this. (init_composite_type): Remove, replace by ... (arch_composite_type): ... this. * gdbtypes.c (alloc_type): No longer support NULL objfile. (init_type): Likewise. (alloc_type_arch): New function. (alloc_type_copy): New function. (get_type_arch): New function. (smash_type): Preserve type ownership information. (make_pointer_type, make_reference_type, make_function_type, smash_to_memberptr_type, smash_to_method_type): No longer preserve OBJFILE across smash_type calls. (make_pointer_type, make_reference_type, make_function_type, lookup_memberptr_type, lookup_methodptr_type, allocate_stub_method, create_range_type, create_array_type, create_set_type, copy_type): Use alloc_type_copy when allocating types. (check_typedef): Use alloc_type_arch. (copy_type_recursive): Likewise. Preserve type ownership data after copying type. (recursive_dump_type): Dump type ownership data. (alloc_type_instance): Update type ownership check. (copy_type, copy_type_recursive): Likewise. (arch_type): New function. (arch_integer_type): Likewise. (arch_character_type): Likewise. (arch_boolean_type): Likewise. (init_float_type): Remove, replace by ... (arch_float_type): ... this. (init_complex_type): Remove, replace by ... (arch_complex_type): ... this. (init_flags_type): Remove, replace by ... (arch_flags_type): ... this. (append_flags_type_flag): Move down. (init_composite_type): Remove, replace by ... (arch_composite_type): ... this. (append_composite_type_field_aligned, append_composite_type_field): Move down. * gdbarch.c (gdbtypes_post_init): Allocate all types using per-architecture routines. * ada-lang.c (ada_language_arch_info): Likewise. * f-lang.c (build_fortran_types): Likewise. * jv-lang.c (build_java_types): Likewise. * m2-lang.c (build_m2_types): Likewise. * scm-lang.c (build_scm_types): Likewise. * ada-lang.c (ada_type_of_array): Use alloc_type_copy. (packed_array_type): Likewise. (ada_template_to_fixed_record_type_1): Likewise. (template_to_static_fixed_type): Likewise. (to_record_with_fixed_variant_part): Likewise. (to_fixed_variant_branch_type): Likewise. (to_fixed_array_type): Likewise. (to_fixed_range_type): Likewise. (empty_record): Use type instead of objfile argument. Use alloc_type_copy. (to_fixed_variant_branch_type): Update call to empty_record. * jv-lang.c (type_from_class): Use alloc_type_arch. * arm-tdep.c (arm_ext_type): Allocate per-architecture type. * i386-tdep.c (i386_eflags_type, i386_mxcsr_type, i387_ext_type, i386_mmx_type, i386_sse_type): Likewise. * ia64-tdep.c (ia64_ext_type): Likewise. * m32c-tdep.c (make_types): Likewise. * m68k-tdep.c (m68k_ps_type, m68881_ext_type): Likewise. * rs6000-tdep.c (rs6000_builtin_type_vec64, rs6000_builtin_type_vec128): Likewise. * sparc-tdep.c (sparc_psr_type, sparc_fsr_type): Likewise. * sparc64-tdep.c (sparc64_pstate_type, sparc64_fsr_type, sparc64_fprs_type): Likewise. * spu-tdep.c (spu_builtin_type_vec128): Likewise. * xtensa-tdep.c (xtensa_register_type): Likewise. * linux-tdep.c (linux_get_siginfo_type): Likewise. * target-descriptions.c (tdesc_gdb_type): Likewise. * gnu-v3-abi.c (build_gdb_vtable_type): Likewise.
2009-07-02 20:55:30 +08:00
builtin_f_type->builtin_real_s8
= init_float_type (alloc, gdbarch_double_bit (gdbarch),
"real*8", gdbarch_double_format (gdbarch));
gdb/fortran: Use floatformats_ia64_quad for fortran 16-byte floats PR gdb/18644 is caused by GDB using the wrong floating point format for gfortran's 16-byte floating point type, including when the 16-byte float is used as the component of a 32-byte complex type. This commit addresses the issue in two places, first in i386-tdep.c, there is already some code to force the use of floatformats_ia64_quad for specific named types, this is extended to include the type names that gfortran uses for its 16-byte floats. Second, the builtin 16-byte float type (in f-lang.c) is changed so it no longer uses gdbarch_long_double_format. On i386 this type is not 16-bytes, but is smaller, this is not what gfortran is expecting. Instead we now use gdbarch_floatformat_for_type and ask for a 16-byte (128 bit) type using the common gfortran type name. This is then spotted in i386-tdep.c (thanks to the first change above) and we again get floatformats_ia64_quad returned. This patch was tested on X86-64/GNU-Linux using '--target_board=unix' and '--target_board=unix/-m32', and resolves all of the known failures associated with PR gdb/18644. I've also added the test case from the original bug report. gdb/ChangeLog: PR gdb/18644: * f-lang.c (build_fortran_types): Use floatformats_ia64_quad for 16-byte floats. * i386-tdep.c (i386_floatformat_for_type): Use floatformats_ia64_quad for the 16-byte floating point component within a fortran 32-byte complex number. gdb/testsuite/ChangeLog: PR gdb/18644 * gdb.fortran/complex.exp: Remove setup_kfail calls. * gdb.fortran/printing-types.exp: Add new test. * gdb.fortran/printing-types.f90: Add 16-byte real variable for testing. * gdb.fortran/type-kinds.exp (test_cast_1_to_type_kind): Remove setup_kfail call.
2019-05-03 22:23:55 +08:00
auto fmt = gdbarch_floatformat_for_type (gdbarch, "real(kind=16)", 128);
if (fmt != nullptr)
builtin_f_type->builtin_real_s16
= init_float_type (alloc, 128, "real*16", fmt);
else if (gdbarch_long_double_bit (gdbarch) == 128)
builtin_f_type->builtin_real_s16
= init_float_type (alloc, gdbarch_long_double_bit (gdbarch),
"real*16", gdbarch_long_double_format (gdbarch));
else
builtin_f_type->builtin_real_s16
= alloc.new_type (TYPE_CODE_ERROR, 128, "real*16");
* gdbtypes.h (TYPE_OBJFILE_OWNED, TYPE_OWNER): New macros. (TYPE_OBJFILE, TYPE_ALLOC, TYPE_ZALLOC): Reimplement. (alloc_type_arch): Add prototype. (alloc_type_copy): Likewise. (get_type_arch): Likewise. (arch_type): Likewise. (arch_integer_type): Likewise. (arch_character_type): Likewise. (arch_boolean_type): Likewise. (init_float_type): Remove, replace by ... (arch_float_type): ... this. (init_complex_type): Remove, replace by ... (arch_complex_type): ... this. (init_flags_type): Remove, replace by ... (arch_flags_type): ... this. (init_composite_type): Remove, replace by ... (arch_composite_type): ... this. * gdbtypes.c (alloc_type): No longer support NULL objfile. (init_type): Likewise. (alloc_type_arch): New function. (alloc_type_copy): New function. (get_type_arch): New function. (smash_type): Preserve type ownership information. (make_pointer_type, make_reference_type, make_function_type, smash_to_memberptr_type, smash_to_method_type): No longer preserve OBJFILE across smash_type calls. (make_pointer_type, make_reference_type, make_function_type, lookup_memberptr_type, lookup_methodptr_type, allocate_stub_method, create_range_type, create_array_type, create_set_type, copy_type): Use alloc_type_copy when allocating types. (check_typedef): Use alloc_type_arch. (copy_type_recursive): Likewise. Preserve type ownership data after copying type. (recursive_dump_type): Dump type ownership data. (alloc_type_instance): Update type ownership check. (copy_type, copy_type_recursive): Likewise. (arch_type): New function. (arch_integer_type): Likewise. (arch_character_type): Likewise. (arch_boolean_type): Likewise. (init_float_type): Remove, replace by ... (arch_float_type): ... this. (init_complex_type): Remove, replace by ... (arch_complex_type): ... this. (init_flags_type): Remove, replace by ... (arch_flags_type): ... this. (append_flags_type_flag): Move down. (init_composite_type): Remove, replace by ... (arch_composite_type): ... this. (append_composite_type_field_aligned, append_composite_type_field): Move down. * gdbarch.c (gdbtypes_post_init): Allocate all types using per-architecture routines. * ada-lang.c (ada_language_arch_info): Likewise. * f-lang.c (build_fortran_types): Likewise. * jv-lang.c (build_java_types): Likewise. * m2-lang.c (build_m2_types): Likewise. * scm-lang.c (build_scm_types): Likewise. * ada-lang.c (ada_type_of_array): Use alloc_type_copy. (packed_array_type): Likewise. (ada_template_to_fixed_record_type_1): Likewise. (template_to_static_fixed_type): Likewise. (to_record_with_fixed_variant_part): Likewise. (to_fixed_variant_branch_type): Likewise. (to_fixed_array_type): Likewise. (to_fixed_range_type): Likewise. (empty_record): Use type instead of objfile argument. Use alloc_type_copy. (to_fixed_variant_branch_type): Update call to empty_record. * jv-lang.c (type_from_class): Use alloc_type_arch. * arm-tdep.c (arm_ext_type): Allocate per-architecture type. * i386-tdep.c (i386_eflags_type, i386_mxcsr_type, i387_ext_type, i386_mmx_type, i386_sse_type): Likewise. * ia64-tdep.c (ia64_ext_type): Likewise. * m32c-tdep.c (make_types): Likewise. * m68k-tdep.c (m68k_ps_type, m68881_ext_type): Likewise. * rs6000-tdep.c (rs6000_builtin_type_vec64, rs6000_builtin_type_vec128): Likewise. * sparc-tdep.c (sparc_psr_type, sparc_fsr_type): Likewise. * sparc64-tdep.c (sparc64_pstate_type, sparc64_fsr_type, sparc64_fprs_type): Likewise. * spu-tdep.c (spu_builtin_type_vec128): Likewise. * xtensa-tdep.c (xtensa_register_type): Likewise. * linux-tdep.c (linux_get_siginfo_type): Likewise. * target-descriptions.c (tdesc_gdb_type): Likewise. * gnu-v3-abi.c (build_gdb_vtable_type): Likewise.
2009-07-02 20:55:30 +08:00
builtin_f_type->builtin_complex
= init_complex_type ("complex*4", builtin_f_type->builtin_real);
* gdbtypes.h (TYPE_OBJFILE_OWNED, TYPE_OWNER): New macros. (TYPE_OBJFILE, TYPE_ALLOC, TYPE_ZALLOC): Reimplement. (alloc_type_arch): Add prototype. (alloc_type_copy): Likewise. (get_type_arch): Likewise. (arch_type): Likewise. (arch_integer_type): Likewise. (arch_character_type): Likewise. (arch_boolean_type): Likewise. (init_float_type): Remove, replace by ... (arch_float_type): ... this. (init_complex_type): Remove, replace by ... (arch_complex_type): ... this. (init_flags_type): Remove, replace by ... (arch_flags_type): ... this. (init_composite_type): Remove, replace by ... (arch_composite_type): ... this. * gdbtypes.c (alloc_type): No longer support NULL objfile. (init_type): Likewise. (alloc_type_arch): New function. (alloc_type_copy): New function. (get_type_arch): New function. (smash_type): Preserve type ownership information. (make_pointer_type, make_reference_type, make_function_type, smash_to_memberptr_type, smash_to_method_type): No longer preserve OBJFILE across smash_type calls. (make_pointer_type, make_reference_type, make_function_type, lookup_memberptr_type, lookup_methodptr_type, allocate_stub_method, create_range_type, create_array_type, create_set_type, copy_type): Use alloc_type_copy when allocating types. (check_typedef): Use alloc_type_arch. (copy_type_recursive): Likewise. Preserve type ownership data after copying type. (recursive_dump_type): Dump type ownership data. (alloc_type_instance): Update type ownership check. (copy_type, copy_type_recursive): Likewise. (arch_type): New function. (arch_integer_type): Likewise. (arch_character_type): Likewise. (arch_boolean_type): Likewise. (init_float_type): Remove, replace by ... (arch_float_type): ... this. (init_complex_type): Remove, replace by ... (arch_complex_type): ... this. (init_flags_type): Remove, replace by ... (arch_flags_type): ... this. (append_flags_type_flag): Move down. (init_composite_type): Remove, replace by ... (arch_composite_type): ... this. (append_composite_type_field_aligned, append_composite_type_field): Move down. * gdbarch.c (gdbtypes_post_init): Allocate all types using per-architecture routines. * ada-lang.c (ada_language_arch_info): Likewise. * f-lang.c (build_fortran_types): Likewise. * jv-lang.c (build_java_types): Likewise. * m2-lang.c (build_m2_types): Likewise. * scm-lang.c (build_scm_types): Likewise. * ada-lang.c (ada_type_of_array): Use alloc_type_copy. (packed_array_type): Likewise. (ada_template_to_fixed_record_type_1): Likewise. (template_to_static_fixed_type): Likewise. (to_record_with_fixed_variant_part): Likewise. (to_fixed_variant_branch_type): Likewise. (to_fixed_array_type): Likewise. (to_fixed_range_type): Likewise. (empty_record): Use type instead of objfile argument. Use alloc_type_copy. (to_fixed_variant_branch_type): Update call to empty_record. * jv-lang.c (type_from_class): Use alloc_type_arch. * arm-tdep.c (arm_ext_type): Allocate per-architecture type. * i386-tdep.c (i386_eflags_type, i386_mxcsr_type, i387_ext_type, i386_mmx_type, i386_sse_type): Likewise. * ia64-tdep.c (ia64_ext_type): Likewise. * m32c-tdep.c (make_types): Likewise. * m68k-tdep.c (m68k_ps_type, m68881_ext_type): Likewise. * rs6000-tdep.c (rs6000_builtin_type_vec64, rs6000_builtin_type_vec128): Likewise. * sparc-tdep.c (sparc_psr_type, sparc_fsr_type): Likewise. * sparc64-tdep.c (sparc64_pstate_type, sparc64_fsr_type, sparc64_fprs_type): Likewise. * spu-tdep.c (spu_builtin_type_vec128): Likewise. * xtensa-tdep.c (xtensa_register_type): Likewise. * linux-tdep.c (linux_get_siginfo_type): Likewise. * target-descriptions.c (tdesc_gdb_type): Likewise. * gnu-v3-abi.c (build_gdb_vtable_type): Likewise.
2009-07-02 20:55:30 +08:00
builtin_f_type->builtin_complex_s8
= init_complex_type ("complex*8", builtin_f_type->builtin_real_s8);
if (builtin_f_type->builtin_real_s16->code () == TYPE_CODE_ERROR)
builtin_f_type->builtin_complex_s16
= alloc.new_type (TYPE_CODE_ERROR, 256, "complex*16");
else
builtin_f_type->builtin_complex_s16
= init_complex_type ("complex*16", builtin_f_type->builtin_real_s16);
return builtin_f_type;
}
static const registry<gdbarch>::key<struct builtin_f_type> f_type_data;
const struct builtin_f_type *
builtin_f_type (struct gdbarch *gdbarch)
{
struct builtin_f_type *result = f_type_data.get (gdbarch);
if (result == nullptr)
{
result = build_fortran_types (gdbarch);
f_type_data.set (gdbarch, result);
}
return result;
}
gdb/fortran: Add support for Fortran array slices at the GDB prompt This commit brings array slice support to GDB. WARNING: This patch contains a rather big hack which is limited to Fortran arrays, this can be seen in gdbtypes.c and f-lang.c. More details on this below. This patch rewrites two areas of GDB's Fortran support, the code to extract an array slice, and the code to print an array. After this commit a user can, from the GDB prompt, ask for a slice of a Fortran array and should get the correct result back. Slices can (optionally) have the lower bound, upper bound, and a stride specified. Slices can also have a negative stride. Fortran has the concept of repacking array slices. Within a compiled Fortran program if a user passes a non-contiguous array slice to a function then the compiler may have to repack the slice, this involves copying the elements of the slice to a new area of memory before the call, and copying the elements back to the original array after the call. Whether repacking occurs will depend on which version of Fortran is being used, and what type of function is being called. This commit adds support for both packed, and unpacked array slicing, with the default being unpacked. With an unpacked array slice, when the user asks for a slice of an array GDB creates a new type that accurately describes where the elements of the slice can be found within the original array, a value of this type is then returned to the user. The address of an element within the slice will be equal to the address of an element within the original array. A user can choose to select packed array slices instead using: (gdb) set fortran repack-array-slices on|off (gdb) show fortran repack-array-slices With packed array slices GDB creates a new type that reflects how the elements of the slice would look if they were laid out in contiguous memory, allocates a value of this type, and then fetches the elements from the original array and places then into the contents buffer of the new value. One benefit of using packed slices over unpacked slices is the memory usage, taking a small slice of N elements from a large array will require (in GDB) N * ELEMENT_SIZE bytes of memory, while an unpacked array will also include all of the "padding" between the non-contiguous elements. There are new tests added that highlight this difference. There is also a new debugging flag added with this commit that introduces these commands: (gdb) set debug fortran-array-slicing on|off (gdb) show debug fortran-array-slicing This prints information about how the array slices are being built. As both the repacking, and the array printing requires GDB to walk through a multi-dimensional Fortran array visiting each element, this commit adds the file f-array-walk.h, which introduces some infrastructure to support this process. This means the array printing code in f-valprint.c is significantly reduced. The only slight issue with this commit is the "rather big hack" that I mentioned above. This hack allows us to handle one specific case, array slices with negative strides. This is something that I don't believe the current GDB value contents model will allow us to correctly handle, and rather than rewrite the value contents code right now, I'm hoping to slip this hack in as a work around. The problem is that, as I see it, the current value contents model assumes that an object base address will be the lowest address within that object, and that the contents of the object start at this base address and occupy the TYPE_LENGTH bytes after that. ( We do have the embedded_offset, which is used for C++ sub-classes, such that an object can start at some offset from the content buffer, however, the assumption that the object then occupies the next TYPE_LENGTH bytes is still true within GDB. ) The problem is that Fortran arrays with a negative stride don't follow this pattern. In this case the base address of the object points to the element with the highest address, the contents of the array then start at some offset _before_ the base address, and proceed for one element _past_ the base address. As the stride for such an array would be negative then, in theory the TYPE_LENGTH for this type would also be negative. However, in many places a value in GDB will degrade to a pointer + length, and the length almost always comes from the TYPE_LENGTH. It is my belief that in order to correctly model this case the value content handling of GDB will need to be reworked to split apart the value's content buffer (which is a block of memory with a length), and the object's in memory base address and length, which could be negative. Things are further complicated because arrays with negative strides like this are always dynamic types. When a value has a dynamic type and its base address needs resolving we actually store the address of the object within the resolved dynamic type, not within the value object itself. In short I don't currently see an easy path to cleanly support this situation within GDB. And so I believe that leaves two options, either add a work around, or catch cases where the user tries to make use of a negative stride, or access an array with a negative stride, and throw an error. This patch currently goes with adding a work around, which is that when we resolve a dynamic Fortran array type, if the stride is negative, then we adjust the base address to point to the lowest address required by the array. The printing and slicing code is aware of this adjustment and will correctly slice and print Fortran arrays. Where this hack will show through to the user is if they ask for the address of an array in their program with a negative array stride, the address they get from GDB will not match the address that would be computed within the Fortran program. gdb/ChangeLog: * Makefile.in (HFILES_NO_SRCDIR): Add f-array-walker.h. * NEWS: Mention new options. * f-array-walker.h: New file. * f-lang.c: Include 'gdbcmd.h' and 'f-array-walker.h'. (repack_array_slices): New static global. (show_repack_array_slices): New function. (fortran_array_slicing_debug): New static global. (show_fortran_array_slicing_debug): New function. (value_f90_subarray): Delete. (skip_undetermined_arglist): Delete. (class fortran_array_repacker_base_impl): New class. (class fortran_lazy_array_repacker_impl): New class. (class fortran_array_repacker_impl): New class. (fortran_value_subarray): Complete rewrite. (set_fortran_list): New static global. (show_fortran_list): Likewise. (_initialize_f_language): Register new commands. (fortran_adjust_dynamic_array_base_address_hack): New function. * f-lang.h (fortran_adjust_dynamic_array_base_address_hack): Declare. * f-valprint.c: Include 'f-array-walker.h'. (class fortran_array_printer_impl): New class. (f77_print_array_1): Delete. (f77_print_array): Delete. (fortran_print_array): New. (f_value_print_inner): Update to call fortran_print_array. * gdbtypes.c: Include 'f-lang.h'. (resolve_dynamic_type_internal): Call fortran_adjust_dynamic_array_base_address_hack. gdb/testsuite/ChangeLog: * gdb.fortran/array-slices-bad.exp: New file. * gdb.fortran/array-slices-bad.f90: New file. * gdb.fortran/array-slices-sub-slices.exp: New file. * gdb.fortran/array-slices-sub-slices.f90: New file. * gdb.fortran/array-slices.exp: Rewrite tests. * gdb.fortran/array-slices.f90: Rewrite tests. * gdb.fortran/vla-sizeof.exp: Correct expected results. gdb/doc/ChangeLog: * gdb.texinfo (Debugging Output): Document 'set/show debug fortran-array-slicing'. (Special Fortran Commands): Document 'set/show fortran repack-array-slices'.
2020-10-08 23:45:59 +08:00
/* Command-list for the "set/show fortran" prefix command. */
static struct cmd_list_element *set_fortran_list;
static struct cmd_list_element *show_fortran_list;
gdb: add back declarations for _initialize functions I'd like to enable the -Wmissing-declarations warning. However, it warns for every _initialize function, for example: CXX dcache.o /home/smarchi/src/binutils-gdb/gdb/dcache.c: In function ‘void _initialize_dcache()’: /home/smarchi/src/binutils-gdb/gdb/dcache.c:688:1: error: no previous declaration for ‘void _initialize_dcache()’ [-Werror=missing-declarations] _initialize_dcache (void) ^~~~~~~~~~~~~~~~~~ The only practical way forward I found is to add back the declarations, which were removed by this commit: commit 481695ed5f6e0a8a9c9c50bfac1cdd2b3151e6c9 Author: John Baldwin <jhb@FreeBSD.org> Date: Sat Sep 9 11:02:37 2017 -0700 Remove unnecessary function prototypes. I don't think it's a big problem to have the declarations for these functions, but if anybody has a better solution for this, I'll be happy to use it. gdb/ChangeLog: * aarch64-fbsd-nat.c (_initialize_aarch64_fbsd_nat): Add declaration. * aarch64-fbsd-tdep.c (_initialize_aarch64_fbsd_tdep): Add declaration. * aarch64-linux-nat.c (_initialize_aarch64_linux_nat): Add declaration. * aarch64-linux-tdep.c (_initialize_aarch64_linux_tdep): Add declaration. * aarch64-newlib-tdep.c (_initialize_aarch64_newlib_tdep): Add declaration. * aarch64-tdep.c (_initialize_aarch64_tdep): Add declaration. * ada-exp.y (_initialize_ada_exp): Add declaration. * ada-lang.c (_initialize_ada_language): Add declaration. * ada-tasks.c (_initialize_tasks): Add declaration. * agent.c (_initialize_agent): Add declaration. * aix-thread.c (_initialize_aix_thread): Add declaration. * alpha-bsd-nat.c (_initialize_alphabsd_nat): Add declaration. * alpha-linux-nat.c (_initialize_alpha_linux_nat): Add declaration. * alpha-linux-tdep.c (_initialize_alpha_linux_tdep): Add declaration. * alpha-nbsd-tdep.c (_initialize_alphanbsd_tdep): Add declaration. * alpha-obsd-tdep.c (_initialize_alphaobsd_tdep): Add declaration. * alpha-tdep.c (_initialize_alpha_tdep): Add declaration. * amd64-darwin-tdep.c (_initialize_amd64_darwin_tdep): Add declaration. * amd64-dicos-tdep.c (_initialize_amd64_dicos_tdep): Add declaration. * amd64-fbsd-nat.c (_initialize_amd64fbsd_nat): Add declaration. * amd64-fbsd-tdep.c (_initialize_amd64fbsd_tdep): Add declaration. * amd64-linux-nat.c (_initialize_amd64_linux_nat): Add declaration. * amd64-linux-tdep.c (_initialize_amd64_linux_tdep): Add declaration. * amd64-nbsd-nat.c (_initialize_amd64nbsd_nat): Add declaration. * amd64-nbsd-tdep.c (_initialize_amd64nbsd_tdep): Add declaration. * amd64-obsd-nat.c (_initialize_amd64obsd_nat): Add declaration. * amd64-obsd-tdep.c (_initialize_amd64obsd_tdep): Add declaration. * amd64-sol2-tdep.c (_initialize_amd64_sol2_tdep): Add declaration. * amd64-tdep.c (_initialize_amd64_tdep): Add declaration. * amd64-windows-nat.c (_initialize_amd64_windows_nat): Add declaration. * amd64-windows-tdep.c (_initialize_amd64_windows_tdep): Add declaration. * annotate.c (_initialize_annotate): Add declaration. * arc-newlib-tdep.c (_initialize_arc_newlib_tdep): Add declaration. * arc-tdep.c (_initialize_arc_tdep): Add declaration. * arch-utils.c (_initialize_gdbarch_utils): Add declaration. * arm-fbsd-nat.c (_initialize_arm_fbsd_nat): Add declaration. * arm-fbsd-tdep.c (_initialize_arm_fbsd_tdep): Add declaration. * arm-linux-nat.c (_initialize_arm_linux_nat): Add declaration. * arm-linux-tdep.c (_initialize_arm_linux_tdep): Add declaration. * arm-nbsd-nat.c (_initialize_arm_netbsd_nat): Add declaration. * arm-nbsd-tdep.c (_initialize_arm_netbsd_tdep): Add declaration. * arm-obsd-tdep.c (_initialize_armobsd_tdep): Add declaration. * arm-pikeos-tdep.c (_initialize_arm_pikeos_tdep): Add declaration. * arm-symbian-tdep.c (_initialize_arm_symbian_tdep): Add declaration. * arm-tdep.c (_initialize_arm_tdep): Add declaration. * arm-wince-tdep.c (_initialize_arm_wince_tdep): Add declaration. * auto-load.c (_initialize_auto_load): Add declaration. * auxv.c (_initialize_auxv): Add declaration. * avr-tdep.c (_initialize_avr_tdep): Add declaration. * ax-gdb.c (_initialize_ax_gdb): Add declaration. * bfin-linux-tdep.c (_initialize_bfin_linux_tdep): Add declaration. * bfin-tdep.c (_initialize_bfin_tdep): Add declaration. * break-catch-sig.c (_initialize_break_catch_sig): Add declaration. * break-catch-syscall.c (_initialize_break_catch_syscall): Add declaration. * break-catch-throw.c (_initialize_break_catch_throw): Add declaration. * breakpoint.c (_initialize_breakpoint): Add declaration. * bsd-uthread.c (_initialize_bsd_uthread): Add declaration. * btrace.c (_initialize_btrace): Add declaration. * charset.c (_initialize_charset): Add declaration. * cli/cli-cmds.c (_initialize_cli_cmds): Add declaration. * cli/cli-dump.c (_initialize_cli_dump): Add declaration. * cli/cli-interp.c (_initialize_cli_interp): Add declaration. * cli/cli-logging.c (_initialize_cli_logging): Add declaration. * cli/cli-script.c (_initialize_cli_script): Add declaration. * cli/cli-style.c (_initialize_cli_style): Add declaration. * coff-pe-read.c (_initialize_coff_pe_read): Add declaration. * coffread.c (_initialize_coffread): Add declaration. * compile/compile-cplus-types.c (_initialize_compile_cplus_types): Add declaration. * compile/compile.c (_initialize_compile): Add declaration. * complaints.c (_initialize_complaints): Add declaration. * completer.c (_initialize_completer): Add declaration. * copying.c (_initialize_copying): Add declaration. * corefile.c (_initialize_core): Add declaration. * corelow.c (_initialize_corelow): Add declaration. * cp-abi.c (_initialize_cp_abi): Add declaration. * cp-namespace.c (_initialize_cp_namespace): Add declaration. * cp-support.c (_initialize_cp_support): Add declaration. * cp-valprint.c (_initialize_cp_valprint): Add declaration. * cris-linux-tdep.c (_initialize_cris_linux_tdep): Add declaration. * cris-tdep.c (_initialize_cris_tdep): Add declaration. * csky-linux-tdep.c (_initialize_csky_linux_tdep): Add declaration. * csky-tdep.c (_initialize_csky_tdep): Add declaration. * ctfread.c (_initialize_ctfread): Add declaration. * d-lang.c (_initialize_d_language): Add declaration. * darwin-nat-info.c (_initialize_darwin_info_commands): Add declaration. * darwin-nat.c (_initialize_darwin_nat): Add declaration. * dbxread.c (_initialize_dbxread): Add declaration. * dcache.c (_initialize_dcache): Add declaration. * disasm-selftests.c (_initialize_disasm_selftests): Add declaration. * disasm.c (_initialize_disasm): Add declaration. * dtrace-probe.c (_initialize_dtrace_probe): Add declaration. * dummy-frame.c (_initialize_dummy_frame): Add declaration. * dwarf-index-cache.c (_initialize_index_cache): Add declaration. * dwarf-index-write.c (_initialize_dwarf_index_write): Add declaration. * dwarf2-frame-tailcall.c (_initialize_tailcall_frame): Add declaration. * dwarf2-frame.c (_initialize_dwarf2_frame): Add declaration. * dwarf2expr.c (_initialize_dwarf2expr): Add declaration. * dwarf2loc.c (_initialize_dwarf2loc): Add declaration. * dwarf2read.c (_initialize_dwarf2_read): Add declaration. * elfread.c (_initialize_elfread): Add declaration. * exec.c (_initialize_exec): Add declaration. * extension.c (_initialize_extension): Add declaration. * f-lang.c (_initialize_f_language): Add declaration. * f-valprint.c (_initialize_f_valprint): Add declaration. * fbsd-nat.c (_initialize_fbsd_nat): Add declaration. * fbsd-tdep.c (_initialize_fbsd_tdep): Add declaration. * filesystem.c (_initialize_filesystem): Add declaration. * findcmd.c (_initialize_mem_search): Add declaration. * findvar.c (_initialize_findvar): Add declaration. * fork-child.c (_initialize_fork_child): Add declaration. * frame-base.c (_initialize_frame_base): Add declaration. * frame-unwind.c (_initialize_frame_unwind): Add declaration. * frame.c (_initialize_frame): Add declaration. * frv-linux-tdep.c (_initialize_frv_linux_tdep): Add declaration. * frv-tdep.c (_initialize_frv_tdep): Add declaration. * ft32-tdep.c (_initialize_ft32_tdep): Add declaration. * gcore.c (_initialize_gcore): Add declaration. * gdb-demangle.c (_initialize_gdb_demangle): Add declaration. * gdb_bfd.c (_initialize_gdb_bfd): Add declaration. * gdbarch-selftests.c (_initialize_gdbarch_selftests): Add declaration. * gdbarch.c (_initialize_gdbarch): Add declaration. * gdbtypes.c (_initialize_gdbtypes): Add declaration. * gnu-nat.c (_initialize_gnu_nat): Add declaration. * gnu-v2-abi.c (_initialize_gnu_v2_abi): Add declaration. * gnu-v3-abi.c (_initialize_gnu_v3_abi): Add declaration. * go-lang.c (_initialize_go_language): Add declaration. * go32-nat.c (_initialize_go32_nat): Add declaration. * guile/guile.c (_initialize_guile): Add declaration. * h8300-tdep.c (_initialize_h8300_tdep): Add declaration. * hppa-linux-nat.c (_initialize_hppa_linux_nat): Add declaration. * hppa-linux-tdep.c (_initialize_hppa_linux_tdep): Add declaration. * hppa-nbsd-nat.c (_initialize_hppanbsd_nat): Add declaration. * hppa-nbsd-tdep.c (_initialize_hppanbsd_tdep): Add declaration. * hppa-obsd-nat.c (_initialize_hppaobsd_nat): Add declaration. * hppa-obsd-tdep.c (_initialize_hppabsd_tdep): Add declaration. * hppa-tdep.c (_initialize_hppa_tdep): Add declaration. * i386-bsd-nat.c (_initialize_i386bsd_nat): Add declaration. * i386-cygwin-tdep.c (_initialize_i386_cygwin_tdep): Add declaration. * i386-darwin-nat.c (_initialize_i386_darwin_nat): Add declaration. * i386-darwin-tdep.c (_initialize_i386_darwin_tdep): Add declaration. * i386-dicos-tdep.c (_initialize_i386_dicos_tdep): Add declaration. * i386-fbsd-nat.c (_initialize_i386fbsd_nat): Add declaration. * i386-fbsd-tdep.c (_initialize_i386fbsd_tdep): Add declaration. * i386-gnu-nat.c (_initialize_i386gnu_nat): Add declaration. * i386-gnu-tdep.c (_initialize_i386gnu_tdep): Add declaration. * i386-go32-tdep.c (_initialize_i386_go32_tdep): Add declaration. * i386-linux-nat.c (_initialize_i386_linux_nat): Add declaration. * i386-linux-tdep.c (_initialize_i386_linux_tdep): Add declaration. * i386-nbsd-nat.c (_initialize_i386nbsd_nat): Add declaration. * i386-nbsd-tdep.c (_initialize_i386nbsd_tdep): Add declaration. * i386-nto-tdep.c (_initialize_i386nto_tdep): Add declaration. * i386-obsd-nat.c (_initialize_i386obsd_nat): Add declaration. * i386-obsd-tdep.c (_initialize_i386obsd_tdep): Add declaration. * i386-sol2-nat.c (_initialize_amd64_sol2_nat): Add declaration. * i386-sol2-tdep.c (_initialize_i386_sol2_tdep): Add declaration. * i386-tdep.c (_initialize_i386_tdep): Add declaration. * i386-windows-nat.c (_initialize_i386_windows_nat): Add declaration. * ia64-libunwind-tdep.c (_initialize_libunwind_frame): Add declaration. * ia64-linux-nat.c (_initialize_ia64_linux_nat): Add declaration. * ia64-linux-tdep.c (_initialize_ia64_linux_tdep): Add declaration. * ia64-tdep.c (_initialize_ia64_tdep): Add declaration. * ia64-vms-tdep.c (_initialize_ia64_vms_tdep): Add declaration. * infcall.c (_initialize_infcall): Add declaration. * infcmd.c (_initialize_infcmd): Add declaration. * inflow.c (_initialize_inflow): Add declaration. * infrun.c (_initialize_infrun): Add declaration. * interps.c (_initialize_interpreter): Add declaration. * iq2000-tdep.c (_initialize_iq2000_tdep): Add declaration. * jit.c (_initialize_jit): Add declaration. * language.c (_initialize_language): Add declaration. * linux-fork.c (_initialize_linux_fork): Add declaration. * linux-nat.c (_initialize_linux_nat): Add declaration. * linux-tdep.c (_initialize_linux_tdep): Add declaration. * linux-thread-db.c (_initialize_thread_db): Add declaration. * lm32-tdep.c (_initialize_lm32_tdep): Add declaration. * m2-lang.c (_initialize_m2_language): Add declaration. * m32c-tdep.c (_initialize_m32c_tdep): Add declaration. * m32r-linux-nat.c (_initialize_m32r_linux_nat): Add declaration. * m32r-linux-tdep.c (_initialize_m32r_linux_tdep): Add declaration. * m32r-tdep.c (_initialize_m32r_tdep): Add declaration. * m68hc11-tdep.c (_initialize_m68hc11_tdep): Add declaration. * m68k-bsd-nat.c (_initialize_m68kbsd_nat): Add declaration. * m68k-bsd-tdep.c (_initialize_m68kbsd_tdep): Add declaration. * m68k-linux-nat.c (_initialize_m68k_linux_nat): Add declaration. * m68k-linux-tdep.c (_initialize_m68k_linux_tdep): Add declaration. * m68k-tdep.c (_initialize_m68k_tdep): Add declaration. * machoread.c (_initialize_machoread): Add declaration. * macrocmd.c (_initialize_macrocmd): Add declaration. * macroscope.c (_initialize_macroscope): Add declaration. * maint-test-options.c (_initialize_maint_test_options): Add declaration. * maint-test-settings.c (_initialize_maint_test_settings): Add declaration. * maint.c (_initialize_maint_cmds): Add declaration. * mdebugread.c (_initialize_mdebugread): Add declaration. * memattr.c (_initialize_mem): Add declaration. * mep-tdep.c (_initialize_mep_tdep): Add declaration. * mi/mi-cmd-env.c (_initialize_mi_cmd_env): Add declaration. * mi/mi-cmds.c (_initialize_mi_cmds): Add declaration. * mi/mi-interp.c (_initialize_mi_interp): Add declaration. * mi/mi-main.c (_initialize_mi_main): Add declaration. * microblaze-linux-tdep.c (_initialize_microblaze_linux_tdep): Add declaration. * microblaze-tdep.c (_initialize_microblaze_tdep): Add declaration. * mips-fbsd-nat.c (_initialize_mips_fbsd_nat): Add declaration. * mips-fbsd-tdep.c (_initialize_mips_fbsd_tdep): Add declaration. * mips-linux-nat.c (_initialize_mips_linux_nat): Add declaration. * mips-linux-tdep.c (_initialize_mips_linux_tdep): Add declaration. * mips-nbsd-nat.c (_initialize_mipsnbsd_nat): Add declaration. * mips-nbsd-tdep.c (_initialize_mipsnbsd_tdep): Add declaration. * mips-sde-tdep.c (_initialize_mips_sde_tdep): Add declaration. * mips-tdep.c (_initialize_mips_tdep): Add declaration. * mips64-obsd-nat.c (_initialize_mips64obsd_nat): Add declaration. * mips64-obsd-tdep.c (_initialize_mips64obsd_tdep): Add declaration. * mipsread.c (_initialize_mipsread): Add declaration. * mn10300-linux-tdep.c (_initialize_mn10300_linux_tdep): Add declaration. * mn10300-tdep.c (_initialize_mn10300_tdep): Add declaration. * moxie-tdep.c (_initialize_moxie_tdep): Add declaration. * msp430-tdep.c (_initialize_msp430_tdep): Add declaration. * nds32-tdep.c (_initialize_nds32_tdep): Add declaration. * nios2-linux-tdep.c (_initialize_nios2_linux_tdep): Add declaration. * nios2-tdep.c (_initialize_nios2_tdep): Add declaration. * nto-procfs.c (_initialize_procfs): Add declaration. * objc-lang.c (_initialize_objc_language): Add declaration. * observable.c (_initialize_observer): Add declaration. * opencl-lang.c (_initialize_opencl_language): Add declaration. * or1k-linux-tdep.c (_initialize_or1k_linux_tdep): Add declaration. * or1k-tdep.c (_initialize_or1k_tdep): Add declaration. * osabi.c (_initialize_gdb_osabi): Add declaration. * osdata.c (_initialize_osdata): Add declaration. * p-valprint.c (_initialize_pascal_valprint): Add declaration. * parse.c (_initialize_parse): Add declaration. * ppc-fbsd-nat.c (_initialize_ppcfbsd_nat): Add declaration. * ppc-fbsd-tdep.c (_initialize_ppcfbsd_tdep): Add declaration. * ppc-linux-nat.c (_initialize_ppc_linux_nat): Add declaration. * ppc-linux-tdep.c (_initialize_ppc_linux_tdep): Add declaration. * ppc-nbsd-nat.c (_initialize_ppcnbsd_nat): Add declaration. * ppc-nbsd-tdep.c (_initialize_ppcnbsd_tdep): Add declaration. * ppc-obsd-nat.c (_initialize_ppcobsd_nat): Add declaration. * ppc-obsd-tdep.c (_initialize_ppcobsd_tdep): Add declaration. * printcmd.c (_initialize_printcmd): Add declaration. * probe.c (_initialize_probe): Add declaration. * proc-api.c (_initialize_proc_api): Add declaration. * proc-events.c (_initialize_proc_events): Add declaration. * proc-service.c (_initialize_proc_service): Add declaration. * procfs.c (_initialize_procfs): Add declaration. * producer.c (_initialize_producer): Add declaration. * psymtab.c (_initialize_psymtab): Add declaration. * python/python.c (_initialize_python): Add declaration. * ravenscar-thread.c (_initialize_ravenscar): Add declaration. * record-btrace.c (_initialize_record_btrace): Add declaration. * record-full.c (_initialize_record_full): Add declaration. * record.c (_initialize_record): Add declaration. * regcache-dump.c (_initialize_regcache_dump): Add declaration. * regcache.c (_initialize_regcache): Add declaration. * reggroups.c (_initialize_reggroup): Add declaration. * remote-notif.c (_initialize_notif): Add declaration. * remote-sim.c (_initialize_remote_sim): Add declaration. * remote.c (_initialize_remote): Add declaration. * reverse.c (_initialize_reverse): Add declaration. * riscv-fbsd-nat.c (_initialize_riscv_fbsd_nat): Add declaration. * riscv-fbsd-tdep.c (_initialize_riscv_fbsd_tdep): Add declaration. * riscv-linux-nat.c (_initialize_riscv_linux_nat): Add declaration. * riscv-linux-tdep.c (_initialize_riscv_linux_tdep): Add declaration. * riscv-tdep.c (_initialize_riscv_tdep): Add declaration. * rl78-tdep.c (_initialize_rl78_tdep): Add declaration. * rs6000-aix-tdep.c (_initialize_rs6000_aix_tdep): Add declaration. * rs6000-lynx178-tdep.c (_initialize_rs6000_lynx178_tdep): Add declaration. * rs6000-nat.c (_initialize_rs6000_nat): Add declaration. * rs6000-tdep.c (_initialize_rs6000_tdep): Add declaration. * run-on-main-thread.c (_initialize_run_on_main_thread): Add declaration. * rust-exp.y (_initialize_rust_exp): Add declaration. * rx-tdep.c (_initialize_rx_tdep): Add declaration. * s12z-tdep.c (_initialize_s12z_tdep): Add declaration. * s390-linux-nat.c (_initialize_s390_nat): Add declaration. * s390-linux-tdep.c (_initialize_s390_linux_tdep): Add declaration. * s390-tdep.c (_initialize_s390_tdep): Add declaration. * score-tdep.c (_initialize_score_tdep): Add declaration. * ser-go32.c (_initialize_ser_dos): Add declaration. * ser-mingw.c (_initialize_ser_windows): Add declaration. * ser-pipe.c (_initialize_ser_pipe): Add declaration. * ser-tcp.c (_initialize_ser_tcp): Add declaration. * ser-uds.c (_initialize_ser_socket): Add declaration. * ser-unix.c (_initialize_ser_hardwire): Add declaration. * serial.c (_initialize_serial): Add declaration. * sh-linux-tdep.c (_initialize_sh_linux_tdep): Add declaration. * sh-nbsd-nat.c (_initialize_shnbsd_nat): Add declaration. * sh-nbsd-tdep.c (_initialize_shnbsd_tdep): Add declaration. * sh-tdep.c (_initialize_sh_tdep): Add declaration. * skip.c (_initialize_step_skip): Add declaration. * sol-thread.c (_initialize_sol_thread): Add declaration. * solib-aix.c (_initialize_solib_aix): Add declaration. * solib-darwin.c (_initialize_darwin_solib): Add declaration. * solib-dsbt.c (_initialize_dsbt_solib): Add declaration. * solib-frv.c (_initialize_frv_solib): Add declaration. * solib-svr4.c (_initialize_svr4_solib): Add declaration. * solib-target.c (_initialize_solib_target): Add declaration. * solib.c (_initialize_solib): Add declaration. * source-cache.c (_initialize_source_cache): Add declaration. * source.c (_initialize_source): Add declaration. * sparc-linux-nat.c (_initialize_sparc_linux_nat): Add declaration. * sparc-linux-tdep.c (_initialize_sparc_linux_tdep): Add declaration. * sparc-nat.c (_initialize_sparc_nat): Add declaration. * sparc-nbsd-nat.c (_initialize_sparcnbsd_nat): Add declaration. * sparc-nbsd-tdep.c (_initialize_sparcnbsd_tdep): Add declaration. * sparc-obsd-tdep.c (_initialize_sparc32obsd_tdep): Add declaration. * sparc-sol2-tdep.c (_initialize_sparc_sol2_tdep): Add declaration. * sparc-tdep.c (_initialize_sparc_tdep): Add declaration. * sparc64-fbsd-nat.c (_initialize_sparc64fbsd_nat): Add declaration. * sparc64-fbsd-tdep.c (_initialize_sparc64fbsd_tdep): Add declaration. * sparc64-linux-nat.c (_initialize_sparc64_linux_nat): Add declaration. * sparc64-linux-tdep.c (_initialize_sparc64_linux_tdep): Add declaration. * sparc64-nat.c (_initialize_sparc64_nat): Add declaration. * sparc64-nbsd-nat.c (_initialize_sparc64nbsd_nat): Add declaration. * sparc64-nbsd-tdep.c (_initialize_sparc64nbsd_tdep): Add declaration. * sparc64-obsd-nat.c (_initialize_sparc64obsd_nat): Add declaration. * sparc64-obsd-tdep.c (_initialize_sparc64obsd_tdep): Add declaration. * sparc64-sol2-tdep.c (_initialize_sparc64_sol2_tdep): Add declaration. * sparc64-tdep.c (_initialize_sparc64_adi_tdep): Add declaration. * stabsread.c (_initialize_stabsread): Add declaration. * stack.c (_initialize_stack): Add declaration. * stap-probe.c (_initialize_stap_probe): Add declaration. * std-regs.c (_initialize_frame_reg): Add declaration. * symfile-debug.c (_initialize_symfile_debug): Add declaration. * symfile-mem.c (_initialize_symfile_mem): Add declaration. * symfile.c (_initialize_symfile): Add declaration. * symmisc.c (_initialize_symmisc): Add declaration. * symtab.c (_initialize_symtab): Add declaration. * target.c (_initialize_target): Add declaration. * target-connection.c (_initialize_target_connection): Add declaration. * target-dcache.c (_initialize_target_dcache): Add declaration. * target-descriptions.c (_initialize_target_descriptions): Add declaration. * thread.c (_initialize_thread): Add declaration. * tic6x-linux-tdep.c (_initialize_tic6x_linux_tdep): Add declaration. * tic6x-tdep.c (_initialize_tic6x_tdep): Add declaration. * tilegx-linux-nat.c (_initialize_tile_linux_nat): Add declaration. * tilegx-linux-tdep.c (_initialize_tilegx_linux_tdep): Add declaration. * tilegx-tdep.c (_initialize_tilegx_tdep): Add declaration. * tracectf.c (_initialize_ctf): Add declaration. * tracefile-tfile.c (_initialize_tracefile_tfile): Add declaration. * tracefile.c (_initialize_tracefile): Add declaration. * tracepoint.c (_initialize_tracepoint): Add declaration. * tui/tui-hooks.c (_initialize_tui_hooks): Add declaration. * tui/tui-interp.c (_initialize_tui_interp): Add declaration. * tui/tui-layout.c (_initialize_tui_layout): Add declaration. * tui/tui-regs.c (_initialize_tui_regs): Add declaration. * tui/tui-stack.c (_initialize_tui_stack): Add declaration. * tui/tui-win.c (_initialize_tui_win): Add declaration. * tui/tui.c (_initialize_tui): Add declaration. * typeprint.c (_initialize_typeprint): Add declaration. * ui-style.c (_initialize_ui_style): Add declaration. * unittests/array-view-selftests.c (_initialize_array_view_selftests): Add declaration. * unittests/child-path-selftests.c (_initialize_child_path_selftests): Add declaration. * unittests/cli-utils-selftests.c (_initialize_cli_utils_selftests): Add declaration. * unittests/common-utils-selftests.c (_initialize_common_utils_selftests): Add declaration. * unittests/copy_bitwise-selftests.c (_initialize_copy_bitwise_utils_selftests): Add declaration. * unittests/environ-selftests.c (_initialize_environ_selftests): Add declaration. * unittests/filtered_iterator-selftests.c (_initialize_filtered_iterator_selftests): Add declaration. * unittests/format_pieces-selftests.c (_initialize_format_pieces_selftests): Add declaration. * unittests/function-view-selftests.c (_initialize_function_view_selftests): Add declaration. * unittests/help-doc-selftests.c (_initialize_help_doc_selftests): Add declaration. * unittests/lookup_name_info-selftests.c (_initialize_lookup_name_info_selftests): Add declaration. * unittests/main-thread-selftests.c (_initialize_main_thread_selftests): Add declaration. * unittests/memory-map-selftests.c (_initialize_memory_map_selftests): Add declaration. * unittests/memrange-selftests.c (_initialize_memrange_selftests): Add declaration. * unittests/mkdir-recursive-selftests.c (_initialize_mkdir_recursive_selftests): Add declaration. * unittests/observable-selftests.c (_initialize_observer_selftest): Add declaration. * unittests/offset-type-selftests.c (_initialize_offset_type_selftests): Add declaration. * unittests/optional-selftests.c (_initialize_optional_selftests): Add declaration. * unittests/parse-connection-spec-selftests.c (_initialize_parse_connection_spec_selftests): Add declaration. * unittests/rsp-low-selftests.c (_initialize_rsp_low_selftests): Add declaration. * unittests/scoped_fd-selftests.c (_initialize_scoped_fd_selftests): Add declaration. * unittests/scoped_mmap-selftests.c (_initialize_scoped_mmap_selftests): Add declaration. * unittests/scoped_restore-selftests.c (_initialize_scoped_restore_selftests): Add declaration. * unittests/string_view-selftests.c (_initialize_string_view_selftests): Add declaration. * unittests/style-selftests.c (_initialize_style_selftest): Add declaration. * unittests/tracepoint-selftests.c (_initialize_tracepoint_selftests): Add declaration. * unittests/tui-selftests.c (_initialize_tui_selftest): Add declaration. * unittests/unpack-selftests.c (_initialize_unpack_selftests): Add declaration. * unittests/utils-selftests.c (_initialize_utils_selftests): Add declaration. * unittests/vec-utils-selftests.c (_initialize_vec_utils_selftests): Add declaration. * unittests/xml-utils-selftests.c (_initialize_xml_utils): Add declaration. * user-regs.c (_initialize_user_regs): Add declaration. * utils.c (_initialize_utils): Add declaration. * v850-tdep.c (_initialize_v850_tdep): Add declaration. * valops.c (_initialize_valops): Add declaration. * valprint.c (_initialize_valprint): Add declaration. * value.c (_initialize_values): Add declaration. * varobj.c (_initialize_varobj): Add declaration. * vax-bsd-nat.c (_initialize_vaxbsd_nat): Add declaration. * vax-nbsd-tdep.c (_initialize_vaxnbsd_tdep): Add declaration. * vax-tdep.c (_initialize_vax_tdep): Add declaration. * windows-nat.c (_initialize_windows_nat): Add declaration. (_initialize_check_for_gdb_ini): Add declaration. (_initialize_loadable): Add declaration. * windows-tdep.c (_initialize_windows_tdep): Add declaration. * x86-bsd-nat.c (_initialize_x86_bsd_nat): Add declaration. * x86-linux-nat.c (_initialize_x86_linux_nat): Add declaration. * xcoffread.c (_initialize_xcoffread): Add declaration. * xml-support.c (_initialize_xml_support): Add declaration. * xstormy16-tdep.c (_initialize_xstormy16_tdep): Add declaration. * xtensa-linux-nat.c (_initialize_xtensa_linux_nat): Add declaration. * xtensa-linux-tdep.c (_initialize_xtensa_linux_tdep): Add declaration. * xtensa-tdep.c (_initialize_xtensa_tdep): Add declaration. Change-Id: I13eec7e0ed2b3c427377a7bdb055cf46da64def9
2020-01-14 03:01:38 +08:00
void _initialize_f_language ();
void
gdb: add back declarations for _initialize functions I'd like to enable the -Wmissing-declarations warning. However, it warns for every _initialize function, for example: CXX dcache.o /home/smarchi/src/binutils-gdb/gdb/dcache.c: In function ‘void _initialize_dcache()’: /home/smarchi/src/binutils-gdb/gdb/dcache.c:688:1: error: no previous declaration for ‘void _initialize_dcache()’ [-Werror=missing-declarations] _initialize_dcache (void) ^~~~~~~~~~~~~~~~~~ The only practical way forward I found is to add back the declarations, which were removed by this commit: commit 481695ed5f6e0a8a9c9c50bfac1cdd2b3151e6c9 Author: John Baldwin <jhb@FreeBSD.org> Date: Sat Sep 9 11:02:37 2017 -0700 Remove unnecessary function prototypes. I don't think it's a big problem to have the declarations for these functions, but if anybody has a better solution for this, I'll be happy to use it. gdb/ChangeLog: * aarch64-fbsd-nat.c (_initialize_aarch64_fbsd_nat): Add declaration. * aarch64-fbsd-tdep.c (_initialize_aarch64_fbsd_tdep): Add declaration. * aarch64-linux-nat.c (_initialize_aarch64_linux_nat): Add declaration. * aarch64-linux-tdep.c (_initialize_aarch64_linux_tdep): Add declaration. * aarch64-newlib-tdep.c (_initialize_aarch64_newlib_tdep): Add declaration. * aarch64-tdep.c (_initialize_aarch64_tdep): Add declaration. * ada-exp.y (_initialize_ada_exp): Add declaration. * ada-lang.c (_initialize_ada_language): Add declaration. * ada-tasks.c (_initialize_tasks): Add declaration. * agent.c (_initialize_agent): Add declaration. * aix-thread.c (_initialize_aix_thread): Add declaration. * alpha-bsd-nat.c (_initialize_alphabsd_nat): Add declaration. * alpha-linux-nat.c (_initialize_alpha_linux_nat): Add declaration. * alpha-linux-tdep.c (_initialize_alpha_linux_tdep): Add declaration. * alpha-nbsd-tdep.c (_initialize_alphanbsd_tdep): Add declaration. * alpha-obsd-tdep.c (_initialize_alphaobsd_tdep): Add declaration. * alpha-tdep.c (_initialize_alpha_tdep): Add declaration. * amd64-darwin-tdep.c (_initialize_amd64_darwin_tdep): Add declaration. * amd64-dicos-tdep.c (_initialize_amd64_dicos_tdep): Add declaration. * amd64-fbsd-nat.c (_initialize_amd64fbsd_nat): Add declaration. * amd64-fbsd-tdep.c (_initialize_amd64fbsd_tdep): Add declaration. * amd64-linux-nat.c (_initialize_amd64_linux_nat): Add declaration. * amd64-linux-tdep.c (_initialize_amd64_linux_tdep): Add declaration. * amd64-nbsd-nat.c (_initialize_amd64nbsd_nat): Add declaration. * amd64-nbsd-tdep.c (_initialize_amd64nbsd_tdep): Add declaration. * amd64-obsd-nat.c (_initialize_amd64obsd_nat): Add declaration. * amd64-obsd-tdep.c (_initialize_amd64obsd_tdep): Add declaration. * amd64-sol2-tdep.c (_initialize_amd64_sol2_tdep): Add declaration. * amd64-tdep.c (_initialize_amd64_tdep): Add declaration. * amd64-windows-nat.c (_initialize_amd64_windows_nat): Add declaration. * amd64-windows-tdep.c (_initialize_amd64_windows_tdep): Add declaration. * annotate.c (_initialize_annotate): Add declaration. * arc-newlib-tdep.c (_initialize_arc_newlib_tdep): Add declaration. * arc-tdep.c (_initialize_arc_tdep): Add declaration. * arch-utils.c (_initialize_gdbarch_utils): Add declaration. * arm-fbsd-nat.c (_initialize_arm_fbsd_nat): Add declaration. * arm-fbsd-tdep.c (_initialize_arm_fbsd_tdep): Add declaration. * arm-linux-nat.c (_initialize_arm_linux_nat): Add declaration. * arm-linux-tdep.c (_initialize_arm_linux_tdep): Add declaration. * arm-nbsd-nat.c (_initialize_arm_netbsd_nat): Add declaration. * arm-nbsd-tdep.c (_initialize_arm_netbsd_tdep): Add declaration. * arm-obsd-tdep.c (_initialize_armobsd_tdep): Add declaration. * arm-pikeos-tdep.c (_initialize_arm_pikeos_tdep): Add declaration. * arm-symbian-tdep.c (_initialize_arm_symbian_tdep): Add declaration. * arm-tdep.c (_initialize_arm_tdep): Add declaration. * arm-wince-tdep.c (_initialize_arm_wince_tdep): Add declaration. * auto-load.c (_initialize_auto_load): Add declaration. * auxv.c (_initialize_auxv): Add declaration. * avr-tdep.c (_initialize_avr_tdep): Add declaration. * ax-gdb.c (_initialize_ax_gdb): Add declaration. * bfin-linux-tdep.c (_initialize_bfin_linux_tdep): Add declaration. * bfin-tdep.c (_initialize_bfin_tdep): Add declaration. * break-catch-sig.c (_initialize_break_catch_sig): Add declaration. * break-catch-syscall.c (_initialize_break_catch_syscall): Add declaration. * break-catch-throw.c (_initialize_break_catch_throw): Add declaration. * breakpoint.c (_initialize_breakpoint): Add declaration. * bsd-uthread.c (_initialize_bsd_uthread): Add declaration. * btrace.c (_initialize_btrace): Add declaration. * charset.c (_initialize_charset): Add declaration. * cli/cli-cmds.c (_initialize_cli_cmds): Add declaration. * cli/cli-dump.c (_initialize_cli_dump): Add declaration. * cli/cli-interp.c (_initialize_cli_interp): Add declaration. * cli/cli-logging.c (_initialize_cli_logging): Add declaration. * cli/cli-script.c (_initialize_cli_script): Add declaration. * cli/cli-style.c (_initialize_cli_style): Add declaration. * coff-pe-read.c (_initialize_coff_pe_read): Add declaration. * coffread.c (_initialize_coffread): Add declaration. * compile/compile-cplus-types.c (_initialize_compile_cplus_types): Add declaration. * compile/compile.c (_initialize_compile): Add declaration. * complaints.c (_initialize_complaints): Add declaration. * completer.c (_initialize_completer): Add declaration. * copying.c (_initialize_copying): Add declaration. * corefile.c (_initialize_core): Add declaration. * corelow.c (_initialize_corelow): Add declaration. * cp-abi.c (_initialize_cp_abi): Add declaration. * cp-namespace.c (_initialize_cp_namespace): Add declaration. * cp-support.c (_initialize_cp_support): Add declaration. * cp-valprint.c (_initialize_cp_valprint): Add declaration. * cris-linux-tdep.c (_initialize_cris_linux_tdep): Add declaration. * cris-tdep.c (_initialize_cris_tdep): Add declaration. * csky-linux-tdep.c (_initialize_csky_linux_tdep): Add declaration. * csky-tdep.c (_initialize_csky_tdep): Add declaration. * ctfread.c (_initialize_ctfread): Add declaration. * d-lang.c (_initialize_d_language): Add declaration. * darwin-nat-info.c (_initialize_darwin_info_commands): Add declaration. * darwin-nat.c (_initialize_darwin_nat): Add declaration. * dbxread.c (_initialize_dbxread): Add declaration. * dcache.c (_initialize_dcache): Add declaration. * disasm-selftests.c (_initialize_disasm_selftests): Add declaration. * disasm.c (_initialize_disasm): Add declaration. * dtrace-probe.c (_initialize_dtrace_probe): Add declaration. * dummy-frame.c (_initialize_dummy_frame): Add declaration. * dwarf-index-cache.c (_initialize_index_cache): Add declaration. * dwarf-index-write.c (_initialize_dwarf_index_write): Add declaration. * dwarf2-frame-tailcall.c (_initialize_tailcall_frame): Add declaration. * dwarf2-frame.c (_initialize_dwarf2_frame): Add declaration. * dwarf2expr.c (_initialize_dwarf2expr): Add declaration. * dwarf2loc.c (_initialize_dwarf2loc): Add declaration. * dwarf2read.c (_initialize_dwarf2_read): Add declaration. * elfread.c (_initialize_elfread): Add declaration. * exec.c (_initialize_exec): Add declaration. * extension.c (_initialize_extension): Add declaration. * f-lang.c (_initialize_f_language): Add declaration. * f-valprint.c (_initialize_f_valprint): Add declaration. * fbsd-nat.c (_initialize_fbsd_nat): Add declaration. * fbsd-tdep.c (_initialize_fbsd_tdep): Add declaration. * filesystem.c (_initialize_filesystem): Add declaration. * findcmd.c (_initialize_mem_search): Add declaration. * findvar.c (_initialize_findvar): Add declaration. * fork-child.c (_initialize_fork_child): Add declaration. * frame-base.c (_initialize_frame_base): Add declaration. * frame-unwind.c (_initialize_frame_unwind): Add declaration. * frame.c (_initialize_frame): Add declaration. * frv-linux-tdep.c (_initialize_frv_linux_tdep): Add declaration. * frv-tdep.c (_initialize_frv_tdep): Add declaration. * ft32-tdep.c (_initialize_ft32_tdep): Add declaration. * gcore.c (_initialize_gcore): Add declaration. * gdb-demangle.c (_initialize_gdb_demangle): Add declaration. * gdb_bfd.c (_initialize_gdb_bfd): Add declaration. * gdbarch-selftests.c (_initialize_gdbarch_selftests): Add declaration. * gdbarch.c (_initialize_gdbarch): Add declaration. * gdbtypes.c (_initialize_gdbtypes): Add declaration. * gnu-nat.c (_initialize_gnu_nat): Add declaration. * gnu-v2-abi.c (_initialize_gnu_v2_abi): Add declaration. * gnu-v3-abi.c (_initialize_gnu_v3_abi): Add declaration. * go-lang.c (_initialize_go_language): Add declaration. * go32-nat.c (_initialize_go32_nat): Add declaration. * guile/guile.c (_initialize_guile): Add declaration. * h8300-tdep.c (_initialize_h8300_tdep): Add declaration. * hppa-linux-nat.c (_initialize_hppa_linux_nat): Add declaration. * hppa-linux-tdep.c (_initialize_hppa_linux_tdep): Add declaration. * hppa-nbsd-nat.c (_initialize_hppanbsd_nat): Add declaration. * hppa-nbsd-tdep.c (_initialize_hppanbsd_tdep): Add declaration. * hppa-obsd-nat.c (_initialize_hppaobsd_nat): Add declaration. * hppa-obsd-tdep.c (_initialize_hppabsd_tdep): Add declaration. * hppa-tdep.c (_initialize_hppa_tdep): Add declaration. * i386-bsd-nat.c (_initialize_i386bsd_nat): Add declaration. * i386-cygwin-tdep.c (_initialize_i386_cygwin_tdep): Add declaration. * i386-darwin-nat.c (_initialize_i386_darwin_nat): Add declaration. * i386-darwin-tdep.c (_initialize_i386_darwin_tdep): Add declaration. * i386-dicos-tdep.c (_initialize_i386_dicos_tdep): Add declaration. * i386-fbsd-nat.c (_initialize_i386fbsd_nat): Add declaration. * i386-fbsd-tdep.c (_initialize_i386fbsd_tdep): Add declaration. * i386-gnu-nat.c (_initialize_i386gnu_nat): Add declaration. * i386-gnu-tdep.c (_initialize_i386gnu_tdep): Add declaration. * i386-go32-tdep.c (_initialize_i386_go32_tdep): Add declaration. * i386-linux-nat.c (_initialize_i386_linux_nat): Add declaration. * i386-linux-tdep.c (_initialize_i386_linux_tdep): Add declaration. * i386-nbsd-nat.c (_initialize_i386nbsd_nat): Add declaration. * i386-nbsd-tdep.c (_initialize_i386nbsd_tdep): Add declaration. * i386-nto-tdep.c (_initialize_i386nto_tdep): Add declaration. * i386-obsd-nat.c (_initialize_i386obsd_nat): Add declaration. * i386-obsd-tdep.c (_initialize_i386obsd_tdep): Add declaration. * i386-sol2-nat.c (_initialize_amd64_sol2_nat): Add declaration. * i386-sol2-tdep.c (_initialize_i386_sol2_tdep): Add declaration. * i386-tdep.c (_initialize_i386_tdep): Add declaration. * i386-windows-nat.c (_initialize_i386_windows_nat): Add declaration. * ia64-libunwind-tdep.c (_initialize_libunwind_frame): Add declaration. * ia64-linux-nat.c (_initialize_ia64_linux_nat): Add declaration. * ia64-linux-tdep.c (_initialize_ia64_linux_tdep): Add declaration. * ia64-tdep.c (_initialize_ia64_tdep): Add declaration. * ia64-vms-tdep.c (_initialize_ia64_vms_tdep): Add declaration. * infcall.c (_initialize_infcall): Add declaration. * infcmd.c (_initialize_infcmd): Add declaration. * inflow.c (_initialize_inflow): Add declaration. * infrun.c (_initialize_infrun): Add declaration. * interps.c (_initialize_interpreter): Add declaration. * iq2000-tdep.c (_initialize_iq2000_tdep): Add declaration. * jit.c (_initialize_jit): Add declaration. * language.c (_initialize_language): Add declaration. * linux-fork.c (_initialize_linux_fork): Add declaration. * linux-nat.c (_initialize_linux_nat): Add declaration. * linux-tdep.c (_initialize_linux_tdep): Add declaration. * linux-thread-db.c (_initialize_thread_db): Add declaration. * lm32-tdep.c (_initialize_lm32_tdep): Add declaration. * m2-lang.c (_initialize_m2_language): Add declaration. * m32c-tdep.c (_initialize_m32c_tdep): Add declaration. * m32r-linux-nat.c (_initialize_m32r_linux_nat): Add declaration. * m32r-linux-tdep.c (_initialize_m32r_linux_tdep): Add declaration. * m32r-tdep.c (_initialize_m32r_tdep): Add declaration. * m68hc11-tdep.c (_initialize_m68hc11_tdep): Add declaration. * m68k-bsd-nat.c (_initialize_m68kbsd_nat): Add declaration. * m68k-bsd-tdep.c (_initialize_m68kbsd_tdep): Add declaration. * m68k-linux-nat.c (_initialize_m68k_linux_nat): Add declaration. * m68k-linux-tdep.c (_initialize_m68k_linux_tdep): Add declaration. * m68k-tdep.c (_initialize_m68k_tdep): Add declaration. * machoread.c (_initialize_machoread): Add declaration. * macrocmd.c (_initialize_macrocmd): Add declaration. * macroscope.c (_initialize_macroscope): Add declaration. * maint-test-options.c (_initialize_maint_test_options): Add declaration. * maint-test-settings.c (_initialize_maint_test_settings): Add declaration. * maint.c (_initialize_maint_cmds): Add declaration. * mdebugread.c (_initialize_mdebugread): Add declaration. * memattr.c (_initialize_mem): Add declaration. * mep-tdep.c (_initialize_mep_tdep): Add declaration. * mi/mi-cmd-env.c (_initialize_mi_cmd_env): Add declaration. * mi/mi-cmds.c (_initialize_mi_cmds): Add declaration. * mi/mi-interp.c (_initialize_mi_interp): Add declaration. * mi/mi-main.c (_initialize_mi_main): Add declaration. * microblaze-linux-tdep.c (_initialize_microblaze_linux_tdep): Add declaration. * microblaze-tdep.c (_initialize_microblaze_tdep): Add declaration. * mips-fbsd-nat.c (_initialize_mips_fbsd_nat): Add declaration. * mips-fbsd-tdep.c (_initialize_mips_fbsd_tdep): Add declaration. * mips-linux-nat.c (_initialize_mips_linux_nat): Add declaration. * mips-linux-tdep.c (_initialize_mips_linux_tdep): Add declaration. * mips-nbsd-nat.c (_initialize_mipsnbsd_nat): Add declaration. * mips-nbsd-tdep.c (_initialize_mipsnbsd_tdep): Add declaration. * mips-sde-tdep.c (_initialize_mips_sde_tdep): Add declaration. * mips-tdep.c (_initialize_mips_tdep): Add declaration. * mips64-obsd-nat.c (_initialize_mips64obsd_nat): Add declaration. * mips64-obsd-tdep.c (_initialize_mips64obsd_tdep): Add declaration. * mipsread.c (_initialize_mipsread): Add declaration. * mn10300-linux-tdep.c (_initialize_mn10300_linux_tdep): Add declaration. * mn10300-tdep.c (_initialize_mn10300_tdep): Add declaration. * moxie-tdep.c (_initialize_moxie_tdep): Add declaration. * msp430-tdep.c (_initialize_msp430_tdep): Add declaration. * nds32-tdep.c (_initialize_nds32_tdep): Add declaration. * nios2-linux-tdep.c (_initialize_nios2_linux_tdep): Add declaration. * nios2-tdep.c (_initialize_nios2_tdep): Add declaration. * nto-procfs.c (_initialize_procfs): Add declaration. * objc-lang.c (_initialize_objc_language): Add declaration. * observable.c (_initialize_observer): Add declaration. * opencl-lang.c (_initialize_opencl_language): Add declaration. * or1k-linux-tdep.c (_initialize_or1k_linux_tdep): Add declaration. * or1k-tdep.c (_initialize_or1k_tdep): Add declaration. * osabi.c (_initialize_gdb_osabi): Add declaration. * osdata.c (_initialize_osdata): Add declaration. * p-valprint.c (_initialize_pascal_valprint): Add declaration. * parse.c (_initialize_parse): Add declaration. * ppc-fbsd-nat.c (_initialize_ppcfbsd_nat): Add declaration. * ppc-fbsd-tdep.c (_initialize_ppcfbsd_tdep): Add declaration. * ppc-linux-nat.c (_initialize_ppc_linux_nat): Add declaration. * ppc-linux-tdep.c (_initialize_ppc_linux_tdep): Add declaration. * ppc-nbsd-nat.c (_initialize_ppcnbsd_nat): Add declaration. * ppc-nbsd-tdep.c (_initialize_ppcnbsd_tdep): Add declaration. * ppc-obsd-nat.c (_initialize_ppcobsd_nat): Add declaration. * ppc-obsd-tdep.c (_initialize_ppcobsd_tdep): Add declaration. * printcmd.c (_initialize_printcmd): Add declaration. * probe.c (_initialize_probe): Add declaration. * proc-api.c (_initialize_proc_api): Add declaration. * proc-events.c (_initialize_proc_events): Add declaration. * proc-service.c (_initialize_proc_service): Add declaration. * procfs.c (_initialize_procfs): Add declaration. * producer.c (_initialize_producer): Add declaration. * psymtab.c (_initialize_psymtab): Add declaration. * python/python.c (_initialize_python): Add declaration. * ravenscar-thread.c (_initialize_ravenscar): Add declaration. * record-btrace.c (_initialize_record_btrace): Add declaration. * record-full.c (_initialize_record_full): Add declaration. * record.c (_initialize_record): Add declaration. * regcache-dump.c (_initialize_regcache_dump): Add declaration. * regcache.c (_initialize_regcache): Add declaration. * reggroups.c (_initialize_reggroup): Add declaration. * remote-notif.c (_initialize_notif): Add declaration. * remote-sim.c (_initialize_remote_sim): Add declaration. * remote.c (_initialize_remote): Add declaration. * reverse.c (_initialize_reverse): Add declaration. * riscv-fbsd-nat.c (_initialize_riscv_fbsd_nat): Add declaration. * riscv-fbsd-tdep.c (_initialize_riscv_fbsd_tdep): Add declaration. * riscv-linux-nat.c (_initialize_riscv_linux_nat): Add declaration. * riscv-linux-tdep.c (_initialize_riscv_linux_tdep): Add declaration. * riscv-tdep.c (_initialize_riscv_tdep): Add declaration. * rl78-tdep.c (_initialize_rl78_tdep): Add declaration. * rs6000-aix-tdep.c (_initialize_rs6000_aix_tdep): Add declaration. * rs6000-lynx178-tdep.c (_initialize_rs6000_lynx178_tdep): Add declaration. * rs6000-nat.c (_initialize_rs6000_nat): Add declaration. * rs6000-tdep.c (_initialize_rs6000_tdep): Add declaration. * run-on-main-thread.c (_initialize_run_on_main_thread): Add declaration. * rust-exp.y (_initialize_rust_exp): Add declaration. * rx-tdep.c (_initialize_rx_tdep): Add declaration. * s12z-tdep.c (_initialize_s12z_tdep): Add declaration. * s390-linux-nat.c (_initialize_s390_nat): Add declaration. * s390-linux-tdep.c (_initialize_s390_linux_tdep): Add declaration. * s390-tdep.c (_initialize_s390_tdep): Add declaration. * score-tdep.c (_initialize_score_tdep): Add declaration. * ser-go32.c (_initialize_ser_dos): Add declaration. * ser-mingw.c (_initialize_ser_windows): Add declaration. * ser-pipe.c (_initialize_ser_pipe): Add declaration. * ser-tcp.c (_initialize_ser_tcp): Add declaration. * ser-uds.c (_initialize_ser_socket): Add declaration. * ser-unix.c (_initialize_ser_hardwire): Add declaration. * serial.c (_initialize_serial): Add declaration. * sh-linux-tdep.c (_initialize_sh_linux_tdep): Add declaration. * sh-nbsd-nat.c (_initialize_shnbsd_nat): Add declaration. * sh-nbsd-tdep.c (_initialize_shnbsd_tdep): Add declaration. * sh-tdep.c (_initialize_sh_tdep): Add declaration. * skip.c (_initialize_step_skip): Add declaration. * sol-thread.c (_initialize_sol_thread): Add declaration. * solib-aix.c (_initialize_solib_aix): Add declaration. * solib-darwin.c (_initialize_darwin_solib): Add declaration. * solib-dsbt.c (_initialize_dsbt_solib): Add declaration. * solib-frv.c (_initialize_frv_solib): Add declaration. * solib-svr4.c (_initialize_svr4_solib): Add declaration. * solib-target.c (_initialize_solib_target): Add declaration. * solib.c (_initialize_solib): Add declaration. * source-cache.c (_initialize_source_cache): Add declaration. * source.c (_initialize_source): Add declaration. * sparc-linux-nat.c (_initialize_sparc_linux_nat): Add declaration. * sparc-linux-tdep.c (_initialize_sparc_linux_tdep): Add declaration. * sparc-nat.c (_initialize_sparc_nat): Add declaration. * sparc-nbsd-nat.c (_initialize_sparcnbsd_nat): Add declaration. * sparc-nbsd-tdep.c (_initialize_sparcnbsd_tdep): Add declaration. * sparc-obsd-tdep.c (_initialize_sparc32obsd_tdep): Add declaration. * sparc-sol2-tdep.c (_initialize_sparc_sol2_tdep): Add declaration. * sparc-tdep.c (_initialize_sparc_tdep): Add declaration. * sparc64-fbsd-nat.c (_initialize_sparc64fbsd_nat): Add declaration. * sparc64-fbsd-tdep.c (_initialize_sparc64fbsd_tdep): Add declaration. * sparc64-linux-nat.c (_initialize_sparc64_linux_nat): Add declaration. * sparc64-linux-tdep.c (_initialize_sparc64_linux_tdep): Add declaration. * sparc64-nat.c (_initialize_sparc64_nat): Add declaration. * sparc64-nbsd-nat.c (_initialize_sparc64nbsd_nat): Add declaration. * sparc64-nbsd-tdep.c (_initialize_sparc64nbsd_tdep): Add declaration. * sparc64-obsd-nat.c (_initialize_sparc64obsd_nat): Add declaration. * sparc64-obsd-tdep.c (_initialize_sparc64obsd_tdep): Add declaration. * sparc64-sol2-tdep.c (_initialize_sparc64_sol2_tdep): Add declaration. * sparc64-tdep.c (_initialize_sparc64_adi_tdep): Add declaration. * stabsread.c (_initialize_stabsread): Add declaration. * stack.c (_initialize_stack): Add declaration. * stap-probe.c (_initialize_stap_probe): Add declaration. * std-regs.c (_initialize_frame_reg): Add declaration. * symfile-debug.c (_initialize_symfile_debug): Add declaration. * symfile-mem.c (_initialize_symfile_mem): Add declaration. * symfile.c (_initialize_symfile): Add declaration. * symmisc.c (_initialize_symmisc): Add declaration. * symtab.c (_initialize_symtab): Add declaration. * target.c (_initialize_target): Add declaration. * target-connection.c (_initialize_target_connection): Add declaration. * target-dcache.c (_initialize_target_dcache): Add declaration. * target-descriptions.c (_initialize_target_descriptions): Add declaration. * thread.c (_initialize_thread): Add declaration. * tic6x-linux-tdep.c (_initialize_tic6x_linux_tdep): Add declaration. * tic6x-tdep.c (_initialize_tic6x_tdep): Add declaration. * tilegx-linux-nat.c (_initialize_tile_linux_nat): Add declaration. * tilegx-linux-tdep.c (_initialize_tilegx_linux_tdep): Add declaration. * tilegx-tdep.c (_initialize_tilegx_tdep): Add declaration. * tracectf.c (_initialize_ctf): Add declaration. * tracefile-tfile.c (_initialize_tracefile_tfile): Add declaration. * tracefile.c (_initialize_tracefile): Add declaration. * tracepoint.c (_initialize_tracepoint): Add declaration. * tui/tui-hooks.c (_initialize_tui_hooks): Add declaration. * tui/tui-interp.c (_initialize_tui_interp): Add declaration. * tui/tui-layout.c (_initialize_tui_layout): Add declaration. * tui/tui-regs.c (_initialize_tui_regs): Add declaration. * tui/tui-stack.c (_initialize_tui_stack): Add declaration. * tui/tui-win.c (_initialize_tui_win): Add declaration. * tui/tui.c (_initialize_tui): Add declaration. * typeprint.c (_initialize_typeprint): Add declaration. * ui-style.c (_initialize_ui_style): Add declaration. * unittests/array-view-selftests.c (_initialize_array_view_selftests): Add declaration. * unittests/child-path-selftests.c (_initialize_child_path_selftests): Add declaration. * unittests/cli-utils-selftests.c (_initialize_cli_utils_selftests): Add declaration. * unittests/common-utils-selftests.c (_initialize_common_utils_selftests): Add declaration. * unittests/copy_bitwise-selftests.c (_initialize_copy_bitwise_utils_selftests): Add declaration. * unittests/environ-selftests.c (_initialize_environ_selftests): Add declaration. * unittests/filtered_iterator-selftests.c (_initialize_filtered_iterator_selftests): Add declaration. * unittests/format_pieces-selftests.c (_initialize_format_pieces_selftests): Add declaration. * unittests/function-view-selftests.c (_initialize_function_view_selftests): Add declaration. * unittests/help-doc-selftests.c (_initialize_help_doc_selftests): Add declaration. * unittests/lookup_name_info-selftests.c (_initialize_lookup_name_info_selftests): Add declaration. * unittests/main-thread-selftests.c (_initialize_main_thread_selftests): Add declaration. * unittests/memory-map-selftests.c (_initialize_memory_map_selftests): Add declaration. * unittests/memrange-selftests.c (_initialize_memrange_selftests): Add declaration. * unittests/mkdir-recursive-selftests.c (_initialize_mkdir_recursive_selftests): Add declaration. * unittests/observable-selftests.c (_initialize_observer_selftest): Add declaration. * unittests/offset-type-selftests.c (_initialize_offset_type_selftests): Add declaration. * unittests/optional-selftests.c (_initialize_optional_selftests): Add declaration. * unittests/parse-connection-spec-selftests.c (_initialize_parse_connection_spec_selftests): Add declaration. * unittests/rsp-low-selftests.c (_initialize_rsp_low_selftests): Add declaration. * unittests/scoped_fd-selftests.c (_initialize_scoped_fd_selftests): Add declaration. * unittests/scoped_mmap-selftests.c (_initialize_scoped_mmap_selftests): Add declaration. * unittests/scoped_restore-selftests.c (_initialize_scoped_restore_selftests): Add declaration. * unittests/string_view-selftests.c (_initialize_string_view_selftests): Add declaration. * unittests/style-selftests.c (_initialize_style_selftest): Add declaration. * unittests/tracepoint-selftests.c (_initialize_tracepoint_selftests): Add declaration. * unittests/tui-selftests.c (_initialize_tui_selftest): Add declaration. * unittests/unpack-selftests.c (_initialize_unpack_selftests): Add declaration. * unittests/utils-selftests.c (_initialize_utils_selftests): Add declaration. * unittests/vec-utils-selftests.c (_initialize_vec_utils_selftests): Add declaration. * unittests/xml-utils-selftests.c (_initialize_xml_utils): Add declaration. * user-regs.c (_initialize_user_regs): Add declaration. * utils.c (_initialize_utils): Add declaration. * v850-tdep.c (_initialize_v850_tdep): Add declaration. * valops.c (_initialize_valops): Add declaration. * valprint.c (_initialize_valprint): Add declaration. * value.c (_initialize_values): Add declaration. * varobj.c (_initialize_varobj): Add declaration. * vax-bsd-nat.c (_initialize_vaxbsd_nat): Add declaration. * vax-nbsd-tdep.c (_initialize_vaxnbsd_tdep): Add declaration. * vax-tdep.c (_initialize_vax_tdep): Add declaration. * windows-nat.c (_initialize_windows_nat): Add declaration. (_initialize_check_for_gdb_ini): Add declaration. (_initialize_loadable): Add declaration. * windows-tdep.c (_initialize_windows_tdep): Add declaration. * x86-bsd-nat.c (_initialize_x86_bsd_nat): Add declaration. * x86-linux-nat.c (_initialize_x86_linux_nat): Add declaration. * xcoffread.c (_initialize_xcoffread): Add declaration. * xml-support.c (_initialize_xml_support): Add declaration. * xstormy16-tdep.c (_initialize_xstormy16_tdep): Add declaration. * xtensa-linux-nat.c (_initialize_xtensa_linux_nat): Add declaration. * xtensa-linux-tdep.c (_initialize_xtensa_linux_tdep): Add declaration. * xtensa-tdep.c (_initialize_xtensa_tdep): Add declaration. Change-Id: I13eec7e0ed2b3c427377a7bdb055cf46da64def9
2020-01-14 03:01:38 +08:00
_initialize_f_language ()
{
add_setshow_prefix_cmd
("fortran", no_class,
_("Prefix command for changing Fortran-specific settings."),
_("Generic command for showing Fortran-specific settings."),
&set_fortran_list, &show_fortran_list,
&setlist, &showlist);
gdb/fortran: Add support for Fortran array slices at the GDB prompt This commit brings array slice support to GDB. WARNING: This patch contains a rather big hack which is limited to Fortran arrays, this can be seen in gdbtypes.c and f-lang.c. More details on this below. This patch rewrites two areas of GDB's Fortran support, the code to extract an array slice, and the code to print an array. After this commit a user can, from the GDB prompt, ask for a slice of a Fortran array and should get the correct result back. Slices can (optionally) have the lower bound, upper bound, and a stride specified. Slices can also have a negative stride. Fortran has the concept of repacking array slices. Within a compiled Fortran program if a user passes a non-contiguous array slice to a function then the compiler may have to repack the slice, this involves copying the elements of the slice to a new area of memory before the call, and copying the elements back to the original array after the call. Whether repacking occurs will depend on which version of Fortran is being used, and what type of function is being called. This commit adds support for both packed, and unpacked array slicing, with the default being unpacked. With an unpacked array slice, when the user asks for a slice of an array GDB creates a new type that accurately describes where the elements of the slice can be found within the original array, a value of this type is then returned to the user. The address of an element within the slice will be equal to the address of an element within the original array. A user can choose to select packed array slices instead using: (gdb) set fortran repack-array-slices on|off (gdb) show fortran repack-array-slices With packed array slices GDB creates a new type that reflects how the elements of the slice would look if they were laid out in contiguous memory, allocates a value of this type, and then fetches the elements from the original array and places then into the contents buffer of the new value. One benefit of using packed slices over unpacked slices is the memory usage, taking a small slice of N elements from a large array will require (in GDB) N * ELEMENT_SIZE bytes of memory, while an unpacked array will also include all of the "padding" between the non-contiguous elements. There are new tests added that highlight this difference. There is also a new debugging flag added with this commit that introduces these commands: (gdb) set debug fortran-array-slicing on|off (gdb) show debug fortran-array-slicing This prints information about how the array slices are being built. As both the repacking, and the array printing requires GDB to walk through a multi-dimensional Fortran array visiting each element, this commit adds the file f-array-walk.h, which introduces some infrastructure to support this process. This means the array printing code in f-valprint.c is significantly reduced. The only slight issue with this commit is the "rather big hack" that I mentioned above. This hack allows us to handle one specific case, array slices with negative strides. This is something that I don't believe the current GDB value contents model will allow us to correctly handle, and rather than rewrite the value contents code right now, I'm hoping to slip this hack in as a work around. The problem is that, as I see it, the current value contents model assumes that an object base address will be the lowest address within that object, and that the contents of the object start at this base address and occupy the TYPE_LENGTH bytes after that. ( We do have the embedded_offset, which is used for C++ sub-classes, such that an object can start at some offset from the content buffer, however, the assumption that the object then occupies the next TYPE_LENGTH bytes is still true within GDB. ) The problem is that Fortran arrays with a negative stride don't follow this pattern. In this case the base address of the object points to the element with the highest address, the contents of the array then start at some offset _before_ the base address, and proceed for one element _past_ the base address. As the stride for such an array would be negative then, in theory the TYPE_LENGTH for this type would also be negative. However, in many places a value in GDB will degrade to a pointer + length, and the length almost always comes from the TYPE_LENGTH. It is my belief that in order to correctly model this case the value content handling of GDB will need to be reworked to split apart the value's content buffer (which is a block of memory with a length), and the object's in memory base address and length, which could be negative. Things are further complicated because arrays with negative strides like this are always dynamic types. When a value has a dynamic type and its base address needs resolving we actually store the address of the object within the resolved dynamic type, not within the value object itself. In short I don't currently see an easy path to cleanly support this situation within GDB. And so I believe that leaves two options, either add a work around, or catch cases where the user tries to make use of a negative stride, or access an array with a negative stride, and throw an error. This patch currently goes with adding a work around, which is that when we resolve a dynamic Fortran array type, if the stride is negative, then we adjust the base address to point to the lowest address required by the array. The printing and slicing code is aware of this adjustment and will correctly slice and print Fortran arrays. Where this hack will show through to the user is if they ask for the address of an array in their program with a negative array stride, the address they get from GDB will not match the address that would be computed within the Fortran program. gdb/ChangeLog: * Makefile.in (HFILES_NO_SRCDIR): Add f-array-walker.h. * NEWS: Mention new options. * f-array-walker.h: New file. * f-lang.c: Include 'gdbcmd.h' and 'f-array-walker.h'. (repack_array_slices): New static global. (show_repack_array_slices): New function. (fortran_array_slicing_debug): New static global. (show_fortran_array_slicing_debug): New function. (value_f90_subarray): Delete. (skip_undetermined_arglist): Delete. (class fortran_array_repacker_base_impl): New class. (class fortran_lazy_array_repacker_impl): New class. (class fortran_array_repacker_impl): New class. (fortran_value_subarray): Complete rewrite. (set_fortran_list): New static global. (show_fortran_list): Likewise. (_initialize_f_language): Register new commands. (fortran_adjust_dynamic_array_base_address_hack): New function. * f-lang.h (fortran_adjust_dynamic_array_base_address_hack): Declare. * f-valprint.c: Include 'f-array-walker.h'. (class fortran_array_printer_impl): New class. (f77_print_array_1): Delete. (f77_print_array): Delete. (fortran_print_array): New. (f_value_print_inner): Update to call fortran_print_array. * gdbtypes.c: Include 'f-lang.h'. (resolve_dynamic_type_internal): Call fortran_adjust_dynamic_array_base_address_hack. gdb/testsuite/ChangeLog: * gdb.fortran/array-slices-bad.exp: New file. * gdb.fortran/array-slices-bad.f90: New file. * gdb.fortran/array-slices-sub-slices.exp: New file. * gdb.fortran/array-slices-sub-slices.f90: New file. * gdb.fortran/array-slices.exp: Rewrite tests. * gdb.fortran/array-slices.f90: Rewrite tests. * gdb.fortran/vla-sizeof.exp: Correct expected results. gdb/doc/ChangeLog: * gdb.texinfo (Debugging Output): Document 'set/show debug fortran-array-slicing'. (Special Fortran Commands): Document 'set/show fortran repack-array-slices'.
2020-10-08 23:45:59 +08:00
add_setshow_boolean_cmd ("repack-array-slices", class_vars,
&repack_array_slices, _("\
Enable or disable repacking of non-contiguous array slices."), _("\
Show whether non-contiguous array slices are repacked."), _("\
When the user requests a slice of a Fortran array then we can either return\n\
a descriptor that describes the array in place (using the original array data\n\
in its existing location) or the original data can be repacked (copied) to a\n\
new location.\n\
\n\
When the content of the array slice is contiguous within the original array\n\
then the result will never be repacked, but when the data for the new array\n\
is non-contiguous within the original array repacking will only be performed\n\
when this setting is on."),
NULL,
show_repack_array_slices,
&set_fortran_list, &show_fortran_list);
/* Debug Fortran's array slicing logic. */
add_setshow_boolean_cmd ("fortran-array-slicing", class_maintenance,
&fortran_array_slicing_debug, _("\
Set debugging of Fortran array slicing."), _("\
Show debugging of Fortran array slicing."), _("\
When on, debugging of Fortran array slicing is enabled."),
NULL,
show_fortran_array_slicing_debug,
&setdebuglist, &showdebuglist);
}
Fortran function calls with arguments Prior to this patch, calling functions on the inferior with arguments and then using these arguments within a function resulted in an invalid memory access. This is because Fortran arguments are typically passed as pointers to values. It is possible to call Fortran functions, but memory must be allocated in the inferior, so a pointer can be passed to the function, and the language must be set to C to enable C-style casting. This is cumbersome and not a pleasant debug experience. This patch implements the GNU Fortran argument passing conventions with caveats. Firstly, it does not handle the VALUE attribute as there is insufficient DWARF information to determine when this is the case. Secondly, functions with optional parameters can only be called with all parameters present. Both these cases are marked as KFAILS in the test. Since the GNU Fortran argument passing convention has been implemented, there is no guarantee that this patch will work correctly, in all cases, with other compilers. Despite these limitations, this patch improves the ease with which functions can be called in many cases, without taking away the existing approach of calling with the language set to C. Regression tested on x86_64, aarch64 and POWER9 with GCC 7.3.0. Regression tested with Ada on x86_64. Regression tested with native-extended-gdbserver target board. gdb/ChangeLog: * eval.c (evaluate_subexp_standard): Call Fortran argument wrapping logic. * f-lang.c (struct value): A value which can be passed into a Fortran function call. (fortran_argument_convert): Wrap Fortran arguments in a pointer where appropriate. (struct type): Value ready for a Fortran function call. (fortran_preserve_arg_pointer): Undo check_typedef, the pointer is needed. * f-lang.h (fortran_argument_convert): Declaration. (fortran_preserve_arg_pointer): Declaration. * infcall.c (value_arg_coerce): Call Fortran argument logic. gdb/testsuite/ChangeLog: * gdb.fortran/function-calls.exp: New file. * gdb.fortran/function-calls.f90: New test.
2019-03-06 16:23:00 +08:00
/* Ensures that function argument VALUE is in the appropriate form to
pass to a Fortran function. Returns a possibly new value that should
be used instead of VALUE.
When IS_ARTIFICIAL is true this indicates an artificial argument,
e.g. hidden string lengths which the GNU Fortran argument passing
convention specifies as being passed by value.
Fortran function calls with arguments Prior to this patch, calling functions on the inferior with arguments and then using these arguments within a function resulted in an invalid memory access. This is because Fortran arguments are typically passed as pointers to values. It is possible to call Fortran functions, but memory must be allocated in the inferior, so a pointer can be passed to the function, and the language must be set to C to enable C-style casting. This is cumbersome and not a pleasant debug experience. This patch implements the GNU Fortran argument passing conventions with caveats. Firstly, it does not handle the VALUE attribute as there is insufficient DWARF information to determine when this is the case. Secondly, functions with optional parameters can only be called with all parameters present. Both these cases are marked as KFAILS in the test. Since the GNU Fortran argument passing convention has been implemented, there is no guarantee that this patch will work correctly, in all cases, with other compilers. Despite these limitations, this patch improves the ease with which functions can be called in many cases, without taking away the existing approach of calling with the language set to C. Regression tested on x86_64, aarch64 and POWER9 with GCC 7.3.0. Regression tested with Ada on x86_64. Regression tested with native-extended-gdbserver target board. gdb/ChangeLog: * eval.c (evaluate_subexp_standard): Call Fortran argument wrapping logic. * f-lang.c (struct value): A value which can be passed into a Fortran function call. (fortran_argument_convert): Wrap Fortran arguments in a pointer where appropriate. (struct type): Value ready for a Fortran function call. (fortran_preserve_arg_pointer): Undo check_typedef, the pointer is needed. * f-lang.h (fortran_argument_convert): Declaration. (fortran_preserve_arg_pointer): Declaration. * infcall.c (value_arg_coerce): Call Fortran argument logic. gdb/testsuite/ChangeLog: * gdb.fortran/function-calls.exp: New file. * gdb.fortran/function-calls.f90: New test.
2019-03-06 16:23:00 +08:00
When IS_ARTIFICIAL is false, the argument is passed by pointer. If the
value is already in target memory then return a value that is a pointer
to VALUE. If VALUE is not in memory (e.g. an integer literal), allocate
space in the target, copy VALUE in, and return a pointer to the in
memory copy. */
static struct value *
Fortran function calls with arguments Prior to this patch, calling functions on the inferior with arguments and then using these arguments within a function resulted in an invalid memory access. This is because Fortran arguments are typically passed as pointers to values. It is possible to call Fortran functions, but memory must be allocated in the inferior, so a pointer can be passed to the function, and the language must be set to C to enable C-style casting. This is cumbersome and not a pleasant debug experience. This patch implements the GNU Fortran argument passing conventions with caveats. Firstly, it does not handle the VALUE attribute as there is insufficient DWARF information to determine when this is the case. Secondly, functions with optional parameters can only be called with all parameters present. Both these cases are marked as KFAILS in the test. Since the GNU Fortran argument passing convention has been implemented, there is no guarantee that this patch will work correctly, in all cases, with other compilers. Despite these limitations, this patch improves the ease with which functions can be called in many cases, without taking away the existing approach of calling with the language set to C. Regression tested on x86_64, aarch64 and POWER9 with GCC 7.3.0. Regression tested with Ada on x86_64. Regression tested with native-extended-gdbserver target board. gdb/ChangeLog: * eval.c (evaluate_subexp_standard): Call Fortran argument wrapping logic. * f-lang.c (struct value): A value which can be passed into a Fortran function call. (fortran_argument_convert): Wrap Fortran arguments in a pointer where appropriate. (struct type): Value ready for a Fortran function call. (fortran_preserve_arg_pointer): Undo check_typedef, the pointer is needed. * f-lang.h (fortran_argument_convert): Declaration. (fortran_preserve_arg_pointer): Declaration. * infcall.c (value_arg_coerce): Call Fortran argument logic. gdb/testsuite/ChangeLog: * gdb.fortran/function-calls.exp: New file. * gdb.fortran/function-calls.f90: New test.
2019-03-06 16:23:00 +08:00
fortran_argument_convert (struct value *value, bool is_artificial)
{
if (!is_artificial)
{
/* If the value is not in the inferior e.g. registers values,
convenience variables and user input. */
if (value->lval () != lval_memory)
Fortran function calls with arguments Prior to this patch, calling functions on the inferior with arguments and then using these arguments within a function resulted in an invalid memory access. This is because Fortran arguments are typically passed as pointers to values. It is possible to call Fortran functions, but memory must be allocated in the inferior, so a pointer can be passed to the function, and the language must be set to C to enable C-style casting. This is cumbersome and not a pleasant debug experience. This patch implements the GNU Fortran argument passing conventions with caveats. Firstly, it does not handle the VALUE attribute as there is insufficient DWARF information to determine when this is the case. Secondly, functions with optional parameters can only be called with all parameters present. Both these cases are marked as KFAILS in the test. Since the GNU Fortran argument passing convention has been implemented, there is no guarantee that this patch will work correctly, in all cases, with other compilers. Despite these limitations, this patch improves the ease with which functions can be called in many cases, without taking away the existing approach of calling with the language set to C. Regression tested on x86_64, aarch64 and POWER9 with GCC 7.3.0. Regression tested with Ada on x86_64. Regression tested with native-extended-gdbserver target board. gdb/ChangeLog: * eval.c (evaluate_subexp_standard): Call Fortran argument wrapping logic. * f-lang.c (struct value): A value which can be passed into a Fortran function call. (fortran_argument_convert): Wrap Fortran arguments in a pointer where appropriate. (struct type): Value ready for a Fortran function call. (fortran_preserve_arg_pointer): Undo check_typedef, the pointer is needed. * f-lang.h (fortran_argument_convert): Declaration. (fortran_preserve_arg_pointer): Declaration. * infcall.c (value_arg_coerce): Call Fortran argument logic. gdb/testsuite/ChangeLog: * gdb.fortran/function-calls.exp: New file. * gdb.fortran/function-calls.f90: New test.
2019-03-06 16:23:00 +08:00
{
struct type *type = value->type ();
const int length = type->length ();
Fortran function calls with arguments Prior to this patch, calling functions on the inferior with arguments and then using these arguments within a function resulted in an invalid memory access. This is because Fortran arguments are typically passed as pointers to values. It is possible to call Fortran functions, but memory must be allocated in the inferior, so a pointer can be passed to the function, and the language must be set to C to enable C-style casting. This is cumbersome and not a pleasant debug experience. This patch implements the GNU Fortran argument passing conventions with caveats. Firstly, it does not handle the VALUE attribute as there is insufficient DWARF information to determine when this is the case. Secondly, functions with optional parameters can only be called with all parameters present. Both these cases are marked as KFAILS in the test. Since the GNU Fortran argument passing convention has been implemented, there is no guarantee that this patch will work correctly, in all cases, with other compilers. Despite these limitations, this patch improves the ease with which functions can be called in many cases, without taking away the existing approach of calling with the language set to C. Regression tested on x86_64, aarch64 and POWER9 with GCC 7.3.0. Regression tested with Ada on x86_64. Regression tested with native-extended-gdbserver target board. gdb/ChangeLog: * eval.c (evaluate_subexp_standard): Call Fortran argument wrapping logic. * f-lang.c (struct value): A value which can be passed into a Fortran function call. (fortran_argument_convert): Wrap Fortran arguments in a pointer where appropriate. (struct type): Value ready for a Fortran function call. (fortran_preserve_arg_pointer): Undo check_typedef, the pointer is needed. * f-lang.h (fortran_argument_convert): Declaration. (fortran_preserve_arg_pointer): Declaration. * infcall.c (value_arg_coerce): Call Fortran argument logic. gdb/testsuite/ChangeLog: * gdb.fortran/function-calls.exp: New file. * gdb.fortran/function-calls.f90: New test.
2019-03-06 16:23:00 +08:00
const CORE_ADDR addr
= value_as_long (value_allocate_space_in_inferior (length));
write_memory (addr, value->contents ().data (), length);
struct value *val = value_from_contents_and_address
(type, value->contents ().data (), addr);
Fortran function calls with arguments Prior to this patch, calling functions on the inferior with arguments and then using these arguments within a function resulted in an invalid memory access. This is because Fortran arguments are typically passed as pointers to values. It is possible to call Fortran functions, but memory must be allocated in the inferior, so a pointer can be passed to the function, and the language must be set to C to enable C-style casting. This is cumbersome and not a pleasant debug experience. This patch implements the GNU Fortran argument passing conventions with caveats. Firstly, it does not handle the VALUE attribute as there is insufficient DWARF information to determine when this is the case. Secondly, functions with optional parameters can only be called with all parameters present. Both these cases are marked as KFAILS in the test. Since the GNU Fortran argument passing convention has been implemented, there is no guarantee that this patch will work correctly, in all cases, with other compilers. Despite these limitations, this patch improves the ease with which functions can be called in many cases, without taking away the existing approach of calling with the language set to C. Regression tested on x86_64, aarch64 and POWER9 with GCC 7.3.0. Regression tested with Ada on x86_64. Regression tested with native-extended-gdbserver target board. gdb/ChangeLog: * eval.c (evaluate_subexp_standard): Call Fortran argument wrapping logic. * f-lang.c (struct value): A value which can be passed into a Fortran function call. (fortran_argument_convert): Wrap Fortran arguments in a pointer where appropriate. (struct type): Value ready for a Fortran function call. (fortran_preserve_arg_pointer): Undo check_typedef, the pointer is needed. * f-lang.h (fortran_argument_convert): Declaration. (fortran_preserve_arg_pointer): Declaration. * infcall.c (value_arg_coerce): Call Fortran argument logic. gdb/testsuite/ChangeLog: * gdb.fortran/function-calls.exp: New file. * gdb.fortran/function-calls.f90: New test.
2019-03-06 16:23:00 +08:00
return value_addr (val);
}
else
return value_addr (value); /* Program variables, e.g. arrays. */
}
return value;
}
/* Prepare (and return) an argument value ready for an inferior function
call to a Fortran function. EXP and POS are the expressions describing
the argument to prepare. ARG_NUM is the argument number being
prepared, with 0 being the first argument and so on. FUNC_TYPE is the
type of the function being called.
IS_INTERNAL_CALL_P is true if this is a call to a function of type
TYPE_CODE_INTERNAL_FUNCTION, otherwise this parameter is false.
NOSIDE has its usual meaning for expression parsing (see eval.c).
Arguments in Fortran are normally passed by address, we coerce the
arguments here rather than in value_arg_coerce as otherwise the call to
malloc (to place the non-lvalue parameters in target memory) is hit by
this Fortran specific logic. This results in malloc being called with a
pointer to an integer followed by an attempt to malloc the arguments to
malloc in target memory. Infinite recursion ensues. */
static value *
fortran_prepare_argument (struct expression *exp,
expr::operation *subexp,
int arg_num, bool is_internal_call_p,
struct type *func_type, enum noside noside)
{
if (is_internal_call_p)
return subexp->evaluate_with_coercion (exp, noside);
bool is_artificial = ((arg_num >= func_type->num_fields ())
? true
: func_type->field (arg_num).is_artificial ());
/* If this is an artificial argument, then either, this is an argument
beyond the end of the known arguments, or possibly, there are no known
arguments (maybe missing debug info).
For these artificial arguments, if the user has prefixed it with '&'
(for address-of), then lets always allow this to succeed, even if the
argument is not actually in inferior memory. This will allow the user
to pass arguments to a Fortran function even when there's no debug
information.
As we already pass the address of non-artificial arguments, all we
need to do if skip the UNOP_ADDR operator in the expression and mark
the argument as non-artificial. */
if (is_artificial)
{
expr::unop_addr_operation *addrop
= dynamic_cast<expr::unop_addr_operation *> (subexp);
if (addrop != nullptr)
{
subexp = addrop->get_expression ().get ();
is_artificial = false;
}
}
struct value *arg_val = subexp->evaluate_with_coercion (exp, noside);
return fortran_argument_convert (arg_val, is_artificial);
}
Fortran function calls with arguments Prior to this patch, calling functions on the inferior with arguments and then using these arguments within a function resulted in an invalid memory access. This is because Fortran arguments are typically passed as pointers to values. It is possible to call Fortran functions, but memory must be allocated in the inferior, so a pointer can be passed to the function, and the language must be set to C to enable C-style casting. This is cumbersome and not a pleasant debug experience. This patch implements the GNU Fortran argument passing conventions with caveats. Firstly, it does not handle the VALUE attribute as there is insufficient DWARF information to determine when this is the case. Secondly, functions with optional parameters can only be called with all parameters present. Both these cases are marked as KFAILS in the test. Since the GNU Fortran argument passing convention has been implemented, there is no guarantee that this patch will work correctly, in all cases, with other compilers. Despite these limitations, this patch improves the ease with which functions can be called in many cases, without taking away the existing approach of calling with the language set to C. Regression tested on x86_64, aarch64 and POWER9 with GCC 7.3.0. Regression tested with Ada on x86_64. Regression tested with native-extended-gdbserver target board. gdb/ChangeLog: * eval.c (evaluate_subexp_standard): Call Fortran argument wrapping logic. * f-lang.c (struct value): A value which can be passed into a Fortran function call. (fortran_argument_convert): Wrap Fortran arguments in a pointer where appropriate. (struct type): Value ready for a Fortran function call. (fortran_preserve_arg_pointer): Undo check_typedef, the pointer is needed. * f-lang.h (fortran_argument_convert): Declaration. (fortran_preserve_arg_pointer): Declaration. * infcall.c (value_arg_coerce): Call Fortran argument logic. gdb/testsuite/ChangeLog: * gdb.fortran/function-calls.exp: New file. * gdb.fortran/function-calls.f90: New test.
2019-03-06 16:23:00 +08:00
/* See f-lang.h. */
struct type *
fortran_preserve_arg_pointer (struct value *arg, struct type *type)
{
if (arg->type ()->code () == TYPE_CODE_PTR)
return arg->type ();
Fortran function calls with arguments Prior to this patch, calling functions on the inferior with arguments and then using these arguments within a function resulted in an invalid memory access. This is because Fortran arguments are typically passed as pointers to values. It is possible to call Fortran functions, but memory must be allocated in the inferior, so a pointer can be passed to the function, and the language must be set to C to enable C-style casting. This is cumbersome and not a pleasant debug experience. This patch implements the GNU Fortran argument passing conventions with caveats. Firstly, it does not handle the VALUE attribute as there is insufficient DWARF information to determine when this is the case. Secondly, functions with optional parameters can only be called with all parameters present. Both these cases are marked as KFAILS in the test. Since the GNU Fortran argument passing convention has been implemented, there is no guarantee that this patch will work correctly, in all cases, with other compilers. Despite these limitations, this patch improves the ease with which functions can be called in many cases, without taking away the existing approach of calling with the language set to C. Regression tested on x86_64, aarch64 and POWER9 with GCC 7.3.0. Regression tested with Ada on x86_64. Regression tested with native-extended-gdbserver target board. gdb/ChangeLog: * eval.c (evaluate_subexp_standard): Call Fortran argument wrapping logic. * f-lang.c (struct value): A value which can be passed into a Fortran function call. (fortran_argument_convert): Wrap Fortran arguments in a pointer where appropriate. (struct type): Value ready for a Fortran function call. (fortran_preserve_arg_pointer): Undo check_typedef, the pointer is needed. * f-lang.h (fortran_argument_convert): Declaration. (fortran_preserve_arg_pointer): Declaration. * infcall.c (value_arg_coerce): Call Fortran argument logic. gdb/testsuite/ChangeLog: * gdb.fortran/function-calls.exp: New file. * gdb.fortran/function-calls.f90: New test.
2019-03-06 16:23:00 +08:00
return type;
}
gdb/fortran: Add support for Fortran array slices at the GDB prompt This commit brings array slice support to GDB. WARNING: This patch contains a rather big hack which is limited to Fortran arrays, this can be seen in gdbtypes.c and f-lang.c. More details on this below. This patch rewrites two areas of GDB's Fortran support, the code to extract an array slice, and the code to print an array. After this commit a user can, from the GDB prompt, ask for a slice of a Fortran array and should get the correct result back. Slices can (optionally) have the lower bound, upper bound, and a stride specified. Slices can also have a negative stride. Fortran has the concept of repacking array slices. Within a compiled Fortran program if a user passes a non-contiguous array slice to a function then the compiler may have to repack the slice, this involves copying the elements of the slice to a new area of memory before the call, and copying the elements back to the original array after the call. Whether repacking occurs will depend on which version of Fortran is being used, and what type of function is being called. This commit adds support for both packed, and unpacked array slicing, with the default being unpacked. With an unpacked array slice, when the user asks for a slice of an array GDB creates a new type that accurately describes where the elements of the slice can be found within the original array, a value of this type is then returned to the user. The address of an element within the slice will be equal to the address of an element within the original array. A user can choose to select packed array slices instead using: (gdb) set fortran repack-array-slices on|off (gdb) show fortran repack-array-slices With packed array slices GDB creates a new type that reflects how the elements of the slice would look if they were laid out in contiguous memory, allocates a value of this type, and then fetches the elements from the original array and places then into the contents buffer of the new value. One benefit of using packed slices over unpacked slices is the memory usage, taking a small slice of N elements from a large array will require (in GDB) N * ELEMENT_SIZE bytes of memory, while an unpacked array will also include all of the "padding" between the non-contiguous elements. There are new tests added that highlight this difference. There is also a new debugging flag added with this commit that introduces these commands: (gdb) set debug fortran-array-slicing on|off (gdb) show debug fortran-array-slicing This prints information about how the array slices are being built. As both the repacking, and the array printing requires GDB to walk through a multi-dimensional Fortran array visiting each element, this commit adds the file f-array-walk.h, which introduces some infrastructure to support this process. This means the array printing code in f-valprint.c is significantly reduced. The only slight issue with this commit is the "rather big hack" that I mentioned above. This hack allows us to handle one specific case, array slices with negative strides. This is something that I don't believe the current GDB value contents model will allow us to correctly handle, and rather than rewrite the value contents code right now, I'm hoping to slip this hack in as a work around. The problem is that, as I see it, the current value contents model assumes that an object base address will be the lowest address within that object, and that the contents of the object start at this base address and occupy the TYPE_LENGTH bytes after that. ( We do have the embedded_offset, which is used for C++ sub-classes, such that an object can start at some offset from the content buffer, however, the assumption that the object then occupies the next TYPE_LENGTH bytes is still true within GDB. ) The problem is that Fortran arrays with a negative stride don't follow this pattern. In this case the base address of the object points to the element with the highest address, the contents of the array then start at some offset _before_ the base address, and proceed for one element _past_ the base address. As the stride for such an array would be negative then, in theory the TYPE_LENGTH for this type would also be negative. However, in many places a value in GDB will degrade to a pointer + length, and the length almost always comes from the TYPE_LENGTH. It is my belief that in order to correctly model this case the value content handling of GDB will need to be reworked to split apart the value's content buffer (which is a block of memory with a length), and the object's in memory base address and length, which could be negative. Things are further complicated because arrays with negative strides like this are always dynamic types. When a value has a dynamic type and its base address needs resolving we actually store the address of the object within the resolved dynamic type, not within the value object itself. In short I don't currently see an easy path to cleanly support this situation within GDB. And so I believe that leaves two options, either add a work around, or catch cases where the user tries to make use of a negative stride, or access an array with a negative stride, and throw an error. This patch currently goes with adding a work around, which is that when we resolve a dynamic Fortran array type, if the stride is negative, then we adjust the base address to point to the lowest address required by the array. The printing and slicing code is aware of this adjustment and will correctly slice and print Fortran arrays. Where this hack will show through to the user is if they ask for the address of an array in their program with a negative array stride, the address they get from GDB will not match the address that would be computed within the Fortran program. gdb/ChangeLog: * Makefile.in (HFILES_NO_SRCDIR): Add f-array-walker.h. * NEWS: Mention new options. * f-array-walker.h: New file. * f-lang.c: Include 'gdbcmd.h' and 'f-array-walker.h'. (repack_array_slices): New static global. (show_repack_array_slices): New function. (fortran_array_slicing_debug): New static global. (show_fortran_array_slicing_debug): New function. (value_f90_subarray): Delete. (skip_undetermined_arglist): Delete. (class fortran_array_repacker_base_impl): New class. (class fortran_lazy_array_repacker_impl): New class. (class fortran_array_repacker_impl): New class. (fortran_value_subarray): Complete rewrite. (set_fortran_list): New static global. (show_fortran_list): Likewise. (_initialize_f_language): Register new commands. (fortran_adjust_dynamic_array_base_address_hack): New function. * f-lang.h (fortran_adjust_dynamic_array_base_address_hack): Declare. * f-valprint.c: Include 'f-array-walker.h'. (class fortran_array_printer_impl): New class. (f77_print_array_1): Delete. (f77_print_array): Delete. (fortran_print_array): New. (f_value_print_inner): Update to call fortran_print_array. * gdbtypes.c: Include 'f-lang.h'. (resolve_dynamic_type_internal): Call fortran_adjust_dynamic_array_base_address_hack. gdb/testsuite/ChangeLog: * gdb.fortran/array-slices-bad.exp: New file. * gdb.fortran/array-slices-bad.f90: New file. * gdb.fortran/array-slices-sub-slices.exp: New file. * gdb.fortran/array-slices-sub-slices.f90: New file. * gdb.fortran/array-slices.exp: Rewrite tests. * gdb.fortran/array-slices.f90: Rewrite tests. * gdb.fortran/vla-sizeof.exp: Correct expected results. gdb/doc/ChangeLog: * gdb.texinfo (Debugging Output): Document 'set/show debug fortran-array-slicing'. (Special Fortran Commands): Document 'set/show fortran repack-array-slices'.
2020-10-08 23:45:59 +08:00
/* See f-lang.h. */
CORE_ADDR
fortran_adjust_dynamic_array_base_address_hack (struct type *type,
CORE_ADDR address)
{
gdb_assert (type->code () == TYPE_CODE_ARRAY);
gdb: avoid resolving dynamic properties for non-allocated arrays In PR gdb/27059 an issue was discovered where GDB would sometimes trigger undefined behaviour in the form of signed integer overflow. The problem here is that GDB was reading random garbage from the inferior memory space, assuming this data was valid, and performing arithmetic on it. This bug raises an interesting general problem with GDB's DWARF expression evaluator, which is this: We currently assume that the DWARF expressions being evaluated are well formed, and well behaving. As an example, this is the expression that the bug was running into problems on, this was used as the expression for a DW_AT_byte_stride of a DW_TAG_subrange_type: DW_OP_push_object_address; DW_OP_plus_uconst: 88; DW_OP_deref; DW_OP_push_object_address; DW_OP_plus_uconst: 32; DW_OP_deref; DW_OP_mul Two values are read from the inferior and multiplied together. GDB should not assume that any value read from the inferior is in any way sane, as such the implementation of DW_OP_mul should be guarding against overflow and doing something semi-sane here. However, it turns out that the original bug PR gdb/27059, is hitting a more specific case, which doesn't require changes to the DWARF expression evaluator, so I'm going to leave the above issue for another day. In the test mentioned in the bug GDB is actually trying to resolve the dynamic type of a Fortran array that is NOT allocated. A non-allocated Fortran array is one that does not have any data allocated for it yet, and even the upper and lower bounds of the array are not yet known. It turns out that, at least for gfortran compiled code, the data fields that describe the byte-stride are not initialised until the array is allocated. This leads me to the following conclusion: GDB should not try to resolve the bounds, or stride information for an array that is not allocated (or not associated, a similar, but slightly different Fortran feature). Instead, each of these properties should be set to undefined if the array is not allocated (or associated). That is what this commit does. There's a new flag that is passed around during the dynamic array resolution. When this flag is true the dynamic properties are resolved using the DWARF expressions as they currently are, but when this flag is false the expressions are not evaluated, and instead the properties are set to undefined. gdb/ChangeLog: PR gdb/27059 * eval.c (evaluate_subexp_for_sizeof): Handle not allocated and not associated arrays. * f-lang.c (fortran_adjust_dynamic_array_base_address_hack): Don't adjust arrays that are not allocated/associated. * gdbtypes.c (resolve_dynamic_range): Update header comment. Add new parameter which is used to sometimes set dynamic properties to undefined. (resolve_dynamic_array_or_string): Update header comment. Add new parameter which is used to guard evaluating dynamic properties. Resolve allocated/associated properties first. gdb/testsuite/ChangeLog: PR gdb/27059 * gdb.dwarf2/dyn-type-unallocated.c: New file. * gdb.dwarf2/dyn-type-unallocated.exp: New file.
2020-12-18 19:59:54 +08:00
/* We can't adjust the base address for arrays that have no content. */
if (type_not_allocated (type) || type_not_associated (type))
return address;
gdb/fortran: Add support for Fortran array slices at the GDB prompt This commit brings array slice support to GDB. WARNING: This patch contains a rather big hack which is limited to Fortran arrays, this can be seen in gdbtypes.c and f-lang.c. More details on this below. This patch rewrites two areas of GDB's Fortran support, the code to extract an array slice, and the code to print an array. After this commit a user can, from the GDB prompt, ask for a slice of a Fortran array and should get the correct result back. Slices can (optionally) have the lower bound, upper bound, and a stride specified. Slices can also have a negative stride. Fortran has the concept of repacking array slices. Within a compiled Fortran program if a user passes a non-contiguous array slice to a function then the compiler may have to repack the slice, this involves copying the elements of the slice to a new area of memory before the call, and copying the elements back to the original array after the call. Whether repacking occurs will depend on which version of Fortran is being used, and what type of function is being called. This commit adds support for both packed, and unpacked array slicing, with the default being unpacked. With an unpacked array slice, when the user asks for a slice of an array GDB creates a new type that accurately describes where the elements of the slice can be found within the original array, a value of this type is then returned to the user. The address of an element within the slice will be equal to the address of an element within the original array. A user can choose to select packed array slices instead using: (gdb) set fortran repack-array-slices on|off (gdb) show fortran repack-array-slices With packed array slices GDB creates a new type that reflects how the elements of the slice would look if they were laid out in contiguous memory, allocates a value of this type, and then fetches the elements from the original array and places then into the contents buffer of the new value. One benefit of using packed slices over unpacked slices is the memory usage, taking a small slice of N elements from a large array will require (in GDB) N * ELEMENT_SIZE bytes of memory, while an unpacked array will also include all of the "padding" between the non-contiguous elements. There are new tests added that highlight this difference. There is also a new debugging flag added with this commit that introduces these commands: (gdb) set debug fortran-array-slicing on|off (gdb) show debug fortran-array-slicing This prints information about how the array slices are being built. As both the repacking, and the array printing requires GDB to walk through a multi-dimensional Fortran array visiting each element, this commit adds the file f-array-walk.h, which introduces some infrastructure to support this process. This means the array printing code in f-valprint.c is significantly reduced. The only slight issue with this commit is the "rather big hack" that I mentioned above. This hack allows us to handle one specific case, array slices with negative strides. This is something that I don't believe the current GDB value contents model will allow us to correctly handle, and rather than rewrite the value contents code right now, I'm hoping to slip this hack in as a work around. The problem is that, as I see it, the current value contents model assumes that an object base address will be the lowest address within that object, and that the contents of the object start at this base address and occupy the TYPE_LENGTH bytes after that. ( We do have the embedded_offset, which is used for C++ sub-classes, such that an object can start at some offset from the content buffer, however, the assumption that the object then occupies the next TYPE_LENGTH bytes is still true within GDB. ) The problem is that Fortran arrays with a negative stride don't follow this pattern. In this case the base address of the object points to the element with the highest address, the contents of the array then start at some offset _before_ the base address, and proceed for one element _past_ the base address. As the stride for such an array would be negative then, in theory the TYPE_LENGTH for this type would also be negative. However, in many places a value in GDB will degrade to a pointer + length, and the length almost always comes from the TYPE_LENGTH. It is my belief that in order to correctly model this case the value content handling of GDB will need to be reworked to split apart the value's content buffer (which is a block of memory with a length), and the object's in memory base address and length, which could be negative. Things are further complicated because arrays with negative strides like this are always dynamic types. When a value has a dynamic type and its base address needs resolving we actually store the address of the object within the resolved dynamic type, not within the value object itself. In short I don't currently see an easy path to cleanly support this situation within GDB. And so I believe that leaves two options, either add a work around, or catch cases where the user tries to make use of a negative stride, or access an array with a negative stride, and throw an error. This patch currently goes with adding a work around, which is that when we resolve a dynamic Fortran array type, if the stride is negative, then we adjust the base address to point to the lowest address required by the array. The printing and slicing code is aware of this adjustment and will correctly slice and print Fortran arrays. Where this hack will show through to the user is if they ask for the address of an array in their program with a negative array stride, the address they get from GDB will not match the address that would be computed within the Fortran program. gdb/ChangeLog: * Makefile.in (HFILES_NO_SRCDIR): Add f-array-walker.h. * NEWS: Mention new options. * f-array-walker.h: New file. * f-lang.c: Include 'gdbcmd.h' and 'f-array-walker.h'. (repack_array_slices): New static global. (show_repack_array_slices): New function. (fortran_array_slicing_debug): New static global. (show_fortran_array_slicing_debug): New function. (value_f90_subarray): Delete. (skip_undetermined_arglist): Delete. (class fortran_array_repacker_base_impl): New class. (class fortran_lazy_array_repacker_impl): New class. (class fortran_array_repacker_impl): New class. (fortran_value_subarray): Complete rewrite. (set_fortran_list): New static global. (show_fortran_list): Likewise. (_initialize_f_language): Register new commands. (fortran_adjust_dynamic_array_base_address_hack): New function. * f-lang.h (fortran_adjust_dynamic_array_base_address_hack): Declare. * f-valprint.c: Include 'f-array-walker.h'. (class fortran_array_printer_impl): New class. (f77_print_array_1): Delete. (f77_print_array): Delete. (fortran_print_array): New. (f_value_print_inner): Update to call fortran_print_array. * gdbtypes.c: Include 'f-lang.h'. (resolve_dynamic_type_internal): Call fortran_adjust_dynamic_array_base_address_hack. gdb/testsuite/ChangeLog: * gdb.fortran/array-slices-bad.exp: New file. * gdb.fortran/array-slices-bad.f90: New file. * gdb.fortran/array-slices-sub-slices.exp: New file. * gdb.fortran/array-slices-sub-slices.f90: New file. * gdb.fortran/array-slices.exp: Rewrite tests. * gdb.fortran/array-slices.f90: Rewrite tests. * gdb.fortran/vla-sizeof.exp: Correct expected results. gdb/doc/ChangeLog: * gdb.texinfo (Debugging Output): Document 'set/show debug fortran-array-slicing'. (Special Fortran Commands): Document 'set/show fortran repack-array-slices'.
2020-10-08 23:45:59 +08:00
int ndimensions = calc_f77_array_dims (type);
LONGEST total_offset = 0;
/* Walk through each of the dimensions of this array type and figure out
if any of the dimensions are "backwards", that is the base address
for this dimension points to the element at the highest memory
address and the stride is negative. */
struct type *tmp_type = type;
for (int i = 0 ; i < ndimensions; ++i)
{
/* Grab the range for this dimension and extract the lower and upper
bounds. */
tmp_type = check_typedef (tmp_type);
struct type *range_type = tmp_type->index_type ();
LONGEST lowerbound, upperbound, stride;
if (!get_discrete_bounds (range_type, &lowerbound, &upperbound))
gdb/fortran: Add support for Fortran array slices at the GDB prompt This commit brings array slice support to GDB. WARNING: This patch contains a rather big hack which is limited to Fortran arrays, this can be seen in gdbtypes.c and f-lang.c. More details on this below. This patch rewrites two areas of GDB's Fortran support, the code to extract an array slice, and the code to print an array. After this commit a user can, from the GDB prompt, ask for a slice of a Fortran array and should get the correct result back. Slices can (optionally) have the lower bound, upper bound, and a stride specified. Slices can also have a negative stride. Fortran has the concept of repacking array slices. Within a compiled Fortran program if a user passes a non-contiguous array slice to a function then the compiler may have to repack the slice, this involves copying the elements of the slice to a new area of memory before the call, and copying the elements back to the original array after the call. Whether repacking occurs will depend on which version of Fortran is being used, and what type of function is being called. This commit adds support for both packed, and unpacked array slicing, with the default being unpacked. With an unpacked array slice, when the user asks for a slice of an array GDB creates a new type that accurately describes where the elements of the slice can be found within the original array, a value of this type is then returned to the user. The address of an element within the slice will be equal to the address of an element within the original array. A user can choose to select packed array slices instead using: (gdb) set fortran repack-array-slices on|off (gdb) show fortran repack-array-slices With packed array slices GDB creates a new type that reflects how the elements of the slice would look if they were laid out in contiguous memory, allocates a value of this type, and then fetches the elements from the original array and places then into the contents buffer of the new value. One benefit of using packed slices over unpacked slices is the memory usage, taking a small slice of N elements from a large array will require (in GDB) N * ELEMENT_SIZE bytes of memory, while an unpacked array will also include all of the "padding" between the non-contiguous elements. There are new tests added that highlight this difference. There is also a new debugging flag added with this commit that introduces these commands: (gdb) set debug fortran-array-slicing on|off (gdb) show debug fortran-array-slicing This prints information about how the array slices are being built. As both the repacking, and the array printing requires GDB to walk through a multi-dimensional Fortran array visiting each element, this commit adds the file f-array-walk.h, which introduces some infrastructure to support this process. This means the array printing code in f-valprint.c is significantly reduced. The only slight issue with this commit is the "rather big hack" that I mentioned above. This hack allows us to handle one specific case, array slices with negative strides. This is something that I don't believe the current GDB value contents model will allow us to correctly handle, and rather than rewrite the value contents code right now, I'm hoping to slip this hack in as a work around. The problem is that, as I see it, the current value contents model assumes that an object base address will be the lowest address within that object, and that the contents of the object start at this base address and occupy the TYPE_LENGTH bytes after that. ( We do have the embedded_offset, which is used for C++ sub-classes, such that an object can start at some offset from the content buffer, however, the assumption that the object then occupies the next TYPE_LENGTH bytes is still true within GDB. ) The problem is that Fortran arrays with a negative stride don't follow this pattern. In this case the base address of the object points to the element with the highest address, the contents of the array then start at some offset _before_ the base address, and proceed for one element _past_ the base address. As the stride for such an array would be negative then, in theory the TYPE_LENGTH for this type would also be negative. However, in many places a value in GDB will degrade to a pointer + length, and the length almost always comes from the TYPE_LENGTH. It is my belief that in order to correctly model this case the value content handling of GDB will need to be reworked to split apart the value's content buffer (which is a block of memory with a length), and the object's in memory base address and length, which could be negative. Things are further complicated because arrays with negative strides like this are always dynamic types. When a value has a dynamic type and its base address needs resolving we actually store the address of the object within the resolved dynamic type, not within the value object itself. In short I don't currently see an easy path to cleanly support this situation within GDB. And so I believe that leaves two options, either add a work around, or catch cases where the user tries to make use of a negative stride, or access an array with a negative stride, and throw an error. This patch currently goes with adding a work around, which is that when we resolve a dynamic Fortran array type, if the stride is negative, then we adjust the base address to point to the lowest address required by the array. The printing and slicing code is aware of this adjustment and will correctly slice and print Fortran arrays. Where this hack will show through to the user is if they ask for the address of an array in their program with a negative array stride, the address they get from GDB will not match the address that would be computed within the Fortran program. gdb/ChangeLog: * Makefile.in (HFILES_NO_SRCDIR): Add f-array-walker.h. * NEWS: Mention new options. * f-array-walker.h: New file. * f-lang.c: Include 'gdbcmd.h' and 'f-array-walker.h'. (repack_array_slices): New static global. (show_repack_array_slices): New function. (fortran_array_slicing_debug): New static global. (show_fortran_array_slicing_debug): New function. (value_f90_subarray): Delete. (skip_undetermined_arglist): Delete. (class fortran_array_repacker_base_impl): New class. (class fortran_lazy_array_repacker_impl): New class. (class fortran_array_repacker_impl): New class. (fortran_value_subarray): Complete rewrite. (set_fortran_list): New static global. (show_fortran_list): Likewise. (_initialize_f_language): Register new commands. (fortran_adjust_dynamic_array_base_address_hack): New function. * f-lang.h (fortran_adjust_dynamic_array_base_address_hack): Declare. * f-valprint.c: Include 'f-array-walker.h'. (class fortran_array_printer_impl): New class. (f77_print_array_1): Delete. (f77_print_array): Delete. (fortran_print_array): New. (f_value_print_inner): Update to call fortran_print_array. * gdbtypes.c: Include 'f-lang.h'. (resolve_dynamic_type_internal): Call fortran_adjust_dynamic_array_base_address_hack. gdb/testsuite/ChangeLog: * gdb.fortran/array-slices-bad.exp: New file. * gdb.fortran/array-slices-bad.f90: New file. * gdb.fortran/array-slices-sub-slices.exp: New file. * gdb.fortran/array-slices-sub-slices.f90: New file. * gdb.fortran/array-slices.exp: Rewrite tests. * gdb.fortran/array-slices.f90: Rewrite tests. * gdb.fortran/vla-sizeof.exp: Correct expected results. gdb/doc/ChangeLog: * gdb.texinfo (Debugging Output): Document 'set/show debug fortran-array-slicing'. (Special Fortran Commands): Document 'set/show fortran repack-array-slices'.
2020-10-08 23:45:59 +08:00
error ("failed to get range bounds");
/* Figure out the stride for this dimension. */
struct type *elt_type = check_typedef (tmp_type->target_type ());
gdb/fortran: Add support for Fortran array slices at the GDB prompt This commit brings array slice support to GDB. WARNING: This patch contains a rather big hack which is limited to Fortran arrays, this can be seen in gdbtypes.c and f-lang.c. More details on this below. This patch rewrites two areas of GDB's Fortran support, the code to extract an array slice, and the code to print an array. After this commit a user can, from the GDB prompt, ask for a slice of a Fortran array and should get the correct result back. Slices can (optionally) have the lower bound, upper bound, and a stride specified. Slices can also have a negative stride. Fortran has the concept of repacking array slices. Within a compiled Fortran program if a user passes a non-contiguous array slice to a function then the compiler may have to repack the slice, this involves copying the elements of the slice to a new area of memory before the call, and copying the elements back to the original array after the call. Whether repacking occurs will depend on which version of Fortran is being used, and what type of function is being called. This commit adds support for both packed, and unpacked array slicing, with the default being unpacked. With an unpacked array slice, when the user asks for a slice of an array GDB creates a new type that accurately describes where the elements of the slice can be found within the original array, a value of this type is then returned to the user. The address of an element within the slice will be equal to the address of an element within the original array. A user can choose to select packed array slices instead using: (gdb) set fortran repack-array-slices on|off (gdb) show fortran repack-array-slices With packed array slices GDB creates a new type that reflects how the elements of the slice would look if they were laid out in contiguous memory, allocates a value of this type, and then fetches the elements from the original array and places then into the contents buffer of the new value. One benefit of using packed slices over unpacked slices is the memory usage, taking a small slice of N elements from a large array will require (in GDB) N * ELEMENT_SIZE bytes of memory, while an unpacked array will also include all of the "padding" between the non-contiguous elements. There are new tests added that highlight this difference. There is also a new debugging flag added with this commit that introduces these commands: (gdb) set debug fortran-array-slicing on|off (gdb) show debug fortran-array-slicing This prints information about how the array slices are being built. As both the repacking, and the array printing requires GDB to walk through a multi-dimensional Fortran array visiting each element, this commit adds the file f-array-walk.h, which introduces some infrastructure to support this process. This means the array printing code in f-valprint.c is significantly reduced. The only slight issue with this commit is the "rather big hack" that I mentioned above. This hack allows us to handle one specific case, array slices with negative strides. This is something that I don't believe the current GDB value contents model will allow us to correctly handle, and rather than rewrite the value contents code right now, I'm hoping to slip this hack in as a work around. The problem is that, as I see it, the current value contents model assumes that an object base address will be the lowest address within that object, and that the contents of the object start at this base address and occupy the TYPE_LENGTH bytes after that. ( We do have the embedded_offset, which is used for C++ sub-classes, such that an object can start at some offset from the content buffer, however, the assumption that the object then occupies the next TYPE_LENGTH bytes is still true within GDB. ) The problem is that Fortran arrays with a negative stride don't follow this pattern. In this case the base address of the object points to the element with the highest address, the contents of the array then start at some offset _before_ the base address, and proceed for one element _past_ the base address. As the stride for such an array would be negative then, in theory the TYPE_LENGTH for this type would also be negative. However, in many places a value in GDB will degrade to a pointer + length, and the length almost always comes from the TYPE_LENGTH. It is my belief that in order to correctly model this case the value content handling of GDB will need to be reworked to split apart the value's content buffer (which is a block of memory with a length), and the object's in memory base address and length, which could be negative. Things are further complicated because arrays with negative strides like this are always dynamic types. When a value has a dynamic type and its base address needs resolving we actually store the address of the object within the resolved dynamic type, not within the value object itself. In short I don't currently see an easy path to cleanly support this situation within GDB. And so I believe that leaves two options, either add a work around, or catch cases where the user tries to make use of a negative stride, or access an array with a negative stride, and throw an error. This patch currently goes with adding a work around, which is that when we resolve a dynamic Fortran array type, if the stride is negative, then we adjust the base address to point to the lowest address required by the array. The printing and slicing code is aware of this adjustment and will correctly slice and print Fortran arrays. Where this hack will show through to the user is if they ask for the address of an array in their program with a negative array stride, the address they get from GDB will not match the address that would be computed within the Fortran program. gdb/ChangeLog: * Makefile.in (HFILES_NO_SRCDIR): Add f-array-walker.h. * NEWS: Mention new options. * f-array-walker.h: New file. * f-lang.c: Include 'gdbcmd.h' and 'f-array-walker.h'. (repack_array_slices): New static global. (show_repack_array_slices): New function. (fortran_array_slicing_debug): New static global. (show_fortran_array_slicing_debug): New function. (value_f90_subarray): Delete. (skip_undetermined_arglist): Delete. (class fortran_array_repacker_base_impl): New class. (class fortran_lazy_array_repacker_impl): New class. (class fortran_array_repacker_impl): New class. (fortran_value_subarray): Complete rewrite. (set_fortran_list): New static global. (show_fortran_list): Likewise. (_initialize_f_language): Register new commands. (fortran_adjust_dynamic_array_base_address_hack): New function. * f-lang.h (fortran_adjust_dynamic_array_base_address_hack): Declare. * f-valprint.c: Include 'f-array-walker.h'. (class fortran_array_printer_impl): New class. (f77_print_array_1): Delete. (f77_print_array): Delete. (fortran_print_array): New. (f_value_print_inner): Update to call fortran_print_array. * gdbtypes.c: Include 'f-lang.h'. (resolve_dynamic_type_internal): Call fortran_adjust_dynamic_array_base_address_hack. gdb/testsuite/ChangeLog: * gdb.fortran/array-slices-bad.exp: New file. * gdb.fortran/array-slices-bad.f90: New file. * gdb.fortran/array-slices-sub-slices.exp: New file. * gdb.fortran/array-slices-sub-slices.f90: New file. * gdb.fortran/array-slices.exp: Rewrite tests. * gdb.fortran/array-slices.f90: Rewrite tests. * gdb.fortran/vla-sizeof.exp: Correct expected results. gdb/doc/ChangeLog: * gdb.texinfo (Debugging Output): Document 'set/show debug fortran-array-slicing'. (Special Fortran Commands): Document 'set/show fortran repack-array-slices'.
2020-10-08 23:45:59 +08:00
stride = tmp_type->index_type ()->bounds ()->bit_stride ();
if (stride == 0)
stride = type_length_units (elt_type);
else
{
int unit_size
= gdbarch_addressable_memory_unit_size (elt_type->arch ());
gdb/fortran: Add support for Fortran array slices at the GDB prompt This commit brings array slice support to GDB. WARNING: This patch contains a rather big hack which is limited to Fortran arrays, this can be seen in gdbtypes.c and f-lang.c. More details on this below. This patch rewrites two areas of GDB's Fortran support, the code to extract an array slice, and the code to print an array. After this commit a user can, from the GDB prompt, ask for a slice of a Fortran array and should get the correct result back. Slices can (optionally) have the lower bound, upper bound, and a stride specified. Slices can also have a negative stride. Fortran has the concept of repacking array slices. Within a compiled Fortran program if a user passes a non-contiguous array slice to a function then the compiler may have to repack the slice, this involves copying the elements of the slice to a new area of memory before the call, and copying the elements back to the original array after the call. Whether repacking occurs will depend on which version of Fortran is being used, and what type of function is being called. This commit adds support for both packed, and unpacked array slicing, with the default being unpacked. With an unpacked array slice, when the user asks for a slice of an array GDB creates a new type that accurately describes where the elements of the slice can be found within the original array, a value of this type is then returned to the user. The address of an element within the slice will be equal to the address of an element within the original array. A user can choose to select packed array slices instead using: (gdb) set fortran repack-array-slices on|off (gdb) show fortran repack-array-slices With packed array slices GDB creates a new type that reflects how the elements of the slice would look if they were laid out in contiguous memory, allocates a value of this type, and then fetches the elements from the original array and places then into the contents buffer of the new value. One benefit of using packed slices over unpacked slices is the memory usage, taking a small slice of N elements from a large array will require (in GDB) N * ELEMENT_SIZE bytes of memory, while an unpacked array will also include all of the "padding" between the non-contiguous elements. There are new tests added that highlight this difference. There is also a new debugging flag added with this commit that introduces these commands: (gdb) set debug fortran-array-slicing on|off (gdb) show debug fortran-array-slicing This prints information about how the array slices are being built. As both the repacking, and the array printing requires GDB to walk through a multi-dimensional Fortran array visiting each element, this commit adds the file f-array-walk.h, which introduces some infrastructure to support this process. This means the array printing code in f-valprint.c is significantly reduced. The only slight issue with this commit is the "rather big hack" that I mentioned above. This hack allows us to handle one specific case, array slices with negative strides. This is something that I don't believe the current GDB value contents model will allow us to correctly handle, and rather than rewrite the value contents code right now, I'm hoping to slip this hack in as a work around. The problem is that, as I see it, the current value contents model assumes that an object base address will be the lowest address within that object, and that the contents of the object start at this base address and occupy the TYPE_LENGTH bytes after that. ( We do have the embedded_offset, which is used for C++ sub-classes, such that an object can start at some offset from the content buffer, however, the assumption that the object then occupies the next TYPE_LENGTH bytes is still true within GDB. ) The problem is that Fortran arrays with a negative stride don't follow this pattern. In this case the base address of the object points to the element with the highest address, the contents of the array then start at some offset _before_ the base address, and proceed for one element _past_ the base address. As the stride for such an array would be negative then, in theory the TYPE_LENGTH for this type would also be negative. However, in many places a value in GDB will degrade to a pointer + length, and the length almost always comes from the TYPE_LENGTH. It is my belief that in order to correctly model this case the value content handling of GDB will need to be reworked to split apart the value's content buffer (which is a block of memory with a length), and the object's in memory base address and length, which could be negative. Things are further complicated because arrays with negative strides like this are always dynamic types. When a value has a dynamic type and its base address needs resolving we actually store the address of the object within the resolved dynamic type, not within the value object itself. In short I don't currently see an easy path to cleanly support this situation within GDB. And so I believe that leaves two options, either add a work around, or catch cases where the user tries to make use of a negative stride, or access an array with a negative stride, and throw an error. This patch currently goes with adding a work around, which is that when we resolve a dynamic Fortran array type, if the stride is negative, then we adjust the base address to point to the lowest address required by the array. The printing and slicing code is aware of this adjustment and will correctly slice and print Fortran arrays. Where this hack will show through to the user is if they ask for the address of an array in their program with a negative array stride, the address they get from GDB will not match the address that would be computed within the Fortran program. gdb/ChangeLog: * Makefile.in (HFILES_NO_SRCDIR): Add f-array-walker.h. * NEWS: Mention new options. * f-array-walker.h: New file. * f-lang.c: Include 'gdbcmd.h' and 'f-array-walker.h'. (repack_array_slices): New static global. (show_repack_array_slices): New function. (fortran_array_slicing_debug): New static global. (show_fortran_array_slicing_debug): New function. (value_f90_subarray): Delete. (skip_undetermined_arglist): Delete. (class fortran_array_repacker_base_impl): New class. (class fortran_lazy_array_repacker_impl): New class. (class fortran_array_repacker_impl): New class. (fortran_value_subarray): Complete rewrite. (set_fortran_list): New static global. (show_fortran_list): Likewise. (_initialize_f_language): Register new commands. (fortran_adjust_dynamic_array_base_address_hack): New function. * f-lang.h (fortran_adjust_dynamic_array_base_address_hack): Declare. * f-valprint.c: Include 'f-array-walker.h'. (class fortran_array_printer_impl): New class. (f77_print_array_1): Delete. (f77_print_array): Delete. (fortran_print_array): New. (f_value_print_inner): Update to call fortran_print_array. * gdbtypes.c: Include 'f-lang.h'. (resolve_dynamic_type_internal): Call fortran_adjust_dynamic_array_base_address_hack. gdb/testsuite/ChangeLog: * gdb.fortran/array-slices-bad.exp: New file. * gdb.fortran/array-slices-bad.f90: New file. * gdb.fortran/array-slices-sub-slices.exp: New file. * gdb.fortran/array-slices-sub-slices.f90: New file. * gdb.fortran/array-slices.exp: Rewrite tests. * gdb.fortran/array-slices.f90: Rewrite tests. * gdb.fortran/vla-sizeof.exp: Correct expected results. gdb/doc/ChangeLog: * gdb.texinfo (Debugging Output): Document 'set/show debug fortran-array-slicing'. (Special Fortran Commands): Document 'set/show fortran repack-array-slices'.
2020-10-08 23:45:59 +08:00
stride /= (unit_size * 8);
}
/* If this dimension is "backward" then figure out the offset
adjustment required to point to the element at the lowest memory
address, and add this to the total offset. */
LONGEST offset = 0;
if (stride < 0 && lowerbound < upperbound)
offset = (upperbound - lowerbound) * stride;
total_offset += offset;
tmp_type = tmp_type->target_type ();
gdb/fortran: Add support for Fortran array slices at the GDB prompt This commit brings array slice support to GDB. WARNING: This patch contains a rather big hack which is limited to Fortran arrays, this can be seen in gdbtypes.c and f-lang.c. More details on this below. This patch rewrites two areas of GDB's Fortran support, the code to extract an array slice, and the code to print an array. After this commit a user can, from the GDB prompt, ask for a slice of a Fortran array and should get the correct result back. Slices can (optionally) have the lower bound, upper bound, and a stride specified. Slices can also have a negative stride. Fortran has the concept of repacking array slices. Within a compiled Fortran program if a user passes a non-contiguous array slice to a function then the compiler may have to repack the slice, this involves copying the elements of the slice to a new area of memory before the call, and copying the elements back to the original array after the call. Whether repacking occurs will depend on which version of Fortran is being used, and what type of function is being called. This commit adds support for both packed, and unpacked array slicing, with the default being unpacked. With an unpacked array slice, when the user asks for a slice of an array GDB creates a new type that accurately describes where the elements of the slice can be found within the original array, a value of this type is then returned to the user. The address of an element within the slice will be equal to the address of an element within the original array. A user can choose to select packed array slices instead using: (gdb) set fortran repack-array-slices on|off (gdb) show fortran repack-array-slices With packed array slices GDB creates a new type that reflects how the elements of the slice would look if they were laid out in contiguous memory, allocates a value of this type, and then fetches the elements from the original array and places then into the contents buffer of the new value. One benefit of using packed slices over unpacked slices is the memory usage, taking a small slice of N elements from a large array will require (in GDB) N * ELEMENT_SIZE bytes of memory, while an unpacked array will also include all of the "padding" between the non-contiguous elements. There are new tests added that highlight this difference. There is also a new debugging flag added with this commit that introduces these commands: (gdb) set debug fortran-array-slicing on|off (gdb) show debug fortran-array-slicing This prints information about how the array slices are being built. As both the repacking, and the array printing requires GDB to walk through a multi-dimensional Fortran array visiting each element, this commit adds the file f-array-walk.h, which introduces some infrastructure to support this process. This means the array printing code in f-valprint.c is significantly reduced. The only slight issue with this commit is the "rather big hack" that I mentioned above. This hack allows us to handle one specific case, array slices with negative strides. This is something that I don't believe the current GDB value contents model will allow us to correctly handle, and rather than rewrite the value contents code right now, I'm hoping to slip this hack in as a work around. The problem is that, as I see it, the current value contents model assumes that an object base address will be the lowest address within that object, and that the contents of the object start at this base address and occupy the TYPE_LENGTH bytes after that. ( We do have the embedded_offset, which is used for C++ sub-classes, such that an object can start at some offset from the content buffer, however, the assumption that the object then occupies the next TYPE_LENGTH bytes is still true within GDB. ) The problem is that Fortran arrays with a negative stride don't follow this pattern. In this case the base address of the object points to the element with the highest address, the contents of the array then start at some offset _before_ the base address, and proceed for one element _past_ the base address. As the stride for such an array would be negative then, in theory the TYPE_LENGTH for this type would also be negative. However, in many places a value in GDB will degrade to a pointer + length, and the length almost always comes from the TYPE_LENGTH. It is my belief that in order to correctly model this case the value content handling of GDB will need to be reworked to split apart the value's content buffer (which is a block of memory with a length), and the object's in memory base address and length, which could be negative. Things are further complicated because arrays with negative strides like this are always dynamic types. When a value has a dynamic type and its base address needs resolving we actually store the address of the object within the resolved dynamic type, not within the value object itself. In short I don't currently see an easy path to cleanly support this situation within GDB. And so I believe that leaves two options, either add a work around, or catch cases where the user tries to make use of a negative stride, or access an array with a negative stride, and throw an error. This patch currently goes with adding a work around, which is that when we resolve a dynamic Fortran array type, if the stride is negative, then we adjust the base address to point to the lowest address required by the array. The printing and slicing code is aware of this adjustment and will correctly slice and print Fortran arrays. Where this hack will show through to the user is if they ask for the address of an array in their program with a negative array stride, the address they get from GDB will not match the address that would be computed within the Fortran program. gdb/ChangeLog: * Makefile.in (HFILES_NO_SRCDIR): Add f-array-walker.h. * NEWS: Mention new options. * f-array-walker.h: New file. * f-lang.c: Include 'gdbcmd.h' and 'f-array-walker.h'. (repack_array_slices): New static global. (show_repack_array_slices): New function. (fortran_array_slicing_debug): New static global. (show_fortran_array_slicing_debug): New function. (value_f90_subarray): Delete. (skip_undetermined_arglist): Delete. (class fortran_array_repacker_base_impl): New class. (class fortran_lazy_array_repacker_impl): New class. (class fortran_array_repacker_impl): New class. (fortran_value_subarray): Complete rewrite. (set_fortran_list): New static global. (show_fortran_list): Likewise. (_initialize_f_language): Register new commands. (fortran_adjust_dynamic_array_base_address_hack): New function. * f-lang.h (fortran_adjust_dynamic_array_base_address_hack): Declare. * f-valprint.c: Include 'f-array-walker.h'. (class fortran_array_printer_impl): New class. (f77_print_array_1): Delete. (f77_print_array): Delete. (fortran_print_array): New. (f_value_print_inner): Update to call fortran_print_array. * gdbtypes.c: Include 'f-lang.h'. (resolve_dynamic_type_internal): Call fortran_adjust_dynamic_array_base_address_hack. gdb/testsuite/ChangeLog: * gdb.fortran/array-slices-bad.exp: New file. * gdb.fortran/array-slices-bad.f90: New file. * gdb.fortran/array-slices-sub-slices.exp: New file. * gdb.fortran/array-slices-sub-slices.f90: New file. * gdb.fortran/array-slices.exp: Rewrite tests. * gdb.fortran/array-slices.f90: Rewrite tests. * gdb.fortran/vla-sizeof.exp: Correct expected results. gdb/doc/ChangeLog: * gdb.texinfo (Debugging Output): Document 'set/show debug fortran-array-slicing'. (Special Fortran Commands): Document 'set/show fortran repack-array-slices'.
2020-10-08 23:45:59 +08:00
}
/* Adjust the address of this object and return it. */
address += total_offset;
return address;
}