diff options
author | Martin Liska <mliska@suse.cz> | 2022-01-14 16:56:44 +0100 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2022-01-17 22:12:04 +0100 |
commit | 5c69acb32329d49e58c26fa41ae74229a52b9106 (patch) | |
tree | ddb05f9d73afb6f998457d2ac4b720e3b3b60483 /gcc/fortran/resolve.c | |
parent | 490e23032baaece71f2ec09fa1805064b150fbc2 (diff) | |
download | gcc-5c69acb32329d49e58c26fa41ae74229a52b9106.zip gcc-5c69acb32329d49e58c26fa41ae74229a52b9106.tar.gz gcc-5c69acb32329d49e58c26fa41ae74229a52b9106.tar.bz2 |
Rename .c files to .cc files.
gcc/ada/ChangeLog:
* adadecode.c: Moved to...
* adadecode.cc: ...here.
* affinity.c: Moved to...
* affinity.cc: ...here.
* argv-lynxos178-raven-cert.c: Moved to...
* argv-lynxos178-raven-cert.cc: ...here.
* argv.c: Moved to...
* argv.cc: ...here.
* aux-io.c: Moved to...
* aux-io.cc: ...here.
* cio.c: Moved to...
* cio.cc: ...here.
* cstreams.c: Moved to...
* cstreams.cc: ...here.
* env.c: Moved to...
* env.cc: ...here.
* exit.c: Moved to...
* exit.cc: ...here.
* expect.c: Moved to...
* expect.cc: ...here.
* final.c: Moved to...
* final.cc: ...here.
* gcc-interface/cuintp.c: Moved to...
* gcc-interface/cuintp.cc: ...here.
* gcc-interface/decl.c: Moved to...
* gcc-interface/decl.cc: ...here.
* gcc-interface/misc.c: Moved to...
* gcc-interface/misc.cc: ...here.
* gcc-interface/targtyps.c: Moved to...
* gcc-interface/targtyps.cc: ...here.
* gcc-interface/trans.c: Moved to...
* gcc-interface/trans.cc: ...here.
* gcc-interface/utils.c: Moved to...
* gcc-interface/utils.cc: ...here.
* gcc-interface/utils2.c: Moved to...
* gcc-interface/utils2.cc: ...here.
* init.c: Moved to...
* init.cc: ...here.
* initialize.c: Moved to...
* initialize.cc: ...here.
* libgnarl/thread.c: Moved to...
* libgnarl/thread.cc: ...here.
* link.c: Moved to...
* link.cc: ...here.
* locales.c: Moved to...
* locales.cc: ...here.
* mkdir.c: Moved to...
* mkdir.cc: ...here.
* raise.c: Moved to...
* raise.cc: ...here.
* rtfinal.c: Moved to...
* rtfinal.cc: ...here.
* rtinit.c: Moved to...
* rtinit.cc: ...here.
* seh_init.c: Moved to...
* seh_init.cc: ...here.
* sigtramp-armdroid.c: Moved to...
* sigtramp-armdroid.cc: ...here.
* sigtramp-ios.c: Moved to...
* sigtramp-ios.cc: ...here.
* sigtramp-qnx.c: Moved to...
* sigtramp-qnx.cc: ...here.
* sigtramp-vxworks.c: Moved to...
* sigtramp-vxworks.cc: ...here.
* socket.c: Moved to...
* socket.cc: ...here.
* tracebak.c: Moved to...
* tracebak.cc: ...here.
* version.c: Moved to...
* version.cc: ...here.
* vx_stack_info.c: Moved to...
* vx_stack_info.cc: ...here.
gcc/ChangeLog:
* adjust-alignment.c: Moved to...
* adjust-alignment.cc: ...here.
* alias.c: Moved to...
* alias.cc: ...here.
* alloc-pool.c: Moved to...
* alloc-pool.cc: ...here.
* asan.c: Moved to...
* asan.cc: ...here.
* attribs.c: Moved to...
* attribs.cc: ...here.
* auto-inc-dec.c: Moved to...
* auto-inc-dec.cc: ...here.
* auto-profile.c: Moved to...
* auto-profile.cc: ...here.
* bb-reorder.c: Moved to...
* bb-reorder.cc: ...here.
* bitmap.c: Moved to...
* bitmap.cc: ...here.
* btfout.c: Moved to...
* btfout.cc: ...here.
* builtins.c: Moved to...
* builtins.cc: ...here.
* caller-save.c: Moved to...
* caller-save.cc: ...here.
* calls.c: Moved to...
* calls.cc: ...here.
* ccmp.c: Moved to...
* ccmp.cc: ...here.
* cfg.c: Moved to...
* cfg.cc: ...here.
* cfganal.c: Moved to...
* cfganal.cc: ...here.
* cfgbuild.c: Moved to...
* cfgbuild.cc: ...here.
* cfgcleanup.c: Moved to...
* cfgcleanup.cc: ...here.
* cfgexpand.c: Moved to...
* cfgexpand.cc: ...here.
* cfghooks.c: Moved to...
* cfghooks.cc: ...here.
* cfgloop.c: Moved to...
* cfgloop.cc: ...here.
* cfgloopanal.c: Moved to...
* cfgloopanal.cc: ...here.
* cfgloopmanip.c: Moved to...
* cfgloopmanip.cc: ...here.
* cfgrtl.c: Moved to...
* cfgrtl.cc: ...here.
* cgraph.c: Moved to...
* cgraph.cc: ...here.
* cgraphbuild.c: Moved to...
* cgraphbuild.cc: ...here.
* cgraphclones.c: Moved to...
* cgraphclones.cc: ...here.
* cgraphunit.c: Moved to...
* cgraphunit.cc: ...here.
* collect-utils.c: Moved to...
* collect-utils.cc: ...here.
* collect2-aix.c: Moved to...
* collect2-aix.cc: ...here.
* collect2.c: Moved to...
* collect2.cc: ...here.
* combine-stack-adj.c: Moved to...
* combine-stack-adj.cc: ...here.
* combine.c: Moved to...
* combine.cc: ...here.
* common/common-targhooks.c: Moved to...
* common/common-targhooks.cc: ...here.
* common/config/aarch64/aarch64-common.c: Moved to...
* common/config/aarch64/aarch64-common.cc: ...here.
* common/config/alpha/alpha-common.c: Moved to...
* common/config/alpha/alpha-common.cc: ...here.
* common/config/arc/arc-common.c: Moved to...
* common/config/arc/arc-common.cc: ...here.
* common/config/arm/arm-common.c: Moved to...
* common/config/arm/arm-common.cc: ...here.
* common/config/avr/avr-common.c: Moved to...
* common/config/avr/avr-common.cc: ...here.
* common/config/bfin/bfin-common.c: Moved to...
* common/config/bfin/bfin-common.cc: ...here.
* common/config/bpf/bpf-common.c: Moved to...
* common/config/bpf/bpf-common.cc: ...here.
* common/config/c6x/c6x-common.c: Moved to...
* common/config/c6x/c6x-common.cc: ...here.
* common/config/cr16/cr16-common.c: Moved to...
* common/config/cr16/cr16-common.cc: ...here.
* common/config/cris/cris-common.c: Moved to...
* common/config/cris/cris-common.cc: ...here.
* common/config/csky/csky-common.c: Moved to...
* common/config/csky/csky-common.cc: ...here.
* common/config/default-common.c: Moved to...
* common/config/default-common.cc: ...here.
* common/config/epiphany/epiphany-common.c: Moved to...
* common/config/epiphany/epiphany-common.cc: ...here.
* common/config/fr30/fr30-common.c: Moved to...
* common/config/fr30/fr30-common.cc: ...here.
* common/config/frv/frv-common.c: Moved to...
* common/config/frv/frv-common.cc: ...here.
* common/config/gcn/gcn-common.c: Moved to...
* common/config/gcn/gcn-common.cc: ...here.
* common/config/h8300/h8300-common.c: Moved to...
* common/config/h8300/h8300-common.cc: ...here.
* common/config/i386/i386-common.c: Moved to...
* common/config/i386/i386-common.cc: ...here.
* common/config/ia64/ia64-common.c: Moved to...
* common/config/ia64/ia64-common.cc: ...here.
* common/config/iq2000/iq2000-common.c: Moved to...
* common/config/iq2000/iq2000-common.cc: ...here.
* common/config/lm32/lm32-common.c: Moved to...
* common/config/lm32/lm32-common.cc: ...here.
* common/config/m32r/m32r-common.c: Moved to...
* common/config/m32r/m32r-common.cc: ...here.
* common/config/m68k/m68k-common.c: Moved to...
* common/config/m68k/m68k-common.cc: ...here.
* common/config/mcore/mcore-common.c: Moved to...
* common/config/mcore/mcore-common.cc: ...here.
* common/config/microblaze/microblaze-common.c: Moved to...
* common/config/microblaze/microblaze-common.cc: ...here.
* common/config/mips/mips-common.c: Moved to...
* common/config/mips/mips-common.cc: ...here.
* common/config/mmix/mmix-common.c: Moved to...
* common/config/mmix/mmix-common.cc: ...here.
* common/config/mn10300/mn10300-common.c: Moved to...
* common/config/mn10300/mn10300-common.cc: ...here.
* common/config/msp430/msp430-common.c: Moved to...
* common/config/msp430/msp430-common.cc: ...here.
* common/config/nds32/nds32-common.c: Moved to...
* common/config/nds32/nds32-common.cc: ...here.
* common/config/nios2/nios2-common.c: Moved to...
* common/config/nios2/nios2-common.cc: ...here.
* common/config/nvptx/nvptx-common.c: Moved to...
* common/config/nvptx/nvptx-common.cc: ...here.
* common/config/or1k/or1k-common.c: Moved to...
* common/config/or1k/or1k-common.cc: ...here.
* common/config/pa/pa-common.c: Moved to...
* common/config/pa/pa-common.cc: ...here.
* common/config/pdp11/pdp11-common.c: Moved to...
* common/config/pdp11/pdp11-common.cc: ...here.
* common/config/pru/pru-common.c: Moved to...
* common/config/pru/pru-common.cc: ...here.
* common/config/riscv/riscv-common.c: Moved to...
* common/config/riscv/riscv-common.cc: ...here.
* common/config/rs6000/rs6000-common.c: Moved to...
* common/config/rs6000/rs6000-common.cc: ...here.
* common/config/rx/rx-common.c: Moved to...
* common/config/rx/rx-common.cc: ...here.
* common/config/s390/s390-common.c: Moved to...
* common/config/s390/s390-common.cc: ...here.
* common/config/sh/sh-common.c: Moved to...
* common/config/sh/sh-common.cc: ...here.
* common/config/sparc/sparc-common.c: Moved to...
* common/config/sparc/sparc-common.cc: ...here.
* common/config/tilegx/tilegx-common.c: Moved to...
* common/config/tilegx/tilegx-common.cc: ...here.
* common/config/tilepro/tilepro-common.c: Moved to...
* common/config/tilepro/tilepro-common.cc: ...here.
* common/config/v850/v850-common.c: Moved to...
* common/config/v850/v850-common.cc: ...here.
* common/config/vax/vax-common.c: Moved to...
* common/config/vax/vax-common.cc: ...here.
* common/config/visium/visium-common.c: Moved to...
* common/config/visium/visium-common.cc: ...here.
* common/config/xstormy16/xstormy16-common.c: Moved to...
* common/config/xstormy16/xstormy16-common.cc: ...here.
* common/config/xtensa/xtensa-common.c: Moved to...
* common/config/xtensa/xtensa-common.cc: ...here.
* compare-elim.c: Moved to...
* compare-elim.cc: ...here.
* config/aarch64/aarch64-bti-insert.c: Moved to...
* config/aarch64/aarch64-bti-insert.cc: ...here.
* config/aarch64/aarch64-builtins.c: Moved to...
* config/aarch64/aarch64-builtins.cc: ...here.
* config/aarch64/aarch64-c.c: Moved to...
* config/aarch64/aarch64-c.cc: ...here.
* config/aarch64/aarch64-d.c: Moved to...
* config/aarch64/aarch64-d.cc: ...here.
* config/aarch64/aarch64.c: Moved to...
* config/aarch64/aarch64.cc: ...here.
* config/aarch64/cortex-a57-fma-steering.c: Moved to...
* config/aarch64/cortex-a57-fma-steering.cc: ...here.
* config/aarch64/driver-aarch64.c: Moved to...
* config/aarch64/driver-aarch64.cc: ...here.
* config/aarch64/falkor-tag-collision-avoidance.c: Moved to...
* config/aarch64/falkor-tag-collision-avoidance.cc: ...here.
* config/aarch64/host-aarch64-darwin.c: Moved to...
* config/aarch64/host-aarch64-darwin.cc: ...here.
* config/alpha/alpha.c: Moved to...
* config/alpha/alpha.cc: ...here.
* config/alpha/driver-alpha.c: Moved to...
* config/alpha/driver-alpha.cc: ...here.
* config/arc/arc-c.c: Moved to...
* config/arc/arc-c.cc: ...here.
* config/arc/arc.c: Moved to...
* config/arc/arc.cc: ...here.
* config/arc/driver-arc.c: Moved to...
* config/arc/driver-arc.cc: ...here.
* config/arm/aarch-common.c: Moved to...
* config/arm/aarch-common.cc: ...here.
* config/arm/arm-builtins.c: Moved to...
* config/arm/arm-builtins.cc: ...here.
* config/arm/arm-c.c: Moved to...
* config/arm/arm-c.cc: ...here.
* config/arm/arm-d.c: Moved to...
* config/arm/arm-d.cc: ...here.
* config/arm/arm.c: Moved to...
* config/arm/arm.cc: ...here.
* config/arm/driver-arm.c: Moved to...
* config/arm/driver-arm.cc: ...here.
* config/avr/avr-c.c: Moved to...
* config/avr/avr-c.cc: ...here.
* config/avr/avr-devices.c: Moved to...
* config/avr/avr-devices.cc: ...here.
* config/avr/avr-log.c: Moved to...
* config/avr/avr-log.cc: ...here.
* config/avr/avr.c: Moved to...
* config/avr/avr.cc: ...here.
* config/avr/driver-avr.c: Moved to...
* config/avr/driver-avr.cc: ...here.
* config/avr/gen-avr-mmcu-specs.c: Moved to...
* config/avr/gen-avr-mmcu-specs.cc: ...here.
* config/avr/gen-avr-mmcu-texi.c: Moved to...
* config/avr/gen-avr-mmcu-texi.cc: ...here.
* config/bfin/bfin.c: Moved to...
* config/bfin/bfin.cc: ...here.
* config/bpf/bpf.c: Moved to...
* config/bpf/bpf.cc: ...here.
* config/bpf/coreout.c: Moved to...
* config/bpf/coreout.cc: ...here.
* config/c6x/c6x.c: Moved to...
* config/c6x/c6x.cc: ...here.
* config/cr16/cr16.c: Moved to...
* config/cr16/cr16.cc: ...here.
* config/cris/cris.c: Moved to...
* config/cris/cris.cc: ...here.
* config/csky/csky.c: Moved to...
* config/csky/csky.cc: ...here.
* config/darwin-c.c: Moved to...
* config/darwin-c.cc: ...here.
* config/darwin-d.c: Moved to...
* config/darwin-d.cc: ...here.
* config/darwin-driver.c: Moved to...
* config/darwin-driver.cc: ...here.
* config/darwin-f.c: Moved to...
* config/darwin-f.cc: ...here.
* config/darwin.c: Moved to...
* config/darwin.cc: ...here.
* config/default-c.c: Moved to...
* config/default-c.cc: ...here.
* config/default-d.c: Moved to...
* config/default-d.cc: ...here.
* config/dragonfly-d.c: Moved to...
* config/dragonfly-d.cc: ...here.
* config/epiphany/epiphany.c: Moved to...
* config/epiphany/epiphany.cc: ...here.
* config/epiphany/mode-switch-use.c: Moved to...
* config/epiphany/mode-switch-use.cc: ...here.
* config/epiphany/resolve-sw-modes.c: Moved to...
* config/epiphany/resolve-sw-modes.cc: ...here.
* config/fr30/fr30.c: Moved to...
* config/fr30/fr30.cc: ...here.
* config/freebsd-d.c: Moved to...
* config/freebsd-d.cc: ...here.
* config/frv/frv.c: Moved to...
* config/frv/frv.cc: ...here.
* config/ft32/ft32.c: Moved to...
* config/ft32/ft32.cc: ...here.
* config/gcn/driver-gcn.c: Moved to...
* config/gcn/driver-gcn.cc: ...here.
* config/gcn/gcn-run.c: Moved to...
* config/gcn/gcn-run.cc: ...here.
* config/gcn/gcn-tree.c: Moved to...
* config/gcn/gcn-tree.cc: ...here.
* config/gcn/gcn.c: Moved to...
* config/gcn/gcn.cc: ...here.
* config/gcn/mkoffload.c: Moved to...
* config/gcn/mkoffload.cc: ...here.
* config/glibc-c.c: Moved to...
* config/glibc-c.cc: ...here.
* config/glibc-d.c: Moved to...
* config/glibc-d.cc: ...here.
* config/h8300/h8300.c: Moved to...
* config/h8300/h8300.cc: ...here.
* config/host-darwin.c: Moved to...
* config/host-darwin.cc: ...here.
* config/host-hpux.c: Moved to...
* config/host-hpux.cc: ...here.
* config/host-linux.c: Moved to...
* config/host-linux.cc: ...here.
* config/host-netbsd.c: Moved to...
* config/host-netbsd.cc: ...here.
* config/host-openbsd.c: Moved to...
* config/host-openbsd.cc: ...here.
* config/host-solaris.c: Moved to...
* config/host-solaris.cc: ...here.
* config/i386/djgpp.c: Moved to...
* config/i386/djgpp.cc: ...here.
* config/i386/driver-i386.c: Moved to...
* config/i386/driver-i386.cc: ...here.
* config/i386/driver-mingw32.c: Moved to...
* config/i386/driver-mingw32.cc: ...here.
* config/i386/gnu-property.c: Moved to...
* config/i386/gnu-property.cc: ...here.
* config/i386/host-cygwin.c: Moved to...
* config/i386/host-cygwin.cc: ...here.
* config/i386/host-i386-darwin.c: Moved to...
* config/i386/host-i386-darwin.cc: ...here.
* config/i386/host-mingw32.c: Moved to...
* config/i386/host-mingw32.cc: ...here.
* config/i386/i386-builtins.c: Moved to...
* config/i386/i386-builtins.cc: ...here.
* config/i386/i386-c.c: Moved to...
* config/i386/i386-c.cc: ...here.
* config/i386/i386-d.c: Moved to...
* config/i386/i386-d.cc: ...here.
* config/i386/i386-expand.c: Moved to...
* config/i386/i386-expand.cc: ...here.
* config/i386/i386-features.c: Moved to...
* config/i386/i386-features.cc: ...here.
* config/i386/i386-options.c: Moved to...
* config/i386/i386-options.cc: ...here.
* config/i386/i386.c: Moved to...
* config/i386/i386.cc: ...here.
* config/i386/intelmic-mkoffload.c: Moved to...
* config/i386/intelmic-mkoffload.cc: ...here.
* config/i386/msformat-c.c: Moved to...
* config/i386/msformat-c.cc: ...here.
* config/i386/winnt-cxx.c: Moved to...
* config/i386/winnt-cxx.cc: ...here.
* config/i386/winnt-d.c: Moved to...
* config/i386/winnt-d.cc: ...here.
* config/i386/winnt-stubs.c: Moved to...
* config/i386/winnt-stubs.cc: ...here.
* config/i386/winnt.c: Moved to...
* config/i386/winnt.cc: ...here.
* config/i386/x86-tune-sched-atom.c: Moved to...
* config/i386/x86-tune-sched-atom.cc: ...here.
* config/i386/x86-tune-sched-bd.c: Moved to...
* config/i386/x86-tune-sched-bd.cc: ...here.
* config/i386/x86-tune-sched-core.c: Moved to...
* config/i386/x86-tune-sched-core.cc: ...here.
* config/i386/x86-tune-sched.c: Moved to...
* config/i386/x86-tune-sched.cc: ...here.
* config/ia64/ia64-c.c: Moved to...
* config/ia64/ia64-c.cc: ...here.
* config/ia64/ia64.c: Moved to...
* config/ia64/ia64.cc: ...here.
* config/iq2000/iq2000.c: Moved to...
* config/iq2000/iq2000.cc: ...here.
* config/linux.c: Moved to...
* config/linux.cc: ...here.
* config/lm32/lm32.c: Moved to...
* config/lm32/lm32.cc: ...here.
* config/m32c/m32c-pragma.c: Moved to...
* config/m32c/m32c-pragma.cc: ...here.
* config/m32c/m32c.c: Moved to...
* config/m32c/m32c.cc: ...here.
* config/m32r/m32r.c: Moved to...
* config/m32r/m32r.cc: ...here.
* config/m68k/m68k.c: Moved to...
* config/m68k/m68k.cc: ...here.
* config/mcore/mcore.c: Moved to...
* config/mcore/mcore.cc: ...here.
* config/microblaze/microblaze-c.c: Moved to...
* config/microblaze/microblaze-c.cc: ...here.
* config/microblaze/microblaze.c: Moved to...
* config/microblaze/microblaze.cc: ...here.
* config/mips/driver-native.c: Moved to...
* config/mips/driver-native.cc: ...here.
* config/mips/frame-header-opt.c: Moved to...
* config/mips/frame-header-opt.cc: ...here.
* config/mips/mips-d.c: Moved to...
* config/mips/mips-d.cc: ...here.
* config/mips/mips.c: Moved to...
* config/mips/mips.cc: ...here.
* config/mmix/mmix.c: Moved to...
* config/mmix/mmix.cc: ...here.
* config/mn10300/mn10300.c: Moved to...
* config/mn10300/mn10300.cc: ...here.
* config/moxie/moxie.c: Moved to...
* config/moxie/moxie.cc: ...here.
* config/msp430/driver-msp430.c: Moved to...
* config/msp430/driver-msp430.cc: ...here.
* config/msp430/msp430-c.c: Moved to...
* config/msp430/msp430-c.cc: ...here.
* config/msp430/msp430-devices.c: Moved to...
* config/msp430/msp430-devices.cc: ...here.
* config/msp430/msp430.c: Moved to...
* config/msp430/msp430.cc: ...here.
* config/nds32/nds32-cost.c: Moved to...
* config/nds32/nds32-cost.cc: ...here.
* config/nds32/nds32-fp-as-gp.c: Moved to...
* config/nds32/nds32-fp-as-gp.cc: ...here.
* config/nds32/nds32-intrinsic.c: Moved to...
* config/nds32/nds32-intrinsic.cc: ...here.
* config/nds32/nds32-isr.c: Moved to...
* config/nds32/nds32-isr.cc: ...here.
* config/nds32/nds32-md-auxiliary.c: Moved to...
* config/nds32/nds32-md-auxiliary.cc: ...here.
* config/nds32/nds32-memory-manipulation.c: Moved to...
* config/nds32/nds32-memory-manipulation.cc: ...here.
* config/nds32/nds32-pipelines-auxiliary.c: Moved to...
* config/nds32/nds32-pipelines-auxiliary.cc: ...here.
* config/nds32/nds32-predicates.c: Moved to...
* config/nds32/nds32-predicates.cc: ...here.
* config/nds32/nds32-relax-opt.c: Moved to...
* config/nds32/nds32-relax-opt.cc: ...here.
* config/nds32/nds32-utils.c: Moved to...
* config/nds32/nds32-utils.cc: ...here.
* config/nds32/nds32.c: Moved to...
* config/nds32/nds32.cc: ...here.
* config/netbsd-d.c: Moved to...
* config/netbsd-d.cc: ...here.
* config/netbsd.c: Moved to...
* config/netbsd.cc: ...here.
* config/nios2/nios2.c: Moved to...
* config/nios2/nios2.cc: ...here.
* config/nvptx/mkoffload.c: Moved to...
* config/nvptx/mkoffload.cc: ...here.
* config/nvptx/nvptx-c.c: Moved to...
* config/nvptx/nvptx-c.cc: ...here.
* config/nvptx/nvptx.c: Moved to...
* config/nvptx/nvptx.cc: ...here.
* config/openbsd-d.c: Moved to...
* config/openbsd-d.cc: ...here.
* config/or1k/or1k.c: Moved to...
* config/or1k/or1k.cc: ...here.
* config/pa/pa-d.c: Moved to...
* config/pa/pa-d.cc: ...here.
* config/pa/pa.c: Moved to...
* config/pa/pa.cc: ...here.
* config/pdp11/pdp11.c: Moved to...
* config/pdp11/pdp11.cc: ...here.
* config/pru/pru-passes.c: Moved to...
* config/pru/pru-passes.cc: ...here.
* config/pru/pru-pragma.c: Moved to...
* config/pru/pru-pragma.cc: ...here.
* config/pru/pru.c: Moved to...
* config/pru/pru.cc: ...here.
* config/riscv/riscv-builtins.c: Moved to...
* config/riscv/riscv-builtins.cc: ...here.
* config/riscv/riscv-c.c: Moved to...
* config/riscv/riscv-c.cc: ...here.
* config/riscv/riscv-d.c: Moved to...
* config/riscv/riscv-d.cc: ...here.
* config/riscv/riscv-shorten-memrefs.c: Moved to...
* config/riscv/riscv-shorten-memrefs.cc: ...here.
* config/riscv/riscv-sr.c: Moved to...
* config/riscv/riscv-sr.cc: ...here.
* config/riscv/riscv.c: Moved to...
* config/riscv/riscv.cc: ...here.
* config/rl78/rl78-c.c: Moved to...
* config/rl78/rl78-c.cc: ...here.
* config/rl78/rl78.c: Moved to...
* config/rl78/rl78.cc: ...here.
* config/rs6000/driver-rs6000.c: Moved to...
* config/rs6000/driver-rs6000.cc: ...here.
* config/rs6000/host-darwin.c: Moved to...
* config/rs6000/host-darwin.cc: ...here.
* config/rs6000/host-ppc64-darwin.c: Moved to...
* config/rs6000/host-ppc64-darwin.cc: ...here.
* config/rs6000/rbtree.c: Moved to...
* config/rs6000/rbtree.cc: ...here.
* config/rs6000/rs6000-c.c: Moved to...
* config/rs6000/rs6000-c.cc: ...here.
* config/rs6000/rs6000-call.c: Moved to...
* config/rs6000/rs6000-call.cc: ...here.
* config/rs6000/rs6000-d.c: Moved to...
* config/rs6000/rs6000-d.cc: ...here.
* config/rs6000/rs6000-gen-builtins.c: Moved to...
* config/rs6000/rs6000-gen-builtins.cc: ...here.
* config/rs6000/rs6000-linux.c: Moved to...
* config/rs6000/rs6000-linux.cc: ...here.
* config/rs6000/rs6000-logue.c: Moved to...
* config/rs6000/rs6000-logue.cc: ...here.
* config/rs6000/rs6000-p8swap.c: Moved to...
* config/rs6000/rs6000-p8swap.cc: ...here.
* config/rs6000/rs6000-pcrel-opt.c: Moved to...
* config/rs6000/rs6000-pcrel-opt.cc: ...here.
* config/rs6000/rs6000-string.c: Moved to...
* config/rs6000/rs6000-string.cc: ...here.
* config/rs6000/rs6000.c: Moved to...
* config/rs6000/rs6000.cc: ...here.
* config/rx/rx.c: Moved to...
* config/rx/rx.cc: ...here.
* config/s390/driver-native.c: Moved to...
* config/s390/driver-native.cc: ...here.
* config/s390/s390-c.c: Moved to...
* config/s390/s390-c.cc: ...here.
* config/s390/s390-d.c: Moved to...
* config/s390/s390-d.cc: ...here.
* config/s390/s390.c: Moved to...
* config/s390/s390.cc: ...here.
* config/sh/divtab-sh4-300.c: Moved to...
* config/sh/divtab-sh4-300.cc: ...here.
* config/sh/divtab-sh4.c: Moved to...
* config/sh/divtab-sh4.cc: ...here.
* config/sh/divtab.c: Moved to...
* config/sh/divtab.cc: ...here.
* config/sh/sh-c.c: Moved to...
* config/sh/sh-c.cc: ...here.
* config/sh/sh.c: Moved to...
* config/sh/sh.cc: ...here.
* config/sol2-c.c: Moved to...
* config/sol2-c.cc: ...here.
* config/sol2-cxx.c: Moved to...
* config/sol2-cxx.cc: ...here.
* config/sol2-d.c: Moved to...
* config/sol2-d.cc: ...here.
* config/sol2-stubs.c: Moved to...
* config/sol2-stubs.cc: ...here.
* config/sol2.c: Moved to...
* config/sol2.cc: ...here.
* config/sparc/driver-sparc.c: Moved to...
* config/sparc/driver-sparc.cc: ...here.
* config/sparc/sparc-c.c: Moved to...
* config/sparc/sparc-c.cc: ...here.
* config/sparc/sparc-d.c: Moved to...
* config/sparc/sparc-d.cc: ...here.
* config/sparc/sparc.c: Moved to...
* config/sparc/sparc.cc: ...here.
* config/stormy16/stormy16.c: Moved to...
* config/stormy16/stormy16.cc: ...here.
* config/tilegx/mul-tables.c: Moved to...
* config/tilegx/mul-tables.cc: ...here.
* config/tilegx/tilegx-c.c: Moved to...
* config/tilegx/tilegx-c.cc: ...here.
* config/tilegx/tilegx.c: Moved to...
* config/tilegx/tilegx.cc: ...here.
* config/tilepro/mul-tables.c: Moved to...
* config/tilepro/mul-tables.cc: ...here.
* config/tilepro/tilepro-c.c: Moved to...
* config/tilepro/tilepro-c.cc: ...here.
* config/tilepro/tilepro.c: Moved to...
* config/tilepro/tilepro.cc: ...here.
* config/v850/v850-c.c: Moved to...
* config/v850/v850-c.cc: ...here.
* config/v850/v850.c: Moved to...
* config/v850/v850.cc: ...here.
* config/vax/vax.c: Moved to...
* config/vax/vax.cc: ...here.
* config/visium/visium.c: Moved to...
* config/visium/visium.cc: ...here.
* config/vms/vms-c.c: Moved to...
* config/vms/vms-c.cc: ...here.
* config/vms/vms-f.c: Moved to...
* config/vms/vms-f.cc: ...here.
* config/vms/vms.c: Moved to...
* config/vms/vms.cc: ...here.
* config/vxworks-c.c: Moved to...
* config/vxworks-c.cc: ...here.
* config/vxworks.c: Moved to...
* config/vxworks.cc: ...here.
* config/winnt-c.c: Moved to...
* config/winnt-c.cc: ...here.
* config/xtensa/xtensa.c: Moved to...
* config/xtensa/xtensa.cc: ...here.
* context.c: Moved to...
* context.cc: ...here.
* convert.c: Moved to...
* convert.cc: ...here.
* coverage.c: Moved to...
* coverage.cc: ...here.
* cppbuiltin.c: Moved to...
* cppbuiltin.cc: ...here.
* cppdefault.c: Moved to...
* cppdefault.cc: ...here.
* cprop.c: Moved to...
* cprop.cc: ...here.
* cse.c: Moved to...
* cse.cc: ...here.
* cselib.c: Moved to...
* cselib.cc: ...here.
* ctfc.c: Moved to...
* ctfc.cc: ...here.
* ctfout.c: Moved to...
* ctfout.cc: ...here.
* data-streamer-in.c: Moved to...
* data-streamer-in.cc: ...here.
* data-streamer-out.c: Moved to...
* data-streamer-out.cc: ...here.
* data-streamer.c: Moved to...
* data-streamer.cc: ...here.
* dbgcnt.c: Moved to...
* dbgcnt.cc: ...here.
* dbxout.c: Moved to...
* dbxout.cc: ...here.
* dce.c: Moved to...
* dce.cc: ...here.
* ddg.c: Moved to...
* ddg.cc: ...here.
* debug.c: Moved to...
* debug.cc: ...here.
* df-core.c: Moved to...
* df-core.cc: ...here.
* df-problems.c: Moved to...
* df-problems.cc: ...here.
* df-scan.c: Moved to...
* df-scan.cc: ...here.
* dfp.c: Moved to...
* dfp.cc: ...here.
* diagnostic-color.c: Moved to...
* diagnostic-color.cc: ...here.
* diagnostic-show-locus.c: Moved to...
* diagnostic-show-locus.cc: ...here.
* diagnostic-spec.c: Moved to...
* diagnostic-spec.cc: ...here.
* diagnostic.c: Moved to...
* diagnostic.cc: ...here.
* dojump.c: Moved to...
* dojump.cc: ...here.
* dominance.c: Moved to...
* dominance.cc: ...here.
* domwalk.c: Moved to...
* domwalk.cc: ...here.
* double-int.c: Moved to...
* double-int.cc: ...here.
* dse.c: Moved to...
* dse.cc: ...here.
* dumpfile.c: Moved to...
* dumpfile.cc: ...here.
* dwarf2asm.c: Moved to...
* dwarf2asm.cc: ...here.
* dwarf2cfi.c: Moved to...
* dwarf2cfi.cc: ...here.
* dwarf2ctf.c: Moved to...
* dwarf2ctf.cc: ...here.
* dwarf2out.c: Moved to...
* dwarf2out.cc: ...here.
* early-remat.c: Moved to...
* early-remat.cc: ...here.
* edit-context.c: Moved to...
* edit-context.cc: ...here.
* emit-rtl.c: Moved to...
* emit-rtl.cc: ...here.
* errors.c: Moved to...
* errors.cc: ...here.
* et-forest.c: Moved to...
* et-forest.cc: ...here.
* except.c: Moved to...
* except.cc: ...here.
* explow.c: Moved to...
* explow.cc: ...here.
* expmed.c: Moved to...
* expmed.cc: ...here.
* expr.c: Moved to...
* expr.cc: ...here.
* fibonacci_heap.c: Moved to...
* fibonacci_heap.cc: ...here.
* file-find.c: Moved to...
* file-find.cc: ...here.
* file-prefix-map.c: Moved to...
* file-prefix-map.cc: ...here.
* final.c: Moved to...
* final.cc: ...here.
* fixed-value.c: Moved to...
* fixed-value.cc: ...here.
* fold-const-call.c: Moved to...
* fold-const-call.cc: ...here.
* fold-const.c: Moved to...
* fold-const.cc: ...here.
* fp-test.c: Moved to...
* fp-test.cc: ...here.
* function-tests.c: Moved to...
* function-tests.cc: ...here.
* function.c: Moved to...
* function.cc: ...here.
* fwprop.c: Moved to...
* fwprop.cc: ...here.
* gcc-ar.c: Moved to...
* gcc-ar.cc: ...here.
* gcc-main.c: Moved to...
* gcc-main.cc: ...here.
* gcc-rich-location.c: Moved to...
* gcc-rich-location.cc: ...here.
* gcc.c: Moved to...
* gcc.cc: ...here.
* gcov-dump.c: Moved to...
* gcov-dump.cc: ...here.
* gcov-io.c: Moved to...
* gcov-io.cc: ...here.
* gcov-tool.c: Moved to...
* gcov-tool.cc: ...here.
* gcov.c: Moved to...
* gcov.cc: ...here.
* gcse-common.c: Moved to...
* gcse-common.cc: ...here.
* gcse.c: Moved to...
* gcse.cc: ...here.
* genattr-common.c: Moved to...
* genattr-common.cc: ...here.
* genattr.c: Moved to...
* genattr.cc: ...here.
* genattrtab.c: Moved to...
* genattrtab.cc: ...here.
* genautomata.c: Moved to...
* genautomata.cc: ...here.
* gencfn-macros.c: Moved to...
* gencfn-macros.cc: ...here.
* gencheck.c: Moved to...
* gencheck.cc: ...here.
* genchecksum.c: Moved to...
* genchecksum.cc: ...here.
* gencodes.c: Moved to...
* gencodes.cc: ...here.
* genconditions.c: Moved to...
* genconditions.cc: ...here.
* genconfig.c: Moved to...
* genconfig.cc: ...here.
* genconstants.c: Moved to...
* genconstants.cc: ...here.
* genemit.c: Moved to...
* genemit.cc: ...here.
* genenums.c: Moved to...
* genenums.cc: ...here.
* generic-match-head.c: Moved to...
* generic-match-head.cc: ...here.
* genextract.c: Moved to...
* genextract.cc: ...here.
* genflags.c: Moved to...
* genflags.cc: ...here.
* gengenrtl.c: Moved to...
* gengenrtl.cc: ...here.
* gengtype-parse.c: Moved to...
* gengtype-parse.cc: ...here.
* gengtype-state.c: Moved to...
* gengtype-state.cc: ...here.
* gengtype.c: Moved to...
* gengtype.cc: ...here.
* genhooks.c: Moved to...
* genhooks.cc: ...here.
* genmatch.c: Moved to...
* genmatch.cc: ...here.
* genmddeps.c: Moved to...
* genmddeps.cc: ...here.
* genmddump.c: Moved to...
* genmddump.cc: ...here.
* genmodes.c: Moved to...
* genmodes.cc: ...here.
* genopinit.c: Moved to...
* genopinit.cc: ...here.
* genoutput.c: Moved to...
* genoutput.cc: ...here.
* genpeep.c: Moved to...
* genpeep.cc: ...here.
* genpreds.c: Moved to...
* genpreds.cc: ...here.
* genrecog.c: Moved to...
* genrecog.cc: ...here.
* gensupport.c: Moved to...
* gensupport.cc: ...here.
* gentarget-def.c: Moved to...
* gentarget-def.cc: ...here.
* genversion.c: Moved to...
* genversion.cc: ...here.
* ggc-common.c: Moved to...
* ggc-common.cc: ...here.
* ggc-none.c: Moved to...
* ggc-none.cc: ...here.
* ggc-page.c: Moved to...
* ggc-page.cc: ...here.
* ggc-tests.c: Moved to...
* ggc-tests.cc: ...here.
* gimple-builder.c: Moved to...
* gimple-builder.cc: ...here.
* gimple-expr.c: Moved to...
* gimple-expr.cc: ...here.
* gimple-fold.c: Moved to...
* gimple-fold.cc: ...here.
* gimple-iterator.c: Moved to...
* gimple-iterator.cc: ...here.
* gimple-laddress.c: Moved to...
* gimple-laddress.cc: ...here.
* gimple-loop-jam.c: Moved to...
* gimple-loop-jam.cc: ...here.
* gimple-low.c: Moved to...
* gimple-low.cc: ...here.
* gimple-match-head.c: Moved to...
* gimple-match-head.cc: ...here.
* gimple-pretty-print.c: Moved to...
* gimple-pretty-print.cc: ...here.
* gimple-ssa-backprop.c: Moved to...
* gimple-ssa-backprop.cc: ...here.
* gimple-ssa-evrp-analyze.c: Moved to...
* gimple-ssa-evrp-analyze.cc: ...here.
* gimple-ssa-evrp.c: Moved to...
* gimple-ssa-evrp.cc: ...here.
* gimple-ssa-isolate-paths.c: Moved to...
* gimple-ssa-isolate-paths.cc: ...here.
* gimple-ssa-nonnull-compare.c: Moved to...
* gimple-ssa-nonnull-compare.cc: ...here.
* gimple-ssa-split-paths.c: Moved to...
* gimple-ssa-split-paths.cc: ...here.
* gimple-ssa-sprintf.c: Moved to...
* gimple-ssa-sprintf.cc: ...here.
* gimple-ssa-store-merging.c: Moved to...
* gimple-ssa-store-merging.cc: ...here.
* gimple-ssa-strength-reduction.c: Moved to...
* gimple-ssa-strength-reduction.cc: ...here.
* gimple-ssa-warn-alloca.c: Moved to...
* gimple-ssa-warn-alloca.cc: ...here.
* gimple-ssa-warn-restrict.c: Moved to...
* gimple-ssa-warn-restrict.cc: ...here.
* gimple-streamer-in.c: Moved to...
* gimple-streamer-in.cc: ...here.
* gimple-streamer-out.c: Moved to...
* gimple-streamer-out.cc: ...here.
* gimple-walk.c: Moved to...
* gimple-walk.cc: ...here.
* gimple-warn-recursion.c: Moved to...
* gimple-warn-recursion.cc: ...here.
* gimple.c: Moved to...
* gimple.cc: ...here.
* gimplify-me.c: Moved to...
* gimplify-me.cc: ...here.
* gimplify.c: Moved to...
* gimplify.cc: ...here.
* godump.c: Moved to...
* godump.cc: ...here.
* graph.c: Moved to...
* graph.cc: ...here.
* graphds.c: Moved to...
* graphds.cc: ...here.
* graphite-dependences.c: Moved to...
* graphite-dependences.cc: ...here.
* graphite-isl-ast-to-gimple.c: Moved to...
* graphite-isl-ast-to-gimple.cc: ...here.
* graphite-optimize-isl.c: Moved to...
* graphite-optimize-isl.cc: ...here.
* graphite-poly.c: Moved to...
* graphite-poly.cc: ...here.
* graphite-scop-detection.c: Moved to...
* graphite-scop-detection.cc: ...here.
* graphite-sese-to-poly.c: Moved to...
* graphite-sese-to-poly.cc: ...here.
* graphite.c: Moved to...
* graphite.cc: ...here.
* haifa-sched.c: Moved to...
* haifa-sched.cc: ...here.
* hash-map-tests.c: Moved to...
* hash-map-tests.cc: ...here.
* hash-set-tests.c: Moved to...
* hash-set-tests.cc: ...here.
* hash-table.c: Moved to...
* hash-table.cc: ...here.
* hooks.c: Moved to...
* hooks.cc: ...here.
* host-default.c: Moved to...
* host-default.cc: ...here.
* hw-doloop.c: Moved to...
* hw-doloop.cc: ...here.
* hwint.c: Moved to...
* hwint.cc: ...here.
* ifcvt.c: Moved to...
* ifcvt.cc: ...here.
* inchash.c: Moved to...
* inchash.cc: ...here.
* incpath.c: Moved to...
* incpath.cc: ...here.
* init-regs.c: Moved to...
* init-regs.cc: ...here.
* input.c: Moved to...
* input.cc: ...here.
* internal-fn.c: Moved to...
* internal-fn.cc: ...here.
* intl.c: Moved to...
* intl.cc: ...here.
* ipa-comdats.c: Moved to...
* ipa-comdats.cc: ...here.
* ipa-cp.c: Moved to...
* ipa-cp.cc: ...here.
* ipa-devirt.c: Moved to...
* ipa-devirt.cc: ...here.
* ipa-fnsummary.c: Moved to...
* ipa-fnsummary.cc: ...here.
* ipa-icf-gimple.c: Moved to...
* ipa-icf-gimple.cc: ...here.
* ipa-icf.c: Moved to...
* ipa-icf.cc: ...here.
* ipa-inline-analysis.c: Moved to...
* ipa-inline-analysis.cc: ...here.
* ipa-inline-transform.c: Moved to...
* ipa-inline-transform.cc: ...here.
* ipa-inline.c: Moved to...
* ipa-inline.cc: ...here.
* ipa-modref-tree.c: Moved to...
* ipa-modref-tree.cc: ...here.
* ipa-modref.c: Moved to...
* ipa-modref.cc: ...here.
* ipa-param-manipulation.c: Moved to...
* ipa-param-manipulation.cc: ...here.
* ipa-polymorphic-call.c: Moved to...
* ipa-polymorphic-call.cc: ...here.
* ipa-predicate.c: Moved to...
* ipa-predicate.cc: ...here.
* ipa-profile.c: Moved to...
* ipa-profile.cc: ...here.
* ipa-prop.c: Moved to...
* ipa-prop.cc: ...here.
* ipa-pure-const.c: Moved to...
* ipa-pure-const.cc: ...here.
* ipa-ref.c: Moved to...
* ipa-ref.cc: ...here.
* ipa-reference.c: Moved to...
* ipa-reference.cc: ...here.
* ipa-split.c: Moved to...
* ipa-split.cc: ...here.
* ipa-sra.c: Moved to...
* ipa-sra.cc: ...here.
* ipa-utils.c: Moved to...
* ipa-utils.cc: ...here.
* ipa-visibility.c: Moved to...
* ipa-visibility.cc: ...here.
* ipa.c: Moved to...
* ipa.cc: ...here.
* ira-build.c: Moved to...
* ira-build.cc: ...here.
* ira-color.c: Moved to...
* ira-color.cc: ...here.
* ira-conflicts.c: Moved to...
* ira-conflicts.cc: ...here.
* ira-costs.c: Moved to...
* ira-costs.cc: ...here.
* ira-emit.c: Moved to...
* ira-emit.cc: ...here.
* ira-lives.c: Moved to...
* ira-lives.cc: ...here.
* ira.c: Moved to...
* ira.cc: ...here.
* jump.c: Moved to...
* jump.cc: ...here.
* langhooks.c: Moved to...
* langhooks.cc: ...here.
* lcm.c: Moved to...
* lcm.cc: ...here.
* lists.c: Moved to...
* lists.cc: ...here.
* loop-doloop.c: Moved to...
* loop-doloop.cc: ...here.
* loop-init.c: Moved to...
* loop-init.cc: ...here.
* loop-invariant.c: Moved to...
* loop-invariant.cc: ...here.
* loop-iv.c: Moved to...
* loop-iv.cc: ...here.
* loop-unroll.c: Moved to...
* loop-unroll.cc: ...here.
* lower-subreg.c: Moved to...
* lower-subreg.cc: ...here.
* lra-assigns.c: Moved to...
* lra-assigns.cc: ...here.
* lra-coalesce.c: Moved to...
* lra-coalesce.cc: ...here.
* lra-constraints.c: Moved to...
* lra-constraints.cc: ...here.
* lra-eliminations.c: Moved to...
* lra-eliminations.cc: ...here.
* lra-lives.c: Moved to...
* lra-lives.cc: ...here.
* lra-remat.c: Moved to...
* lra-remat.cc: ...here.
* lra-spills.c: Moved to...
* lra-spills.cc: ...here.
* lra.c: Moved to...
* lra.cc: ...here.
* lto-cgraph.c: Moved to...
* lto-cgraph.cc: ...here.
* lto-compress.c: Moved to...
* lto-compress.cc: ...here.
* lto-opts.c: Moved to...
* lto-opts.cc: ...here.
* lto-section-in.c: Moved to...
* lto-section-in.cc: ...here.
* lto-section-out.c: Moved to...
* lto-section-out.cc: ...here.
* lto-streamer-in.c: Moved to...
* lto-streamer-in.cc: ...here.
* lto-streamer-out.c: Moved to...
* lto-streamer-out.cc: ...here.
* lto-streamer.c: Moved to...
* lto-streamer.cc: ...here.
* lto-wrapper.c: Moved to...
* lto-wrapper.cc: ...here.
* main.c: Moved to...
* main.cc: ...here.
* mcf.c: Moved to...
* mcf.cc: ...here.
* mode-switching.c: Moved to...
* mode-switching.cc: ...here.
* modulo-sched.c: Moved to...
* modulo-sched.cc: ...here.
* multiple_target.c: Moved to...
* multiple_target.cc: ...here.
* omp-expand.c: Moved to...
* omp-expand.cc: ...here.
* omp-general.c: Moved to...
* omp-general.cc: ...here.
* omp-low.c: Moved to...
* omp-low.cc: ...here.
* omp-offload.c: Moved to...
* omp-offload.cc: ...here.
* omp-simd-clone.c: Moved to...
* omp-simd-clone.cc: ...here.
* opt-suggestions.c: Moved to...
* opt-suggestions.cc: ...here.
* optabs-libfuncs.c: Moved to...
* optabs-libfuncs.cc: ...here.
* optabs-query.c: Moved to...
* optabs-query.cc: ...here.
* optabs-tree.c: Moved to...
* optabs-tree.cc: ...here.
* optabs.c: Moved to...
* optabs.cc: ...here.
* opts-common.c: Moved to...
* opts-common.cc: ...here.
* opts-global.c: Moved to...
* opts-global.cc: ...here.
* opts.c: Moved to...
* opts.cc: ...here.
* passes.c: Moved to...
* passes.cc: ...here.
* plugin.c: Moved to...
* plugin.cc: ...here.
* postreload-gcse.c: Moved to...
* postreload-gcse.cc: ...here.
* postreload.c: Moved to...
* postreload.cc: ...here.
* predict.c: Moved to...
* predict.cc: ...here.
* prefix.c: Moved to...
* prefix.cc: ...here.
* pretty-print.c: Moved to...
* pretty-print.cc: ...here.
* print-rtl-function.c: Moved to...
* print-rtl-function.cc: ...here.
* print-rtl.c: Moved to...
* print-rtl.cc: ...here.
* print-tree.c: Moved to...
* print-tree.cc: ...here.
* profile-count.c: Moved to...
* profile-count.cc: ...here.
* profile.c: Moved to...
* profile.cc: ...here.
* read-md.c: Moved to...
* read-md.cc: ...here.
* read-rtl-function.c: Moved to...
* read-rtl-function.cc: ...here.
* read-rtl.c: Moved to...
* read-rtl.cc: ...here.
* real.c: Moved to...
* real.cc: ...here.
* realmpfr.c: Moved to...
* realmpfr.cc: ...here.
* recog.c: Moved to...
* recog.cc: ...here.
* ree.c: Moved to...
* ree.cc: ...here.
* reg-stack.c: Moved to...
* reg-stack.cc: ...here.
* regcprop.c: Moved to...
* regcprop.cc: ...here.
* reginfo.c: Moved to...
* reginfo.cc: ...here.
* regrename.c: Moved to...
* regrename.cc: ...here.
* regstat.c: Moved to...
* regstat.cc: ...here.
* reload.c: Moved to...
* reload.cc: ...here.
* reload1.c: Moved to...
* reload1.cc: ...here.
* reorg.c: Moved to...
* reorg.cc: ...here.
* resource.c: Moved to...
* resource.cc: ...here.
* rtl-error.c: Moved to...
* rtl-error.cc: ...here.
* rtl-tests.c: Moved to...
* rtl-tests.cc: ...here.
* rtl.c: Moved to...
* rtl.cc: ...here.
* rtlanal.c: Moved to...
* rtlanal.cc: ...here.
* rtlhash.c: Moved to...
* rtlhash.cc: ...here.
* rtlhooks.c: Moved to...
* rtlhooks.cc: ...here.
* rtx-vector-builder.c: Moved to...
* rtx-vector-builder.cc: ...here.
* run-rtl-passes.c: Moved to...
* run-rtl-passes.cc: ...here.
* sancov.c: Moved to...
* sancov.cc: ...here.
* sanopt.c: Moved to...
* sanopt.cc: ...here.
* sbitmap.c: Moved to...
* sbitmap.cc: ...here.
* sched-deps.c: Moved to...
* sched-deps.cc: ...here.
* sched-ebb.c: Moved to...
* sched-ebb.cc: ...here.
* sched-rgn.c: Moved to...
* sched-rgn.cc: ...here.
* sel-sched-dump.c: Moved to...
* sel-sched-dump.cc: ...here.
* sel-sched-ir.c: Moved to...
* sel-sched-ir.cc: ...here.
* sel-sched.c: Moved to...
* sel-sched.cc: ...here.
* selftest-diagnostic.c: Moved to...
* selftest-diagnostic.cc: ...here.
* selftest-rtl.c: Moved to...
* selftest-rtl.cc: ...here.
* selftest-run-tests.c: Moved to...
* selftest-run-tests.cc: ...here.
* selftest.c: Moved to...
* selftest.cc: ...here.
* sese.c: Moved to...
* sese.cc: ...here.
* shrink-wrap.c: Moved to...
* shrink-wrap.cc: ...here.
* simplify-rtx.c: Moved to...
* simplify-rtx.cc: ...here.
* sparseset.c: Moved to...
* sparseset.cc: ...here.
* spellcheck-tree.c: Moved to...
* spellcheck-tree.cc: ...here.
* spellcheck.c: Moved to...
* spellcheck.cc: ...here.
* sreal.c: Moved to...
* sreal.cc: ...here.
* stack-ptr-mod.c: Moved to...
* stack-ptr-mod.cc: ...here.
* statistics.c: Moved to...
* statistics.cc: ...here.
* stmt.c: Moved to...
* stmt.cc: ...here.
* stor-layout.c: Moved to...
* stor-layout.cc: ...here.
* store-motion.c: Moved to...
* store-motion.cc: ...here.
* streamer-hooks.c: Moved to...
* streamer-hooks.cc: ...here.
* stringpool.c: Moved to...
* stringpool.cc: ...here.
* substring-locations.c: Moved to...
* substring-locations.cc: ...here.
* symtab.c: Moved to...
* symtab.cc: ...here.
* target-globals.c: Moved to...
* target-globals.cc: ...here.
* targhooks.c: Moved to...
* targhooks.cc: ...here.
* timevar.c: Moved to...
* timevar.cc: ...here.
* toplev.c: Moved to...
* toplev.cc: ...here.
* tracer.c: Moved to...
* tracer.cc: ...here.
* trans-mem.c: Moved to...
* trans-mem.cc: ...here.
* tree-affine.c: Moved to...
* tree-affine.cc: ...here.
* tree-call-cdce.c: Moved to...
* tree-call-cdce.cc: ...here.
* tree-cfg.c: Moved to...
* tree-cfg.cc: ...here.
* tree-cfgcleanup.c: Moved to...
* tree-cfgcleanup.cc: ...here.
* tree-chrec.c: Moved to...
* tree-chrec.cc: ...here.
* tree-complex.c: Moved to...
* tree-complex.cc: ...here.
* tree-data-ref.c: Moved to...
* tree-data-ref.cc: ...here.
* tree-dfa.c: Moved to...
* tree-dfa.cc: ...here.
* tree-diagnostic.c: Moved to...
* tree-diagnostic.cc: ...here.
* tree-dump.c: Moved to...
* tree-dump.cc: ...here.
* tree-eh.c: Moved to...
* tree-eh.cc: ...here.
* tree-emutls.c: Moved to...
* tree-emutls.cc: ...here.
* tree-if-conv.c: Moved to...
* tree-if-conv.cc: ...here.
* tree-inline.c: Moved to...
* tree-inline.cc: ...here.
* tree-into-ssa.c: Moved to...
* tree-into-ssa.cc: ...here.
* tree-iterator.c: Moved to...
* tree-iterator.cc: ...here.
* tree-loop-distribution.c: Moved to...
* tree-loop-distribution.cc: ...here.
* tree-nested.c: Moved to...
* tree-nested.cc: ...here.
* tree-nrv.c: Moved to...
* tree-nrv.cc: ...here.
* tree-object-size.c: Moved to...
* tree-object-size.cc: ...here.
* tree-outof-ssa.c: Moved to...
* tree-outof-ssa.cc: ...here.
* tree-parloops.c: Moved to...
* tree-parloops.cc: ...here.
* tree-phinodes.c: Moved to...
* tree-phinodes.cc: ...here.
* tree-predcom.c: Moved to...
* tree-predcom.cc: ...here.
* tree-pretty-print.c: Moved to...
* tree-pretty-print.cc: ...here.
* tree-profile.c: Moved to...
* tree-profile.cc: ...here.
* tree-scalar-evolution.c: Moved to...
* tree-scalar-evolution.cc: ...here.
* tree-sra.c: Moved to...
* tree-sra.cc: ...here.
* tree-ssa-address.c: Moved to...
* tree-ssa-address.cc: ...here.
* tree-ssa-alias.c: Moved to...
* tree-ssa-alias.cc: ...here.
* tree-ssa-ccp.c: Moved to...
* tree-ssa-ccp.cc: ...here.
* tree-ssa-coalesce.c: Moved to...
* tree-ssa-coalesce.cc: ...here.
* tree-ssa-copy.c: Moved to...
* tree-ssa-copy.cc: ...here.
* tree-ssa-dce.c: Moved to...
* tree-ssa-dce.cc: ...here.
* tree-ssa-dom.c: Moved to...
* tree-ssa-dom.cc: ...here.
* tree-ssa-dse.c: Moved to...
* tree-ssa-dse.cc: ...here.
* tree-ssa-forwprop.c: Moved to...
* tree-ssa-forwprop.cc: ...here.
* tree-ssa-ifcombine.c: Moved to...
* tree-ssa-ifcombine.cc: ...here.
* tree-ssa-live.c: Moved to...
* tree-ssa-live.cc: ...here.
* tree-ssa-loop-ch.c: Moved to...
* tree-ssa-loop-ch.cc: ...here.
* tree-ssa-loop-im.c: Moved to...
* tree-ssa-loop-im.cc: ...here.
* tree-ssa-loop-ivcanon.c: Moved to...
* tree-ssa-loop-ivcanon.cc: ...here.
* tree-ssa-loop-ivopts.c: Moved to...
* tree-ssa-loop-ivopts.cc: ...here.
* tree-ssa-loop-manip.c: Moved to...
* tree-ssa-loop-manip.cc: ...here.
* tree-ssa-loop-niter.c: Moved to...
* tree-ssa-loop-niter.cc: ...here.
* tree-ssa-loop-prefetch.c: Moved to...
* tree-ssa-loop-prefetch.cc: ...here.
* tree-ssa-loop-split.c: Moved to...
* tree-ssa-loop-split.cc: ...here.
* tree-ssa-loop-unswitch.c: Moved to...
* tree-ssa-loop-unswitch.cc: ...here.
* tree-ssa-loop.c: Moved to...
* tree-ssa-loop.cc: ...here.
* tree-ssa-math-opts.c: Moved to...
* tree-ssa-math-opts.cc: ...here.
* tree-ssa-operands.c: Moved to...
* tree-ssa-operands.cc: ...here.
* tree-ssa-phiopt.c: Moved to...
* tree-ssa-phiopt.cc: ...here.
* tree-ssa-phiprop.c: Moved to...
* tree-ssa-phiprop.cc: ...here.
* tree-ssa-pre.c: Moved to...
* tree-ssa-pre.cc: ...here.
* tree-ssa-propagate.c: Moved to...
* tree-ssa-propagate.cc: ...here.
* tree-ssa-reassoc.c: Moved to...
* tree-ssa-reassoc.cc: ...here.
* tree-ssa-sccvn.c: Moved to...
* tree-ssa-sccvn.cc: ...here.
* tree-ssa-scopedtables.c: Moved to...
* tree-ssa-scopedtables.cc: ...here.
* tree-ssa-sink.c: Moved to...
* tree-ssa-sink.cc: ...here.
* tree-ssa-strlen.c: Moved to...
* tree-ssa-strlen.cc: ...here.
* tree-ssa-structalias.c: Moved to...
* tree-ssa-structalias.cc: ...here.
* tree-ssa-tail-merge.c: Moved to...
* tree-ssa-tail-merge.cc: ...here.
* tree-ssa-ter.c: Moved to...
* tree-ssa-ter.cc: ...here.
* tree-ssa-threadbackward.c: Moved to...
* tree-ssa-threadbackward.cc: ...here.
* tree-ssa-threadedge.c: Moved to...
* tree-ssa-threadedge.cc: ...here.
* tree-ssa-threadupdate.c: Moved to...
* tree-ssa-threadupdate.cc: ...here.
* tree-ssa-uncprop.c: Moved to...
* tree-ssa-uncprop.cc: ...here.
* tree-ssa-uninit.c: Moved to...
* tree-ssa-uninit.cc: ...here.
* tree-ssa.c: Moved to...
* tree-ssa.cc: ...here.
* tree-ssanames.c: Moved to...
* tree-ssanames.cc: ...here.
* tree-stdarg.c: Moved to...
* tree-stdarg.cc: ...here.
* tree-streamer-in.c: Moved to...
* tree-streamer-in.cc: ...here.
* tree-streamer-out.c: Moved to...
* tree-streamer-out.cc: ...here.
* tree-streamer.c: Moved to...
* tree-streamer.cc: ...here.
* tree-switch-conversion.c: Moved to...
* tree-switch-conversion.cc: ...here.
* tree-tailcall.c: Moved to...
* tree-tailcall.cc: ...here.
* tree-vect-data-refs.c: Moved to...
* tree-vect-data-refs.cc: ...here.
* tree-vect-generic.c: Moved to...
* tree-vect-generic.cc: ...here.
* tree-vect-loop-manip.c: Moved to...
* tree-vect-loop-manip.cc: ...here.
* tree-vect-loop.c: Moved to...
* tree-vect-loop.cc: ...here.
* tree-vect-patterns.c: Moved to...
* tree-vect-patterns.cc: ...here.
* tree-vect-slp-patterns.c: Moved to...
* tree-vect-slp-patterns.cc: ...here.
* tree-vect-slp.c: Moved to...
* tree-vect-slp.cc: ...here.
* tree-vect-stmts.c: Moved to...
* tree-vect-stmts.cc: ...here.
* tree-vector-builder.c: Moved to...
* tree-vector-builder.cc: ...here.
* tree-vectorizer.c: Moved to...
* tree-vectorizer.cc: ...here.
* tree-vrp.c: Moved to...
* tree-vrp.cc: ...here.
* tree.c: Moved to...
* tree.cc: ...here.
* tsan.c: Moved to...
* tsan.cc: ...here.
* typed-splay-tree.c: Moved to...
* typed-splay-tree.cc: ...here.
* ubsan.c: Moved to...
* ubsan.cc: ...here.
* valtrack.c: Moved to...
* valtrack.cc: ...here.
* value-prof.c: Moved to...
* value-prof.cc: ...here.
* var-tracking.c: Moved to...
* var-tracking.cc: ...here.
* varasm.c: Moved to...
* varasm.cc: ...here.
* varpool.c: Moved to...
* varpool.cc: ...here.
* vec-perm-indices.c: Moved to...
* vec-perm-indices.cc: ...here.
* vec.c: Moved to...
* vec.cc: ...here.
* vmsdbgout.c: Moved to...
* vmsdbgout.cc: ...here.
* vr-values.c: Moved to...
* vr-values.cc: ...here.
* vtable-verify.c: Moved to...
* vtable-verify.cc: ...here.
* web.c: Moved to...
* web.cc: ...here.
* xcoffout.c: Moved to...
* xcoffout.cc: ...here.
gcc/c-family/ChangeLog:
* c-ada-spec.c: Moved to...
* c-ada-spec.cc: ...here.
* c-attribs.c: Moved to...
* c-attribs.cc: ...here.
* c-common.c: Moved to...
* c-common.cc: ...here.
* c-cppbuiltin.c: Moved to...
* c-cppbuiltin.cc: ...here.
* c-dump.c: Moved to...
* c-dump.cc: ...here.
* c-format.c: Moved to...
* c-format.cc: ...here.
* c-gimplify.c: Moved to...
* c-gimplify.cc: ...here.
* c-indentation.c: Moved to...
* c-indentation.cc: ...here.
* c-lex.c: Moved to...
* c-lex.cc: ...here.
* c-omp.c: Moved to...
* c-omp.cc: ...here.
* c-opts.c: Moved to...
* c-opts.cc: ...here.
* c-pch.c: Moved to...
* c-pch.cc: ...here.
* c-ppoutput.c: Moved to...
* c-ppoutput.cc: ...here.
* c-pragma.c: Moved to...
* c-pragma.cc: ...here.
* c-pretty-print.c: Moved to...
* c-pretty-print.cc: ...here.
* c-semantics.c: Moved to...
* c-semantics.cc: ...here.
* c-ubsan.c: Moved to...
* c-ubsan.cc: ...here.
* c-warn.c: Moved to...
* c-warn.cc: ...here.
* cppspec.c: Moved to...
* cppspec.cc: ...here.
* stub-objc.c: Moved to...
* stub-objc.cc: ...here.
gcc/c/ChangeLog:
* c-aux-info.c: Moved to...
* c-aux-info.cc: ...here.
* c-convert.c: Moved to...
* c-convert.cc: ...here.
* c-decl.c: Moved to...
* c-decl.cc: ...here.
* c-errors.c: Moved to...
* c-errors.cc: ...here.
* c-fold.c: Moved to...
* c-fold.cc: ...here.
* c-lang.c: Moved to...
* c-lang.cc: ...here.
* c-objc-common.c: Moved to...
* c-objc-common.cc: ...here.
* c-parser.c: Moved to...
* c-parser.cc: ...here.
* c-typeck.c: Moved to...
* c-typeck.cc: ...here.
* gccspec.c: Moved to...
* gccspec.cc: ...here.
* gimple-parser.c: Moved to...
* gimple-parser.cc: ...here.
gcc/cp/ChangeLog:
* call.c: Moved to...
* call.cc: ...here.
* class.c: Moved to...
* class.cc: ...here.
* constexpr.c: Moved to...
* constexpr.cc: ...here.
* cp-gimplify.c: Moved to...
* cp-gimplify.cc: ...here.
* cp-lang.c: Moved to...
* cp-lang.cc: ...here.
* cp-objcp-common.c: Moved to...
* cp-objcp-common.cc: ...here.
* cp-ubsan.c: Moved to...
* cp-ubsan.cc: ...here.
* cvt.c: Moved to...
* cvt.cc: ...here.
* cxx-pretty-print.c: Moved to...
* cxx-pretty-print.cc: ...here.
* decl.c: Moved to...
* decl.cc: ...here.
* decl2.c: Moved to...
* decl2.cc: ...here.
* dump.c: Moved to...
* dump.cc: ...here.
* error.c: Moved to...
* error.cc: ...here.
* except.c: Moved to...
* except.cc: ...here.
* expr.c: Moved to...
* expr.cc: ...here.
* friend.c: Moved to...
* friend.cc: ...here.
* g++spec.c: Moved to...
* g++spec.cc: ...here.
* init.c: Moved to...
* init.cc: ...here.
* lambda.c: Moved to...
* lambda.cc: ...here.
* lex.c: Moved to...
* lex.cc: ...here.
* mangle.c: Moved to...
* mangle.cc: ...here.
* method.c: Moved to...
* method.cc: ...here.
* name-lookup.c: Moved to...
* name-lookup.cc: ...here.
* optimize.c: Moved to...
* optimize.cc: ...here.
* parser.c: Moved to...
* parser.cc: ...here.
* pt.c: Moved to...
* pt.cc: ...here.
* ptree.c: Moved to...
* ptree.cc: ...here.
* rtti.c: Moved to...
* rtti.cc: ...here.
* search.c: Moved to...
* search.cc: ...here.
* semantics.c: Moved to...
* semantics.cc: ...here.
* tree.c: Moved to...
* tree.cc: ...here.
* typeck.c: Moved to...
* typeck.cc: ...here.
* typeck2.c: Moved to...
* typeck2.cc: ...here.
* vtable-class-hierarchy.c: Moved to...
* vtable-class-hierarchy.cc: ...here.
gcc/fortran/ChangeLog:
* arith.c: Moved to...
* arith.cc: ...here.
* array.c: Moved to...
* array.cc: ...here.
* bbt.c: Moved to...
* bbt.cc: ...here.
* check.c: Moved to...
* check.cc: ...here.
* class.c: Moved to...
* class.cc: ...here.
* constructor.c: Moved to...
* constructor.cc: ...here.
* convert.c: Moved to...
* convert.cc: ...here.
* cpp.c: Moved to...
* cpp.cc: ...here.
* data.c: Moved to...
* data.cc: ...here.
* decl.c: Moved to...
* decl.cc: ...here.
* dependency.c: Moved to...
* dependency.cc: ...here.
* dump-parse-tree.c: Moved to...
* dump-parse-tree.cc: ...here.
* error.c: Moved to...
* error.cc: ...here.
* expr.c: Moved to...
* expr.cc: ...here.
* f95-lang.c: Moved to...
* f95-lang.cc: ...here.
* frontend-passes.c: Moved to...
* frontend-passes.cc: ...here.
* gfortranspec.c: Moved to...
* gfortranspec.cc: ...here.
* interface.c: Moved to...
* interface.cc: ...here.
* intrinsic.c: Moved to...
* intrinsic.cc: ...here.
* io.c: Moved to...
* io.cc: ...here.
* iresolve.c: Moved to...
* iresolve.cc: ...here.
* match.c: Moved to...
* match.cc: ...here.
* matchexp.c: Moved to...
* matchexp.cc: ...here.
* misc.c: Moved to...
* misc.cc: ...here.
* module.c: Moved to...
* module.cc: ...here.
* openmp.c: Moved to...
* openmp.cc: ...here.
* options.c: Moved to...
* options.cc: ...here.
* parse.c: Moved to...
* parse.cc: ...here.
* primary.c: Moved to...
* primary.cc: ...here.
* resolve.c: Moved to...
* resolve.cc: ...here.
* scanner.c: Moved to...
* scanner.cc: ...here.
* simplify.c: Moved to...
* simplify.cc: ...here.
* st.c: Moved to...
* st.cc: ...here.
* symbol.c: Moved to...
* symbol.cc: ...here.
* target-memory.c: Moved to...
* target-memory.cc: ...here.
* trans-array.c: Moved to...
* trans-array.cc: ...here.
* trans-common.c: Moved to...
* trans-common.cc: ...here.
* trans-const.c: Moved to...
* trans-const.cc: ...here.
* trans-decl.c: Moved to...
* trans-decl.cc: ...here.
* trans-expr.c: Moved to...
* trans-expr.cc: ...here.
* trans-intrinsic.c: Moved to...
* trans-intrinsic.cc: ...here.
* trans-io.c: Moved to...
* trans-io.cc: ...here.
* trans-openmp.c: Moved to...
* trans-openmp.cc: ...here.
* trans-stmt.c: Moved to...
* trans-stmt.cc: ...here.
* trans-types.c: Moved to...
* trans-types.cc: ...here.
* trans.c: Moved to...
* trans.cc: ...here.
gcc/go/ChangeLog:
* go-backend.c: Moved to...
* go-backend.cc: ...here.
* go-lang.c: Moved to...
* go-lang.cc: ...here.
* gospec.c: Moved to...
* gospec.cc: ...here.
gcc/jit/ChangeLog:
* dummy-frontend.c: Moved to...
* dummy-frontend.cc: ...here.
* jit-builtins.c: Moved to...
* jit-builtins.cc: ...here.
* jit-logging.c: Moved to...
* jit-logging.cc: ...here.
* jit-playback.c: Moved to...
* jit-playback.cc: ...here.
* jit-recording.c: Moved to...
* jit-recording.cc: ...here.
* jit-result.c: Moved to...
* jit-result.cc: ...here.
* jit-spec.c: Moved to...
* jit-spec.cc: ...here.
* jit-tempdir.c: Moved to...
* jit-tempdir.cc: ...here.
* jit-w32.c: Moved to...
* jit-w32.cc: ...here.
* libgccjit.c: Moved to...
* libgccjit.cc: ...here.
gcc/lto/ChangeLog:
* common.c: Moved to...
* common.cc: ...here.
* lto-common.c: Moved to...
* lto-common.cc: ...here.
* lto-dump.c: Moved to...
* lto-dump.cc: ...here.
* lto-lang.c: Moved to...
* lto-lang.cc: ...here.
* lto-object.c: Moved to...
* lto-object.cc: ...here.
* lto-partition.c: Moved to...
* lto-partition.cc: ...here.
* lto-symtab.c: Moved to...
* lto-symtab.cc: ...here.
* lto.c: Moved to...
* lto.cc: ...here.
gcc/objc/ChangeLog:
* objc-act.c: Moved to...
* objc-act.cc: ...here.
* objc-encoding.c: Moved to...
* objc-encoding.cc: ...here.
* objc-gnu-runtime-abi-01.c: Moved to...
* objc-gnu-runtime-abi-01.cc: ...here.
* objc-lang.c: Moved to...
* objc-lang.cc: ...here.
* objc-map.c: Moved to...
* objc-map.cc: ...here.
* objc-next-runtime-abi-01.c: Moved to...
* objc-next-runtime-abi-01.cc: ...here.
* objc-next-runtime-abi-02.c: Moved to...
* objc-next-runtime-abi-02.cc: ...here.
* objc-runtime-shared-support.c: Moved to...
* objc-runtime-shared-support.cc: ...here.
gcc/objcp/ChangeLog:
* objcp-decl.c: Moved to...
* objcp-decl.cc: ...here.
* objcp-lang.c: Moved to...
* objcp-lang.cc: ...here.
libcpp/ChangeLog:
* charset.c: Moved to...
* charset.cc: ...here.
* directives.c: Moved to...
* directives.cc: ...here.
* errors.c: Moved to...
* errors.cc: ...here.
* expr.c: Moved to...
* expr.cc: ...here.
* files.c: Moved to...
* files.cc: ...here.
* identifiers.c: Moved to...
* identifiers.cc: ...here.
* init.c: Moved to...
* init.cc: ...here.
* lex.c: Moved to...
* lex.cc: ...here.
* line-map.c: Moved to...
* line-map.cc: ...here.
* macro.c: Moved to...
* macro.cc: ...here.
* makeucnid.c: Moved to...
* makeucnid.cc: ...here.
* mkdeps.c: Moved to...
* mkdeps.cc: ...here.
* pch.c: Moved to...
* pch.cc: ...here.
* symtab.c: Moved to...
* symtab.cc: ...here.
* traditional.c: Moved to...
* traditional.cc: ...here.
Diffstat (limited to 'gcc/fortran/resolve.c')
-rw-r--r-- | gcc/fortran/resolve.c | 17582 |
1 files changed, 0 insertions, 17582 deletions
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c deleted file mode 100644 index 43eeefe..0000000 --- a/gcc/fortran/resolve.c +++ /dev/null @@ -1,17582 +0,0 @@ -/* Perform type resolution on the various structures. - Copyright (C) 2001-2022 Free Software Foundation, Inc. - Contributed by Andy Vaught - -This file is part of GCC. - -GCC 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, or (at your option) any later -version. - -GCC is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -for more details. - -You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING3. If not see -<http://www.gnu.org/licenses/>. */ - -#include "config.h" -#include "system.h" -#include "coretypes.h" -#include "options.h" -#include "bitmap.h" -#include "gfortran.h" -#include "arith.h" /* For gfc_compare_expr(). */ -#include "dependency.h" -#include "data.h" -#include "target-memory.h" /* for gfc_simplify_transfer */ -#include "constructor.h" - -/* Types used in equivalence statements. */ - -enum seq_type -{ - SEQ_NONDEFAULT, SEQ_NUMERIC, SEQ_CHARACTER, SEQ_MIXED -}; - -/* Stack to keep track of the nesting of blocks as we move through the - code. See resolve_branch() and gfc_resolve_code(). */ - -typedef struct code_stack -{ - struct gfc_code *head, *current; - struct code_stack *prev; - - /* This bitmap keeps track of the targets valid for a branch from - inside this block except for END {IF|SELECT}s of enclosing - blocks. */ - bitmap reachable_labels; -} -code_stack; - -static code_stack *cs_base = NULL; - - -/* Nonzero if we're inside a FORALL or DO CONCURRENT block. */ - -static int forall_flag; -int gfc_do_concurrent_flag; - -/* True when we are resolving an expression that is an actual argument to - a procedure. */ -static bool actual_arg = false; -/* True when we are resolving an expression that is the first actual argument - to a procedure. */ -static bool first_actual_arg = false; - - -/* Nonzero if we're inside a OpenMP WORKSHARE or PARALLEL WORKSHARE block. */ - -static int omp_workshare_flag; - -/* True if we are processing a formal arglist. The corresponding function - resets the flag each time that it is read. */ -static bool formal_arg_flag = false; - -/* True if we are resolving a specification expression. */ -static bool specification_expr = false; - -/* The id of the last entry seen. */ -static int current_entry_id; - -/* We use bitmaps to determine if a branch target is valid. */ -static bitmap_obstack labels_obstack; - -/* True when simplifying a EXPR_VARIABLE argument to an inquiry function. */ -static bool inquiry_argument = false; - - -bool -gfc_is_formal_arg (void) -{ - return formal_arg_flag; -} - -/* Is the symbol host associated? */ -static bool -is_sym_host_assoc (gfc_symbol *sym, gfc_namespace *ns) -{ - for (ns = ns->parent; ns; ns = ns->parent) - { - if (sym->ns == ns) - return true; - } - - return false; -} - -/* Ensure a typespec used is valid; for instance, TYPE(t) is invalid if t is - an ABSTRACT derived-type. If where is not NULL, an error message with that - locus is printed, optionally using name. */ - -static bool -resolve_typespec_used (gfc_typespec* ts, locus* where, const char* name) -{ - if (ts->type == BT_DERIVED && ts->u.derived->attr.abstract) - { - if (where) - { - if (name) - gfc_error ("%qs at %L is of the ABSTRACT type %qs", - name, where, ts->u.derived->name); - else - gfc_error ("ABSTRACT type %qs used at %L", - ts->u.derived->name, where); - } - - return false; - } - - return true; -} - - -static bool -check_proc_interface (gfc_symbol *ifc, locus *where) -{ - /* Several checks for F08:C1216. */ - if (ifc->attr.procedure) - { - gfc_error ("Interface %qs at %L is declared " - "in a later PROCEDURE statement", ifc->name, where); - return false; - } - if (ifc->generic) - { - /* For generic interfaces, check if there is - a specific procedure with the same name. */ - gfc_interface *gen = ifc->generic; - while (gen && strcmp (gen->sym->name, ifc->name) != 0) - gen = gen->next; - if (!gen) - { - gfc_error ("Interface %qs at %L may not be generic", - ifc->name, where); - return false; - } - } - if (ifc->attr.proc == PROC_ST_FUNCTION) - { - gfc_error ("Interface %qs at %L may not be a statement function", - ifc->name, where); - return false; - } - if (gfc_is_intrinsic (ifc, 0, ifc->declared_at) - || gfc_is_intrinsic (ifc, 1, ifc->declared_at)) - ifc->attr.intrinsic = 1; - if (ifc->attr.intrinsic && !gfc_intrinsic_actual_ok (ifc->name, 0)) - { - gfc_error ("Intrinsic procedure %qs not allowed in " - "PROCEDURE statement at %L", ifc->name, where); - return false; - } - if (!ifc->attr.if_source && !ifc->attr.intrinsic && ifc->name[0] != '\0') - { - gfc_error ("Interface %qs at %L must be explicit", ifc->name, where); - return false; - } - return true; -} - - -static void resolve_symbol (gfc_symbol *sym); - - -/* Resolve the interface for a PROCEDURE declaration or procedure pointer. */ - -static bool -resolve_procedure_interface (gfc_symbol *sym) -{ - gfc_symbol *ifc = sym->ts.interface; - - if (!ifc) - return true; - - if (ifc == sym) - { - gfc_error ("PROCEDURE %qs at %L may not be used as its own interface", - sym->name, &sym->declared_at); - return false; - } - if (!check_proc_interface (ifc, &sym->declared_at)) - return false; - - if (ifc->attr.if_source || ifc->attr.intrinsic) - { - /* Resolve interface and copy attributes. */ - resolve_symbol (ifc); - if (ifc->attr.intrinsic) - gfc_resolve_intrinsic (ifc, &ifc->declared_at); - - if (ifc->result) - { - sym->ts = ifc->result->ts; - sym->attr.allocatable = ifc->result->attr.allocatable; - sym->attr.pointer = ifc->result->attr.pointer; - sym->attr.dimension = ifc->result->attr.dimension; - sym->attr.class_ok = ifc->result->attr.class_ok; - sym->as = gfc_copy_array_spec (ifc->result->as); - sym->result = sym; - } - else - { - sym->ts = ifc->ts; - sym->attr.allocatable = ifc->attr.allocatable; - sym->attr.pointer = ifc->attr.pointer; - sym->attr.dimension = ifc->attr.dimension; - sym->attr.class_ok = ifc->attr.class_ok; - sym->as = gfc_copy_array_spec (ifc->as); - } - sym->ts.interface = ifc; - sym->attr.function = ifc->attr.function; - sym->attr.subroutine = ifc->attr.subroutine; - - sym->attr.pure = ifc->attr.pure; - sym->attr.elemental = ifc->attr.elemental; - sym->attr.contiguous = ifc->attr.contiguous; - sym->attr.recursive = ifc->attr.recursive; - sym->attr.always_explicit = ifc->attr.always_explicit; - sym->attr.ext_attr |= ifc->attr.ext_attr; - sym->attr.is_bind_c = ifc->attr.is_bind_c; - /* Copy char length. */ - if (ifc->ts.type == BT_CHARACTER && ifc->ts.u.cl) - { - sym->ts.u.cl = gfc_new_charlen (sym->ns, ifc->ts.u.cl); - if (sym->ts.u.cl->length && !sym->ts.u.cl->resolved - && !gfc_resolve_expr (sym->ts.u.cl->length)) - return false; - } - } - - return true; -} - - -/* Resolve types of formal argument lists. These have to be done early so that - the formal argument lists of module procedures can be copied to the - containing module before the individual procedures are resolved - individually. We also resolve argument lists of procedures in interface - blocks because they are self-contained scoping units. - - Since a dummy argument cannot be a non-dummy procedure, the only - resort left for untyped names are the IMPLICIT types. */ - -void -gfc_resolve_formal_arglist (gfc_symbol *proc) -{ - gfc_formal_arglist *f; - gfc_symbol *sym; - bool saved_specification_expr; - int i; - - if (proc->result != NULL) - sym = proc->result; - else - sym = proc; - - if (gfc_elemental (proc) - || sym->attr.pointer || sym->attr.allocatable - || (sym->as && sym->as->rank != 0)) - { - proc->attr.always_explicit = 1; - sym->attr.always_explicit = 1; - } - - formal_arg_flag = true; - - for (f = proc->formal; f; f = f->next) - { - gfc_array_spec *as; - - sym = f->sym; - - if (sym == NULL) - { - /* Alternate return placeholder. */ - if (gfc_elemental (proc)) - gfc_error ("Alternate return specifier in elemental subroutine " - "%qs at %L is not allowed", proc->name, - &proc->declared_at); - if (proc->attr.function) - gfc_error ("Alternate return specifier in function " - "%qs at %L is not allowed", proc->name, - &proc->declared_at); - continue; - } - else if (sym->attr.procedure && sym->attr.if_source != IFSRC_DECL - && !resolve_procedure_interface (sym)) - return; - - if (strcmp (proc->name, sym->name) == 0) - { - gfc_error ("Self-referential argument " - "%qs at %L is not allowed", sym->name, - &proc->declared_at); - return; - } - - if (sym->attr.if_source != IFSRC_UNKNOWN) - gfc_resolve_formal_arglist (sym); - - if (sym->attr.subroutine || sym->attr.external) - { - if (sym->attr.flavor == FL_UNKNOWN) - gfc_add_flavor (&sym->attr, FL_PROCEDURE, sym->name, &sym->declared_at); - } - else - { - if (sym->ts.type == BT_UNKNOWN && !proc->attr.intrinsic - && (!sym->attr.function || sym->result == sym)) - gfc_set_default_type (sym, 1, sym->ns); - } - - as = sym->ts.type == BT_CLASS && sym->attr.class_ok - ? CLASS_DATA (sym)->as : sym->as; - - saved_specification_expr = specification_expr; - specification_expr = true; - gfc_resolve_array_spec (as, 0); - specification_expr = saved_specification_expr; - - /* We can't tell if an array with dimension (:) is assumed or deferred - shape until we know if it has the pointer or allocatable attributes. - */ - if (as && as->rank > 0 && as->type == AS_DEFERRED - && ((sym->ts.type != BT_CLASS - && !(sym->attr.pointer || sym->attr.allocatable)) - || (sym->ts.type == BT_CLASS - && !(CLASS_DATA (sym)->attr.class_pointer - || CLASS_DATA (sym)->attr.allocatable))) - && sym->attr.flavor != FL_PROCEDURE) - { - as->type = AS_ASSUMED_SHAPE; - for (i = 0; i < as->rank; i++) - as->lower[i] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1); - } - - if ((as && as->rank > 0 && as->type == AS_ASSUMED_SHAPE) - || (as && as->type == AS_ASSUMED_RANK) - || sym->attr.pointer || sym->attr.allocatable || sym->attr.target - || (sym->ts.type == BT_CLASS && sym->attr.class_ok - && (CLASS_DATA (sym)->attr.class_pointer - || CLASS_DATA (sym)->attr.allocatable - || CLASS_DATA (sym)->attr.target)) - || sym->attr.optional) - { - proc->attr.always_explicit = 1; - if (proc->result) - proc->result->attr.always_explicit = 1; - } - - /* If the flavor is unknown at this point, it has to be a variable. - A procedure specification would have already set the type. */ - - if (sym->attr.flavor == FL_UNKNOWN) - gfc_add_flavor (&sym->attr, FL_VARIABLE, sym->name, &sym->declared_at); - - if (gfc_pure (proc)) - { - if (sym->attr.flavor == FL_PROCEDURE) - { - /* F08:C1279. */ - if (!gfc_pure (sym)) - { - gfc_error ("Dummy procedure %qs of PURE procedure at %L must " - "also be PURE", sym->name, &sym->declared_at); - continue; - } - } - else if (!sym->attr.pointer) - { - if (proc->attr.function && sym->attr.intent != INTENT_IN) - { - if (sym->attr.value) - gfc_notify_std (GFC_STD_F2008, "Argument %qs" - " of pure function %qs at %L with VALUE " - "attribute but without INTENT(IN)", - sym->name, proc->name, &sym->declared_at); - else - gfc_error ("Argument %qs of pure function %qs at %L must " - "be INTENT(IN) or VALUE", sym->name, proc->name, - &sym->declared_at); - } - - if (proc->attr.subroutine && sym->attr.intent == INTENT_UNKNOWN) - { - if (sym->attr.value) - gfc_notify_std (GFC_STD_F2008, "Argument %qs" - " of pure subroutine %qs at %L with VALUE " - "attribute but without INTENT", sym->name, - proc->name, &sym->declared_at); - else - gfc_error ("Argument %qs of pure subroutine %qs at %L " - "must have its INTENT specified or have the " - "VALUE attribute", sym->name, proc->name, - &sym->declared_at); - } - } - - /* F08:C1278a. */ - if (sym->ts.type == BT_CLASS && sym->attr.intent == INTENT_OUT) - { - gfc_error ("INTENT(OUT) argument %qs of pure procedure %qs at %L" - " may not be polymorphic", sym->name, proc->name, - &sym->declared_at); - continue; - } - } - - if (proc->attr.implicit_pure) - { - if (sym->attr.flavor == FL_PROCEDURE) - { - if (!gfc_pure (sym)) - proc->attr.implicit_pure = 0; - } - else if (!sym->attr.pointer) - { - if (proc->attr.function && sym->attr.intent != INTENT_IN - && !sym->value) - proc->attr.implicit_pure = 0; - - if (proc->attr.subroutine && sym->attr.intent == INTENT_UNKNOWN - && !sym->value) - proc->attr.implicit_pure = 0; - } - } - - if (gfc_elemental (proc)) - { - /* F08:C1289. */ - if (sym->attr.codimension - || (sym->ts.type == BT_CLASS && CLASS_DATA (sym) - && CLASS_DATA (sym)->attr.codimension)) - { - gfc_error ("Coarray dummy argument %qs at %L to elemental " - "procedure", sym->name, &sym->declared_at); - continue; - } - - if (sym->as || (sym->ts.type == BT_CLASS && CLASS_DATA (sym) - && CLASS_DATA (sym)->as)) - { - gfc_error ("Argument %qs of elemental procedure at %L must " - "be scalar", sym->name, &sym->declared_at); - continue; - } - - if (sym->attr.allocatable - || (sym->ts.type == BT_CLASS && CLASS_DATA (sym) - && CLASS_DATA (sym)->attr.allocatable)) - { - gfc_error ("Argument %qs of elemental procedure at %L cannot " - "have the ALLOCATABLE attribute", sym->name, - &sym->declared_at); - continue; - } - - if (sym->attr.pointer - || (sym->ts.type == BT_CLASS && CLASS_DATA (sym) - && CLASS_DATA (sym)->attr.class_pointer)) - { - gfc_error ("Argument %qs of elemental procedure at %L cannot " - "have the POINTER attribute", sym->name, - &sym->declared_at); - continue; - } - - if (sym->attr.flavor == FL_PROCEDURE) - { - gfc_error ("Dummy procedure %qs not allowed in elemental " - "procedure %qs at %L", sym->name, proc->name, - &sym->declared_at); - continue; - } - - /* Fortran 2008 Corrigendum 1, C1290a. */ - if (sym->attr.intent == INTENT_UNKNOWN && !sym->attr.value) - { - gfc_error ("Argument %qs of elemental procedure %qs at %L must " - "have its INTENT specified or have the VALUE " - "attribute", sym->name, proc->name, - &sym->declared_at); - continue; - } - } - - /* Each dummy shall be specified to be scalar. */ - if (proc->attr.proc == PROC_ST_FUNCTION) - { - if (sym->as != NULL) - { - /* F03:C1263 (R1238) The function-name and each dummy-arg-name - shall be specified, explicitly or implicitly, to be scalar. */ - gfc_error ("Argument '%s' of statement function '%s' at %L " - "must be scalar", sym->name, proc->name, - &proc->declared_at); - continue; - } - - if (sym->ts.type == BT_CHARACTER) - { - gfc_charlen *cl = sym->ts.u.cl; - if (!cl || !cl->length || cl->length->expr_type != EXPR_CONSTANT) - { - gfc_error ("Character-valued argument %qs of statement " - "function at %L must have constant length", - sym->name, &sym->declared_at); - continue; - } - } - } - } - formal_arg_flag = false; -} - - -/* Work function called when searching for symbols that have argument lists - associated with them. */ - -static void -find_arglists (gfc_symbol *sym) -{ - if (sym->attr.if_source == IFSRC_UNKNOWN || sym->ns != gfc_current_ns - || gfc_fl_struct (sym->attr.flavor) || sym->attr.intrinsic) - return; - - gfc_resolve_formal_arglist (sym); -} - - -/* Given a namespace, resolve all formal argument lists within the namespace. - */ - -static void -resolve_formal_arglists (gfc_namespace *ns) -{ - if (ns == NULL) - return; - - gfc_traverse_ns (ns, find_arglists); -} - - -static void -resolve_contained_fntype (gfc_symbol *sym, gfc_namespace *ns) -{ - bool t; - - if (sym && sym->attr.flavor == FL_PROCEDURE - && sym->ns->parent - && sym->ns->parent->proc_name - && sym->ns->parent->proc_name->attr.flavor == FL_PROCEDURE - && !strcmp (sym->name, sym->ns->parent->proc_name->name)) - gfc_error ("Contained procedure %qs at %L has the same name as its " - "encompassing procedure", sym->name, &sym->declared_at); - - /* If this namespace is not a function or an entry master function, - ignore it. */ - if (! sym || !(sym->attr.function || sym->attr.flavor == FL_VARIABLE) - || sym->attr.entry_master) - return; - - if (!sym->result) - return; - - /* Try to find out of what the return type is. */ - if (sym->result->ts.type == BT_UNKNOWN && sym->result->ts.interface == NULL) - { - t = gfc_set_default_type (sym->result, 0, ns); - - if (!t && !sym->result->attr.untyped) - { - if (sym->result == sym) - gfc_error ("Contained function %qs at %L has no IMPLICIT type", - sym->name, &sym->declared_at); - else if (!sym->result->attr.proc_pointer) - gfc_error ("Result %qs of contained function %qs at %L has " - "no IMPLICIT type", sym->result->name, sym->name, - &sym->result->declared_at); - sym->result->attr.untyped = 1; - } - } - - /* Fortran 2008 Draft Standard, page 535, C418, on type-param-value - type, lists the only ways a character length value of * can be used: - dummy arguments of procedures, named constants, function results and - in allocate statements if the allocate_object is an assumed length dummy - in external functions. Internal function results and results of module - procedures are not on this list, ergo, not permitted. */ - - if (sym->result->ts.type == BT_CHARACTER) - { - gfc_charlen *cl = sym->result->ts.u.cl; - if ((!cl || !cl->length) && !sym->result->ts.deferred) - { - /* See if this is a module-procedure and adapt error message - accordingly. */ - bool module_proc; - gcc_assert (ns->parent && ns->parent->proc_name); - module_proc = (ns->parent->proc_name->attr.flavor == FL_MODULE); - - gfc_error (module_proc - ? G_("Character-valued module procedure %qs at %L" - " must not be assumed length") - : G_("Character-valued internal function %qs at %L" - " must not be assumed length"), - sym->name, &sym->declared_at); - } - } -} - - -/* Add NEW_ARGS to the formal argument list of PROC, taking care not to - introduce duplicates. */ - -static void -merge_argument_lists (gfc_symbol *proc, gfc_formal_arglist *new_args) -{ - gfc_formal_arglist *f, *new_arglist; - gfc_symbol *new_sym; - - for (; new_args != NULL; new_args = new_args->next) - { - new_sym = new_args->sym; - /* See if this arg is already in the formal argument list. */ - for (f = proc->formal; f; f = f->next) - { - if (new_sym == f->sym) - break; - } - - if (f) - continue; - - /* Add a new argument. Argument order is not important. */ - new_arglist = gfc_get_formal_arglist (); - new_arglist->sym = new_sym; - new_arglist->next = proc->formal; - proc->formal = new_arglist; - } -} - - -/* Flag the arguments that are not present in all entries. */ - -static void -check_argument_lists (gfc_symbol *proc, gfc_formal_arglist *new_args) -{ - gfc_formal_arglist *f, *head; - head = new_args; - - for (f = proc->formal; f; f = f->next) - { - if (f->sym == NULL) - continue; - - for (new_args = head; new_args; new_args = new_args->next) - { - if (new_args->sym == f->sym) - break; - } - - if (new_args) - continue; - - f->sym->attr.not_always_present = 1; - } -} - - -/* Resolve alternate entry points. If a symbol has multiple entry points we - create a new master symbol for the main routine, and turn the existing - symbol into an entry point. */ - -static void -resolve_entries (gfc_namespace *ns) -{ - gfc_namespace *old_ns; - gfc_code *c; - gfc_symbol *proc; - gfc_entry_list *el; - char name[GFC_MAX_SYMBOL_LEN + 1]; - static int master_count = 0; - - if (ns->proc_name == NULL) - return; - - /* No need to do anything if this procedure doesn't have alternate entry - points. */ - if (!ns->entries) - return; - - /* We may already have resolved alternate entry points. */ - if (ns->proc_name->attr.entry_master) - return; - - /* If this isn't a procedure something has gone horribly wrong. */ - gcc_assert (ns->proc_name->attr.flavor == FL_PROCEDURE); - - /* Remember the current namespace. */ - old_ns = gfc_current_ns; - - gfc_current_ns = ns; - - /* Add the main entry point to the list of entry points. */ - el = gfc_get_entry_list (); - el->sym = ns->proc_name; - el->id = 0; - el->next = ns->entries; - ns->entries = el; - ns->proc_name->attr.entry = 1; - - /* If it is a module function, it needs to be in the right namespace - so that gfc_get_fake_result_decl can gather up the results. The - need for this arose in get_proc_name, where these beasts were - left in their own namespace, to keep prior references linked to - the entry declaration.*/ - if (ns->proc_name->attr.function - && ns->parent && ns->parent->proc_name->attr.flavor == FL_MODULE) - el->sym->ns = ns; - - /* Do the same for entries where the master is not a module - procedure. These are retained in the module namespace because - of the module procedure declaration. */ - for (el = el->next; el; el = el->next) - if (el->sym->ns->proc_name->attr.flavor == FL_MODULE - && el->sym->attr.mod_proc) - el->sym->ns = ns; - el = ns->entries; - - /* Add an entry statement for it. */ - c = gfc_get_code (EXEC_ENTRY); - c->ext.entry = el; - c->next = ns->code; - ns->code = c; - - /* Create a new symbol for the master function. */ - /* Give the internal function a unique name (within this file). - Also include the function name so the user has some hope of figuring - out what is going on. */ - snprintf (name, GFC_MAX_SYMBOL_LEN, "master.%d.%s", - master_count++, ns->proc_name->name); - gfc_get_ha_symbol (name, &proc); - gcc_assert (proc != NULL); - - gfc_add_procedure (&proc->attr, PROC_INTERNAL, proc->name, NULL); - if (ns->proc_name->attr.subroutine) - gfc_add_subroutine (&proc->attr, proc->name, NULL); - else - { - gfc_symbol *sym; - gfc_typespec *ts, *fts; - gfc_array_spec *as, *fas; - gfc_add_function (&proc->attr, proc->name, NULL); - proc->result = proc; - fas = ns->entries->sym->as; - fas = fas ? fas : ns->entries->sym->result->as; - fts = &ns->entries->sym->result->ts; - if (fts->type == BT_UNKNOWN) - fts = gfc_get_default_type (ns->entries->sym->result->name, NULL); - for (el = ns->entries->next; el; el = el->next) - { - ts = &el->sym->result->ts; - as = el->sym->as; - as = as ? as : el->sym->result->as; - if (ts->type == BT_UNKNOWN) - ts = gfc_get_default_type (el->sym->result->name, NULL); - - if (! gfc_compare_types (ts, fts) - || (el->sym->result->attr.dimension - != ns->entries->sym->result->attr.dimension) - || (el->sym->result->attr.pointer - != ns->entries->sym->result->attr.pointer)) - break; - else if (as && fas && ns->entries->sym->result != el->sym->result - && gfc_compare_array_spec (as, fas) == 0) - gfc_error ("Function %s at %L has entries with mismatched " - "array specifications", ns->entries->sym->name, - &ns->entries->sym->declared_at); - /* The characteristics need to match and thus both need to have - the same string length, i.e. both len=*, or both len=4. - Having both len=<variable> is also possible, but difficult to - check at compile time. */ - else if (ts->type == BT_CHARACTER - && (el->sym->result->attr.allocatable - != ns->entries->sym->result->attr.allocatable)) - { - gfc_error ("Function %s at %L has entry %s with mismatched " - "characteristics", ns->entries->sym->name, - &ns->entries->sym->declared_at, el->sym->name); - goto cleanup; - } - else if (ts->type == BT_CHARACTER && ts->u.cl && fts->u.cl - && (((ts->u.cl->length && !fts->u.cl->length) - ||(!ts->u.cl->length && fts->u.cl->length)) - || (ts->u.cl->length - && ts->u.cl->length->expr_type - != fts->u.cl->length->expr_type) - || (ts->u.cl->length - && ts->u.cl->length->expr_type == EXPR_CONSTANT - && mpz_cmp (ts->u.cl->length->value.integer, - fts->u.cl->length->value.integer) != 0))) - gfc_notify_std (GFC_STD_GNU, "Function %s at %L with " - "entries returning variables of different " - "string lengths", ns->entries->sym->name, - &ns->entries->sym->declared_at); - } - - if (el == NULL) - { - sym = ns->entries->sym->result; - /* All result types the same. */ - proc->ts = *fts; - if (sym->attr.dimension) - gfc_set_array_spec (proc, gfc_copy_array_spec (sym->as), NULL); - if (sym->attr.pointer) - gfc_add_pointer (&proc->attr, NULL); - } - else - { - /* Otherwise the result will be passed through a union by - reference. */ - proc->attr.mixed_entry_master = 1; - for (el = ns->entries; el; el = el->next) - { - sym = el->sym->result; - if (sym->attr.dimension) - { - if (el == ns->entries) - gfc_error ("FUNCTION result %s cannot be an array in " - "FUNCTION %s at %L", sym->name, - ns->entries->sym->name, &sym->declared_at); - else - gfc_error ("ENTRY result %s cannot be an array in " - "FUNCTION %s at %L", sym->name, - ns->entries->sym->name, &sym->declared_at); - } - else if (sym->attr.pointer) - { - if (el == ns->entries) - gfc_error ("FUNCTION result %s cannot be a POINTER in " - "FUNCTION %s at %L", sym->name, - ns->entries->sym->name, &sym->declared_at); - else - gfc_error ("ENTRY result %s cannot be a POINTER in " - "FUNCTION %s at %L", sym->name, - ns->entries->sym->name, &sym->declared_at); - } - else - { - ts = &sym->ts; - if (ts->type == BT_UNKNOWN) - ts = gfc_get_default_type (sym->name, NULL); - switch (ts->type) - { - case BT_INTEGER: - if (ts->kind == gfc_default_integer_kind) - sym = NULL; - break; - case BT_REAL: - if (ts->kind == gfc_default_real_kind - || ts->kind == gfc_default_double_kind) - sym = NULL; - break; - case BT_COMPLEX: - if (ts->kind == gfc_default_complex_kind) - sym = NULL; - break; - case BT_LOGICAL: - if (ts->kind == gfc_default_logical_kind) - sym = NULL; - break; - case BT_UNKNOWN: - /* We will issue error elsewhere. */ - sym = NULL; - break; - default: - break; - } - if (sym) - { - if (el == ns->entries) - gfc_error ("FUNCTION result %s cannot be of type %s " - "in FUNCTION %s at %L", sym->name, - gfc_typename (ts), ns->entries->sym->name, - &sym->declared_at); - else - gfc_error ("ENTRY result %s cannot be of type %s " - "in FUNCTION %s at %L", sym->name, - gfc_typename (ts), ns->entries->sym->name, - &sym->declared_at); - } - } - } - } - } - -cleanup: - proc->attr.access = ACCESS_PRIVATE; - proc->attr.entry_master = 1; - - /* Merge all the entry point arguments. */ - for (el = ns->entries; el; el = el->next) - merge_argument_lists (proc, el->sym->formal); - - /* Check the master formal arguments for any that are not - present in all entry points. */ - for (el = ns->entries; el; el = el->next) - check_argument_lists (proc, el->sym->formal); - - /* Use the master function for the function body. */ - ns->proc_name = proc; - - /* Finalize the new symbols. */ - gfc_commit_symbols (); - - /* Restore the original namespace. */ - gfc_current_ns = old_ns; -} - - -/* Resolve common variables. */ -static void -resolve_common_vars (gfc_common_head *common_block, bool named_common) -{ - gfc_symbol *csym = common_block->head; - gfc_gsymbol *gsym; - - for (; csym; csym = csym->common_next) - { - gsym = gfc_find_gsymbol (gfc_gsym_root, csym->name); - if (gsym && (gsym->type == GSYM_MODULE || gsym->type == GSYM_PROGRAM)) - gfc_error_now ("Global entity %qs at %L cannot appear in a " - "COMMON block at %L", gsym->name, - &gsym->where, &csym->common_block->where); - - /* gfc_add_in_common may have been called before, but the reported errors - have been ignored to continue parsing. - We do the checks again here. */ - if (!csym->attr.use_assoc) - { - gfc_add_in_common (&csym->attr, csym->name, &common_block->where); - gfc_notify_std (GFC_STD_F2018_OBS, "COMMON block at %L", - &common_block->where); - } - - if (csym->value || csym->attr.data) - { - if (!csym->ns->is_block_data) - gfc_notify_std (GFC_STD_GNU, "Variable %qs at %L is in COMMON " - "but only in BLOCK DATA initialization is " - "allowed", csym->name, &csym->declared_at); - else if (!named_common) - gfc_notify_std (GFC_STD_GNU, "Initialized variable %qs at %L is " - "in a blank COMMON but initialization is only " - "allowed in named common blocks", csym->name, - &csym->declared_at); - } - - if (UNLIMITED_POLY (csym)) - gfc_error_now ("%qs at %L cannot appear in COMMON " - "[F2008:C5100]", csym->name, &csym->declared_at); - - if (csym->ts.type != BT_DERIVED) - continue; - - if (!(csym->ts.u.derived->attr.sequence - || csym->ts.u.derived->attr.is_bind_c)) - gfc_error_now ("Derived type variable %qs in COMMON at %L " - "has neither the SEQUENCE nor the BIND(C) " - "attribute", csym->name, &csym->declared_at); - if (csym->ts.u.derived->attr.alloc_comp) - gfc_error_now ("Derived type variable %qs in COMMON at %L " - "has an ultimate component that is " - "allocatable", csym->name, &csym->declared_at); - if (gfc_has_default_initializer (csym->ts.u.derived)) - gfc_error_now ("Derived type variable %qs in COMMON at %L " - "may not have default initializer", csym->name, - &csym->declared_at); - - if (csym->attr.flavor == FL_UNKNOWN && !csym->attr.proc_pointer) - gfc_add_flavor (&csym->attr, FL_VARIABLE, csym->name, &csym->declared_at); - } -} - -/* Resolve common blocks. */ -static void -resolve_common_blocks (gfc_symtree *common_root) -{ - gfc_symbol *sym; - gfc_gsymbol * gsym; - - if (common_root == NULL) - return; - - if (common_root->left) - resolve_common_blocks (common_root->left); - if (common_root->right) - resolve_common_blocks (common_root->right); - - resolve_common_vars (common_root->n.common, true); - - /* The common name is a global name - in Fortran 2003 also if it has a - C binding name, since Fortran 2008 only the C binding name is a global - identifier. */ - if (!common_root->n.common->binding_label - || gfc_notification_std (GFC_STD_F2008)) - { - gsym = gfc_find_gsymbol (gfc_gsym_root, - common_root->n.common->name); - - if (gsym && gfc_notification_std (GFC_STD_F2008) - && gsym->type == GSYM_COMMON - && ((common_root->n.common->binding_label - && (!gsym->binding_label - || strcmp (common_root->n.common->binding_label, - gsym->binding_label) != 0)) - || (!common_root->n.common->binding_label - && gsym->binding_label))) - { - gfc_error ("In Fortran 2003 COMMON %qs block at %L is a global " - "identifier and must thus have the same binding name " - "as the same-named COMMON block at %L: %s vs %s", - common_root->n.common->name, &common_root->n.common->where, - &gsym->where, - common_root->n.common->binding_label - ? common_root->n.common->binding_label : "(blank)", - gsym->binding_label ? gsym->binding_label : "(blank)"); - return; - } - - if (gsym && gsym->type != GSYM_COMMON - && !common_root->n.common->binding_label) - { - gfc_error ("COMMON block %qs at %L uses the same global identifier " - "as entity at %L", - common_root->n.common->name, &common_root->n.common->where, - &gsym->where); - return; - } - if (gsym && gsym->type != GSYM_COMMON) - { - gfc_error ("Fortran 2008: COMMON block %qs with binding label at " - "%L sharing the identifier with global non-COMMON-block " - "entity at %L", common_root->n.common->name, - &common_root->n.common->where, &gsym->where); - return; - } - if (!gsym) - { - gsym = gfc_get_gsymbol (common_root->n.common->name, false); - gsym->type = GSYM_COMMON; - gsym->where = common_root->n.common->where; - gsym->defined = 1; - } - gsym->used = 1; - } - - if (common_root->n.common->binding_label) - { - gsym = gfc_find_gsymbol (gfc_gsym_root, - common_root->n.common->binding_label); - if (gsym && gsym->type != GSYM_COMMON) - { - gfc_error ("COMMON block at %L with binding label %qs uses the same " - "global identifier as entity at %L", - &common_root->n.common->where, - common_root->n.common->binding_label, &gsym->where); - return; - } - if (!gsym) - { - gsym = gfc_get_gsymbol (common_root->n.common->binding_label, true); - gsym->type = GSYM_COMMON; - gsym->where = common_root->n.common->where; - gsym->defined = 1; - } - gsym->used = 1; - } - - gfc_find_symbol (common_root->name, gfc_current_ns, 0, &sym); - if (sym == NULL) - return; - - if (sym->attr.flavor == FL_PARAMETER) - gfc_error ("COMMON block %qs at %L is used as PARAMETER at %L", - sym->name, &common_root->n.common->where, &sym->declared_at); - - if (sym->attr.external) - gfc_error ("COMMON block %qs at %L cannot have the EXTERNAL attribute", - sym->name, &common_root->n.common->where); - - if (sym->attr.intrinsic) - gfc_error ("COMMON block %qs at %L is also an intrinsic procedure", - sym->name, &common_root->n.common->where); - else if (sym->attr.result - || gfc_is_function_return_value (sym, gfc_current_ns)) - gfc_notify_std (GFC_STD_F2003, "COMMON block %qs at %L " - "that is also a function result", sym->name, - &common_root->n.common->where); - else if (sym->attr.flavor == FL_PROCEDURE && sym->attr.proc != PROC_INTERNAL - && sym->attr.proc != PROC_ST_FUNCTION) - gfc_notify_std (GFC_STD_F2003, "COMMON block %qs at %L " - "that is also a global procedure", sym->name, - &common_root->n.common->where); -} - - -/* Resolve contained function types. Because contained functions can call one - another, they have to be worked out before any of the contained procedures - can be resolved. - - The good news is that if a function doesn't already have a type, the only - way it can get one is through an IMPLICIT type or a RESULT variable, because - by definition contained functions are contained namespace they're contained - in, not in a sibling or parent namespace. */ - -static void -resolve_contained_functions (gfc_namespace *ns) -{ - gfc_namespace *child; - gfc_entry_list *el; - - resolve_formal_arglists (ns); - - for (child = ns->contained; child; child = child->sibling) - { - /* Resolve alternate entry points first. */ - resolve_entries (child); - - /* Then check function return types. */ - resolve_contained_fntype (child->proc_name, child); - for (el = child->entries; el; el = el->next) - resolve_contained_fntype (el->sym, child); - } -} - - - -/* A Parameterized Derived Type constructor must contain values for - the PDT KIND parameters or they must have a default initializer. - Go through the constructor picking out the KIND expressions, - storing them in 'param_list' and then call gfc_get_pdt_instance - to obtain the PDT instance. */ - -static gfc_actual_arglist *param_list, *param_tail, *param; - -static bool -get_pdt_spec_expr (gfc_component *c, gfc_expr *expr) -{ - param = gfc_get_actual_arglist (); - if (!param_list) - param_list = param_tail = param; - else - { - param_tail->next = param; - param_tail = param_tail->next; - } - - param_tail->name = c->name; - if (expr) - param_tail->expr = gfc_copy_expr (expr); - else if (c->initializer) - param_tail->expr = gfc_copy_expr (c->initializer); - else - { - param_tail->spec_type = SPEC_ASSUMED; - if (c->attr.pdt_kind) - { - gfc_error ("The KIND parameter %qs in the PDT constructor " - "at %C has no value", param->name); - return false; - } - } - - return true; -} - -static bool -get_pdt_constructor (gfc_expr *expr, gfc_constructor **constr, - gfc_symbol *derived) -{ - gfc_constructor *cons = NULL; - gfc_component *comp; - bool t = true; - - if (expr && expr->expr_type == EXPR_STRUCTURE) - cons = gfc_constructor_first (expr->value.constructor); - else if (constr) - cons = *constr; - gcc_assert (cons); - - comp = derived->components; - - for (; comp && cons; comp = comp->next, cons = gfc_constructor_next (cons)) - { - if (cons->expr - && cons->expr->expr_type == EXPR_STRUCTURE - && comp->ts.type == BT_DERIVED) - { - t = get_pdt_constructor (cons->expr, NULL, comp->ts.u.derived); - if (!t) - return t; - } - else if (comp->ts.type == BT_DERIVED) - { - t = get_pdt_constructor (NULL, &cons, comp->ts.u.derived); - if (!t) - return t; - } - else if ((comp->attr.pdt_kind || comp->attr.pdt_len) - && derived->attr.pdt_template) - { - t = get_pdt_spec_expr (comp, cons->expr); - if (!t) - return t; - } - } - return t; -} - - -static bool resolve_fl_derived0 (gfc_symbol *sym); -static bool resolve_fl_struct (gfc_symbol *sym); - - -/* Resolve all of the elements of a structure constructor and make sure that - the types are correct. The 'init' flag indicates that the given - constructor is an initializer. */ - -static bool -resolve_structure_cons (gfc_expr *expr, int init) -{ - gfc_constructor *cons; - gfc_component *comp; - bool t; - symbol_attribute a; - - t = true; - - if (expr->ts.type == BT_DERIVED || expr->ts.type == BT_UNION) - { - if (expr->ts.u.derived->attr.flavor == FL_DERIVED) - resolve_fl_derived0 (expr->ts.u.derived); - else - resolve_fl_struct (expr->ts.u.derived); - - /* If this is a Parameterized Derived Type template, find the - instance corresponding to the PDT kind parameters. */ - if (expr->ts.u.derived->attr.pdt_template) - { - param_list = NULL; - t = get_pdt_constructor (expr, NULL, expr->ts.u.derived); - if (!t) - return t; - gfc_get_pdt_instance (param_list, &expr->ts.u.derived, NULL); - - expr->param_list = gfc_copy_actual_arglist (param_list); - - if (param_list) - gfc_free_actual_arglist (param_list); - - if (!expr->ts.u.derived->attr.pdt_type) - return false; - } - } - - cons = gfc_constructor_first (expr->value.constructor); - - /* A constructor may have references if it is the result of substituting a - parameter variable. In this case we just pull out the component we - want. */ - if (expr->ref) - comp = expr->ref->u.c.sym->components; - else - comp = expr->ts.u.derived->components; - - for (; comp && cons; comp = comp->next, cons = gfc_constructor_next (cons)) - { - int rank; - - if (!cons->expr) - continue; - - /* Unions use an EXPR_NULL contrived expression to tell the translation - phase to generate an initializer of the appropriate length. - Ignore it here. */ - if (cons->expr->ts.type == BT_UNION && cons->expr->expr_type == EXPR_NULL) - continue; - - if (!gfc_resolve_expr (cons->expr)) - { - t = false; - continue; - } - - rank = comp->as ? comp->as->rank : 0; - if (comp->ts.type == BT_CLASS - && !comp->ts.u.derived->attr.unlimited_polymorphic - && CLASS_DATA (comp)->as) - rank = CLASS_DATA (comp)->as->rank; - - if (cons->expr->expr_type != EXPR_NULL && rank != cons->expr->rank - && (comp->attr.allocatable || cons->expr->rank)) - { - gfc_error ("The rank of the element in the structure " - "constructor at %L does not match that of the " - "component (%d/%d)", &cons->expr->where, - cons->expr->rank, rank); - t = false; - } - - /* If we don't have the right type, try to convert it. */ - - if (!comp->attr.proc_pointer && - !gfc_compare_types (&cons->expr->ts, &comp->ts)) - { - if (strcmp (comp->name, "_extends") == 0) - { - /* Can afford to be brutal with the _extends initializer. - The derived type can get lost because it is PRIVATE - but it is not usage constrained by the standard. */ - cons->expr->ts = comp->ts; - } - else if (comp->attr.pointer && cons->expr->ts.type != BT_UNKNOWN) - { - gfc_error ("The element in the structure constructor at %L, " - "for pointer component %qs, is %s but should be %s", - &cons->expr->where, comp->name, - gfc_basic_typename (cons->expr->ts.type), - gfc_basic_typename (comp->ts.type)); - t = false; - } - else - { - bool t2 = gfc_convert_type (cons->expr, &comp->ts, 1); - if (t) - t = t2; - } - } - - /* For strings, the length of the constructor should be the same as - the one of the structure, ensure this if the lengths are known at - compile time and when we are dealing with PARAMETER or structure - constructors. */ - if (cons->expr->ts.type == BT_CHARACTER && comp->ts.u.cl - && comp->ts.u.cl->length - && comp->ts.u.cl->length->expr_type == EXPR_CONSTANT - && cons->expr->ts.u.cl && cons->expr->ts.u.cl->length - && cons->expr->ts.u.cl->length->expr_type == EXPR_CONSTANT - && cons->expr->rank != 0 - && mpz_cmp (cons->expr->ts.u.cl->length->value.integer, - comp->ts.u.cl->length->value.integer) != 0) - { - if (cons->expr->expr_type == EXPR_VARIABLE - && cons->expr->symtree->n.sym->attr.flavor == FL_PARAMETER) - { - /* Wrap the parameter in an array constructor (EXPR_ARRAY) - to make use of the gfc_resolve_character_array_constructor - machinery. The expression is later simplified away to - an array of string literals. */ - gfc_expr *para = cons->expr; - cons->expr = gfc_get_expr (); - cons->expr->ts = para->ts; - cons->expr->where = para->where; - cons->expr->expr_type = EXPR_ARRAY; - cons->expr->rank = para->rank; - cons->expr->shape = gfc_copy_shape (para->shape, para->rank); - gfc_constructor_append_expr (&cons->expr->value.constructor, - para, &cons->expr->where); - } - - if (cons->expr->expr_type == EXPR_ARRAY) - { - /* Rely on the cleanup of the namespace to deal correctly with - the old charlen. (There was a block here that attempted to - remove the charlen but broke the chain in so doing.) */ - cons->expr->ts.u.cl = gfc_new_charlen (gfc_current_ns, NULL); - cons->expr->ts.u.cl->length_from_typespec = true; - cons->expr->ts.u.cl->length = gfc_copy_expr (comp->ts.u.cl->length); - gfc_resolve_character_array_constructor (cons->expr); - } - } - - if (cons->expr->expr_type == EXPR_NULL - && !(comp->attr.pointer || comp->attr.allocatable - || comp->attr.proc_pointer || comp->ts.f90_type == BT_VOID - || (comp->ts.type == BT_CLASS - && (CLASS_DATA (comp)->attr.class_pointer - || CLASS_DATA (comp)->attr.allocatable)))) - { - t = false; - gfc_error ("The NULL in the structure constructor at %L is " - "being applied to component %qs, which is neither " - "a POINTER nor ALLOCATABLE", &cons->expr->where, - comp->name); - } - - if (comp->attr.proc_pointer && comp->ts.interface) - { - /* Check procedure pointer interface. */ - gfc_symbol *s2 = NULL; - gfc_component *c2; - const char *name; - char err[200]; - - c2 = gfc_get_proc_ptr_comp (cons->expr); - if (c2) - { - s2 = c2->ts.interface; - name = c2->name; - } - else if (cons->expr->expr_type == EXPR_FUNCTION) - { - s2 = cons->expr->symtree->n.sym->result; - name = cons->expr->symtree->n.sym->result->name; - } - else if (cons->expr->expr_type != EXPR_NULL) - { - s2 = cons->expr->symtree->n.sym; - name = cons->expr->symtree->n.sym->name; - } - - if (s2 && !gfc_compare_interfaces (comp->ts.interface, s2, name, 0, 1, - err, sizeof (err), NULL, NULL)) - { - gfc_error_opt (0, "Interface mismatch for procedure-pointer " - "component %qs in structure constructor at %L:" - " %s", comp->name, &cons->expr->where, err); - return false; - } - } - - /* Validate shape, except for dynamic or PDT arrays. */ - if (cons->expr->expr_type == EXPR_ARRAY && rank == cons->expr->rank - && comp->as && !comp->attr.allocatable && !comp->attr.pointer - && !comp->attr.pdt_array) - { - mpz_t len; - mpz_init (len); - for (int n = 0; n < rank; n++) - { - if (comp->as->upper[n]->expr_type != EXPR_CONSTANT - || comp->as->lower[n]->expr_type != EXPR_CONSTANT) - { - gfc_error ("Bad array spec of component %qs referenced in " - "structure constructor at %L", - comp->name, &cons->expr->where); - t = false; - break; - }; - mpz_set_ui (len, 1); - mpz_add (len, len, comp->as->upper[n]->value.integer); - mpz_sub (len, len, comp->as->lower[n]->value.integer); - if (mpz_cmp (cons->expr->shape[n], len) != 0) - { - gfc_error ("The shape of component %qs in the structure " - "constructor at %L differs from the shape of the " - "declared component for dimension %d (%ld/%ld)", - comp->name, &cons->expr->where, n+1, - mpz_get_si (cons->expr->shape[n]), - mpz_get_si (len)); - t = false; - } - } - mpz_clear (len); - } - - if (!comp->attr.pointer || comp->attr.proc_pointer - || cons->expr->expr_type == EXPR_NULL) - continue; - - a = gfc_expr_attr (cons->expr); - - if (!a.pointer && !a.target) - { - t = false; - gfc_error ("The element in the structure constructor at %L, " - "for pointer component %qs should be a POINTER or " - "a TARGET", &cons->expr->where, comp->name); - } - - if (init) - { - /* F08:C461. Additional checks for pointer initialization. */ - if (a.allocatable) - { - t = false; - gfc_error ("Pointer initialization target at %L " - "must not be ALLOCATABLE", &cons->expr->where); - } - if (!a.save) - { - t = false; - gfc_error ("Pointer initialization target at %L " - "must have the SAVE attribute", &cons->expr->where); - } - } - - /* F2003, C1272 (3). */ - bool impure = cons->expr->expr_type == EXPR_VARIABLE - && (gfc_impure_variable (cons->expr->symtree->n.sym) - || gfc_is_coindexed (cons->expr)); - if (impure && gfc_pure (NULL)) - { - t = false; - gfc_error ("Invalid expression in the structure constructor for " - "pointer component %qs at %L in PURE procedure", - comp->name, &cons->expr->where); - } - - if (impure) - gfc_unset_implicit_pure (NULL); - } - - return t; -} - - -/****************** Expression name resolution ******************/ - -/* Returns 0 if a symbol was not declared with a type or - attribute declaration statement, nonzero otherwise. */ - -static int -was_declared (gfc_symbol *sym) -{ - symbol_attribute a; - - a = sym->attr; - - if (!a.implicit_type && sym->ts.type != BT_UNKNOWN) - return 1; - - if (a.allocatable || a.dimension || a.dummy || a.external || a.intrinsic - || a.optional || a.pointer || a.save || a.target || a.volatile_ - || a.value || a.access != ACCESS_UNKNOWN || a.intent != INTENT_UNKNOWN - || a.asynchronous || a.codimension) - return 1; - - return 0; -} - - -/* Determine if a symbol is generic or not. */ - -static int -generic_sym (gfc_symbol *sym) -{ - gfc_symbol *s; - - if (sym->attr.generic || - (sym->attr.intrinsic && gfc_generic_intrinsic (sym->name))) - return 1; - - if (was_declared (sym) || sym->ns->parent == NULL) - return 0; - - gfc_find_symbol (sym->name, sym->ns->parent, 1, &s); - - if (s != NULL) - { - if (s == sym) - return 0; - else - return generic_sym (s); - } - - return 0; -} - - -/* Determine if a symbol is specific or not. */ - -static int -specific_sym (gfc_symbol *sym) -{ - gfc_symbol *s; - - if (sym->attr.if_source == IFSRC_IFBODY - || sym->attr.proc == PROC_MODULE - || sym->attr.proc == PROC_INTERNAL - || sym->attr.proc == PROC_ST_FUNCTION - || (sym->attr.intrinsic && gfc_specific_intrinsic (sym->name)) - || sym->attr.external) - return 1; - - if (was_declared (sym) || sym->ns->parent == NULL) - return 0; - - gfc_find_symbol (sym->name, sym->ns->parent, 1, &s); - - return (s == NULL) ? 0 : specific_sym (s); -} - - -/* Figure out if the procedure is specific, generic or unknown. */ - -enum proc_type -{ PTYPE_GENERIC = 1, PTYPE_SPECIFIC, PTYPE_UNKNOWN }; - -static proc_type -procedure_kind (gfc_symbol *sym) -{ - if (generic_sym (sym)) - return PTYPE_GENERIC; - - if (specific_sym (sym)) - return PTYPE_SPECIFIC; - - return PTYPE_UNKNOWN; -} - -/* Check references to assumed size arrays. The flag need_full_assumed_size - is nonzero when matching actual arguments. */ - -static int need_full_assumed_size = 0; - -static bool -check_assumed_size_reference (gfc_symbol *sym, gfc_expr *e) -{ - if (need_full_assumed_size || !(sym->as && sym->as->type == AS_ASSUMED_SIZE)) - return false; - - /* FIXME: The comparison "e->ref->u.ar.type == AR_FULL" is wrong. - What should it be? */ - if (e->ref && (e->ref->u.ar.end[e->ref->u.ar.as->rank - 1] == NULL) - && (e->ref->u.ar.as->type == AS_ASSUMED_SIZE) - && (e->ref->u.ar.type == AR_FULL)) - { - gfc_error ("The upper bound in the last dimension must " - "appear in the reference to the assumed size " - "array %qs at %L", sym->name, &e->where); - return true; - } - return false; -} - - -/* Look for bad assumed size array references in argument expressions - of elemental and array valued intrinsic procedures. Since this is - called from procedure resolution functions, it only recurses at - operators. */ - -static bool -resolve_assumed_size_actual (gfc_expr *e) -{ - if (e == NULL) - return false; - - switch (e->expr_type) - { - case EXPR_VARIABLE: - if (e->symtree && check_assumed_size_reference (e->symtree->n.sym, e)) - return true; - break; - - case EXPR_OP: - if (resolve_assumed_size_actual (e->value.op.op1) - || resolve_assumed_size_actual (e->value.op.op2)) - return true; - break; - - default: - break; - } - return false; -} - - -/* Check a generic procedure, passed as an actual argument, to see if - there is a matching specific name. If none, it is an error, and if - more than one, the reference is ambiguous. */ -static int -count_specific_procs (gfc_expr *e) -{ - int n; - gfc_interface *p; - gfc_symbol *sym; - - n = 0; - sym = e->symtree->n.sym; - - for (p = sym->generic; p; p = p->next) - if (strcmp (sym->name, p->sym->name) == 0) - { - e->symtree = gfc_find_symtree (p->sym->ns->sym_root, - sym->name); - n++; - } - - if (n > 1) - gfc_error ("%qs at %L is ambiguous", e->symtree->n.sym->name, - &e->where); - - if (n == 0) - gfc_error ("GENERIC procedure %qs is not allowed as an actual " - "argument at %L", sym->name, &e->where); - - return n; -} - - -/* See if a call to sym could possibly be a not allowed RECURSION because of - a missing RECURSIVE declaration. This means that either sym is the current - context itself, or sym is the parent of a contained procedure calling its - non-RECURSIVE containing procedure. - This also works if sym is an ENTRY. */ - -static bool -is_illegal_recursion (gfc_symbol* sym, gfc_namespace* context) -{ - gfc_symbol* proc_sym; - gfc_symbol* context_proc; - gfc_namespace* real_context; - - if (sym->attr.flavor == FL_PROGRAM - || gfc_fl_struct (sym->attr.flavor)) - return false; - - /* If we've got an ENTRY, find real procedure. */ - if (sym->attr.entry && sym->ns->entries) - proc_sym = sym->ns->entries->sym; - else - proc_sym = sym; - - /* If sym is RECURSIVE, all is well of course. */ - if (proc_sym->attr.recursive || flag_recursive) - return false; - - /* Find the context procedure's "real" symbol if it has entries. - We look for a procedure symbol, so recurse on the parents if we don't - find one (like in case of a BLOCK construct). */ - for (real_context = context; ; real_context = real_context->parent) - { - /* We should find something, eventually! */ - gcc_assert (real_context); - - context_proc = (real_context->entries ? real_context->entries->sym - : real_context->proc_name); - - /* In some special cases, there may not be a proc_name, like for this - invalid code: - real(bad_kind()) function foo () ... - when checking the call to bad_kind (). - In these cases, we simply return here and assume that the - call is ok. */ - if (!context_proc) - return false; - - if (context_proc->attr.flavor != FL_LABEL) - break; - } - - /* A call from sym's body to itself is recursion, of course. */ - if (context_proc == proc_sym) - return true; - - /* The same is true if context is a contained procedure and sym the - containing one. */ - if (context_proc->attr.contained) - { - gfc_symbol* parent_proc; - - gcc_assert (context->parent); - parent_proc = (context->parent->entries ? context->parent->entries->sym - : context->parent->proc_name); - - if (parent_proc == proc_sym) - return true; - } - - return false; -} - - -/* Resolve an intrinsic procedure: Set its function/subroutine attribute, - its typespec and formal argument list. */ - -bool -gfc_resolve_intrinsic (gfc_symbol *sym, locus *loc) -{ - gfc_intrinsic_sym* isym = NULL; - const char* symstd; - - if (sym->resolve_symbol_called >= 2) - return true; - - sym->resolve_symbol_called = 2; - - /* Already resolved. */ - if (sym->from_intmod && sym->ts.type != BT_UNKNOWN) - return true; - - /* We already know this one is an intrinsic, so we don't call - gfc_is_intrinsic for full checking but rather use gfc_find_function and - gfc_find_subroutine directly to check whether it is a function or - subroutine. */ - - if (sym->intmod_sym_id && sym->attr.subroutine) - { - gfc_isym_id id = gfc_isym_id_by_intmod_sym (sym); - isym = gfc_intrinsic_subroutine_by_id (id); - } - else if (sym->intmod_sym_id) - { - gfc_isym_id id = gfc_isym_id_by_intmod_sym (sym); - isym = gfc_intrinsic_function_by_id (id); - } - else if (!sym->attr.subroutine) - isym = gfc_find_function (sym->name); - - if (isym && !sym->attr.subroutine) - { - if (sym->ts.type != BT_UNKNOWN && warn_surprising - && !sym->attr.implicit_type) - gfc_warning (OPT_Wsurprising, - "Type specified for intrinsic function %qs at %L is" - " ignored", sym->name, &sym->declared_at); - - if (!sym->attr.function && - !gfc_add_function(&sym->attr, sym->name, loc)) - return false; - - sym->ts = isym->ts; - } - else if (isym || (isym = gfc_find_subroutine (sym->name))) - { - if (sym->ts.type != BT_UNKNOWN && !sym->attr.implicit_type) - { - gfc_error ("Intrinsic subroutine %qs at %L shall not have a type" - " specifier", sym->name, &sym->declared_at); - return false; - } - - if (!sym->attr.subroutine && - !gfc_add_subroutine(&sym->attr, sym->name, loc)) - return false; - } - else - { - gfc_error ("%qs declared INTRINSIC at %L does not exist", sym->name, - &sym->declared_at); - return false; - } - - gfc_copy_formal_args_intr (sym, isym, NULL); - - sym->attr.pure = isym->pure; - sym->attr.elemental = isym->elemental; - - /* Check it is actually available in the standard settings. */ - if (!gfc_check_intrinsic_standard (isym, &symstd, false, sym->declared_at)) - { - gfc_error ("The intrinsic %qs declared INTRINSIC at %L is not " - "available in the current standard settings but %s. Use " - "an appropriate %<-std=*%> option or enable " - "%<-fall-intrinsics%> in order to use it.", - sym->name, &sym->declared_at, symstd); - return false; - } - - return true; -} - - -/* Resolve a procedure expression, like passing it to a called procedure or as - RHS for a procedure pointer assignment. */ - -static bool -resolve_procedure_expression (gfc_expr* expr) -{ - gfc_symbol* sym; - - if (expr->expr_type != EXPR_VARIABLE) - return true; - gcc_assert (expr->symtree); - - sym = expr->symtree->n.sym; - - if (sym->attr.intrinsic) - gfc_resolve_intrinsic (sym, &expr->where); - - if (sym->attr.flavor != FL_PROCEDURE - || (sym->attr.function && sym->result == sym)) - return true; - - /* A non-RECURSIVE procedure that is used as procedure expression within its - own body is in danger of being called recursively. */ - if (is_illegal_recursion (sym, gfc_current_ns)) - gfc_warning (0, "Non-RECURSIVE procedure %qs at %L is possibly calling" - " itself recursively. Declare it RECURSIVE or use" - " %<-frecursive%>", sym->name, &expr->where); - - return true; -} - - -/* Check that name is not a derived type. */ - -static bool -is_dt_name (const char *name) -{ - gfc_symbol *dt_list, *dt_first; - - dt_list = dt_first = gfc_derived_types; - for (; dt_list; dt_list = dt_list->dt_next) - { - if (strcmp(dt_list->name, name) == 0) - return true; - if (dt_first == dt_list->dt_next) - break; - } - return false; -} - - -/* Resolve an actual argument list. Most of the time, this is just - resolving the expressions in the list. - The exception is that we sometimes have to decide whether arguments - that look like procedure arguments are really simple variable - references. */ - -static bool -resolve_actual_arglist (gfc_actual_arglist *arg, procedure_type ptype, - bool no_formal_args) -{ - gfc_symbol *sym; - gfc_symtree *parent_st; - gfc_expr *e; - gfc_component *comp; - int save_need_full_assumed_size; - bool return_value = false; - bool actual_arg_sav = actual_arg, first_actual_arg_sav = first_actual_arg; - - actual_arg = true; - first_actual_arg = true; - - for (; arg; arg = arg->next) - { - e = arg->expr; - if (e == NULL) - { - /* Check the label is a valid branching target. */ - if (arg->label) - { - if (arg->label->defined == ST_LABEL_UNKNOWN) - { - gfc_error ("Label %d referenced at %L is never defined", - arg->label->value, &arg->label->where); - goto cleanup; - } - } - first_actual_arg = false; - continue; - } - - if (e->expr_type == EXPR_VARIABLE - && e->symtree->n.sym->attr.generic - && no_formal_args - && count_specific_procs (e) != 1) - goto cleanup; - - if (e->ts.type != BT_PROCEDURE) - { - save_need_full_assumed_size = need_full_assumed_size; - if (e->expr_type != EXPR_VARIABLE) - need_full_assumed_size = 0; - if (!gfc_resolve_expr (e)) - goto cleanup; - need_full_assumed_size = save_need_full_assumed_size; - goto argument_list; - } - - /* See if the expression node should really be a variable reference. */ - - sym = e->symtree->n.sym; - - if (sym->attr.flavor == FL_PROCEDURE && is_dt_name (sym->name)) - { - gfc_error ("Derived type %qs is used as an actual " - "argument at %L", sym->name, &e->where); - goto cleanup; - } - - if (sym->attr.flavor == FL_PROCEDURE - || sym->attr.intrinsic - || sym->attr.external) - { - int actual_ok; - - /* If a procedure is not already determined to be something else - check if it is intrinsic. */ - if (gfc_is_intrinsic (sym, sym->attr.subroutine, e->where)) - sym->attr.intrinsic = 1; - - if (sym->attr.proc == PROC_ST_FUNCTION) - { - gfc_error ("Statement function %qs at %L is not allowed as an " - "actual argument", sym->name, &e->where); - } - - actual_ok = gfc_intrinsic_actual_ok (sym->name, - sym->attr.subroutine); - if (sym->attr.intrinsic && actual_ok == 0) - { - gfc_error ("Intrinsic %qs at %L is not allowed as an " - "actual argument", sym->name, &e->where); - } - - if (sym->attr.contained && !sym->attr.use_assoc - && sym->ns->proc_name->attr.flavor != FL_MODULE) - { - if (!gfc_notify_std (GFC_STD_F2008, "Internal procedure %qs is" - " used as actual argument at %L", - sym->name, &e->where)) - goto cleanup; - } - - if (sym->attr.elemental && !sym->attr.intrinsic) - { - gfc_error ("ELEMENTAL non-INTRINSIC procedure %qs is not " - "allowed as an actual argument at %L", sym->name, - &e->where); - } - - /* Check if a generic interface has a specific procedure - with the same name before emitting an error. */ - if (sym->attr.generic && count_specific_procs (e) != 1) - goto cleanup; - - /* Just in case a specific was found for the expression. */ - sym = e->symtree->n.sym; - - /* If the symbol is the function that names the current (or - parent) scope, then we really have a variable reference. */ - - if (gfc_is_function_return_value (sym, sym->ns)) - goto got_variable; - - /* If all else fails, see if we have a specific intrinsic. */ - if (sym->ts.type == BT_UNKNOWN && sym->attr.intrinsic) - { - gfc_intrinsic_sym *isym; - - isym = gfc_find_function (sym->name); - if (isym == NULL || !isym->specific) - { - gfc_error ("Unable to find a specific INTRINSIC procedure " - "for the reference %qs at %L", sym->name, - &e->where); - goto cleanup; - } - sym->ts = isym->ts; - sym->attr.intrinsic = 1; - sym->attr.function = 1; - } - - if (!gfc_resolve_expr (e)) - goto cleanup; - goto argument_list; - } - - /* See if the name is a module procedure in a parent unit. */ - - if (was_declared (sym) || sym->ns->parent == NULL) - goto got_variable; - - if (gfc_find_sym_tree (sym->name, sym->ns->parent, 1, &parent_st)) - { - gfc_error ("Symbol %qs at %L is ambiguous", sym->name, &e->where); - goto cleanup; - } - - if (parent_st == NULL) - goto got_variable; - - sym = parent_st->n.sym; - e->symtree = parent_st; /* Point to the right thing. */ - - if (sym->attr.flavor == FL_PROCEDURE - || sym->attr.intrinsic - || sym->attr.external) - { - if (!gfc_resolve_expr (e)) - goto cleanup; - goto argument_list; - } - - got_variable: - e->expr_type = EXPR_VARIABLE; - e->ts = sym->ts; - if ((sym->as != NULL && sym->ts.type != BT_CLASS) - || (sym->ts.type == BT_CLASS && sym->attr.class_ok - && CLASS_DATA (sym)->as)) - { - e->rank = sym->ts.type == BT_CLASS - ? CLASS_DATA (sym)->as->rank : sym->as->rank; - e->ref = gfc_get_ref (); - e->ref->type = REF_ARRAY; - e->ref->u.ar.type = AR_FULL; - e->ref->u.ar.as = sym->ts.type == BT_CLASS - ? CLASS_DATA (sym)->as : sym->as; - } - - /* Expressions are assigned a default ts.type of BT_PROCEDURE in - primary.c (match_actual_arg). If above code determines that it - is a variable instead, it needs to be resolved as it was not - done at the beginning of this function. */ - save_need_full_assumed_size = need_full_assumed_size; - if (e->expr_type != EXPR_VARIABLE) - need_full_assumed_size = 0; - if (!gfc_resolve_expr (e)) - goto cleanup; - need_full_assumed_size = save_need_full_assumed_size; - - argument_list: - /* Check argument list functions %VAL, %LOC and %REF. There is - nothing to do for %REF. */ - if (arg->name && arg->name[0] == '%') - { - if (strcmp ("%VAL", arg->name) == 0) - { - if (e->ts.type == BT_CHARACTER || e->ts.type == BT_DERIVED) - { - gfc_error ("By-value argument at %L is not of numeric " - "type", &e->where); - goto cleanup; - } - - if (e->rank) - { - gfc_error ("By-value argument at %L cannot be an array or " - "an array section", &e->where); - goto cleanup; - } - - /* Intrinsics are still PROC_UNKNOWN here. However, - since same file external procedures are not resolvable - in gfortran, it is a good deal easier to leave them to - intrinsic.c. */ - if (ptype != PROC_UNKNOWN - && ptype != PROC_DUMMY - && ptype != PROC_EXTERNAL - && ptype != PROC_MODULE) - { - gfc_error ("By-value argument at %L is not allowed " - "in this context", &e->where); - goto cleanup; - } - } - - /* Statement functions have already been excluded above. */ - else if (strcmp ("%LOC", arg->name) == 0 - && e->ts.type == BT_PROCEDURE) - { - if (e->symtree->n.sym->attr.proc == PROC_INTERNAL) - { - gfc_error ("Passing internal procedure at %L by location " - "not allowed", &e->where); - goto cleanup; - } - } - } - - comp = gfc_get_proc_ptr_comp(e); - if (e->expr_type == EXPR_VARIABLE - && comp && comp->attr.elemental) - { - gfc_error ("ELEMENTAL procedure pointer component %qs is not " - "allowed as an actual argument at %L", comp->name, - &e->where); - } - - /* Fortran 2008, C1237. */ - if (e->expr_type == EXPR_VARIABLE && gfc_is_coindexed (e) - && gfc_has_ultimate_pointer (e)) - { - gfc_error ("Coindexed actual argument at %L with ultimate pointer " - "component", &e->where); - goto cleanup; - } - - first_actual_arg = false; - } - - return_value = true; - -cleanup: - actual_arg = actual_arg_sav; - first_actual_arg = first_actual_arg_sav; - - return return_value; -} - - -/* Do the checks of the actual argument list that are specific to elemental - procedures. If called with c == NULL, we have a function, otherwise if - expr == NULL, we have a subroutine. */ - -static bool -resolve_elemental_actual (gfc_expr *expr, gfc_code *c) -{ - gfc_actual_arglist *arg0; - gfc_actual_arglist *arg; - gfc_symbol *esym = NULL; - gfc_intrinsic_sym *isym = NULL; - gfc_expr *e = NULL; - gfc_intrinsic_arg *iformal = NULL; - gfc_formal_arglist *eformal = NULL; - bool formal_optional = false; - bool set_by_optional = false; - int i; - int rank = 0; - - /* Is this an elemental procedure? */ - if (expr && expr->value.function.actual != NULL) - { - if (expr->value.function.esym != NULL - && expr->value.function.esym->attr.elemental) - { - arg0 = expr->value.function.actual; - esym = expr->value.function.esym; - } - else if (expr->value.function.isym != NULL - && expr->value.function.isym->elemental) - { - arg0 = expr->value.function.actual; - isym = expr->value.function.isym; - } - else - return true; - } - else if (c && c->ext.actual != NULL) - { - arg0 = c->ext.actual; - - if (c->resolved_sym) - esym = c->resolved_sym; - else - esym = c->symtree->n.sym; - gcc_assert (esym); - - if (!esym->attr.elemental) - return true; - } - else - return true; - - /* The rank of an elemental is the rank of its array argument(s). */ - for (arg = arg0; arg; arg = arg->next) - { - if (arg->expr != NULL && arg->expr->rank != 0) - { - rank = arg->expr->rank; - if (arg->expr->expr_type == EXPR_VARIABLE - && arg->expr->symtree->n.sym->attr.optional) - set_by_optional = true; - - /* Function specific; set the result rank and shape. */ - if (expr) - { - expr->rank = rank; - if (!expr->shape && arg->expr->shape) - { - expr->shape = gfc_get_shape (rank); - for (i = 0; i < rank; i++) - mpz_init_set (expr->shape[i], arg->expr->shape[i]); - } - } - break; - } - } - - /* If it is an array, it shall not be supplied as an actual argument - to an elemental procedure unless an array of the same rank is supplied - as an actual argument corresponding to a nonoptional dummy argument of - that elemental procedure(12.4.1.5). */ - formal_optional = false; - if (isym) - iformal = isym->formal; - else - eformal = esym->formal; - - for (arg = arg0; arg; arg = arg->next) - { - if (eformal) - { - if (eformal->sym && eformal->sym->attr.optional) - formal_optional = true; - eformal = eformal->next; - } - else if (isym && iformal) - { - if (iformal->optional) - formal_optional = true; - iformal = iformal->next; - } - else if (isym) - formal_optional = true; - - if (pedantic && arg->expr != NULL - && arg->expr->expr_type == EXPR_VARIABLE - && arg->expr->symtree->n.sym->attr.optional - && formal_optional - && arg->expr->rank - && (set_by_optional || arg->expr->rank != rank) - && !(isym && isym->id == GFC_ISYM_CONVERSION)) - { - bool t = false; - gfc_actual_arglist *a; - - /* Scan the argument list for a non-optional argument with the - same rank as arg. */ - for (a = arg0; a; a = a->next) - if (a != arg - && a->expr->rank == arg->expr->rank - && !a->expr->symtree->n.sym->attr.optional) - { - t = true; - break; - } - - if (!t) - gfc_warning (OPT_Wpedantic, - "%qs at %L is an array and OPTIONAL; If it is not " - "present, then it cannot be the actual argument of " - "an ELEMENTAL procedure unless there is a non-optional" - " argument with the same rank " - "(Fortran 2018, 15.5.2.12)", - arg->expr->symtree->n.sym->name, &arg->expr->where); - } - } - - for (arg = arg0; arg; arg = arg->next) - { - if (arg->expr == NULL || arg->expr->rank == 0) - continue; - - /* Being elemental, the last upper bound of an assumed size array - argument must be present. */ - if (resolve_assumed_size_actual (arg->expr)) - return false; - - /* Elemental procedure's array actual arguments must conform. */ - if (e != NULL) - { - if (!gfc_check_conformance (arg->expr, e, _("elemental procedure"))) - return false; - } - else - e = arg->expr; - } - - /* INTENT(OUT) is only allowed for subroutines; if any actual argument - is an array, the intent inout/out variable needs to be also an array. */ - if (rank > 0 && esym && expr == NULL) - for (eformal = esym->formal, arg = arg0; arg && eformal; - arg = arg->next, eformal = eformal->next) - if ((eformal->sym->attr.intent == INTENT_OUT - || eformal->sym->attr.intent == INTENT_INOUT) - && arg->expr && arg->expr->rank == 0) - { - gfc_error ("Actual argument at %L for INTENT(%s) dummy %qs of " - "ELEMENTAL subroutine %qs is a scalar, but another " - "actual argument is an array", &arg->expr->where, - (eformal->sym->attr.intent == INTENT_OUT) ? "OUT" - : "INOUT", eformal->sym->name, esym->name); - return false; - } - return true; -} - - -/* This function does the checking of references to global procedures - as defined in sections 18.1 and 14.1, respectively, of the Fortran - 77 and 95 standards. It checks for a gsymbol for the name, making - one if it does not already exist. If it already exists, then the - reference being resolved must correspond to the type of gsymbol. - Otherwise, the new symbol is equipped with the attributes of the - reference. The corresponding code that is called in creating - global entities is parse.c. - - In addition, for all but -std=legacy, the gsymbols are used to - check the interfaces of external procedures from the same file. - The namespace of the gsymbol is resolved and then, once this is - done the interface is checked. */ - - -static bool -not_in_recursive (gfc_symbol *sym, gfc_namespace *gsym_ns) -{ - if (!gsym_ns->proc_name->attr.recursive) - return true; - - if (sym->ns == gsym_ns) - return false; - - if (sym->ns->parent && sym->ns->parent == gsym_ns) - return false; - - return true; -} - -static bool -not_entry_self_reference (gfc_symbol *sym, gfc_namespace *gsym_ns) -{ - if (gsym_ns->entries) - { - gfc_entry_list *entry = gsym_ns->entries; - - for (; entry; entry = entry->next) - { - if (strcmp (sym->name, entry->sym->name) == 0) - { - if (strcmp (gsym_ns->proc_name->name, - sym->ns->proc_name->name) == 0) - return false; - - if (sym->ns->parent - && strcmp (gsym_ns->proc_name->name, - sym->ns->parent->proc_name->name) == 0) - return false; - } - } - } - return true; -} - - -/* Check for the requirement of an explicit interface. F08:12.4.2.2. */ - -bool -gfc_explicit_interface_required (gfc_symbol *sym, char *errmsg, int err_len) -{ - gfc_formal_arglist *arg = gfc_sym_get_dummy_args (sym); - - for ( ; arg; arg = arg->next) - { - if (!arg->sym) - continue; - - if (arg->sym->attr.allocatable) /* (2a) */ - { - strncpy (errmsg, _("allocatable argument"), err_len); - return true; - } - else if (arg->sym->attr.asynchronous) - { - strncpy (errmsg, _("asynchronous argument"), err_len); - return true; - } - else if (arg->sym->attr.optional) - { - strncpy (errmsg, _("optional argument"), err_len); - return true; - } - else if (arg->sym->attr.pointer) - { - strncpy (errmsg, _("pointer argument"), err_len); - return true; - } - else if (arg->sym->attr.target) - { - strncpy (errmsg, _("target argument"), err_len); - return true; - } - else if (arg->sym->attr.value) - { - strncpy (errmsg, _("value argument"), err_len); - return true; - } - else if (arg->sym->attr.volatile_) - { - strncpy (errmsg, _("volatile argument"), err_len); - return true; - } - else if (arg->sym->as && arg->sym->as->type == AS_ASSUMED_SHAPE) /* (2b) */ - { - strncpy (errmsg, _("assumed-shape argument"), err_len); - return true; - } - else if (arg->sym->as && arg->sym->as->type == AS_ASSUMED_RANK) /* TS 29113, 6.2. */ - { - strncpy (errmsg, _("assumed-rank argument"), err_len); - return true; - } - else if (arg->sym->attr.codimension) /* (2c) */ - { - strncpy (errmsg, _("coarray argument"), err_len); - return true; - } - else if (false) /* (2d) TODO: parametrized derived type */ - { - strncpy (errmsg, _("parametrized derived type argument"), err_len); - return true; - } - else if (arg->sym->ts.type == BT_CLASS) /* (2e) */ - { - strncpy (errmsg, _("polymorphic argument"), err_len); - return true; - } - else if (arg->sym->attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK)) - { - strncpy (errmsg, _("NO_ARG_CHECK attribute"), err_len); - return true; - } - else if (arg->sym->ts.type == BT_ASSUMED) - { - /* As assumed-type is unlimited polymorphic (cf. above). - See also TS 29113, Note 6.1. */ - strncpy (errmsg, _("assumed-type argument"), err_len); - return true; - } - } - - if (sym->attr.function) - { - gfc_symbol *res = sym->result ? sym->result : sym; - - if (res->attr.dimension) /* (3a) */ - { - strncpy (errmsg, _("array result"), err_len); - return true; - } - else if (res->attr.pointer || res->attr.allocatable) /* (3b) */ - { - strncpy (errmsg, _("pointer or allocatable result"), err_len); - return true; - } - else if (res->ts.type == BT_CHARACTER && res->ts.u.cl - && res->ts.u.cl->length - && res->ts.u.cl->length->expr_type != EXPR_CONSTANT) /* (3c) */ - { - strncpy (errmsg, _("result with non-constant character length"), err_len); - return true; - } - } - - if (sym->attr.elemental && !sym->attr.intrinsic) /* (4) */ - { - strncpy (errmsg, _("elemental procedure"), err_len); - return true; - } - else if (sym->attr.is_bind_c) /* (5) */ - { - strncpy (errmsg, _("bind(c) procedure"), err_len); - return true; - } - - return false; -} - - -static void -resolve_global_procedure (gfc_symbol *sym, locus *where, int sub) -{ - gfc_gsymbol * gsym; - gfc_namespace *ns; - enum gfc_symbol_type type; - char reason[200]; - - type = sub ? GSYM_SUBROUTINE : GSYM_FUNCTION; - - gsym = gfc_get_gsymbol (sym->binding_label ? sym->binding_label : sym->name, - sym->binding_label != NULL); - - if ((gsym->type != GSYM_UNKNOWN && gsym->type != type)) - gfc_global_used (gsym, where); - - if ((sym->attr.if_source == IFSRC_UNKNOWN - || sym->attr.if_source == IFSRC_IFBODY) - && gsym->type != GSYM_UNKNOWN - && !gsym->binding_label - && gsym->ns - && gsym->ns->proc_name - && not_in_recursive (sym, gsym->ns) - && not_entry_self_reference (sym, gsym->ns)) - { - gfc_symbol *def_sym; - def_sym = gsym->ns->proc_name; - - if (gsym->ns->resolved != -1) - { - - /* Resolve the gsymbol namespace if needed. */ - if (!gsym->ns->resolved) - { - gfc_symbol *old_dt_list; - - /* Stash away derived types so that the backend_decls - do not get mixed up. */ - old_dt_list = gfc_derived_types; - gfc_derived_types = NULL; - - gfc_resolve (gsym->ns); - - /* Store the new derived types with the global namespace. */ - if (gfc_derived_types) - gsym->ns->derived_types = gfc_derived_types; - - /* Restore the derived types of this namespace. */ - gfc_derived_types = old_dt_list; - } - - /* Make sure that translation for the gsymbol occurs before - the procedure currently being resolved. */ - ns = gfc_global_ns_list; - for (; ns && ns != gsym->ns; ns = ns->sibling) - { - if (ns->sibling == gsym->ns) - { - ns->sibling = gsym->ns->sibling; - gsym->ns->sibling = gfc_global_ns_list; - gfc_global_ns_list = gsym->ns; - break; - } - } - - /* This can happen if a binding name has been specified. */ - if (gsym->binding_label && gsym->sym_name != def_sym->name) - gfc_find_symbol (gsym->sym_name, gsym->ns, 0, &def_sym); - - if (def_sym->attr.entry_master || def_sym->attr.entry) - { - gfc_entry_list *entry; - for (entry = gsym->ns->entries; entry; entry = entry->next) - if (strcmp (entry->sym->name, sym->name) == 0) - { - def_sym = entry->sym; - break; - } - } - } - - if (sym->attr.function && !gfc_compare_types (&sym->ts, &def_sym->ts)) - { - gfc_error ("Return type mismatch of function %qs at %L (%s/%s)", - sym->name, &sym->declared_at, gfc_typename (&sym->ts), - gfc_typename (&def_sym->ts)); - goto done; - } - - if (sym->attr.if_source == IFSRC_UNKNOWN - && gfc_explicit_interface_required (def_sym, reason, sizeof(reason))) - { - gfc_error ("Explicit interface required for %qs at %L: %s", - sym->name, &sym->declared_at, reason); - goto done; - } - - bool bad_result_characteristics; - if (!gfc_compare_interfaces (sym, def_sym, sym->name, 0, 1, - reason, sizeof(reason), NULL, NULL, - &bad_result_characteristics)) - { - /* Turn erros into warnings with -std=gnu and -std=legacy, - unless a function returns a wrong type, which can lead - to all kinds of ICEs and wrong code. */ - - if (!pedantic && (gfc_option.allow_std & GFC_STD_GNU) - && !bad_result_characteristics) - gfc_errors_to_warnings (true); - - gfc_error ("Interface mismatch in global procedure %qs at %L: %s", - sym->name, &sym->declared_at, reason); - sym->error = 1; - gfc_errors_to_warnings (false); - goto done; - } - } - -done: - - if (gsym->type == GSYM_UNKNOWN) - { - gsym->type = type; - gsym->where = *where; - } - - gsym->used = 1; -} - - -/************* Function resolution *************/ - -/* Resolve a function call known to be generic. - Section 14.1.2.4.1. */ - -static match -resolve_generic_f0 (gfc_expr *expr, gfc_symbol *sym) -{ - gfc_symbol *s; - - if (sym->attr.generic) - { - s = gfc_search_interface (sym->generic, 0, &expr->value.function.actual); - if (s != NULL) - { - expr->value.function.name = s->name; - expr->value.function.esym = s; - - if (s->ts.type != BT_UNKNOWN) - expr->ts = s->ts; - else if (s->result != NULL && s->result->ts.type != BT_UNKNOWN) - expr->ts = s->result->ts; - - if (s->as != NULL) - expr->rank = s->as->rank; - else if (s->result != NULL && s->result->as != NULL) - expr->rank = s->result->as->rank; - - gfc_set_sym_referenced (expr->value.function.esym); - - return MATCH_YES; - } - - /* TODO: Need to search for elemental references in generic - interface. */ - } - - if (sym->attr.intrinsic) - return gfc_intrinsic_func_interface (expr, 0); - - return MATCH_NO; -} - - -static bool -resolve_generic_f (gfc_expr *expr) -{ - gfc_symbol *sym; - match m; - gfc_interface *intr = NULL; - - sym = expr->symtree->n.sym; - - for (;;) - { - m = resolve_generic_f0 (expr, sym); - if (m == MATCH_YES) - return true; - else if (m == MATCH_ERROR) - return false; - -generic: - if (!intr) - for (intr = sym->generic; intr; intr = intr->next) - if (gfc_fl_struct (intr->sym->attr.flavor)) - break; - - if (sym->ns->parent == NULL) - break; - gfc_find_symbol (sym->name, sym->ns->parent, 1, &sym); - - if (sym == NULL) - break; - if (!generic_sym (sym)) - goto generic; - } - - /* Last ditch attempt. See if the reference is to an intrinsic - that possesses a matching interface. 14.1.2.4 */ - if (sym && !intr && !gfc_is_intrinsic (sym, 0, expr->where)) - { - if (gfc_init_expr_flag) - gfc_error ("Function %qs in initialization expression at %L " - "must be an intrinsic function", - expr->symtree->n.sym->name, &expr->where); - else - gfc_error ("There is no specific function for the generic %qs " - "at %L", expr->symtree->n.sym->name, &expr->where); - return false; - } - - if (intr) - { - if (!gfc_convert_to_structure_constructor (expr, intr->sym, NULL, - NULL, false)) - return false; - if (!gfc_use_derived (expr->ts.u.derived)) - return false; - return resolve_structure_cons (expr, 0); - } - - m = gfc_intrinsic_func_interface (expr, 0); - if (m == MATCH_YES) - return true; - - if (m == MATCH_NO) - gfc_error ("Generic function %qs at %L is not consistent with a " - "specific intrinsic interface", expr->symtree->n.sym->name, - &expr->where); - - return false; -} - - -/* Resolve a function call known to be specific. */ - -static match -resolve_specific_f0 (gfc_symbol *sym, gfc_expr *expr) -{ - match m; - - if (sym->attr.external || sym->attr.if_source == IFSRC_IFBODY) - { - if (sym->attr.dummy) - { - sym->attr.proc = PROC_DUMMY; - goto found; - } - - sym->attr.proc = PROC_EXTERNAL; - goto found; - } - - if (sym->attr.proc == PROC_MODULE - || sym->attr.proc == PROC_ST_FUNCTION - || sym->attr.proc == PROC_INTERNAL) - goto found; - - if (sym->attr.intrinsic) - { - m = gfc_intrinsic_func_interface (expr, 1); - if (m == MATCH_YES) - return MATCH_YES; - if (m == MATCH_NO) - gfc_error ("Function %qs at %L is INTRINSIC but is not compatible " - "with an intrinsic", sym->name, &expr->where); - - return MATCH_ERROR; - } - - return MATCH_NO; - -found: - gfc_procedure_use (sym, &expr->value.function.actual, &expr->where); - - if (sym->result) - expr->ts = sym->result->ts; - else - expr->ts = sym->ts; - expr->value.function.name = sym->name; - expr->value.function.esym = sym; - /* Prevent crash when sym->ts.u.derived->components is not set due to previous - error(s). */ - if (sym->ts.type == BT_CLASS && !CLASS_DATA (sym)) - return MATCH_ERROR; - if (sym->ts.type == BT_CLASS && CLASS_DATA (sym)->as) - expr->rank = CLASS_DATA (sym)->as->rank; - else if (sym->as != NULL) - expr->rank = sym->as->rank; - - return MATCH_YES; -} - - -static bool -resolve_specific_f (gfc_expr *expr) -{ - gfc_symbol *sym; - match m; - - sym = expr->symtree->n.sym; - - for (;;) - { - m = resolve_specific_f0 (sym, expr); - if (m == MATCH_YES) - return true; - if (m == MATCH_ERROR) - return false; - - if (sym->ns->parent == NULL) - break; - - gfc_find_symbol (sym->name, sym->ns->parent, 1, &sym); - - if (sym == NULL) - break; - } - - gfc_error ("Unable to resolve the specific function %qs at %L", - expr->symtree->n.sym->name, &expr->where); - - return true; -} - -/* Recursively append candidate SYM to CANDIDATES. Store the number of - candidates in CANDIDATES_LEN. */ - -static void -lookup_function_fuzzy_find_candidates (gfc_symtree *sym, - char **&candidates, - size_t &candidates_len) -{ - gfc_symtree *p; - - if (sym == NULL) - return; - if ((sym->n.sym->ts.type != BT_UNKNOWN || sym->n.sym->attr.external) - && sym->n.sym->attr.flavor == FL_PROCEDURE) - vec_push (candidates, candidates_len, sym->name); - - p = sym->left; - if (p) - lookup_function_fuzzy_find_candidates (p, candidates, candidates_len); - - p = sym->right; - if (p) - lookup_function_fuzzy_find_candidates (p, candidates, candidates_len); -} - - -/* Lookup function FN fuzzily, taking names in SYMROOT into account. */ - -const char* -gfc_lookup_function_fuzzy (const char *fn, gfc_symtree *symroot) -{ - char **candidates = NULL; - size_t candidates_len = 0; - lookup_function_fuzzy_find_candidates (symroot, candidates, candidates_len); - return gfc_closest_fuzzy_match (fn, candidates); -} - - -/* Resolve a procedure call not known to be generic nor specific. */ - -static bool -resolve_unknown_f (gfc_expr *expr) -{ - gfc_symbol *sym; - gfc_typespec *ts; - - sym = expr->symtree->n.sym; - - if (sym->attr.dummy) - { - sym->attr.proc = PROC_DUMMY; - expr->value.function.name = sym->name; - goto set_type; - } - - /* See if we have an intrinsic function reference. */ - - if (gfc_is_intrinsic (sym, 0, expr->where)) - { - if (gfc_intrinsic_func_interface (expr, 1) == MATCH_YES) - return true; - return false; - } - - /* IMPLICIT NONE (external) procedures require an explicit EXTERNAL attr. */ - /* Intrinsics were handled above, only non-intrinsics left here. */ - if (sym->attr.flavor == FL_PROCEDURE - && sym->attr.implicit_type - && sym->ns - && sym->ns->has_implicit_none_export) - { - gfc_error ("Missing explicit declaration with EXTERNAL attribute " - "for symbol %qs at %L", sym->name, &sym->declared_at); - sym->error = 1; - return false; - } - - /* The reference is to an external name. */ - - sym->attr.proc = PROC_EXTERNAL; - expr->value.function.name = sym->name; - expr->value.function.esym = expr->symtree->n.sym; - - if (sym->as != NULL) - expr->rank = sym->as->rank; - - /* Type of the expression is either the type of the symbol or the - default type of the symbol. */ - -set_type: - gfc_procedure_use (sym, &expr->value.function.actual, &expr->where); - - if (sym->ts.type != BT_UNKNOWN) - expr->ts = sym->ts; - else - { - ts = gfc_get_default_type (sym->name, sym->ns); - - if (ts->type == BT_UNKNOWN) - { - const char *guessed - = gfc_lookup_function_fuzzy (sym->name, sym->ns->sym_root); - if (guessed) - gfc_error ("Function %qs at %L has no IMPLICIT type" - "; did you mean %qs?", - sym->name, &expr->where, guessed); - else - gfc_error ("Function %qs at %L has no IMPLICIT type", - sym->name, &expr->where); - return false; - } - else - expr->ts = *ts; - } - - return true; -} - - -/* Return true, if the symbol is an external procedure. */ -static bool -is_external_proc (gfc_symbol *sym) -{ - if (!sym->attr.dummy && !sym->attr.contained - && !gfc_is_intrinsic (sym, sym->attr.subroutine, sym->declared_at) - && sym->attr.proc != PROC_ST_FUNCTION - && !sym->attr.proc_pointer - && !sym->attr.use_assoc - && sym->name) - return true; - - return false; -} - - -/* Figure out if a function reference is pure or not. Also set the name - of the function for a potential error message. Return nonzero if the - function is PURE, zero if not. */ -static int -pure_stmt_function (gfc_expr *, gfc_symbol *); - -int -gfc_pure_function (gfc_expr *e, const char **name) -{ - int pure; - gfc_component *comp; - - *name = NULL; - - if (e->symtree != NULL - && e->symtree->n.sym != NULL - && e->symtree->n.sym->attr.proc == PROC_ST_FUNCTION) - return pure_stmt_function (e, e->symtree->n.sym); - - comp = gfc_get_proc_ptr_comp (e); - if (comp) - { - pure = gfc_pure (comp->ts.interface); - *name = comp->name; - } - else if (e->value.function.esym) - { - pure = gfc_pure (e->value.function.esym); - *name = e->value.function.esym->name; - } - else if (e->value.function.isym) - { - pure = e->value.function.isym->pure - || e->value.function.isym->elemental; - *name = e->value.function.isym->name; - } - else - { - /* Implicit functions are not pure. */ - pure = 0; - *name = e->value.function.name; - } - - return pure; -} - - -/* Check if the expression is a reference to an implicitly pure function. */ - -int -gfc_implicit_pure_function (gfc_expr *e) -{ - gfc_component *comp = gfc_get_proc_ptr_comp (e); - if (comp) - return gfc_implicit_pure (comp->ts.interface); - else if (e->value.function.esym) - return gfc_implicit_pure (e->value.function.esym); - else - return 0; -} - - -static bool -impure_stmt_fcn (gfc_expr *e, gfc_symbol *sym, - int *f ATTRIBUTE_UNUSED) -{ - const char *name; - - /* Don't bother recursing into other statement functions - since they will be checked individually for purity. */ - if (e->expr_type != EXPR_FUNCTION - || !e->symtree - || e->symtree->n.sym == sym - || e->symtree->n.sym->attr.proc == PROC_ST_FUNCTION) - return false; - - return gfc_pure_function (e, &name) ? false : true; -} - - -static int -pure_stmt_function (gfc_expr *e, gfc_symbol *sym) -{ - return gfc_traverse_expr (e, sym, impure_stmt_fcn, 0) ? 0 : 1; -} - - -/* Check if an impure function is allowed in the current context. */ - -static bool check_pure_function (gfc_expr *e) -{ - const char *name = NULL; - if (!gfc_pure_function (e, &name) && name) - { - if (forall_flag) - { - gfc_error ("Reference to impure function %qs at %L inside a " - "FORALL %s", name, &e->where, - forall_flag == 2 ? "mask" : "block"); - return false; - } - else if (gfc_do_concurrent_flag) - { - gfc_error ("Reference to impure function %qs at %L inside a " - "DO CONCURRENT %s", name, &e->where, - gfc_do_concurrent_flag == 2 ? "mask" : "block"); - return false; - } - else if (gfc_pure (NULL)) - { - gfc_error ("Reference to impure function %qs at %L " - "within a PURE procedure", name, &e->where); - return false; - } - if (!gfc_implicit_pure_function (e)) - gfc_unset_implicit_pure (NULL); - } - return true; -} - - -/* Update current procedure's array_outer_dependency flag, considering - a call to procedure SYM. */ - -static void -update_current_proc_array_outer_dependency (gfc_symbol *sym) -{ - /* Check to see if this is a sibling function that has not yet - been resolved. */ - gfc_namespace *sibling = gfc_current_ns->sibling; - for (; sibling; sibling = sibling->sibling) - { - if (sibling->proc_name == sym) - { - gfc_resolve (sibling); - break; - } - } - - /* If SYM has references to outer arrays, so has the procedure calling - SYM. If SYM is a procedure pointer, we can assume the worst. */ - if ((sym->attr.array_outer_dependency || sym->attr.proc_pointer) - && gfc_current_ns->proc_name) - gfc_current_ns->proc_name->attr.array_outer_dependency = 1; -} - - -/* Resolve a function call, which means resolving the arguments, then figuring - out which entity the name refers to. */ - -static bool -resolve_function (gfc_expr *expr) -{ - gfc_actual_arglist *arg; - gfc_symbol *sym; - bool t; - int temp; - procedure_type p = PROC_INTRINSIC; - bool no_formal_args; - - sym = NULL; - if (expr->symtree) - sym = expr->symtree->n.sym; - - /* If this is a procedure pointer component, it has already been resolved. */ - if (gfc_is_proc_ptr_comp (expr)) - return true; - - /* Avoid re-resolving the arguments of caf_get, which can lead to inserting - another caf_get. */ - if (sym && sym->attr.intrinsic - && (sym->intmod_sym_id == GFC_ISYM_CAF_GET - || sym->intmod_sym_id == GFC_ISYM_CAF_SEND)) - return true; - - if (expr->ref) - { - gfc_error ("Unexpected junk after %qs at %L", expr->symtree->n.sym->name, - &expr->where); - return false; - } - - if (sym && sym->attr.intrinsic - && !gfc_resolve_intrinsic (sym, &expr->where)) - return false; - - if (sym && (sym->attr.flavor == FL_VARIABLE || sym->attr.subroutine)) - { - gfc_error ("%qs at %L is not a function", sym->name, &expr->where); - return false; - } - - /* If this is a deferred TBP with an abstract interface (which may - of course be referenced), expr->value.function.esym will be set. */ - if (sym && sym->attr.abstract && !expr->value.function.esym) - { - gfc_error ("ABSTRACT INTERFACE %qs must not be referenced at %L", - sym->name, &expr->where); - return false; - } - - /* If this is a deferred TBP with an abstract interface, its result - cannot be an assumed length character (F2003: C418). */ - if (sym && sym->attr.abstract && sym->attr.function - && sym->result->ts.u.cl - && sym->result->ts.u.cl->length == NULL - && !sym->result->ts.deferred) - { - gfc_error ("ABSTRACT INTERFACE %qs at %L must not have an assumed " - "character length result (F2008: C418)", sym->name, - &sym->declared_at); - return false; - } - - /* Switch off assumed size checking and do this again for certain kinds - of procedure, once the procedure itself is resolved. */ - need_full_assumed_size++; - - if (expr->symtree && expr->symtree->n.sym) - p = expr->symtree->n.sym->attr.proc; - - if (expr->value.function.isym && expr->value.function.isym->inquiry) - inquiry_argument = true; - no_formal_args = sym && is_external_proc (sym) - && gfc_sym_get_dummy_args (sym) == NULL; - - if (!resolve_actual_arglist (expr->value.function.actual, - p, no_formal_args)) - { - inquiry_argument = false; - return false; - } - - inquiry_argument = false; - - /* Resume assumed_size checking. */ - need_full_assumed_size--; - - /* If the procedure is external, check for usage. */ - if (sym && is_external_proc (sym)) - resolve_global_procedure (sym, &expr->where, 0); - - if (sym && sym->ts.type == BT_CHARACTER - && sym->ts.u.cl - && sym->ts.u.cl->length == NULL - && !sym->attr.dummy - && !sym->ts.deferred - && expr->value.function.esym == NULL - && !sym->attr.contained) - { - /* Internal procedures are taken care of in resolve_contained_fntype. */ - gfc_error ("Function %qs is declared CHARACTER(*) and cannot " - "be used at %L since it is not a dummy argument", - sym->name, &expr->where); - return false; - } - - /* See if function is already resolved. */ - - if (expr->value.function.name != NULL - || expr->value.function.isym != NULL) - { - if (expr->ts.type == BT_UNKNOWN) - expr->ts = sym->ts; - t = true; - } - else - { - /* Apply the rules of section 14.1.2. */ - - switch (procedure_kind (sym)) - { - case PTYPE_GENERIC: - t = resolve_generic_f (expr); - break; - - case PTYPE_SPECIFIC: - t = resolve_specific_f (expr); - break; - - case PTYPE_UNKNOWN: - t = resolve_unknown_f (expr); - break; - - default: - gfc_internal_error ("resolve_function(): bad function type"); - } - } - - /* If the expression is still a function (it might have simplified), - then we check to see if we are calling an elemental function. */ - - if (expr->expr_type != EXPR_FUNCTION) - return t; - - /* Walk the argument list looking for invalid BOZ. */ - for (arg = expr->value.function.actual; arg; arg = arg->next) - if (arg->expr && arg->expr->ts.type == BT_BOZ) - { - gfc_error ("A BOZ literal constant at %L cannot appear as an " - "actual argument in a function reference", - &arg->expr->where); - return false; - } - - temp = need_full_assumed_size; - need_full_assumed_size = 0; - - if (!resolve_elemental_actual (expr, NULL)) - return false; - - if (omp_workshare_flag - && expr->value.function.esym - && ! gfc_elemental (expr->value.function.esym)) - { - gfc_error ("User defined non-ELEMENTAL function %qs at %L not allowed " - "in WORKSHARE construct", expr->value.function.esym->name, - &expr->where); - t = false; - } - -#define GENERIC_ID expr->value.function.isym->id - else if (expr->value.function.actual != NULL - && expr->value.function.isym != NULL - && GENERIC_ID != GFC_ISYM_LBOUND - && GENERIC_ID != GFC_ISYM_LCOBOUND - && GENERIC_ID != GFC_ISYM_UCOBOUND - && GENERIC_ID != GFC_ISYM_LEN - && GENERIC_ID != GFC_ISYM_LOC - && GENERIC_ID != GFC_ISYM_C_LOC - && GENERIC_ID != GFC_ISYM_PRESENT) - { - /* Array intrinsics must also have the last upper bound of an - assumed size array argument. UBOUND and SIZE have to be - excluded from the check if the second argument is anything - than a constant. */ - - for (arg = expr->value.function.actual; arg; arg = arg->next) - { - if ((GENERIC_ID == GFC_ISYM_UBOUND || GENERIC_ID == GFC_ISYM_SIZE) - && arg == expr->value.function.actual - && arg->next != NULL && arg->next->expr) - { - if (arg->next->expr->expr_type != EXPR_CONSTANT) - break; - - if (arg->next->name && strcmp (arg->next->name, "kind") == 0) - break; - - if ((int)mpz_get_si (arg->next->expr->value.integer) - < arg->expr->rank) - break; - } - - if (arg->expr != NULL - && arg->expr->rank > 0 - && resolve_assumed_size_actual (arg->expr)) - return false; - } - } -#undef GENERIC_ID - - need_full_assumed_size = temp; - - if (!check_pure_function(expr)) - t = false; - - /* Functions without the RECURSIVE attribution are not allowed to - * call themselves. */ - if (expr->value.function.esym && !expr->value.function.esym->attr.recursive) - { - gfc_symbol *esym; - esym = expr->value.function.esym; - - if (is_illegal_recursion (esym, gfc_current_ns)) - { - if (esym->attr.entry && esym->ns->entries) - gfc_error ("ENTRY %qs at %L cannot be called recursively, as" - " function %qs is not RECURSIVE", - esym->name, &expr->where, esym->ns->entries->sym->name); - else - gfc_error ("Function %qs at %L cannot be called recursively, as it" - " is not RECURSIVE", esym->name, &expr->where); - - t = false; - } - } - - /* Character lengths of use associated functions may contains references to - symbols not referenced from the current program unit otherwise. Make sure - those symbols are marked as referenced. */ - - if (expr->ts.type == BT_CHARACTER && expr->value.function.esym - && expr->value.function.esym->attr.use_assoc) - { - gfc_expr_set_symbols_referenced (expr->ts.u.cl->length); - } - - /* Make sure that the expression has a typespec that works. */ - if (expr->ts.type == BT_UNKNOWN) - { - if (expr->symtree->n.sym->result - && expr->symtree->n.sym->result->ts.type != BT_UNKNOWN - && !expr->symtree->n.sym->result->attr.proc_pointer) - expr->ts = expr->symtree->n.sym->result->ts; - } - - if (!expr->ref && !expr->value.function.isym) - { - if (expr->value.function.esym) - update_current_proc_array_outer_dependency (expr->value.function.esym); - else - update_current_proc_array_outer_dependency (sym); - } - else if (expr->ref) - /* typebound procedure: Assume the worst. */ - gfc_current_ns->proc_name->attr.array_outer_dependency = 1; - - if (expr->value.function.esym - && expr->value.function.esym->attr.ext_attr & (1 << EXT_ATTR_DEPRECATED)) - gfc_warning (OPT_Wdeprecated_declarations, - "Using function %qs at %L is deprecated", - sym->name, &expr->where); - return t; -} - - -/************* Subroutine resolution *************/ - -static bool -pure_subroutine (gfc_symbol *sym, const char *name, locus *loc) -{ - if (gfc_pure (sym)) - return true; - - if (forall_flag) - { - gfc_error ("Subroutine call to %qs in FORALL block at %L is not PURE", - name, loc); - return false; - } - else if (gfc_do_concurrent_flag) - { - gfc_error ("Subroutine call to %qs in DO CONCURRENT block at %L is not " - "PURE", name, loc); - return false; - } - else if (gfc_pure (NULL)) - { - gfc_error ("Subroutine call to %qs at %L is not PURE", name, loc); - return false; - } - - gfc_unset_implicit_pure (NULL); - return true; -} - - -static match -resolve_generic_s0 (gfc_code *c, gfc_symbol *sym) -{ - gfc_symbol *s; - - if (sym->attr.generic) - { - s = gfc_search_interface (sym->generic, 1, &c->ext.actual); - if (s != NULL) - { - c->resolved_sym = s; - if (!pure_subroutine (s, s->name, &c->loc)) - return MATCH_ERROR; - return MATCH_YES; - } - - /* TODO: Need to search for elemental references in generic interface. */ - } - - if (sym->attr.intrinsic) - return gfc_intrinsic_sub_interface (c, 0); - - return MATCH_NO; -} - - -static bool -resolve_generic_s (gfc_code *c) -{ - gfc_symbol *sym; - match m; - - sym = c->symtree->n.sym; - - for (;;) - { - m = resolve_generic_s0 (c, sym); - if (m == MATCH_YES) - return true; - else if (m == MATCH_ERROR) - return false; - -generic: - if (sym->ns->parent == NULL) - break; - gfc_find_symbol (sym->name, sym->ns->parent, 1, &sym); - - if (sym == NULL) - break; - if (!generic_sym (sym)) - goto generic; - } - - /* Last ditch attempt. See if the reference is to an intrinsic - that possesses a matching interface. 14.1.2.4 */ - sym = c->symtree->n.sym; - - if (!gfc_is_intrinsic (sym, 1, c->loc)) - { - gfc_error ("There is no specific subroutine for the generic %qs at %L", - sym->name, &c->loc); - return false; - } - - m = gfc_intrinsic_sub_interface (c, 0); - if (m == MATCH_YES) - return true; - if (m == MATCH_NO) - gfc_error ("Generic subroutine %qs at %L is not consistent with an " - "intrinsic subroutine interface", sym->name, &c->loc); - - return false; -} - - -/* Resolve a subroutine call known to be specific. */ - -static match -resolve_specific_s0 (gfc_code *c, gfc_symbol *sym) -{ - match m; - - if (sym->attr.external || sym->attr.if_source == IFSRC_IFBODY) - { - if (sym->attr.dummy) - { - sym->attr.proc = PROC_DUMMY; - goto found; - } - - sym->attr.proc = PROC_EXTERNAL; - goto found; - } - - if (sym->attr.proc == PROC_MODULE || sym->attr.proc == PROC_INTERNAL) - goto found; - - if (sym->attr.intrinsic) - { - m = gfc_intrinsic_sub_interface (c, 1); - if (m == MATCH_YES) - return MATCH_YES; - if (m == MATCH_NO) - gfc_error ("Subroutine %qs at %L is INTRINSIC but is not compatible " - "with an intrinsic", sym->name, &c->loc); - - return MATCH_ERROR; - } - - return MATCH_NO; - -found: - gfc_procedure_use (sym, &c->ext.actual, &c->loc); - - c->resolved_sym = sym; - if (!pure_subroutine (sym, sym->name, &c->loc)) - return MATCH_ERROR; - - return MATCH_YES; -} - - -static bool -resolve_specific_s (gfc_code *c) -{ - gfc_symbol *sym; - match m; - - sym = c->symtree->n.sym; - - for (;;) - { - m = resolve_specific_s0 (c, sym); - if (m == MATCH_YES) - return true; - if (m == MATCH_ERROR) - return false; - - if (sym->ns->parent == NULL) - break; - - gfc_find_symbol (sym->name, sym->ns->parent, 1, &sym); - - if (sym == NULL) - break; - } - - sym = c->symtree->n.sym; - gfc_error ("Unable to resolve the specific subroutine %qs at %L", - sym->name, &c->loc); - - return false; -} - - -/* Resolve a subroutine call not known to be generic nor specific. */ - -static bool -resolve_unknown_s (gfc_code *c) -{ - gfc_symbol *sym; - - sym = c->symtree->n.sym; - - if (sym->attr.dummy) - { - sym->attr.proc = PROC_DUMMY; - goto found; - } - - /* See if we have an intrinsic function reference. */ - - if (gfc_is_intrinsic (sym, 1, c->loc)) - { - if (gfc_intrinsic_sub_interface (c, 1) == MATCH_YES) - return true; - return false; - } - - /* The reference is to an external name. */ - -found: - gfc_procedure_use (sym, &c->ext.actual, &c->loc); - - c->resolved_sym = sym; - - return pure_subroutine (sym, sym->name, &c->loc); -} - - -/* Resolve a subroutine call. Although it was tempting to use the same code - for functions, subroutines and functions are stored differently and this - makes things awkward. */ - -static bool -resolve_call (gfc_code *c) -{ - bool t; - procedure_type ptype = PROC_INTRINSIC; - gfc_symbol *csym, *sym; - bool no_formal_args; - - csym = c->symtree ? c->symtree->n.sym : NULL; - - if (csym && csym->ts.type != BT_UNKNOWN) - { - gfc_error ("%qs at %L has a type, which is not consistent with " - "the CALL at %L", csym->name, &csym->declared_at, &c->loc); - return false; - } - - if (csym && gfc_current_ns->parent && csym->ns != gfc_current_ns) - { - gfc_symtree *st; - gfc_find_sym_tree (c->symtree->name, gfc_current_ns, 1, &st); - sym = st ? st->n.sym : NULL; - if (sym && csym != sym - && sym->ns == gfc_current_ns - && sym->attr.flavor == FL_PROCEDURE - && sym->attr.contained) - { - sym->refs++; - if (csym->attr.generic) - c->symtree->n.sym = sym; - else - c->symtree = st; - csym = c->symtree->n.sym; - } - } - - /* If this ia a deferred TBP, c->expr1 will be set. */ - if (!c->expr1 && csym) - { - if (csym->attr.abstract) - { - gfc_error ("ABSTRACT INTERFACE %qs must not be referenced at %L", - csym->name, &c->loc); - return false; - } - - /* Subroutines without the RECURSIVE attribution are not allowed to - call themselves. */ - if (is_illegal_recursion (csym, gfc_current_ns)) - { - if (csym->attr.entry && csym->ns->entries) - gfc_error ("ENTRY %qs at %L cannot be called recursively, " - "as subroutine %qs is not RECURSIVE", - csym->name, &c->loc, csym->ns->entries->sym->name); - else - gfc_error ("SUBROUTINE %qs at %L cannot be called recursively, " - "as it is not RECURSIVE", csym->name, &c->loc); - - t = false; - } - } - - /* Switch off assumed size checking and do this again for certain kinds - of procedure, once the procedure itself is resolved. */ - need_full_assumed_size++; - - if (csym) - ptype = csym->attr.proc; - - no_formal_args = csym && is_external_proc (csym) - && gfc_sym_get_dummy_args (csym) == NULL; - if (!resolve_actual_arglist (c->ext.actual, ptype, no_formal_args)) - return false; - - /* Resume assumed_size checking. */ - need_full_assumed_size--; - - /* If external, check for usage. */ - if (csym && is_external_proc (csym)) - resolve_global_procedure (csym, &c->loc, 1); - - t = true; - if (c->resolved_sym == NULL) - { - c->resolved_isym = NULL; - switch (procedure_kind (csym)) - { - case PTYPE_GENERIC: - t = resolve_generic_s (c); - break; - - case PTYPE_SPECIFIC: - t = resolve_specific_s (c); - break; - - case PTYPE_UNKNOWN: - t = resolve_unknown_s (c); - break; - - default: - gfc_internal_error ("resolve_subroutine(): bad function type"); - } - } - - /* Some checks of elemental subroutine actual arguments. */ - if (!resolve_elemental_actual (NULL, c)) - return false; - - if (!c->expr1) - update_current_proc_array_outer_dependency (csym); - else - /* Typebound procedure: Assume the worst. */ - gfc_current_ns->proc_name->attr.array_outer_dependency = 1; - - if (c->resolved_sym - && c->resolved_sym->attr.ext_attr & (1 << EXT_ATTR_DEPRECATED)) - gfc_warning (OPT_Wdeprecated_declarations, - "Using subroutine %qs at %L is deprecated", - c->resolved_sym->name, &c->loc); - - return t; -} - - -/* Compare the shapes of two arrays that have non-NULL shapes. If both - op1->shape and op2->shape are non-NULL return true if their shapes - match. If both op1->shape and op2->shape are non-NULL return false - if their shapes do not match. If either op1->shape or op2->shape is - NULL, return true. */ - -static bool -compare_shapes (gfc_expr *op1, gfc_expr *op2) -{ - bool t; - int i; - - t = true; - - if (op1->shape != NULL && op2->shape != NULL) - { - for (i = 0; i < op1->rank; i++) - { - if (mpz_cmp (op1->shape[i], op2->shape[i]) != 0) - { - gfc_error ("Shapes for operands at %L and %L are not conformable", - &op1->where, &op2->where); - t = false; - break; - } - } - } - - return t; -} - -/* Convert a logical operator to the corresponding bitwise intrinsic call. - For example A .AND. B becomes IAND(A, B). */ -static gfc_expr * -logical_to_bitwise (gfc_expr *e) -{ - gfc_expr *tmp, *op1, *op2; - gfc_isym_id isym; - gfc_actual_arglist *args = NULL; - - gcc_assert (e->expr_type == EXPR_OP); - - isym = GFC_ISYM_NONE; - op1 = e->value.op.op1; - op2 = e->value.op.op2; - - switch (e->value.op.op) - { - case INTRINSIC_NOT: - isym = GFC_ISYM_NOT; - break; - case INTRINSIC_AND: - isym = GFC_ISYM_IAND; - break; - case INTRINSIC_OR: - isym = GFC_ISYM_IOR; - break; - case INTRINSIC_NEQV: - isym = GFC_ISYM_IEOR; - break; - case INTRINSIC_EQV: - /* "Bitwise eqv" is just the complement of NEQV === IEOR. - Change the old expression to NEQV, which will get replaced by IEOR, - and wrap it in NOT. */ - tmp = gfc_copy_expr (e); - tmp->value.op.op = INTRINSIC_NEQV; - tmp = logical_to_bitwise (tmp); - isym = GFC_ISYM_NOT; - op1 = tmp; - op2 = NULL; - break; - default: - gfc_internal_error ("logical_to_bitwise(): Bad intrinsic"); - } - - /* Inherit the original operation's operands as arguments. */ - args = gfc_get_actual_arglist (); - args->expr = op1; - if (op2) - { - args->next = gfc_get_actual_arglist (); - args->next->expr = op2; - } - - /* Convert the expression to a function call. */ - e->expr_type = EXPR_FUNCTION; - e->value.function.actual = args; - e->value.function.isym = gfc_intrinsic_function_by_id (isym); - e->value.function.name = e->value.function.isym->name; - e->value.function.esym = NULL; - - /* Make up a pre-resolved function call symtree if we need to. */ - if (!e->symtree || !e->symtree->n.sym) - { - gfc_symbol *sym; - gfc_get_ha_sym_tree (e->value.function.isym->name, &e->symtree); - sym = e->symtree->n.sym; - sym->result = sym; - sym->attr.flavor = FL_PROCEDURE; - sym->attr.function = 1; - sym->attr.elemental = 1; - sym->attr.pure = 1; - sym->attr.referenced = 1; - gfc_intrinsic_symbol (sym); - gfc_commit_symbol (sym); - } - - args->name = e->value.function.isym->formal->name; - if (e->value.function.isym->formal->next) - args->next->name = e->value.function.isym->formal->next->name; - - return e; -} - -/* Recursively append candidate UOP to CANDIDATES. Store the number of - candidates in CANDIDATES_LEN. */ -static void -lookup_uop_fuzzy_find_candidates (gfc_symtree *uop, - char **&candidates, - size_t &candidates_len) -{ - gfc_symtree *p; - - if (uop == NULL) - return; - - /* Not sure how to properly filter here. Use all for a start. - n.uop.op is NULL for empty interface operators (is that legal?) disregard - these as i suppose they don't make terribly sense. */ - - if (uop->n.uop->op != NULL) - vec_push (candidates, candidates_len, uop->name); - - p = uop->left; - if (p) - lookup_uop_fuzzy_find_candidates (p, candidates, candidates_len); - - p = uop->right; - if (p) - lookup_uop_fuzzy_find_candidates (p, candidates, candidates_len); -} - -/* Lookup user-operator OP fuzzily, taking names in UOP into account. */ - -static const char* -lookup_uop_fuzzy (const char *op, gfc_symtree *uop) -{ - char **candidates = NULL; - size_t candidates_len = 0; - lookup_uop_fuzzy_find_candidates (uop, candidates, candidates_len); - return gfc_closest_fuzzy_match (op, candidates); -} - - -/* Callback finding an impure function as an operand to an .and. or - .or. expression. Remember the last function warned about to - avoid double warnings when recursing. */ - -static int -impure_function_callback (gfc_expr **e, int *walk_subtrees ATTRIBUTE_UNUSED, - void *data) -{ - gfc_expr *f = *e; - const char *name; - static gfc_expr *last = NULL; - bool *found = (bool *) data; - - if (f->expr_type == EXPR_FUNCTION) - { - *found = 1; - if (f != last && !gfc_pure_function (f, &name) - && !gfc_implicit_pure_function (f)) - { - if (name) - gfc_warning (OPT_Wfunction_elimination, - "Impure function %qs at %L might not be evaluated", - name, &f->where); - else - gfc_warning (OPT_Wfunction_elimination, - "Impure function at %L might not be evaluated", - &f->where); - } - last = f; - } - - return 0; -} - -/* Return true if TYPE is character based, false otherwise. */ - -static int -is_character_based (bt type) -{ - return type == BT_CHARACTER || type == BT_HOLLERITH; -} - - -/* If expression is a hollerith, convert it to character and issue a warning - for the conversion. */ - -static void -convert_hollerith_to_character (gfc_expr *e) -{ - if (e->ts.type == BT_HOLLERITH) - { - gfc_typespec t; - gfc_clear_ts (&t); - t.type = BT_CHARACTER; - t.kind = e->ts.kind; - gfc_convert_type_warn (e, &t, 2, 1); - } -} - -/* Convert to numeric and issue a warning for the conversion. */ - -static void -convert_to_numeric (gfc_expr *a, gfc_expr *b) -{ - gfc_typespec t; - gfc_clear_ts (&t); - t.type = b->ts.type; - t.kind = b->ts.kind; - gfc_convert_type_warn (a, &t, 2, 1); -} - -/* Resolve an operator expression node. This can involve replacing the - operation with a user defined function call. */ - -static bool -resolve_operator (gfc_expr *e) -{ - gfc_expr *op1, *op2; - /* One error uses 3 names; additional space for wording (also via gettext). */ - char msg[3*GFC_MAX_SYMBOL_LEN + 1 + 50]; - bool dual_locus_error; - bool t = true; - - /* Resolve all subnodes-- give them types. */ - - switch (e->value.op.op) - { - default: - if (!gfc_resolve_expr (e->value.op.op2)) - t = false; - - /* Fall through. */ - - case INTRINSIC_NOT: - case INTRINSIC_UPLUS: - case INTRINSIC_UMINUS: - case INTRINSIC_PARENTHESES: - if (!gfc_resolve_expr (e->value.op.op1)) - return false; - if (e->value.op.op1 - && e->value.op.op1->ts.type == BT_BOZ && !e->value.op.op2) - { - gfc_error ("BOZ literal constant at %L cannot be an operand of " - "unary operator %qs", &e->value.op.op1->where, - gfc_op2string (e->value.op.op)); - return false; - } - break; - } - - /* Typecheck the new node. */ - - op1 = e->value.op.op1; - op2 = e->value.op.op2; - if (op1 == NULL && op2 == NULL) - return false; - /* Error out if op2 did not resolve. We already diagnosed op1. */ - if (t == false) - return false; - - dual_locus_error = false; - - /* op1 and op2 cannot both be BOZ. */ - if (op1 && op1->ts.type == BT_BOZ - && op2 && op2->ts.type == BT_BOZ) - { - gfc_error ("Operands at %L and %L cannot appear as operands of " - "binary operator %qs", &op1->where, &op2->where, - gfc_op2string (e->value.op.op)); - return false; - } - - if ((op1 && op1->expr_type == EXPR_NULL) - || (op2 && op2->expr_type == EXPR_NULL)) - { - snprintf (msg, sizeof (msg), - _("Invalid context for NULL() pointer at %%L")); - goto bad_op; - } - - switch (e->value.op.op) - { - case INTRINSIC_UPLUS: - case INTRINSIC_UMINUS: - if (op1->ts.type == BT_INTEGER - || op1->ts.type == BT_REAL - || op1->ts.type == BT_COMPLEX) - { - e->ts = op1->ts; - break; - } - - snprintf (msg, sizeof (msg), - _("Operand of unary numeric operator %%<%s%%> at %%L is %s"), - gfc_op2string (e->value.op.op), gfc_typename (e)); - goto bad_op; - - case INTRINSIC_PLUS: - case INTRINSIC_MINUS: - case INTRINSIC_TIMES: - case INTRINSIC_DIVIDE: - case INTRINSIC_POWER: - if (gfc_numeric_ts (&op1->ts) && gfc_numeric_ts (&op2->ts)) - { - gfc_type_convert_binary (e, 1); - break; - } - - if (op1->ts.type == BT_DERIVED || op2->ts.type == BT_DERIVED) - snprintf (msg, sizeof (msg), - _("Unexpected derived-type entities in binary intrinsic " - "numeric operator %%<%s%%> at %%L"), - gfc_op2string (e->value.op.op)); - else - snprintf (msg, sizeof(msg), - _("Operands of binary numeric operator %%<%s%%> at %%L are %s/%s"), - gfc_op2string (e->value.op.op), gfc_typename (op1), - gfc_typename (op2)); - goto bad_op; - - case INTRINSIC_CONCAT: - if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER - && op1->ts.kind == op2->ts.kind) - { - e->ts.type = BT_CHARACTER; - e->ts.kind = op1->ts.kind; - break; - } - - snprintf (msg, sizeof (msg), - _("Operands of string concatenation operator at %%L are %s/%s"), - gfc_typename (op1), gfc_typename (op2)); - goto bad_op; - - case INTRINSIC_AND: - case INTRINSIC_OR: - case INTRINSIC_EQV: - case INTRINSIC_NEQV: - if (op1->ts.type == BT_LOGICAL && op2->ts.type == BT_LOGICAL) - { - e->ts.type = BT_LOGICAL; - e->ts.kind = gfc_kind_max (op1, op2); - if (op1->ts.kind < e->ts.kind) - gfc_convert_type (op1, &e->ts, 2); - else if (op2->ts.kind < e->ts.kind) - gfc_convert_type (op2, &e->ts, 2); - - if (flag_frontend_optimize && - (e->value.op.op == INTRINSIC_AND || e->value.op.op == INTRINSIC_OR)) - { - /* Warn about short-circuiting - with impure function as second operand. */ - bool op2_f = false; - gfc_expr_walker (&op2, impure_function_callback, &op2_f); - } - break; - } - - /* Logical ops on integers become bitwise ops with -fdec. */ - else if (flag_dec - && (op1->ts.type == BT_INTEGER || op2->ts.type == BT_INTEGER)) - { - e->ts.type = BT_INTEGER; - e->ts.kind = gfc_kind_max (op1, op2); - if (op1->ts.type != e->ts.type || op1->ts.kind != e->ts.kind) - gfc_convert_type (op1, &e->ts, 1); - if (op2->ts.type != e->ts.type || op2->ts.kind != e->ts.kind) - gfc_convert_type (op2, &e->ts, 1); - e = logical_to_bitwise (e); - goto simplify_op; - } - - snprintf (msg, sizeof (msg), - _("Operands of logical operator %%<%s%%> at %%L are %s/%s"), - gfc_op2string (e->value.op.op), gfc_typename (op1), - gfc_typename (op2)); - - goto bad_op; - - case INTRINSIC_NOT: - /* Logical ops on integers become bitwise ops with -fdec. */ - if (flag_dec && op1->ts.type == BT_INTEGER) - { - e->ts.type = BT_INTEGER; - e->ts.kind = op1->ts.kind; - e = logical_to_bitwise (e); - goto simplify_op; - } - - if (op1->ts.type == BT_LOGICAL) - { - e->ts.type = BT_LOGICAL; - e->ts.kind = op1->ts.kind; - break; - } - - snprintf (msg, sizeof (msg), _("Operand of .not. operator at %%L is %s"), - gfc_typename (op1)); - goto bad_op; - - case INTRINSIC_GT: - case INTRINSIC_GT_OS: - case INTRINSIC_GE: - case INTRINSIC_GE_OS: - case INTRINSIC_LT: - case INTRINSIC_LT_OS: - case INTRINSIC_LE: - case INTRINSIC_LE_OS: - if (op1->ts.type == BT_COMPLEX || op2->ts.type == BT_COMPLEX) - { - strcpy (msg, _("COMPLEX quantities cannot be compared at %L")); - goto bad_op; - } - - /* Fall through. */ - - case INTRINSIC_EQ: - case INTRINSIC_EQ_OS: - case INTRINSIC_NE: - case INTRINSIC_NE_OS: - - if (flag_dec - && is_character_based (op1->ts.type) - && is_character_based (op2->ts.type)) - { - convert_hollerith_to_character (op1); - convert_hollerith_to_character (op2); - } - - if (op1->ts.type == BT_CHARACTER && op2->ts.type == BT_CHARACTER - && op1->ts.kind == op2->ts.kind) - { - e->ts.type = BT_LOGICAL; - e->ts.kind = gfc_default_logical_kind; - break; - } - - /* If op1 is BOZ, then op2 is not!. Try to convert to type of op2. */ - if (op1->ts.type == BT_BOZ) - { - if (gfc_invalid_boz (G_("BOZ literal constant near %L cannot appear " - "as an operand of a relational operator"), - &op1->where)) - return false; - - if (op2->ts.type == BT_INTEGER && !gfc_boz2int (op1, op2->ts.kind)) - return false; - - if (op2->ts.type == BT_REAL && !gfc_boz2real (op1, op2->ts.kind)) - return false; - } - - /* If op2 is BOZ, then op1 is not!. Try to convert to type of op2. */ - if (op2->ts.type == BT_BOZ) - { - if (gfc_invalid_boz (G_("BOZ literal constant near %L cannot appear" - " as an operand of a relational operator"), - &op2->where)) - return false; - - if (op1->ts.type == BT_INTEGER && !gfc_boz2int (op2, op1->ts.kind)) - return false; - - if (op1->ts.type == BT_REAL && !gfc_boz2real (op2, op1->ts.kind)) - return false; - } - if (flag_dec - && op1->ts.type == BT_HOLLERITH && gfc_numeric_ts (&op2->ts)) - convert_to_numeric (op1, op2); - - if (flag_dec - && gfc_numeric_ts (&op1->ts) && op2->ts.type == BT_HOLLERITH) - convert_to_numeric (op2, op1); - - if (gfc_numeric_ts (&op1->ts) && gfc_numeric_ts (&op2->ts)) - { - gfc_type_convert_binary (e, 1); - - e->ts.type = BT_LOGICAL; - e->ts.kind = gfc_default_logical_kind; - - if (warn_compare_reals) - { - gfc_intrinsic_op op = e->value.op.op; - - /* Type conversion has made sure that the types of op1 and op2 - agree, so it is only necessary to check the first one. */ - if ((op1->ts.type == BT_REAL || op1->ts.type == BT_COMPLEX) - && (op == INTRINSIC_EQ || op == INTRINSIC_EQ_OS - || op == INTRINSIC_NE || op == INTRINSIC_NE_OS)) - { - const char *msg; - - if (op == INTRINSIC_EQ || op == INTRINSIC_EQ_OS) - msg = G_("Equality comparison for %s at %L"); - else - msg = G_("Inequality comparison for %s at %L"); - - gfc_warning (OPT_Wcompare_reals, msg, - gfc_typename (op1), &op1->where); - } - } - - break; - } - - if (op1->ts.type == BT_LOGICAL && op2->ts.type == BT_LOGICAL) - snprintf (msg, sizeof (msg), - _("Logicals at %%L must be compared with %s instead of %s"), - (e->value.op.op == INTRINSIC_EQ - || e->value.op.op == INTRINSIC_EQ_OS) - ? ".eqv." : ".neqv.", gfc_op2string (e->value.op.op)); - else - snprintf (msg, sizeof (msg), - _("Operands of comparison operator %%<%s%%> at %%L are %s/%s"), - gfc_op2string (e->value.op.op), gfc_typename (op1), - gfc_typename (op2)); - - goto bad_op; - - case INTRINSIC_USER: - if (e->value.op.uop->op == NULL) - { - const char *name = e->value.op.uop->name; - const char *guessed; - guessed = lookup_uop_fuzzy (name, e->value.op.uop->ns->uop_root); - if (guessed) - snprintf (msg, sizeof (msg), - _("Unknown operator %%<%s%%> at %%L; did you mean '%s'?"), - name, guessed); - else - snprintf (msg, sizeof (msg), _("Unknown operator %%<%s%%> at %%L"), - name); - } - else if (op2 == NULL) - snprintf (msg, sizeof (msg), - _("Operand of user operator %%<%s%%> at %%L is %s"), - e->value.op.uop->name, gfc_typename (op1)); - else - { - snprintf (msg, sizeof (msg), - _("Operands of user operator %%<%s%%> at %%L are %s/%s"), - e->value.op.uop->name, gfc_typename (op1), - gfc_typename (op2)); - e->value.op.uop->op->sym->attr.referenced = 1; - } - - goto bad_op; - - case INTRINSIC_PARENTHESES: - e->ts = op1->ts; - if (e->ts.type == BT_CHARACTER) - e->ts.u.cl = op1->ts.u.cl; - break; - - default: - gfc_internal_error ("resolve_operator(): Bad intrinsic"); - } - - /* Deal with arrayness of an operand through an operator. */ - - switch (e->value.op.op) - { - case INTRINSIC_PLUS: - case INTRINSIC_MINUS: - case INTRINSIC_TIMES: - case INTRINSIC_DIVIDE: - case INTRINSIC_POWER: - case INTRINSIC_CONCAT: - case INTRINSIC_AND: - case INTRINSIC_OR: - case INTRINSIC_EQV: - case INTRINSIC_NEQV: - case INTRINSIC_EQ: - case INTRINSIC_EQ_OS: - case INTRINSIC_NE: - case INTRINSIC_NE_OS: - case INTRINSIC_GT: - case INTRINSIC_GT_OS: - case INTRINSIC_GE: - case INTRINSIC_GE_OS: - case INTRINSIC_LT: - case INTRINSIC_LT_OS: - case INTRINSIC_LE: - case INTRINSIC_LE_OS: - - if (op1->rank == 0 && op2->rank == 0) - e->rank = 0; - - if (op1->rank == 0 && op2->rank != 0) - { - e->rank = op2->rank; - - if (e->shape == NULL) - e->shape = gfc_copy_shape (op2->shape, op2->rank); - } - - if (op1->rank != 0 && op2->rank == 0) - { - e->rank = op1->rank; - - if (e->shape == NULL) - e->shape = gfc_copy_shape (op1->shape, op1->rank); - } - - if (op1->rank != 0 && op2->rank != 0) - { - if (op1->rank == op2->rank) - { - e->rank = op1->rank; - if (e->shape == NULL) - { - t = compare_shapes (op1, op2); - if (!t) - e->shape = NULL; - else - e->shape = gfc_copy_shape (op1->shape, op1->rank); - } - } - else - { - /* Allow higher level expressions to work. */ - e->rank = 0; - - /* Try user-defined operators, and otherwise throw an error. */ - dual_locus_error = true; - snprintf (msg, sizeof (msg), - _("Inconsistent ranks for operator at %%L and %%L")); - goto bad_op; - } - } - - break; - - case INTRINSIC_PARENTHESES: - case INTRINSIC_NOT: - case INTRINSIC_UPLUS: - case INTRINSIC_UMINUS: - /* Simply copy arrayness attribute */ - e->rank = op1->rank; - - if (e->shape == NULL) - e->shape = gfc_copy_shape (op1->shape, op1->rank); - - break; - - default: - break; - } - -simplify_op: - - /* Attempt to simplify the expression. */ - if (t) - { - t = gfc_simplify_expr (e, 0); - /* Some calls do not succeed in simplification and return false - even though there is no error; e.g. variable references to - PARAMETER arrays. */ - if (!gfc_is_constant_expr (e)) - t = true; - } - return t; - -bad_op: - - { - match m = gfc_extend_expr (e); - if (m == MATCH_YES) - return true; - if (m == MATCH_ERROR) - return false; - } - - if (dual_locus_error) - gfc_error (msg, &op1->where, &op2->where); - else - gfc_error (msg, &e->where); - - return false; -} - - -/************** Array resolution subroutines **************/ - -enum compare_result -{ CMP_LT, CMP_EQ, CMP_GT, CMP_UNKNOWN }; - -/* Compare two integer expressions. */ - -static compare_result -compare_bound (gfc_expr *a, gfc_expr *b) -{ - int i; - - if (a == NULL || a->expr_type != EXPR_CONSTANT - || b == NULL || b->expr_type != EXPR_CONSTANT) - return CMP_UNKNOWN; - - /* If either of the types isn't INTEGER, we must have - raised an error earlier. */ - - if (a->ts.type != BT_INTEGER || b->ts.type != BT_INTEGER) - return CMP_UNKNOWN; - - i = mpz_cmp (a->value.integer, b->value.integer); - - if (i < 0) - return CMP_LT; - if (i > 0) - return CMP_GT; - return CMP_EQ; -} - - -/* Compare an integer expression with an integer. */ - -static compare_result -compare_bound_int (gfc_expr *a, int b) -{ - int i; - - if (a == NULL || a->expr_type != EXPR_CONSTANT) - return CMP_UNKNOWN; - - if (a->ts.type != BT_INTEGER) - gfc_internal_error ("compare_bound_int(): Bad expression"); - - i = mpz_cmp_si (a->value.integer, b); - - if (i < 0) - return CMP_LT; - if (i > 0) - return CMP_GT; - return CMP_EQ; -} - - -/* Compare an integer expression with a mpz_t. */ - -static compare_result -compare_bound_mpz_t (gfc_expr *a, mpz_t b) -{ - int i; - - if (a == NULL || a->expr_type != EXPR_CONSTANT) - return CMP_UNKNOWN; - - if (a->ts.type != BT_INTEGER) - gfc_internal_error ("compare_bound_int(): Bad expression"); - - i = mpz_cmp (a->value.integer, b); - - if (i < 0) - return CMP_LT; - if (i > 0) - return CMP_GT; - return CMP_EQ; -} - - -/* Compute the last value of a sequence given by a triplet. - Return 0 if it wasn't able to compute the last value, or if the - sequence if empty, and 1 otherwise. */ - -static int -compute_last_value_for_triplet (gfc_expr *start, gfc_expr *end, - gfc_expr *stride, mpz_t last) -{ - mpz_t rem; - - if (start == NULL || start->expr_type != EXPR_CONSTANT - || end == NULL || end->expr_type != EXPR_CONSTANT - || (stride != NULL && stride->expr_type != EXPR_CONSTANT)) - return 0; - - if (start->ts.type != BT_INTEGER || end->ts.type != BT_INTEGER - || (stride != NULL && stride->ts.type != BT_INTEGER)) - return 0; - - if (stride == NULL || compare_bound_int (stride, 1) == CMP_EQ) - { - if (compare_bound (start, end) == CMP_GT) - return 0; - mpz_set (last, end->value.integer); - return 1; - } - - if (compare_bound_int (stride, 0) == CMP_GT) - { - /* Stride is positive */ - if (mpz_cmp (start->value.integer, end->value.integer) > 0) - return 0; - } - else - { - /* Stride is negative */ - if (mpz_cmp (start->value.integer, end->value.integer) < 0) - return 0; - } - - mpz_init (rem); - mpz_sub (rem, end->value.integer, start->value.integer); - mpz_tdiv_r (rem, rem, stride->value.integer); - mpz_sub (last, end->value.integer, rem); - mpz_clear (rem); - - return 1; -} - - -/* Compare a single dimension of an array reference to the array - specification. */ - -static bool -check_dimension (int i, gfc_array_ref *ar, gfc_array_spec *as) -{ - mpz_t last_value; - - if (ar->dimen_type[i] == DIMEN_STAR) - { - gcc_assert (ar->stride[i] == NULL); - /* This implies [*] as [*:] and [*:3] are not possible. */ - if (ar->start[i] == NULL) - { - gcc_assert (ar->end[i] == NULL); - return true; - } - } - -/* Given start, end and stride values, calculate the minimum and - maximum referenced indexes. */ - - switch (ar->dimen_type[i]) - { - case DIMEN_VECTOR: - case DIMEN_THIS_IMAGE: - break; - - case DIMEN_STAR: - case DIMEN_ELEMENT: - if (compare_bound (ar->start[i], as->lower[i]) == CMP_LT) - { - if (i < as->rank) - gfc_warning (0, "Array reference at %L is out of bounds " - "(%ld < %ld) in dimension %d", &ar->c_where[i], - mpz_get_si (ar->start[i]->value.integer), - mpz_get_si (as->lower[i]->value.integer), i+1); - else - gfc_warning (0, "Array reference at %L is out of bounds " - "(%ld < %ld) in codimension %d", &ar->c_where[i], - mpz_get_si (ar->start[i]->value.integer), - mpz_get_si (as->lower[i]->value.integer), - i + 1 - as->rank); - return true; - } - if (compare_bound (ar->start[i], as->upper[i]) == CMP_GT) - { - if (i < as->rank) - gfc_warning (0, "Array reference at %L is out of bounds " - "(%ld > %ld) in dimension %d", &ar->c_where[i], - mpz_get_si (ar->start[i]->value.integer), - mpz_get_si (as->upper[i]->value.integer), i+1); - else - gfc_warning (0, "Array reference at %L is out of bounds " - "(%ld > %ld) in codimension %d", &ar->c_where[i], - mpz_get_si (ar->start[i]->value.integer), - mpz_get_si (as->upper[i]->value.integer), - i + 1 - as->rank); - return true; - } - - break; - - case DIMEN_RANGE: - { -#define AR_START (ar->start[i] ? ar->start[i] : as->lower[i]) -#define AR_END (ar->end[i] ? ar->end[i] : as->upper[i]) - - compare_result comp_start_end = compare_bound (AR_START, AR_END); - - /* Check for zero stride, which is not allowed. */ - if (compare_bound_int (ar->stride[i], 0) == CMP_EQ) - { - gfc_error ("Illegal stride of zero at %L", &ar->c_where[i]); - return false; - } - - /* if start == len || (stride > 0 && start < len) - || (stride < 0 && start > len), - then the array section contains at least one element. In this - case, there is an out-of-bounds access if - (start < lower || start > upper). */ - if (compare_bound (AR_START, AR_END) == CMP_EQ - || ((compare_bound_int (ar->stride[i], 0) == CMP_GT - || ar->stride[i] == NULL) && comp_start_end == CMP_LT) - || (compare_bound_int (ar->stride[i], 0) == CMP_LT - && comp_start_end == CMP_GT)) - { - if (compare_bound (AR_START, as->lower[i]) == CMP_LT) - { - gfc_warning (0, "Lower array reference at %L is out of bounds " - "(%ld < %ld) in dimension %d", &ar->c_where[i], - mpz_get_si (AR_START->value.integer), - mpz_get_si (as->lower[i]->value.integer), i+1); - return true; - } - if (compare_bound (AR_START, as->upper[i]) == CMP_GT) - { - gfc_warning (0, "Lower array reference at %L is out of bounds " - "(%ld > %ld) in dimension %d", &ar->c_where[i], - mpz_get_si (AR_START->value.integer), - mpz_get_si (as->upper[i]->value.integer), i+1); - return true; - } - } - - /* If we can compute the highest index of the array section, - then it also has to be between lower and upper. */ - mpz_init (last_value); - if (compute_last_value_for_triplet (AR_START, AR_END, ar->stride[i], - last_value)) - { - if (compare_bound_mpz_t (as->lower[i], last_value) == CMP_GT) - { - gfc_warning (0, "Upper array reference at %L is out of bounds " - "(%ld < %ld) in dimension %d", &ar->c_where[i], - mpz_get_si (last_value), - mpz_get_si (as->lower[i]->value.integer), i+1); - mpz_clear (last_value); - return true; - } - if (compare_bound_mpz_t (as->upper[i], last_value) == CMP_LT) - { - gfc_warning (0, "Upper array reference at %L is out of bounds " - "(%ld > %ld) in dimension %d", &ar->c_where[i], - mpz_get_si (last_value), - mpz_get_si (as->upper[i]->value.integer), i+1); - mpz_clear (last_value); - return true; - } - } - mpz_clear (last_value); - -#undef AR_START -#undef AR_END - } - break; - - default: - gfc_internal_error ("check_dimension(): Bad array reference"); - } - - return true; -} - - -/* Compare an array reference with an array specification. */ - -static bool -compare_spec_to_ref (gfc_array_ref *ar) -{ - gfc_array_spec *as; - int i; - - as = ar->as; - i = as->rank - 1; - /* TODO: Full array sections are only allowed as actual parameters. */ - if (as->type == AS_ASSUMED_SIZE - && (/*ar->type == AR_FULL - ||*/ (ar->type == AR_SECTION - && ar->dimen_type[i] == DIMEN_RANGE && ar->end[i] == NULL))) - { - gfc_error ("Rightmost upper bound of assumed size array section " - "not specified at %L", &ar->where); - return false; - } - - if (ar->type == AR_FULL) - return true; - - if (as->rank != ar->dimen) - { - gfc_error ("Rank mismatch in array reference at %L (%d/%d)", - &ar->where, ar->dimen, as->rank); - return false; - } - - /* ar->codimen == 0 is a local array. */ - if (as->corank != ar->codimen && ar->codimen != 0) - { - gfc_error ("Coindex rank mismatch in array reference at %L (%d/%d)", - &ar->where, ar->codimen, as->corank); - return false; - } - - for (i = 0; i < as->rank; i++) - if (!check_dimension (i, ar, as)) - return false; - - /* Local access has no coarray spec. */ - if (ar->codimen != 0) - for (i = as->rank; i < as->rank + as->corank; i++) - { - if (ar->dimen_type[i] != DIMEN_ELEMENT && !ar->in_allocate - && ar->dimen_type[i] != DIMEN_THIS_IMAGE) - { - gfc_error ("Coindex of codimension %d must be a scalar at %L", - i + 1 - as->rank, &ar->where); - return false; - } - if (!check_dimension (i, ar, as)) - return false; - } - - return true; -} - - -/* Resolve one part of an array index. */ - -static bool -gfc_resolve_index_1 (gfc_expr *index, int check_scalar, - int force_index_integer_kind) -{ - gfc_typespec ts; - - if (index == NULL) - return true; - - if (!gfc_resolve_expr (index)) - return false; - - if (check_scalar && index->rank != 0) - { - gfc_error ("Array index at %L must be scalar", &index->where); - return false; - } - - if (index->ts.type != BT_INTEGER && index->ts.type != BT_REAL) - { - gfc_error ("Array index at %L must be of INTEGER type, found %s", - &index->where, gfc_basic_typename (index->ts.type)); - return false; - } - - if (index->ts.type == BT_REAL) - if (!gfc_notify_std (GFC_STD_LEGACY, "REAL array index at %L", - &index->where)) - return false; - - if ((index->ts.kind != gfc_index_integer_kind - && force_index_integer_kind) - || index->ts.type != BT_INTEGER) - { - gfc_clear_ts (&ts); - ts.type = BT_INTEGER; - ts.kind = gfc_index_integer_kind; - - gfc_convert_type_warn (index, &ts, 2, 0); - } - - return true; -} - -/* Resolve one part of an array index. */ - -bool -gfc_resolve_index (gfc_expr *index, int check_scalar) -{ - return gfc_resolve_index_1 (index, check_scalar, 1); -} - -/* Resolve a dim argument to an intrinsic function. */ - -bool -gfc_resolve_dim_arg (gfc_expr *dim) -{ - if (dim == NULL) - return true; - - if (!gfc_resolve_expr (dim)) - return false; - - if (dim->rank != 0) - { - gfc_error ("Argument dim at %L must be scalar", &dim->where); - return false; - - } - - if (dim->ts.type != BT_INTEGER) - { - gfc_error ("Argument dim at %L must be of INTEGER type", &dim->where); - return false; - } - - if (dim->ts.kind != gfc_index_integer_kind) - { - gfc_typespec ts; - - gfc_clear_ts (&ts); - ts.type = BT_INTEGER; - ts.kind = gfc_index_integer_kind; - - gfc_convert_type_warn (dim, &ts, 2, 0); - } - - return true; -} - -/* Given an expression that contains array references, update those array - references to point to the right array specifications. While this is - filled in during matching, this information is difficult to save and load - in a module, so we take care of it here. - - The idea here is that the original array reference comes from the - base symbol. We traverse the list of reference structures, setting - the stored reference to references. Component references can - provide an additional array specification. */ -static void -resolve_assoc_var (gfc_symbol* sym, bool resolve_target); - -static void -find_array_spec (gfc_expr *e) -{ - gfc_array_spec *as; - gfc_component *c; - gfc_ref *ref; - bool class_as = false; - - if (e->symtree->n.sym->assoc) - { - if (e->symtree->n.sym->assoc->target) - gfc_resolve_expr (e->symtree->n.sym->assoc->target); - resolve_assoc_var (e->symtree->n.sym, false); - } - - if (e->symtree->n.sym->ts.type == BT_CLASS) - { - as = CLASS_DATA (e->symtree->n.sym)->as; - class_as = true; - } - else - as = e->symtree->n.sym->as; - - for (ref = e->ref; ref; ref = ref->next) - switch (ref->type) - { - case REF_ARRAY: - if (as == NULL) - gfc_internal_error ("find_array_spec(): Missing spec"); - - ref->u.ar.as = as; - as = NULL; - break; - - case REF_COMPONENT: - c = ref->u.c.component; - if (c->attr.dimension) - { - if (as != NULL && !(class_as && as == c->as)) - gfc_internal_error ("find_array_spec(): unused as(1)"); - as = c->as; - } - - break; - - case REF_SUBSTRING: - case REF_INQUIRY: - break; - } - - if (as != NULL) - gfc_internal_error ("find_array_spec(): unused as(2)"); -} - - -/* Resolve an array reference. */ - -static bool -resolve_array_ref (gfc_array_ref *ar) -{ - int i, check_scalar; - gfc_expr *e; - - for (i = 0; i < ar->dimen + ar->codimen; i++) - { - check_scalar = ar->dimen_type[i] == DIMEN_RANGE; - - /* Do not force gfc_index_integer_kind for the start. We can - do fine with any integer kind. This avoids temporary arrays - created for indexing with a vector. */ - if (!gfc_resolve_index_1 (ar->start[i], check_scalar, 0)) - return false; - if (!gfc_resolve_index (ar->end[i], check_scalar)) - return false; - if (!gfc_resolve_index (ar->stride[i], check_scalar)) - return false; - - e = ar->start[i]; - - if (ar->dimen_type[i] == DIMEN_UNKNOWN) - switch (e->rank) - { - case 0: - ar->dimen_type[i] = DIMEN_ELEMENT; - break; - - case 1: - ar->dimen_type[i] = DIMEN_VECTOR; - if (e->expr_type == EXPR_VARIABLE - && e->symtree->n.sym->ts.type == BT_DERIVED) - ar->start[i] = gfc_get_parentheses (e); - break; - - default: - gfc_error ("Array index at %L is an array of rank %d", - &ar->c_where[i], e->rank); - return false; - } - - /* Fill in the upper bound, which may be lower than the - specified one for something like a(2:10:5), which is - identical to a(2:7:5). Only relevant for strides not equal - to one. Don't try a division by zero. */ - if (ar->dimen_type[i] == DIMEN_RANGE - && ar->stride[i] != NULL && ar->stride[i]->expr_type == EXPR_CONSTANT - && mpz_cmp_si (ar->stride[i]->value.integer, 1L) != 0 - && mpz_cmp_si (ar->stride[i]->value.integer, 0L) != 0) - { - mpz_t size, end; - - if (gfc_ref_dimen_size (ar, i, &size, &end)) - { - if (ar->end[i] == NULL) - { - ar->end[i] = - gfc_get_constant_expr (BT_INTEGER, gfc_index_integer_kind, - &ar->where); - mpz_set (ar->end[i]->value.integer, end); - } - else if (ar->end[i]->ts.type == BT_INTEGER - && ar->end[i]->expr_type == EXPR_CONSTANT) - { - mpz_set (ar->end[i]->value.integer, end); - } - else - gcc_unreachable (); - - mpz_clear (size); - mpz_clear (end); - } - } - } - - if (ar->type == AR_FULL) - { - if (ar->as->rank == 0) - ar->type = AR_ELEMENT; - - /* Make sure array is the same as array(:,:), this way - we don't need to special case all the time. */ - ar->dimen = ar->as->rank; - for (i = 0; i < ar->dimen; i++) - { - ar->dimen_type[i] = DIMEN_RANGE; - - gcc_assert (ar->start[i] == NULL); - gcc_assert (ar->end[i] == NULL); - gcc_assert (ar->stride[i] == NULL); - } - } - - /* If the reference type is unknown, figure out what kind it is. */ - - if (ar->type == AR_UNKNOWN) - { - ar->type = AR_ELEMENT; - for (i = 0; i < ar->dimen; i++) - if (ar->dimen_type[i] == DIMEN_RANGE - || ar->dimen_type[i] == DIMEN_VECTOR) - { - ar->type = AR_SECTION; - break; - } - } - - if (!ar->as->cray_pointee && !compare_spec_to_ref (ar)) - return false; - - if (ar->as->corank && ar->codimen == 0) - { - int n; - ar->codimen = ar->as->corank; - for (n = ar->dimen; n < ar->dimen + ar->codimen; n++) - ar->dimen_type[n] = DIMEN_THIS_IMAGE; - } - - return true; -} - - -bool -gfc_resolve_substring (gfc_ref *ref, bool *equal_length) -{ - int k = gfc_validate_kind (BT_INTEGER, gfc_charlen_int_kind, false); - - if (ref->u.ss.start != NULL) - { - if (!gfc_resolve_expr (ref->u.ss.start)) - return false; - - if (ref->u.ss.start->ts.type != BT_INTEGER) - { - gfc_error ("Substring start index at %L must be of type INTEGER", - &ref->u.ss.start->where); - return false; - } - - if (ref->u.ss.start->rank != 0) - { - gfc_error ("Substring start index at %L must be scalar", - &ref->u.ss.start->where); - return false; - } - - if (compare_bound_int (ref->u.ss.start, 1) == CMP_LT - && (compare_bound (ref->u.ss.end, ref->u.ss.start) == CMP_EQ - || compare_bound (ref->u.ss.end, ref->u.ss.start) == CMP_GT)) - { - gfc_error ("Substring start index at %L is less than one", - &ref->u.ss.start->where); - return false; - } - } - - if (ref->u.ss.end != NULL) - { - if (!gfc_resolve_expr (ref->u.ss.end)) - return false; - - if (ref->u.ss.end->ts.type != BT_INTEGER) - { - gfc_error ("Substring end index at %L must be of type INTEGER", - &ref->u.ss.end->where); - return false; - } - - if (ref->u.ss.end->rank != 0) - { - gfc_error ("Substring end index at %L must be scalar", - &ref->u.ss.end->where); - return false; - } - - if (ref->u.ss.length != NULL - && compare_bound (ref->u.ss.end, ref->u.ss.length->length) == CMP_GT - && (compare_bound (ref->u.ss.end, ref->u.ss.start) == CMP_EQ - || compare_bound (ref->u.ss.end, ref->u.ss.start) == CMP_GT)) - { - gfc_error ("Substring end index at %L exceeds the string length", - &ref->u.ss.start->where); - return false; - } - - if (compare_bound_mpz_t (ref->u.ss.end, - gfc_integer_kinds[k].huge) == CMP_GT - && (compare_bound (ref->u.ss.end, ref->u.ss.start) == CMP_EQ - || compare_bound (ref->u.ss.end, ref->u.ss.start) == CMP_GT)) - { - gfc_error ("Substring end index at %L is too large", - &ref->u.ss.end->where); - return false; - } - /* If the substring has the same length as the original - variable, the reference itself can be deleted. */ - - if (ref->u.ss.length != NULL - && compare_bound (ref->u.ss.end, ref->u.ss.length->length) == CMP_EQ - && compare_bound_int (ref->u.ss.start, 1) == CMP_EQ) - *equal_length = true; - } - - return true; -} - - -/* This function supplies missing substring charlens. */ - -void -gfc_resolve_substring_charlen (gfc_expr *e) -{ - gfc_ref *char_ref; - gfc_expr *start, *end; - gfc_typespec *ts = NULL; - mpz_t diff; - - for (char_ref = e->ref; char_ref; char_ref = char_ref->next) - { - if (char_ref->type == REF_SUBSTRING || char_ref->type == REF_INQUIRY) - break; - if (char_ref->type == REF_COMPONENT) - ts = &char_ref->u.c.component->ts; - } - - if (!char_ref || char_ref->type == REF_INQUIRY) - return; - - gcc_assert (char_ref->next == NULL); - - if (e->ts.u.cl) - { - if (e->ts.u.cl->length) - gfc_free_expr (e->ts.u.cl->length); - else if (e->expr_type == EXPR_VARIABLE && e->symtree->n.sym->attr.dummy) - return; - } - - if (!e->ts.u.cl) - e->ts.u.cl = gfc_new_charlen (gfc_current_ns, NULL); - - if (char_ref->u.ss.start) - start = gfc_copy_expr (char_ref->u.ss.start); - else - start = gfc_get_int_expr (gfc_charlen_int_kind, NULL, 1); - - if (char_ref->u.ss.end) - end = gfc_copy_expr (char_ref->u.ss.end); - else if (e->expr_type == EXPR_VARIABLE) - { - if (!ts) - ts = &e->symtree->n.sym->ts; - end = gfc_copy_expr (ts->u.cl->length); - } - else - end = NULL; - - if (!start || !end) - { - gfc_free_expr (start); - gfc_free_expr (end); - return; - } - - /* Length = (end - start + 1). - Check first whether it has a constant length. */ - if (gfc_dep_difference (end, start, &diff)) - { - gfc_expr *len = gfc_get_constant_expr (BT_INTEGER, gfc_charlen_int_kind, - &e->where); - - mpz_add_ui (len->value.integer, diff, 1); - mpz_clear (diff); - e->ts.u.cl->length = len; - /* The check for length < 0 is handled below */ - } - else - { - e->ts.u.cl->length = gfc_subtract (end, start); - e->ts.u.cl->length = gfc_add (e->ts.u.cl->length, - gfc_get_int_expr (gfc_charlen_int_kind, - NULL, 1)); - } - - /* F2008, 6.4.1: Both the starting point and the ending point shall - be within the range 1, 2, ..., n unless the starting point exceeds - the ending point, in which case the substring has length zero. */ - - if (mpz_cmp_si (e->ts.u.cl->length->value.integer, 0) < 0) - mpz_set_si (e->ts.u.cl->length->value.integer, 0); - - e->ts.u.cl->length->ts.type = BT_INTEGER; - e->ts.u.cl->length->ts.kind = gfc_charlen_int_kind; - - /* Make sure that the length is simplified. */ - gfc_simplify_expr (e->ts.u.cl->length, 1); - gfc_resolve_expr (e->ts.u.cl->length); -} - - -/* Resolve subtype references. */ - -bool -gfc_resolve_ref (gfc_expr *expr) -{ - int current_part_dimension, n_components, seen_part_dimension, dim; - gfc_ref *ref, **prev, *array_ref; - bool equal_length; - - for (ref = expr->ref; ref; ref = ref->next) - if (ref->type == REF_ARRAY && ref->u.ar.as == NULL) - { - find_array_spec (expr); - break; - } - - for (prev = &expr->ref; *prev != NULL; - prev = *prev == NULL ? prev : &(*prev)->next) - switch ((*prev)->type) - { - case REF_ARRAY: - if (!resolve_array_ref (&(*prev)->u.ar)) - return false; - break; - - case REF_COMPONENT: - case REF_INQUIRY: - break; - - case REF_SUBSTRING: - equal_length = false; - if (!gfc_resolve_substring (*prev, &equal_length)) - return false; - - if (expr->expr_type != EXPR_SUBSTRING && equal_length) - { - /* Remove the reference and move the charlen, if any. */ - ref = *prev; - *prev = ref->next; - ref->next = NULL; - expr->ts.u.cl = ref->u.ss.length; - ref->u.ss.length = NULL; - gfc_free_ref_list (ref); - } - break; - } - - /* Check constraints on part references. */ - - current_part_dimension = 0; - seen_part_dimension = 0; - n_components = 0; - array_ref = NULL; - - for (ref = expr->ref; ref; ref = ref->next) - { - switch (ref->type) - { - case REF_ARRAY: - array_ref = ref; - switch (ref->u.ar.type) - { - case AR_FULL: - /* Coarray scalar. */ - if (ref->u.ar.as->rank == 0) - { - current_part_dimension = 0; - break; - } - /* Fall through. */ - case AR_SECTION: - current_part_dimension = 1; - break; - - case AR_ELEMENT: - array_ref = NULL; - current_part_dimension = 0; - break; - - case AR_UNKNOWN: - gfc_internal_error ("resolve_ref(): Bad array reference"); - } - - break; - - case REF_COMPONENT: - if (current_part_dimension || seen_part_dimension) - { - /* F03:C614. */ - if (ref->u.c.component->attr.pointer - || ref->u.c.component->attr.proc_pointer - || (ref->u.c.component->ts.type == BT_CLASS - && CLASS_DATA (ref->u.c.component)->attr.pointer)) - { - gfc_error ("Component to the right of a part reference " - "with nonzero rank must not have the POINTER " - "attribute at %L", &expr->where); - return false; - } - else if (ref->u.c.component->attr.allocatable - || (ref->u.c.component->ts.type == BT_CLASS - && CLASS_DATA (ref->u.c.component)->attr.allocatable)) - - { - gfc_error ("Component to the right of a part reference " - "with nonzero rank must not have the ALLOCATABLE " - "attribute at %L", &expr->where); - return false; - } - } - - n_components++; - break; - - case REF_SUBSTRING: - break; - - case REF_INQUIRY: - /* Implement requirement in note 9.7 of F2018 that the result of the - LEN inquiry be a scalar. */ - if (ref->u.i == INQUIRY_LEN && array_ref && expr->ts.deferred) - { - array_ref->u.ar.type = AR_ELEMENT; - expr->rank = 0; - /* INQUIRY_LEN is not evaluated from the rest of the expr - but directly from the string length. This means that setting - the array indices to one does not matter but might trigger - a runtime bounds error. Suppress the check. */ - expr->no_bounds_check = 1; - for (dim = 0; dim < array_ref->u.ar.dimen; dim++) - { - array_ref->u.ar.dimen_type[dim] = DIMEN_ELEMENT; - if (array_ref->u.ar.start[dim]) - gfc_free_expr (array_ref->u.ar.start[dim]); - array_ref->u.ar.start[dim] - = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1); - if (array_ref->u.ar.end[dim]) - gfc_free_expr (array_ref->u.ar.end[dim]); - if (array_ref->u.ar.stride[dim]) - gfc_free_expr (array_ref->u.ar.stride[dim]); - } - } - break; - } - - if (((ref->type == REF_COMPONENT && n_components > 1) - || ref->next == NULL) - && current_part_dimension - && seen_part_dimension) - { - gfc_error ("Two or more part references with nonzero rank must " - "not be specified at %L", &expr->where); - return false; - } - - if (ref->type == REF_COMPONENT) - { - if (current_part_dimension) - seen_part_dimension = 1; - - /* reset to make sure */ - current_part_dimension = 0; - } - } - - return true; -} - - -/* Given an expression, determine its shape. This is easier than it sounds. - Leaves the shape array NULL if it is not possible to determine the shape. */ - -static void -expression_shape (gfc_expr *e) -{ - mpz_t array[GFC_MAX_DIMENSIONS]; - int i; - - if (e->rank <= 0 || e->shape != NULL) - return; - - for (i = 0; i < e->rank; i++) - if (!gfc_array_dimen_size (e, i, &array[i])) - goto fail; - - e->shape = gfc_get_shape (e->rank); - - memcpy (e->shape, array, e->rank * sizeof (mpz_t)); - - return; - -fail: - for (i--; i >= 0; i--) - mpz_clear (array[i]); -} - - -/* Given a variable expression node, compute the rank of the expression by - examining the base symbol and any reference structures it may have. */ - -void -gfc_expression_rank (gfc_expr *e) -{ - gfc_ref *ref; - int i, rank; - - /* Just to make sure, because EXPR_COMPCALL's also have an e->ref and that - could lead to serious confusion... */ - gcc_assert (e->expr_type != EXPR_COMPCALL); - - if (e->ref == NULL) - { - if (e->expr_type == EXPR_ARRAY) - goto done; - /* Constructors can have a rank different from one via RESHAPE(). */ - - e->rank = ((e->symtree == NULL || e->symtree->n.sym->as == NULL) - ? 0 : e->symtree->n.sym->as->rank); - goto done; - } - - rank = 0; - - for (ref = e->ref; ref; ref = ref->next) - { - if (ref->type == REF_COMPONENT && ref->u.c.component->attr.proc_pointer - && ref->u.c.component->attr.function && !ref->next) - rank = ref->u.c.component->as ? ref->u.c.component->as->rank : 0; - - if (ref->type != REF_ARRAY) - continue; - - if (ref->u.ar.type == AR_FULL) - { - rank = ref->u.ar.as->rank; - break; - } - - if (ref->u.ar.type == AR_SECTION) - { - /* Figure out the rank of the section. */ - if (rank != 0) - gfc_internal_error ("gfc_expression_rank(): Two array specs"); - - for (i = 0; i < ref->u.ar.dimen; i++) - if (ref->u.ar.dimen_type[i] == DIMEN_RANGE - || ref->u.ar.dimen_type[i] == DIMEN_VECTOR) - rank++; - - break; - } - } - - e->rank = rank; - -done: - expression_shape (e); -} - - -static void -add_caf_get_intrinsic (gfc_expr *e) -{ - gfc_expr *wrapper, *tmp_expr; - gfc_ref *ref; - int n; - - for (ref = e->ref; ref; ref = ref->next) - if (ref->type == REF_ARRAY && ref->u.ar.codimen > 0) - break; - if (ref == NULL) - return; - - for (n = ref->u.ar.dimen; n < ref->u.ar.dimen + ref->u.ar.codimen; n++) - if (ref->u.ar.dimen_type[n] != DIMEN_ELEMENT) - return; - - tmp_expr = XCNEW (gfc_expr); - *tmp_expr = *e; - wrapper = gfc_build_intrinsic_call (gfc_current_ns, GFC_ISYM_CAF_GET, - "caf_get", tmp_expr->where, 1, tmp_expr); - wrapper->ts = e->ts; - wrapper->rank = e->rank; - if (e->rank) - wrapper->shape = gfc_copy_shape (e->shape, e->rank); - *e = *wrapper; - free (wrapper); -} - - -static void -remove_caf_get_intrinsic (gfc_expr *e) -{ - gcc_assert (e->expr_type == EXPR_FUNCTION && e->value.function.isym - && e->value.function.isym->id == GFC_ISYM_CAF_GET); - gfc_expr *e2 = e->value.function.actual->expr; - e->value.function.actual->expr = NULL; - gfc_free_actual_arglist (e->value.function.actual); - gfc_free_shape (&e->shape, e->rank); - *e = *e2; - free (e2); -} - - -/* Resolve a variable expression. */ - -static bool -resolve_variable (gfc_expr *e) -{ - gfc_symbol *sym; - bool t; - - t = true; - - if (e->symtree == NULL) - return false; - sym = e->symtree->n.sym; - - /* Use same check as for TYPE(*) below; this check has to be before TYPE(*) - as ts.type is set to BT_ASSUMED in resolve_symbol. */ - if (sym->attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK)) - { - if (!actual_arg || inquiry_argument) - { - gfc_error ("Variable %s at %L with NO_ARG_CHECK attribute may only " - "be used as actual argument", sym->name, &e->where); - return false; - } - } - /* TS 29113, 407b. */ - else if (e->ts.type == BT_ASSUMED) - { - if (!actual_arg) - { - gfc_error ("Assumed-type variable %s at %L may only be used " - "as actual argument", sym->name, &e->where); - return false; - } - else if (inquiry_argument && !first_actual_arg) - { - /* FIXME: It doesn't work reliably as inquiry_argument is not set - for all inquiry functions in resolve_function; the reason is - that the function-name resolution happens too late in that - function. */ - gfc_error ("Assumed-type variable %s at %L as actual argument to " - "an inquiry function shall be the first argument", - sym->name, &e->where); - return false; - } - } - /* TS 29113, C535b. */ - else if (((sym->ts.type == BT_CLASS && sym->attr.class_ok - && sym->ts.u.derived && CLASS_DATA (sym) - && CLASS_DATA (sym)->as - && CLASS_DATA (sym)->as->type == AS_ASSUMED_RANK) - || (sym->ts.type != BT_CLASS && sym->as - && sym->as->type == AS_ASSUMED_RANK)) - && !sym->attr.select_rank_temporary) - { - if (!actual_arg - && !(cs_base && cs_base->current - && cs_base->current->op == EXEC_SELECT_RANK)) - { - gfc_error ("Assumed-rank variable %s at %L may only be used as " - "actual argument", sym->name, &e->where); - return false; - } - else if (inquiry_argument && !first_actual_arg) - { - /* FIXME: It doesn't work reliably as inquiry_argument is not set - for all inquiry functions in resolve_function; the reason is - that the function-name resolution happens too late in that - function. */ - gfc_error ("Assumed-rank variable %s at %L as actual argument " - "to an inquiry function shall be the first argument", - sym->name, &e->where); - return false; - } - } - - if ((sym->attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK)) && e->ref - && !(e->ref->type == REF_ARRAY && e->ref->u.ar.type == AR_FULL - && e->ref->next == NULL)) - { - gfc_error ("Variable %s at %L with NO_ARG_CHECK attribute shall not have " - "a subobject reference", sym->name, &e->ref->u.ar.where); - return false; - } - /* TS 29113, 407b. */ - else if (e->ts.type == BT_ASSUMED && e->ref - && !(e->ref->type == REF_ARRAY && e->ref->u.ar.type == AR_FULL - && e->ref->next == NULL)) - { - gfc_error ("Assumed-type variable %s at %L shall not have a subobject " - "reference", sym->name, &e->ref->u.ar.where); - return false; - } - - /* TS 29113, C535b. */ - if (((sym->ts.type == BT_CLASS && sym->attr.class_ok - && sym->ts.u.derived && CLASS_DATA (sym) - && CLASS_DATA (sym)->as - && CLASS_DATA (sym)->as->type == AS_ASSUMED_RANK) - || (sym->ts.type != BT_CLASS && sym->as - && sym->as->type == AS_ASSUMED_RANK)) - && e->ref - && !(e->ref->type == REF_ARRAY && e->ref->u.ar.type == AR_FULL - && e->ref->next == NULL)) - { - gfc_error ("Assumed-rank variable %s at %L shall not have a subobject " - "reference", sym->name, &e->ref->u.ar.where); - return false; - } - - /* For variables that are used in an associate (target => object) where - the object's basetype is array valued while the target is scalar, - the ts' type of the component refs is still array valued, which - can't be translated that way. */ - if (sym->assoc && e->rank == 0 && e->ref && sym->ts.type == BT_CLASS - && sym->assoc->target && sym->assoc->target->ts.type == BT_CLASS - && sym->assoc->target->ts.u.derived - && CLASS_DATA (sym->assoc->target) - && CLASS_DATA (sym->assoc->target)->as) - { - gfc_ref *ref = e->ref; - while (ref) - { - switch (ref->type) - { - case REF_COMPONENT: - ref->u.c.sym = sym->ts.u.derived; - /* Stop the loop. */ - ref = NULL; - break; - default: - ref = ref->next; - break; - } - } - } - - /* If this is an associate-name, it may be parsed with an array reference - in error even though the target is scalar. Fail directly in this case. - TODO Understand why class scalar expressions must be excluded. */ - if (sym->assoc && !(sym->ts.type == BT_CLASS && e->rank == 0)) - { - if (sym->ts.type == BT_CLASS) - gfc_fix_class_refs (e); - if (!sym->attr.dimension && e->ref && e->ref->type == REF_ARRAY) - return false; - else if (sym->attr.dimension && (!e->ref || e->ref->type != REF_ARRAY)) - { - /* This can happen because the parser did not detect that the - associate name is an array and the expression had no array - part_ref. */ - gfc_ref *ref = gfc_get_ref (); - ref->type = REF_ARRAY; - ref->u.ar.type = AR_FULL; - if (sym->as) - { - ref->u.ar.as = sym->as; - ref->u.ar.dimen = sym->as->rank; - } - ref->next = e->ref; - e->ref = ref; - - } - } - - if (sym->ts.type == BT_DERIVED && sym->ts.u.derived->attr.generic) - sym->ts.u.derived = gfc_find_dt_in_generic (sym->ts.u.derived); - - /* On the other hand, the parser may not have known this is an array; - in this case, we have to add a FULL reference. */ - if (sym->assoc && sym->attr.dimension && !e->ref) - { - e->ref = gfc_get_ref (); - e->ref->type = REF_ARRAY; - e->ref->u.ar.type = AR_FULL; - e->ref->u.ar.dimen = 0; - } - - /* Like above, but for class types, where the checking whether an array - ref is present is more complicated. Furthermore make sure not to add - the full array ref to _vptr or _len refs. */ - if (sym->assoc && sym->ts.type == BT_CLASS && sym->ts.u.derived - && CLASS_DATA (sym) - && CLASS_DATA (sym)->attr.dimension - && (e->ts.type != BT_DERIVED || !e->ts.u.derived->attr.vtype)) - { - gfc_ref *ref, *newref; - - newref = gfc_get_ref (); - newref->type = REF_ARRAY; - newref->u.ar.type = AR_FULL; - newref->u.ar.dimen = 0; - /* Because this is an associate var and the first ref either is a ref to - the _data component or not, no traversal of the ref chain is - needed. The array ref needs to be inserted after the _data ref, - or when that is not present, which may happend for polymorphic - types, then at the first position. */ - ref = e->ref; - if (!ref) - e->ref = newref; - else if (ref->type == REF_COMPONENT - && strcmp ("_data", ref->u.c.component->name) == 0) - { - if (!ref->next || ref->next->type != REF_ARRAY) - { - newref->next = ref->next; - ref->next = newref; - } - else - /* Array ref present already. */ - gfc_free_ref_list (newref); - } - else if (ref->type == REF_ARRAY) - /* Array ref present already. */ - gfc_free_ref_list (newref); - else - { - newref->next = ref; - e->ref = newref; - } - } - - if (e->ref && !gfc_resolve_ref (e)) - return false; - - if (sym->attr.flavor == FL_PROCEDURE - && (!sym->attr.function - || (sym->attr.function && sym->result - && sym->result->attr.proc_pointer - && !sym->result->attr.function))) - { - e->ts.type = BT_PROCEDURE; - goto resolve_procedure; - } - - if (sym->ts.type != BT_UNKNOWN) - gfc_variable_attr (e, &e->ts); - else if (sym->attr.flavor == FL_PROCEDURE - && sym->attr.function && sym->result - && sym->result->ts.type != BT_UNKNOWN - && sym->result->attr.proc_pointer) - e->ts = sym->result->ts; - else - { - /* Must be a simple variable reference. */ - if (!gfc_set_default_type (sym, 1, sym->ns)) - return false; - e->ts = sym->ts; - } - - if (check_assumed_size_reference (sym, e)) - return false; - - /* Deal with forward references to entries during gfc_resolve_code, to - satisfy, at least partially, 12.5.2.5. */ - if (gfc_current_ns->entries - && current_entry_id == sym->entry_id - && cs_base - && cs_base->current - && cs_base->current->op != EXEC_ENTRY) - { - gfc_entry_list *entry; - gfc_formal_arglist *formal; - int n; - bool seen, saved_specification_expr; - - /* If the symbol is a dummy... */ - if (sym->attr.dummy && sym->ns == gfc_current_ns) - { - entry = gfc_current_ns->entries; - seen = false; - - /* ...test if the symbol is a parameter of previous entries. */ - for (; entry && entry->id <= current_entry_id; entry = entry->next) - for (formal = entry->sym->formal; formal; formal = formal->next) - { - if (formal->sym && sym->name == formal->sym->name) - { - seen = true; - break; - } - } - - /* If it has not been seen as a dummy, this is an error. */ - if (!seen) - { - if (specification_expr) - gfc_error ("Variable %qs, used in a specification expression" - ", is referenced at %L before the ENTRY statement " - "in which it is a parameter", - sym->name, &cs_base->current->loc); - else - gfc_error ("Variable %qs is used at %L before the ENTRY " - "statement in which it is a parameter", - sym->name, &cs_base->current->loc); - t = false; - } - } - - /* Now do the same check on the specification expressions. */ - saved_specification_expr = specification_expr; - specification_expr = true; - if (sym->ts.type == BT_CHARACTER - && !gfc_resolve_expr (sym->ts.u.cl->length)) - t = false; - - if (sym->as) - for (n = 0; n < sym->as->rank; n++) - { - if (!gfc_resolve_expr (sym->as->lower[n])) - t = false; - if (!gfc_resolve_expr (sym->as->upper[n])) - t = false; - } - specification_expr = saved_specification_expr; - - if (t) - /* Update the symbol's entry level. */ - sym->entry_id = current_entry_id + 1; - } - - /* If a symbol has been host_associated mark it. This is used latter, - to identify if aliasing is possible via host association. */ - if (sym->attr.flavor == FL_VARIABLE - && gfc_current_ns->parent - && (gfc_current_ns->parent == sym->ns - || (gfc_current_ns->parent->parent - && gfc_current_ns->parent->parent == sym->ns))) - sym->attr.host_assoc = 1; - - if (gfc_current_ns->proc_name - && sym->attr.dimension - && (sym->ns != gfc_current_ns - || sym->attr.use_assoc - || sym->attr.in_common)) - gfc_current_ns->proc_name->attr.array_outer_dependency = 1; - -resolve_procedure: - if (t && !resolve_procedure_expression (e)) - t = false; - - /* F2008, C617 and C1229. */ - if (!inquiry_argument && (e->ts.type == BT_CLASS || e->ts.type == BT_DERIVED) - && gfc_is_coindexed (e)) - { - gfc_ref *ref, *ref2 = NULL; - - for (ref = e->ref; ref; ref = ref->next) - { - if (ref->type == REF_COMPONENT) - ref2 = ref; - if (ref->type == REF_ARRAY && ref->u.ar.codimen > 0) - break; - } - - for ( ; ref; ref = ref->next) - if (ref->type == REF_COMPONENT) - break; - - /* Expression itself is not coindexed object. */ - if (ref && e->ts.type == BT_CLASS) - { - gfc_error ("Polymorphic subobject of coindexed object at %L", - &e->where); - t = false; - } - - /* Expression itself is coindexed object. */ - if (ref == NULL) - { - gfc_component *c; - c = ref2 ? ref2->u.c.component : e->symtree->n.sym->components; - for ( ; c; c = c->next) - if (c->attr.allocatable && c->ts.type == BT_CLASS) - { - gfc_error ("Coindexed object with polymorphic allocatable " - "subcomponent at %L", &e->where); - t = false; - break; - } - } - } - - if (t) - gfc_expression_rank (e); - - if (t && flag_coarray == GFC_FCOARRAY_LIB && gfc_is_coindexed (e)) - add_caf_get_intrinsic (e); - - if (sym->attr.ext_attr & (1 << EXT_ATTR_DEPRECATED) && sym != sym->result) - gfc_warning (OPT_Wdeprecated_declarations, - "Using variable %qs at %L is deprecated", - sym->name, &e->where); - /* Simplify cases where access to a parameter array results in a - single constant. Suppress errors since those will have been - issued before, as warnings. */ - if (e->rank == 0 && sym->as && sym->attr.flavor == FL_PARAMETER) - { - gfc_push_suppress_errors (); - gfc_simplify_expr (e, 1); - gfc_pop_suppress_errors (); - } - - return t; -} - - -/* Checks to see that the correct symbol has been host associated. - The only situation where this arises is that in which a twice - contained function is parsed after the host association is made. - Therefore, on detecting this, change the symbol in the expression - and convert the array reference into an actual arglist if the old - symbol is a variable. */ -static bool -check_host_association (gfc_expr *e) -{ - gfc_symbol *sym, *old_sym; - gfc_symtree *st; - int n; - gfc_ref *ref; - gfc_actual_arglist *arg, *tail = NULL; - bool retval = e->expr_type == EXPR_FUNCTION; - - /* If the expression is the result of substitution in - interface.c(gfc_extend_expr) because there is no way in - which the host association can be wrong. */ - if (e->symtree == NULL - || e->symtree->n.sym == NULL - || e->user_operator) - return retval; - - old_sym = e->symtree->n.sym; - - if (gfc_current_ns->parent - && old_sym->ns != gfc_current_ns) - { - /* Use the 'USE' name so that renamed module symbols are - correctly handled. */ - gfc_find_symbol (e->symtree->name, gfc_current_ns, 1, &sym); - - if (sym && old_sym != sym - && sym->ts.type == old_sym->ts.type - && sym->attr.flavor == FL_PROCEDURE - && sym->attr.contained) - { - /* Clear the shape, since it might not be valid. */ - gfc_free_shape (&e->shape, e->rank); - - /* Give the expression the right symtree! */ - gfc_find_sym_tree (e->symtree->name, NULL, 1, &st); - gcc_assert (st != NULL); - - if (old_sym->attr.flavor == FL_PROCEDURE - || e->expr_type == EXPR_FUNCTION) - { - /* Original was function so point to the new symbol, since - the actual argument list is already attached to the - expression. */ - e->value.function.esym = NULL; - e->symtree = st; - } - else - { - /* Original was variable so convert array references into - an actual arglist. This does not need any checking now - since resolve_function will take care of it. */ - e->value.function.actual = NULL; - e->expr_type = EXPR_FUNCTION; - e->symtree = st; - - /* Ambiguity will not arise if the array reference is not - the last reference. */ - for (ref = e->ref; ref; ref = ref->next) - if (ref->type == REF_ARRAY && ref->next == NULL) - break; - - if ((ref == NULL || ref->type != REF_ARRAY) - && sym->attr.proc == PROC_INTERNAL) - { - gfc_error ("%qs at %L is host associated at %L into " - "a contained procedure with an internal " - "procedure of the same name", sym->name, - &old_sym->declared_at, &e->where); - return false; - } - - gcc_assert (ref->type == REF_ARRAY); - - /* Grab the start expressions from the array ref and - copy them into actual arguments. */ - for (n = 0; n < ref->u.ar.dimen; n++) - { - arg = gfc_get_actual_arglist (); - arg->expr = gfc_copy_expr (ref->u.ar.start[n]); - if (e->value.function.actual == NULL) - tail = e->value.function.actual = arg; - else - { - tail->next = arg; - tail = arg; - } - } - - /* Dump the reference list and set the rank. */ - gfc_free_ref_list (e->ref); - e->ref = NULL; - e->rank = sym->as ? sym->as->rank : 0; - } - - gfc_resolve_expr (e); - sym->refs++; - } - } - /* This might have changed! */ - return e->expr_type == EXPR_FUNCTION; -} - - -static void -gfc_resolve_character_operator (gfc_expr *e) -{ - gfc_expr *op1 = e->value.op.op1; - gfc_expr *op2 = e->value.op.op2; - gfc_expr *e1 = NULL; - gfc_expr *e2 = NULL; - - gcc_assert (e->value.op.op == INTRINSIC_CONCAT); - - if (op1->ts.u.cl && op1->ts.u.cl->length) - e1 = gfc_copy_expr (op1->ts.u.cl->length); - else if (op1->expr_type == EXPR_CONSTANT) - e1 = gfc_get_int_expr (gfc_charlen_int_kind, NULL, - op1->value.character.length); - - if (op2->ts.u.cl && op2->ts.u.cl->length) - e2 = gfc_copy_expr (op2->ts.u.cl->length); - else if (op2->expr_type == EXPR_CONSTANT) - e2 = gfc_get_int_expr (gfc_charlen_int_kind, NULL, - op2->value.character.length); - - e->ts.u.cl = gfc_new_charlen (gfc_current_ns, NULL); - - if (!e1 || !e2) - { - gfc_free_expr (e1); - gfc_free_expr (e2); - - return; - } - - e->ts.u.cl->length = gfc_add (e1, e2); - e->ts.u.cl->length->ts.type = BT_INTEGER; - e->ts.u.cl->length->ts.kind = gfc_charlen_int_kind; - gfc_simplify_expr (e->ts.u.cl->length, 0); - gfc_resolve_expr (e->ts.u.cl->length); - - return; -} - - -/* Ensure that an character expression has a charlen and, if possible, a - length expression. */ - -static void -fixup_charlen (gfc_expr *e) -{ - /* The cases fall through so that changes in expression type and the need - for multiple fixes are picked up. In all circumstances, a charlen should - be available for the middle end to hang a backend_decl on. */ - switch (e->expr_type) - { - case EXPR_OP: - gfc_resolve_character_operator (e); - /* FALLTHRU */ - - case EXPR_ARRAY: - if (e->expr_type == EXPR_ARRAY) - gfc_resolve_character_array_constructor (e); - /* FALLTHRU */ - - case EXPR_SUBSTRING: - if (!e->ts.u.cl && e->ref) - gfc_resolve_substring_charlen (e); - /* FALLTHRU */ - - default: - if (!e->ts.u.cl) - e->ts.u.cl = gfc_new_charlen (gfc_current_ns, NULL); - - break; - } -} - - -/* Update an actual argument to include the passed-object for type-bound - procedures at the right position. */ - -static gfc_actual_arglist* -update_arglist_pass (gfc_actual_arglist* lst, gfc_expr* po, unsigned argpos, - const char *name) -{ - gcc_assert (argpos > 0); - - if (argpos == 1) - { - gfc_actual_arglist* result; - - result = gfc_get_actual_arglist (); - result->expr = po; - result->next = lst; - if (name) - result->name = name; - - return result; - } - - if (lst) - lst->next = update_arglist_pass (lst->next, po, argpos - 1, name); - else - lst = update_arglist_pass (NULL, po, argpos - 1, name); - return lst; -} - - -/* Extract the passed-object from an EXPR_COMPCALL (a copy of it). */ - -static gfc_expr* -extract_compcall_passed_object (gfc_expr* e) -{ - gfc_expr* po; - - if (e->expr_type == EXPR_UNKNOWN) - { - gfc_error ("Error in typebound call at %L", - &e->where); - return NULL; - } - - gcc_assert (e->expr_type == EXPR_COMPCALL); - - if (e->value.compcall.base_object) - po = gfc_copy_expr (e->value.compcall.base_object); - else - { - po = gfc_get_expr (); - po->expr_type = EXPR_VARIABLE; - po->symtree = e->symtree; - po->ref = gfc_copy_ref (e->ref); - po->where = e->where; - } - - if (!gfc_resolve_expr (po)) - return NULL; - - return po; -} - - -/* Update the arglist of an EXPR_COMPCALL expression to include the - passed-object. */ - -static bool -update_compcall_arglist (gfc_expr* e) -{ - gfc_expr* po; - gfc_typebound_proc* tbp; - - tbp = e->value.compcall.tbp; - - if (tbp->error) - return false; - - po = extract_compcall_passed_object (e); - if (!po) - return false; - - if (tbp->nopass || e->value.compcall.ignore_pass) - { - gfc_free_expr (po); - return true; - } - - if (tbp->pass_arg_num <= 0) - return false; - - e->value.compcall.actual = update_arglist_pass (e->value.compcall.actual, po, - tbp->pass_arg_num, - tbp->pass_arg); - - return true; -} - - -/* Extract the passed object from a PPC call (a copy of it). */ - -static gfc_expr* -extract_ppc_passed_object (gfc_expr *e) -{ - gfc_expr *po; - gfc_ref **ref; - - po = gfc_get_expr (); - po->expr_type = EXPR_VARIABLE; - po->symtree = e->symtree; - po->ref = gfc_copy_ref (e->ref); - po->where = e->where; - - /* Remove PPC reference. */ - ref = &po->ref; - while ((*ref)->next) - ref = &(*ref)->next; - gfc_free_ref_list (*ref); - *ref = NULL; - - if (!gfc_resolve_expr (po)) - return NULL; - - return po; -} - - -/* Update the actual arglist of a procedure pointer component to include the - passed-object. */ - -static bool -update_ppc_arglist (gfc_expr* e) -{ - gfc_expr* po; - gfc_component *ppc; - gfc_typebound_proc* tb; - - ppc = gfc_get_proc_ptr_comp (e); - if (!ppc) - return false; - - tb = ppc->tb; - - if (tb->error) - return false; - else if (tb->nopass) - return true; - - po = extract_ppc_passed_object (e); - if (!po) - return false; - - /* F08:R739. */ - if (po->rank != 0) - { - gfc_error ("Passed-object at %L must be scalar", &e->where); - return false; - } - - /* F08:C611. */ - if (po->ts.type == BT_DERIVED && po->ts.u.derived->attr.abstract) - { - gfc_error ("Base object for procedure-pointer component call at %L is of" - " ABSTRACT type %qs", &e->where, po->ts.u.derived->name); - return false; - } - - gcc_assert (tb->pass_arg_num > 0); - e->value.compcall.actual = update_arglist_pass (e->value.compcall.actual, po, - tb->pass_arg_num, - tb->pass_arg); - - return true; -} - - -/* Check that the object a TBP is called on is valid, i.e. it must not be - of ABSTRACT type (as in subobject%abstract_parent%tbp()). */ - -static bool -check_typebound_baseobject (gfc_expr* e) -{ - gfc_expr* base; - bool return_value = false; - - base = extract_compcall_passed_object (e); - if (!base) - return false; - - if (base->ts.type != BT_DERIVED && base->ts.type != BT_CLASS) - { - gfc_error ("Error in typebound call at %L", &e->where); - goto cleanup; - } - - if (base->ts.type == BT_CLASS && !gfc_expr_attr (base).class_ok) - return false; - - /* F08:C611. */ - if (base->ts.type == BT_DERIVED && base->ts.u.derived->attr.abstract) - { - gfc_error ("Base object for type-bound procedure call at %L is of" - " ABSTRACT type %qs", &e->where, base->ts.u.derived->name); - goto cleanup; - } - - /* F08:C1230. If the procedure called is NOPASS, - the base object must be scalar. */ - if (e->value.compcall.tbp->nopass && base->rank != 0) - { - gfc_error ("Base object for NOPASS type-bound procedure call at %L must" - " be scalar", &e->where); - goto cleanup; - } - - return_value = true; - -cleanup: - gfc_free_expr (base); - return return_value; -} - - -/* Resolve a call to a type-bound procedure, either function or subroutine, - statically from the data in an EXPR_COMPCALL expression. The adapted - arglist and the target-procedure symtree are returned. */ - -static bool -resolve_typebound_static (gfc_expr* e, gfc_symtree** target, - gfc_actual_arglist** actual) -{ - gcc_assert (e->expr_type == EXPR_COMPCALL); - gcc_assert (!e->value.compcall.tbp->is_generic); - - /* Update the actual arglist for PASS. */ - if (!update_compcall_arglist (e)) - return false; - - *actual = e->value.compcall.actual; - *target = e->value.compcall.tbp->u.specific; - - gfc_free_ref_list (e->ref); - e->ref = NULL; - e->value.compcall.actual = NULL; - - /* If we find a deferred typebound procedure, check for derived types - that an overriding typebound procedure has not been missed. */ - if (e->value.compcall.name - && !e->value.compcall.tbp->non_overridable - && e->value.compcall.base_object - && e->value.compcall.base_object->ts.type == BT_DERIVED) - { - gfc_symtree *st; - gfc_symbol *derived; - - /* Use the derived type of the base_object. */ - derived = e->value.compcall.base_object->ts.u.derived; - st = NULL; - - /* If necessary, go through the inheritance chain. */ - while (!st && derived) - { - /* Look for the typebound procedure 'name'. */ - if (derived->f2k_derived && derived->f2k_derived->tb_sym_root) - st = gfc_find_symtree (derived->f2k_derived->tb_sym_root, - e->value.compcall.name); - if (!st) - derived = gfc_get_derived_super_type (derived); - } - - /* Now find the specific name in the derived type namespace. */ - if (st && st->n.tb && st->n.tb->u.specific) - gfc_find_sym_tree (st->n.tb->u.specific->name, - derived->ns, 1, &st); - if (st) - *target = st; - } - return true; -} - - -/* Get the ultimate declared type from an expression. In addition, - return the last class/derived type reference and the copy of the - reference list. If check_types is set true, derived types are - identified as well as class references. */ -static gfc_symbol* -get_declared_from_expr (gfc_ref **class_ref, gfc_ref **new_ref, - gfc_expr *e, bool check_types) -{ - gfc_symbol *declared; - gfc_ref *ref; - - declared = NULL; - if (class_ref) - *class_ref = NULL; - if (new_ref) - *new_ref = gfc_copy_ref (e->ref); - - for (ref = e->ref; ref; ref = ref->next) - { - if (ref->type != REF_COMPONENT) - continue; - - if ((ref->u.c.component->ts.type == BT_CLASS - || (check_types && gfc_bt_struct (ref->u.c.component->ts.type))) - && ref->u.c.component->attr.flavor != FL_PROCEDURE) - { - declared = ref->u.c.component->ts.u.derived; - if (class_ref) - *class_ref = ref; - } - } - - if (declared == NULL) - declared = e->symtree->n.sym->ts.u.derived; - - return declared; -} - - -/* Given an EXPR_COMPCALL calling a GENERIC typebound procedure, figure out - which of the specific bindings (if any) matches the arglist and transform - the expression into a call of that binding. */ - -static bool -resolve_typebound_generic_call (gfc_expr* e, const char **name) -{ - gfc_typebound_proc* genproc; - const char* genname; - gfc_symtree *st; - gfc_symbol *derived; - - gcc_assert (e->expr_type == EXPR_COMPCALL); - genname = e->value.compcall.name; - genproc = e->value.compcall.tbp; - - if (!genproc->is_generic) - return true; - - /* Try the bindings on this type and in the inheritance hierarchy. */ - for (; genproc; genproc = genproc->overridden) - { - gfc_tbp_generic* g; - - gcc_assert (genproc->is_generic); - for (g = genproc->u.generic; g; g = g->next) - { - gfc_symbol* target; - gfc_actual_arglist* args; - bool matches; - - gcc_assert (g->specific); - - if (g->specific->error) - continue; - - target = g->specific->u.specific->n.sym; - - /* Get the right arglist by handling PASS/NOPASS. */ - args = gfc_copy_actual_arglist (e->value.compcall.actual); - if (!g->specific->nopass) - { - gfc_expr* po; - po = extract_compcall_passed_object (e); - if (!po) - { - gfc_free_actual_arglist (args); - return false; - } - - gcc_assert (g->specific->pass_arg_num > 0); - gcc_assert (!g->specific->error); - args = update_arglist_pass (args, po, g->specific->pass_arg_num, - g->specific->pass_arg); - } - resolve_actual_arglist (args, target->attr.proc, - is_external_proc (target) - && gfc_sym_get_dummy_args (target) == NULL); - - /* Check if this arglist matches the formal. */ - matches = gfc_arglist_matches_symbol (&args, target); - - /* Clean up and break out of the loop if we've found it. */ - gfc_free_actual_arglist (args); - if (matches) - { - e->value.compcall.tbp = g->specific; - genname = g->specific_st->name; - /* Pass along the name for CLASS methods, where the vtab - procedure pointer component has to be referenced. */ - if (name) - *name = genname; - goto success; - } - } - } - - /* Nothing matching found! */ - gfc_error ("Found no matching specific binding for the call to the GENERIC" - " %qs at %L", genname, &e->where); - return false; - -success: - /* Make sure that we have the right specific instance for the name. */ - derived = get_declared_from_expr (NULL, NULL, e, true); - - st = gfc_find_typebound_proc (derived, NULL, genname, true, &e->where); - if (st) - e->value.compcall.tbp = st->n.tb; - - return true; -} - - -/* Resolve a call to a type-bound subroutine. */ - -static bool -resolve_typebound_call (gfc_code* c, const char **name, bool *overridable) -{ - gfc_actual_arglist* newactual; - gfc_symtree* target; - - /* Check that's really a SUBROUTINE. */ - if (!c->expr1->value.compcall.tbp->subroutine) - { - if (!c->expr1->value.compcall.tbp->is_generic - && c->expr1->value.compcall.tbp->u.specific - && c->expr1->value.compcall.tbp->u.specific->n.sym - && c->expr1->value.compcall.tbp->u.specific->n.sym->attr.subroutine) - c->expr1->value.compcall.tbp->subroutine = 1; - else - { - gfc_error ("%qs at %L should be a SUBROUTINE", - c->expr1->value.compcall.name, &c->loc); - return false; - } - } - - if (!check_typebound_baseobject (c->expr1)) - return false; - - /* Pass along the name for CLASS methods, where the vtab - procedure pointer component has to be referenced. */ - if (name) - *name = c->expr1->value.compcall.name; - - if (!resolve_typebound_generic_call (c->expr1, name)) - return false; - - /* Pass along the NON_OVERRIDABLE attribute of the specific TBP. */ - if (overridable) - *overridable = !c->expr1->value.compcall.tbp->non_overridable; - - /* Transform into an ordinary EXEC_CALL for now. */ - - if (!resolve_typebound_static (c->expr1, &target, &newactual)) - return false; - - c->ext.actual = newactual; - c->symtree = target; - c->op = (c->expr1->value.compcall.assign ? EXEC_ASSIGN_CALL : EXEC_CALL); - - gcc_assert (!c->expr1->ref && !c->expr1->value.compcall.actual); - - gfc_free_expr (c->expr1); - c->expr1 = gfc_get_expr (); - c->expr1->expr_type = EXPR_FUNCTION; - c->expr1->symtree = target; - c->expr1->where = c->loc; - - return resolve_call (c); -} - - -/* Resolve a component-call expression. */ -static bool -resolve_compcall (gfc_expr* e, const char **name) -{ - gfc_actual_arglist* newactual; - gfc_symtree* target; - - /* Check that's really a FUNCTION. */ - if (!e->value.compcall.tbp->function) - { - gfc_error ("%qs at %L should be a FUNCTION", - e->value.compcall.name, &e->where); - return false; - } - - - /* These must not be assign-calls! */ - gcc_assert (!e->value.compcall.assign); - - if (!check_typebound_baseobject (e)) - return false; - - /* Pass along the name for CLASS methods, where the vtab - procedure pointer component has to be referenced. */ - if (name) - *name = e->value.compcall.name; - - if (!resolve_typebound_generic_call (e, name)) - return false; - gcc_assert (!e->value.compcall.tbp->is_generic); - - /* Take the rank from the function's symbol. */ - if (e->value.compcall.tbp->u.specific->n.sym->as) - e->rank = e->value.compcall.tbp->u.specific->n.sym->as->rank; - - /* For now, we simply transform it into an EXPR_FUNCTION call with the same - arglist to the TBP's binding target. */ - - if (!resolve_typebound_static (e, &target, &newactual)) - return false; - - e->value.function.actual = newactual; - e->value.function.name = NULL; - e->value.function.esym = target->n.sym; - e->value.function.isym = NULL; - e->symtree = target; - e->ts = target->n.sym->ts; - e->expr_type = EXPR_FUNCTION; - - /* Resolution is not necessary if this is a class subroutine; this - function only has to identify the specific proc. Resolution of - the call will be done next in resolve_typebound_call. */ - return gfc_resolve_expr (e); -} - - -static bool resolve_fl_derived (gfc_symbol *sym); - - -/* Resolve a typebound function, or 'method'. First separate all - the non-CLASS references by calling resolve_compcall directly. */ - -static bool -resolve_typebound_function (gfc_expr* e) -{ - gfc_symbol *declared; - gfc_component *c; - gfc_ref *new_ref; - gfc_ref *class_ref; - gfc_symtree *st; - const char *name; - gfc_typespec ts; - gfc_expr *expr; - bool overridable; - - st = e->symtree; - - /* Deal with typebound operators for CLASS objects. */ - expr = e->value.compcall.base_object; - overridable = !e->value.compcall.tbp->non_overridable; - if (expr && expr->ts.type == BT_CLASS && e->value.compcall.name) - { - /* Since the typebound operators are generic, we have to ensure - that any delays in resolution are corrected and that the vtab - is present. */ - ts = expr->ts; - declared = ts.u.derived; - c = gfc_find_component (declared, "_vptr", true, true, NULL); - if (c->ts.u.derived == NULL) - c->ts.u.derived = gfc_find_derived_vtab (declared); - - if (!resolve_compcall (e, &name)) - return false; - - /* Use the generic name if it is there. */ - name = name ? name : e->value.function.esym->name; - e->symtree = expr->symtree; - e->ref = gfc_copy_ref (expr->ref); - get_declared_from_expr (&class_ref, NULL, e, false); - - /* Trim away the extraneous references that emerge from nested - use of interface.c (extend_expr). */ - if (class_ref && class_ref->next) - { - gfc_free_ref_list (class_ref->next); - class_ref->next = NULL; - } - else if (e->ref && !class_ref && expr->ts.type != BT_CLASS) - { - gfc_free_ref_list (e->ref); - e->ref = NULL; - } - - gfc_add_vptr_component (e); - gfc_add_component_ref (e, name); - e->value.function.esym = NULL; - if (expr->expr_type != EXPR_VARIABLE) - e->base_expr = expr; - return true; - } - - if (st == NULL) - return resolve_compcall (e, NULL); - - if (!gfc_resolve_ref (e)) - return false; - - /* Get the CLASS declared type. */ - declared = get_declared_from_expr (&class_ref, &new_ref, e, true); - - if (!resolve_fl_derived (declared)) - return false; - - /* Weed out cases of the ultimate component being a derived type. */ - if ((class_ref && gfc_bt_struct (class_ref->u.c.component->ts.type)) - || (!class_ref && st->n.sym->ts.type != BT_CLASS)) - { - gfc_free_ref_list (new_ref); - return resolve_compcall (e, NULL); - } - - c = gfc_find_component (declared, "_data", true, true, NULL); - - /* Treat the call as if it is a typebound procedure, in order to roll - out the correct name for the specific function. */ - if (!resolve_compcall (e, &name)) - { - gfc_free_ref_list (new_ref); - return false; - } - ts = e->ts; - - if (overridable) - { - /* Convert the expression to a procedure pointer component call. */ - e->value.function.esym = NULL; - e->symtree = st; - - if (new_ref) - e->ref = new_ref; - - /* '_vptr' points to the vtab, which contains the procedure pointers. */ - gfc_add_vptr_component (e); - gfc_add_component_ref (e, name); - - /* Recover the typespec for the expression. This is really only - necessary for generic procedures, where the additional call - to gfc_add_component_ref seems to throw the collection of the - correct typespec. */ - e->ts = ts; - } - else if (new_ref) - gfc_free_ref_list (new_ref); - - return true; -} - -/* Resolve a typebound subroutine, or 'method'. First separate all - the non-CLASS references by calling resolve_typebound_call - directly. */ - -static bool -resolve_typebound_subroutine (gfc_code *code) -{ - gfc_symbol *declared; - gfc_component *c; - gfc_ref *new_ref; - gfc_ref *class_ref; - gfc_symtree *st; - const char *name; - gfc_typespec ts; - gfc_expr *expr; - bool overridable; - - st = code->expr1->symtree; - - /* Deal with typebound operators for CLASS objects. */ - expr = code->expr1->value.compcall.base_object; - overridable = !code->expr1->value.compcall.tbp->non_overridable; - if (expr && expr->ts.type == BT_CLASS && code->expr1->value.compcall.name) - { - /* If the base_object is not a variable, the corresponding actual - argument expression must be stored in e->base_expression so - that the corresponding tree temporary can be used as the base - object in gfc_conv_procedure_call. */ - if (expr->expr_type != EXPR_VARIABLE) - { - gfc_actual_arglist *args; - - args= code->expr1->value.function.actual; - for (; args; args = args->next) - if (expr == args->expr) - expr = args->expr; - } - - /* Since the typebound operators are generic, we have to ensure - that any delays in resolution are corrected and that the vtab - is present. */ - declared = expr->ts.u.derived; - c = gfc_find_component (declared, "_vptr", true, true, NULL); - if (c->ts.u.derived == NULL) - c->ts.u.derived = gfc_find_derived_vtab (declared); - - if (!resolve_typebound_call (code, &name, NULL)) - return false; - - /* Use the generic name if it is there. */ - name = name ? name : code->expr1->value.function.esym->name; - code->expr1->symtree = expr->symtree; - code->expr1->ref = gfc_copy_ref (expr->ref); - - /* Trim away the extraneous references that emerge from nested - use of interface.c (extend_expr). */ - get_declared_from_expr (&class_ref, NULL, code->expr1, false); - if (class_ref && class_ref->next) - { - gfc_free_ref_list (class_ref->next); - class_ref->next = NULL; - } - else if (code->expr1->ref && !class_ref) - { - gfc_free_ref_list (code->expr1->ref); - code->expr1->ref = NULL; - } - - /* Now use the procedure in the vtable. */ - gfc_add_vptr_component (code->expr1); - gfc_add_component_ref (code->expr1, name); - code->expr1->value.function.esym = NULL; - if (expr->expr_type != EXPR_VARIABLE) - code->expr1->base_expr = expr; - return true; - } - - if (st == NULL) - return resolve_typebound_call (code, NULL, NULL); - - if (!gfc_resolve_ref (code->expr1)) - return false; - - /* Get the CLASS declared type. */ - get_declared_from_expr (&class_ref, &new_ref, code->expr1, true); - - /* Weed out cases of the ultimate component being a derived type. */ - if ((class_ref && gfc_bt_struct (class_ref->u.c.component->ts.type)) - || (!class_ref && st->n.sym->ts.type != BT_CLASS)) - { - gfc_free_ref_list (new_ref); - return resolve_typebound_call (code, NULL, NULL); - } - - if (!resolve_typebound_call (code, &name, &overridable)) - { - gfc_free_ref_list (new_ref); - return false; - } - ts = code->expr1->ts; - - if (overridable) - { - /* Convert the expression to a procedure pointer component call. */ - code->expr1->value.function.esym = NULL; - code->expr1->symtree = st; - - if (new_ref) - code->expr1->ref = new_ref; - - /* '_vptr' points to the vtab, which contains the procedure pointers. */ - gfc_add_vptr_component (code->expr1); - gfc_add_component_ref (code->expr1, name); - - /* Recover the typespec for the expression. This is really only - necessary for generic procedures, where the additional call - to gfc_add_component_ref seems to throw the collection of the - correct typespec. */ - code->expr1->ts = ts; - } - else if (new_ref) - gfc_free_ref_list (new_ref); - - return true; -} - - -/* Resolve a CALL to a Procedure Pointer Component (Subroutine). */ - -static bool -resolve_ppc_call (gfc_code* c) -{ - gfc_component *comp; - - comp = gfc_get_proc_ptr_comp (c->expr1); - gcc_assert (comp != NULL); - - c->resolved_sym = c->expr1->symtree->n.sym; - c->expr1->expr_type = EXPR_VARIABLE; - - if (!comp->attr.subroutine) - gfc_add_subroutine (&comp->attr, comp->name, &c->expr1->where); - - if (!gfc_resolve_ref (c->expr1)) - return false; - - if (!update_ppc_arglist (c->expr1)) - return false; - - c->ext.actual = c->expr1->value.compcall.actual; - - if (!resolve_actual_arglist (c->ext.actual, comp->attr.proc, - !(comp->ts.interface - && comp->ts.interface->formal))) - return false; - - if (!pure_subroutine (comp->ts.interface, comp->name, &c->expr1->where)) - return false; - - gfc_ppc_use (comp, &c->expr1->value.compcall.actual, &c->expr1->where); - - return true; -} - - -/* Resolve a Function Call to a Procedure Pointer Component (Function). */ - -static bool -resolve_expr_ppc (gfc_expr* e) -{ - gfc_component *comp; - - comp = gfc_get_proc_ptr_comp (e); - gcc_assert (comp != NULL); - - /* Convert to EXPR_FUNCTION. */ - e->expr_type = EXPR_FUNCTION; - e->value.function.isym = NULL; - e->value.function.actual = e->value.compcall.actual; - e->ts = comp->ts; - if (comp->as != NULL) - e->rank = comp->as->rank; - - if (!comp->attr.function) - gfc_add_function (&comp->attr, comp->name, &e->where); - - if (!gfc_resolve_ref (e)) - return false; - - if (!resolve_actual_arglist (e->value.function.actual, comp->attr.proc, - !(comp->ts.interface - && comp->ts.interface->formal))) - return false; - - if (!update_ppc_arglist (e)) - return false; - - if (!check_pure_function(e)) - return false; - - gfc_ppc_use (comp, &e->value.compcall.actual, &e->where); - - return true; -} - - -static bool -gfc_is_expandable_expr (gfc_expr *e) -{ - gfc_constructor *con; - - if (e->expr_type == EXPR_ARRAY) - { - /* Traverse the constructor looking for variables that are flavor - parameter. Parameters must be expanded since they are fully used at - compile time. */ - con = gfc_constructor_first (e->value.constructor); - for (; con; con = gfc_constructor_next (con)) - { - if (con->expr->expr_type == EXPR_VARIABLE - && con->expr->symtree - && (con->expr->symtree->n.sym->attr.flavor == FL_PARAMETER - || con->expr->symtree->n.sym->attr.flavor == FL_VARIABLE)) - return true; - if (con->expr->expr_type == EXPR_ARRAY - && gfc_is_expandable_expr (con->expr)) - return true; - } - } - - return false; -} - - -/* Sometimes variables in specification expressions of the result - of module procedures in submodules wind up not being the 'real' - dummy. Find this, if possible, in the namespace of the first - formal argument. */ - -static void -fixup_unique_dummy (gfc_expr *e) -{ - gfc_symtree *st = NULL; - gfc_symbol *s = NULL; - - if (e->symtree->n.sym->ns->proc_name - && e->symtree->n.sym->ns->proc_name->formal) - s = e->symtree->n.sym->ns->proc_name->formal->sym; - - if (s != NULL) - st = gfc_find_symtree (s->ns->sym_root, e->symtree->n.sym->name); - - if (st != NULL - && st->n.sym != NULL - && st->n.sym->attr.dummy) - e->symtree = st; -} - -/* Resolve an expression. That is, make sure that types of operands agree - with their operators, intrinsic operators are converted to function calls - for overloaded types and unresolved function references are resolved. */ - -bool -gfc_resolve_expr (gfc_expr *e) -{ - bool t; - bool inquiry_save, actual_arg_save, first_actual_arg_save; - - if (e == NULL || e->do_not_resolve_again) - return true; - - /* inquiry_argument only applies to variables. */ - inquiry_save = inquiry_argument; - actual_arg_save = actual_arg; - first_actual_arg_save = first_actual_arg; - - if (e->expr_type != EXPR_VARIABLE) - { - inquiry_argument = false; - actual_arg = false; - first_actual_arg = false; - } - else if (e->symtree != NULL - && *e->symtree->name == '@' - && e->symtree->n.sym->attr.dummy) - { - /* Deal with submodule specification expressions that are not - found to be referenced in module.c(read_cleanup). */ - fixup_unique_dummy (e); - } - - switch (e->expr_type) - { - case EXPR_OP: - t = resolve_operator (e); - break; - - case EXPR_FUNCTION: - case EXPR_VARIABLE: - - if (check_host_association (e)) - t = resolve_function (e); - else - t = resolve_variable (e); - - if (e->ts.type == BT_CHARACTER && e->ts.u.cl == NULL && e->ref - && e->ref->type != REF_SUBSTRING) - gfc_resolve_substring_charlen (e); - - break; - - case EXPR_COMPCALL: - t = resolve_typebound_function (e); - break; - - case EXPR_SUBSTRING: - t = gfc_resolve_ref (e); - break; - - case EXPR_CONSTANT: - case EXPR_NULL: - t = true; - break; - - case EXPR_PPC: - t = resolve_expr_ppc (e); - break; - - case EXPR_ARRAY: - t = false; - if (!gfc_resolve_ref (e)) - break; - - t = gfc_resolve_array_constructor (e); - /* Also try to expand a constructor. */ - if (t) - { - gfc_expression_rank (e); - if (gfc_is_constant_expr (e) || gfc_is_expandable_expr (e)) - gfc_expand_constructor (e, false); - } - - /* This provides the opportunity for the length of constructors with - character valued function elements to propagate the string length - to the expression. */ - if (t && e->ts.type == BT_CHARACTER) - { - /* For efficiency, we call gfc_expand_constructor for BT_CHARACTER - here rather then add a duplicate test for it above. */ - gfc_expand_constructor (e, false); - t = gfc_resolve_character_array_constructor (e); - } - - break; - - case EXPR_STRUCTURE: - t = gfc_resolve_ref (e); - if (!t) - break; - - t = resolve_structure_cons (e, 0); - if (!t) - break; - - t = gfc_simplify_expr (e, 0); - break; - - default: - gfc_internal_error ("gfc_resolve_expr(): Bad expression type"); - } - - if (e->ts.type == BT_CHARACTER && t && !e->ts.u.cl) - fixup_charlen (e); - - inquiry_argument = inquiry_save; - actual_arg = actual_arg_save; - first_actual_arg = first_actual_arg_save; - - /* For some reason, resolving these expressions a second time mangles - the typespec of the expression itself. */ - if (t && e->expr_type == EXPR_VARIABLE - && e->symtree->n.sym->attr.select_rank_temporary - && UNLIMITED_POLY (e->symtree->n.sym)) - e->do_not_resolve_again = 1; - - return t; -} - - -/* Resolve an expression from an iterator. They must be scalar and have - INTEGER or (optionally) REAL type. */ - -static bool -gfc_resolve_iterator_expr (gfc_expr *expr, bool real_ok, - const char *name_msgid) -{ - if (!gfc_resolve_expr (expr)) - return false; - - if (expr->rank != 0) - { - gfc_error ("%s at %L must be a scalar", _(name_msgid), &expr->where); - return false; - } - - if (expr->ts.type != BT_INTEGER) - { - if (expr->ts.type == BT_REAL) - { - if (real_ok) - return gfc_notify_std (GFC_STD_F95_DEL, - "%s at %L must be integer", - _(name_msgid), &expr->where); - else - { - gfc_error ("%s at %L must be INTEGER", _(name_msgid), - &expr->where); - return false; - } - } - else - { - gfc_error ("%s at %L must be INTEGER", _(name_msgid), &expr->where); - return false; - } - } - return true; -} - - -/* Resolve the expressions in an iterator structure. If REAL_OK is - false allow only INTEGER type iterators, otherwise allow REAL types. - Set own_scope to true for ac-implied-do and data-implied-do as those - have a separate scope such that, e.g., a INTENT(IN) doesn't apply. */ - -bool -gfc_resolve_iterator (gfc_iterator *iter, bool real_ok, bool own_scope) -{ - if (!gfc_resolve_iterator_expr (iter->var, real_ok, "Loop variable")) - return false; - - if (!gfc_check_vardef_context (iter->var, false, false, own_scope, - _("iterator variable"))) - return false; - - if (!gfc_resolve_iterator_expr (iter->start, real_ok, - "Start expression in DO loop")) - return false; - - if (!gfc_resolve_iterator_expr (iter->end, real_ok, - "End expression in DO loop")) - return false; - - if (!gfc_resolve_iterator_expr (iter->step, real_ok, - "Step expression in DO loop")) - return false; - - /* Convert start, end, and step to the same type as var. */ - if (iter->start->ts.kind != iter->var->ts.kind - || iter->start->ts.type != iter->var->ts.type) - gfc_convert_type (iter->start, &iter->var->ts, 1); - - if (iter->end->ts.kind != iter->var->ts.kind - || iter->end->ts.type != iter->var->ts.type) - gfc_convert_type (iter->end, &iter->var->ts, 1); - - if (iter->step->ts.kind != iter->var->ts.kind - || iter->step->ts.type != iter->var->ts.type) - gfc_convert_type (iter->step, &iter->var->ts, 1); - - if (iter->step->expr_type == EXPR_CONSTANT) - { - if ((iter->step->ts.type == BT_INTEGER - && mpz_cmp_ui (iter->step->value.integer, 0) == 0) - || (iter->step->ts.type == BT_REAL - && mpfr_sgn (iter->step->value.real) == 0)) - { - gfc_error ("Step expression in DO loop at %L cannot be zero", - &iter->step->where); - return false; - } - } - - if (iter->start->expr_type == EXPR_CONSTANT - && iter->end->expr_type == EXPR_CONSTANT - && iter->step->expr_type == EXPR_CONSTANT) - { - int sgn, cmp; - if (iter->start->ts.type == BT_INTEGER) - { - sgn = mpz_cmp_ui (iter->step->value.integer, 0); - cmp = mpz_cmp (iter->end->value.integer, iter->start->value.integer); - } - else - { - sgn = mpfr_sgn (iter->step->value.real); - cmp = mpfr_cmp (iter->end->value.real, iter->start->value.real); - } - if (warn_zerotrip && ((sgn > 0 && cmp < 0) || (sgn < 0 && cmp > 0))) - gfc_warning (OPT_Wzerotrip, - "DO loop at %L will be executed zero times", - &iter->step->where); - } - - if (iter->end->expr_type == EXPR_CONSTANT - && iter->end->ts.type == BT_INTEGER - && iter->step->expr_type == EXPR_CONSTANT - && iter->step->ts.type == BT_INTEGER - && (mpz_cmp_si (iter->step->value.integer, -1L) == 0 - || mpz_cmp_si (iter->step->value.integer, 1L) == 0)) - { - bool is_step_positive = mpz_cmp_ui (iter->step->value.integer, 1) == 0; - int k = gfc_validate_kind (BT_INTEGER, iter->end->ts.kind, false); - - if (is_step_positive - && mpz_cmp (iter->end->value.integer, gfc_integer_kinds[k].huge) == 0) - gfc_warning (OPT_Wundefined_do_loop, - "DO loop at %L is undefined as it overflows", - &iter->step->where); - else if (!is_step_positive - && mpz_cmp (iter->end->value.integer, - gfc_integer_kinds[k].min_int) == 0) - gfc_warning (OPT_Wundefined_do_loop, - "DO loop at %L is undefined as it underflows", - &iter->step->where); - } - - return true; -} - - -/* Traversal function for find_forall_index. f == 2 signals that - that variable itself is not to be checked - only the references. */ - -static bool -forall_index (gfc_expr *expr, gfc_symbol *sym, int *f) -{ - if (expr->expr_type != EXPR_VARIABLE) - return false; - - /* A scalar assignment */ - if (!expr->ref || *f == 1) - { - if (expr->symtree->n.sym == sym) - return true; - else - return false; - } - - if (*f == 2) - *f = 1; - return false; -} - - -/* Check whether the FORALL index appears in the expression or not. - Returns true if SYM is found in EXPR. */ - -bool -find_forall_index (gfc_expr *expr, gfc_symbol *sym, int f) -{ - if (gfc_traverse_expr (expr, sym, forall_index, f)) - return true; - else - return false; -} - - -/* Resolve a list of FORALL iterators. The FORALL index-name is constrained - to be a scalar INTEGER variable. The subscripts and stride are scalar - INTEGERs, and if stride is a constant it must be nonzero. - Furthermore "A subscript or stride in a forall-triplet-spec shall - not contain a reference to any index-name in the - forall-triplet-spec-list in which it appears." (7.5.4.1) */ - -static void -resolve_forall_iterators (gfc_forall_iterator *it) -{ - gfc_forall_iterator *iter, *iter2; - - for (iter = it; iter; iter = iter->next) - { - if (gfc_resolve_expr (iter->var) - && (iter->var->ts.type != BT_INTEGER || iter->var->rank != 0)) - gfc_error ("FORALL index-name at %L must be a scalar INTEGER", - &iter->var->where); - - if (gfc_resolve_expr (iter->start) - && (iter->start->ts.type != BT_INTEGER || iter->start->rank != 0)) - gfc_error ("FORALL start expression at %L must be a scalar INTEGER", - &iter->start->where); - if (iter->var->ts.kind != iter->start->ts.kind) - gfc_convert_type (iter->start, &iter->var->ts, 1); - - if (gfc_resolve_expr (iter->end) - && (iter->end->ts.type != BT_INTEGER || iter->end->rank != 0)) - gfc_error ("FORALL end expression at %L must be a scalar INTEGER", - &iter->end->where); - if (iter->var->ts.kind != iter->end->ts.kind) - gfc_convert_type (iter->end, &iter->var->ts, 1); - - if (gfc_resolve_expr (iter->stride)) - { - if (iter->stride->ts.type != BT_INTEGER || iter->stride->rank != 0) - gfc_error ("FORALL stride expression at %L must be a scalar %s", - &iter->stride->where, "INTEGER"); - - if (iter->stride->expr_type == EXPR_CONSTANT - && mpz_cmp_ui (iter->stride->value.integer, 0) == 0) - gfc_error ("FORALL stride expression at %L cannot be zero", - &iter->stride->where); - } - if (iter->var->ts.kind != iter->stride->ts.kind) - gfc_convert_type (iter->stride, &iter->var->ts, 1); - } - - for (iter = it; iter; iter = iter->next) - for (iter2 = iter; iter2; iter2 = iter2->next) - { - if (find_forall_index (iter2->start, iter->var->symtree->n.sym, 0) - || find_forall_index (iter2->end, iter->var->symtree->n.sym, 0) - || find_forall_index (iter2->stride, iter->var->symtree->n.sym, 0)) - gfc_error ("FORALL index %qs may not appear in triplet " - "specification at %L", iter->var->symtree->name, - &iter2->start->where); - } -} - - -/* Given a pointer to a symbol that is a derived type, see if it's - inaccessible, i.e. if it's defined in another module and the components are - PRIVATE. The search is recursive if necessary. Returns zero if no - inaccessible components are found, nonzero otherwise. */ - -static int -derived_inaccessible (gfc_symbol *sym) -{ - gfc_component *c; - - if (sym->attr.use_assoc && sym->attr.private_comp) - return 1; - - for (c = sym->components; c; c = c->next) - { - /* Prevent an infinite loop through this function. */ - if (c->ts.type == BT_DERIVED && c->attr.pointer - && sym == c->ts.u.derived) - continue; - - if (c->ts.type == BT_DERIVED && derived_inaccessible (c->ts.u.derived)) - return 1; - } - - return 0; -} - - -/* Resolve the argument of a deallocate expression. The expression must be - a pointer or a full array. */ - -static bool -resolve_deallocate_expr (gfc_expr *e) -{ - symbol_attribute attr; - int allocatable, pointer; - gfc_ref *ref; - gfc_symbol *sym; - gfc_component *c; - bool unlimited; - - if (!gfc_resolve_expr (e)) - return false; - - if (e->expr_type != EXPR_VARIABLE) - goto bad; - - sym = e->symtree->n.sym; - unlimited = UNLIMITED_POLY(sym); - - if (sym->ts.type == BT_CLASS) - { - allocatable = CLASS_DATA (sym)->attr.allocatable; - pointer = CLASS_DATA (sym)->attr.class_pointer; - } - else - { - allocatable = sym->attr.allocatable; - pointer = sym->attr.pointer; - } - for (ref = e->ref; ref; ref = ref->next) - { - switch (ref->type) - { - case REF_ARRAY: - if (ref->u.ar.type != AR_FULL - && !(ref->u.ar.type == AR_ELEMENT && ref->u.ar.as->rank == 0 - && ref->u.ar.codimen && gfc_ref_this_image (ref))) - allocatable = 0; - break; - - case REF_COMPONENT: - c = ref->u.c.component; - if (c->ts.type == BT_CLASS) - { - allocatable = CLASS_DATA (c)->attr.allocatable; - pointer = CLASS_DATA (c)->attr.class_pointer; - } - else - { - allocatable = c->attr.allocatable; - pointer = c->attr.pointer; - } - break; - - case REF_SUBSTRING: - case REF_INQUIRY: - allocatable = 0; - break; - } - } - - attr = gfc_expr_attr (e); - - if (allocatable == 0 && attr.pointer == 0 && !unlimited) - { - bad: - gfc_error ("Allocate-object at %L must be ALLOCATABLE or a POINTER", - &e->where); - return false; - } - - /* F2008, C644. */ - if (gfc_is_coindexed (e)) - { - gfc_error ("Coindexed allocatable object at %L", &e->where); - return false; - } - - if (pointer - && !gfc_check_vardef_context (e, true, true, false, - _("DEALLOCATE object"))) - return false; - if (!gfc_check_vardef_context (e, false, true, false, - _("DEALLOCATE object"))) - return false; - - return true; -} - - -/* Returns true if the expression e contains a reference to the symbol sym. */ -static bool -sym_in_expr (gfc_expr *e, gfc_symbol *sym, int *f ATTRIBUTE_UNUSED) -{ - if (e->expr_type == EXPR_VARIABLE && e->symtree->n.sym == sym) - return true; - - return false; -} - -bool -gfc_find_sym_in_expr (gfc_symbol *sym, gfc_expr *e) -{ - return gfc_traverse_expr (e, sym, sym_in_expr, 0); -} - - -/* Given the expression node e for an allocatable/pointer of derived type to be - allocated, get the expression node to be initialized afterwards (needed for - derived types with default initializers, and derived types with allocatable - components that need nullification.) */ - -gfc_expr * -gfc_expr_to_initialize (gfc_expr *e) -{ - gfc_expr *result; - gfc_ref *ref; - int i; - - result = gfc_copy_expr (e); - - /* Change the last array reference from AR_ELEMENT to AR_FULL. */ - for (ref = result->ref; ref; ref = ref->next) - if (ref->type == REF_ARRAY && ref->next == NULL) - { - if (ref->u.ar.dimen == 0 - && ref->u.ar.as && ref->u.ar.as->corank) - return result; - - ref->u.ar.type = AR_FULL; - - for (i = 0; i < ref->u.ar.dimen; i++) - ref->u.ar.start[i] = ref->u.ar.end[i] = ref->u.ar.stride[i] = NULL; - - break; - } - - gfc_free_shape (&result->shape, result->rank); - - /* Recalculate rank, shape, etc. */ - gfc_resolve_expr (result); - return result; -} - - -/* If the last ref of an expression is an array ref, return a copy of the - expression with that one removed. Otherwise, a copy of the original - expression. This is used for allocate-expressions and pointer assignment - LHS, where there may be an array specification that needs to be stripped - off when using gfc_check_vardef_context. */ - -static gfc_expr* -remove_last_array_ref (gfc_expr* e) -{ - gfc_expr* e2; - gfc_ref** r; - - e2 = gfc_copy_expr (e); - for (r = &e2->ref; *r; r = &(*r)->next) - if ((*r)->type == REF_ARRAY && !(*r)->next) - { - gfc_free_ref_list (*r); - *r = NULL; - break; - } - - return e2; -} - - -/* Used in resolve_allocate_expr to check that a allocation-object and - a source-expr are conformable. This does not catch all possible - cases; in particular a runtime checking is needed. */ - -static bool -conformable_arrays (gfc_expr *e1, gfc_expr *e2) -{ - gfc_ref *tail; - for (tail = e2->ref; tail && tail->next; tail = tail->next); - - /* First compare rank. */ - if ((tail && (!tail->u.ar.as || e1->rank != tail->u.ar.as->rank)) - || (!tail && e1->rank != e2->rank)) - { - gfc_error ("Source-expr at %L must be scalar or have the " - "same rank as the allocate-object at %L", - &e1->where, &e2->where); - return false; - } - - if (e1->shape) - { - int i; - mpz_t s; - - mpz_init (s); - - for (i = 0; i < e1->rank; i++) - { - if (tail->u.ar.start[i] == NULL) - break; - - if (tail->u.ar.end[i]) - { - mpz_set (s, tail->u.ar.end[i]->value.integer); - mpz_sub (s, s, tail->u.ar.start[i]->value.integer); - mpz_add_ui (s, s, 1); - } - else - { - mpz_set (s, tail->u.ar.start[i]->value.integer); - } - - if (mpz_cmp (e1->shape[i], s) != 0) - { - gfc_error ("Source-expr at %L and allocate-object at %L must " - "have the same shape", &e1->where, &e2->where); - mpz_clear (s); - return false; - } - } - - mpz_clear (s); - } - - return true; -} - - -/* Resolve the expression in an ALLOCATE statement, doing the additional - checks to see whether the expression is OK or not. The expression must - have a trailing array reference that gives the size of the array. */ - -static bool -resolve_allocate_expr (gfc_expr *e, gfc_code *code, bool *array_alloc_wo_spec) -{ - int i, pointer, allocatable, dimension, is_abstract; - int codimension; - bool coindexed; - bool unlimited; - symbol_attribute attr; - gfc_ref *ref, *ref2; - gfc_expr *e2; - gfc_array_ref *ar; - gfc_symbol *sym = NULL; - gfc_alloc *a; - gfc_component *c; - bool t; - - /* Mark the utmost array component as being in allocate to allow DIMEN_STAR - checking of coarrays. */ - for (ref = e->ref; ref; ref = ref->next) - if (ref->next == NULL) - break; - - if (ref && ref->type == REF_ARRAY) - ref->u.ar.in_allocate = true; - - if (!gfc_resolve_expr (e)) - goto failure; - - /* Make sure the expression is allocatable or a pointer. If it is - pointer, the next-to-last reference must be a pointer. */ - - ref2 = NULL; - if (e->symtree) - sym = e->symtree->n.sym; - - /* Check whether ultimate component is abstract and CLASS. */ - is_abstract = 0; - - /* Is the allocate-object unlimited polymorphic? */ - unlimited = UNLIMITED_POLY(e); - - if (e->expr_type != EXPR_VARIABLE) - { - allocatable = 0; - attr = gfc_expr_attr (e); - pointer = attr.pointer; - dimension = attr.dimension; - codimension = attr.codimension; - } - else - { - if (sym->ts.type == BT_CLASS && CLASS_DATA (sym)) - { - allocatable = CLASS_DATA (sym)->attr.allocatable; - pointer = CLASS_DATA (sym)->attr.class_pointer; - dimension = CLASS_DATA (sym)->attr.dimension; - codimension = CLASS_DATA (sym)->attr.codimension; - is_abstract = CLASS_DATA (sym)->attr.abstract; - } - else - { - allocatable = sym->attr.allocatable; - pointer = sym->attr.pointer; - dimension = sym->attr.dimension; - codimension = sym->attr.codimension; - } - - coindexed = false; - - for (ref = e->ref; ref; ref2 = ref, ref = ref->next) - { - switch (ref->type) - { - case REF_ARRAY: - if (ref->u.ar.codimen > 0) - { - int n; - for (n = ref->u.ar.dimen; - n < ref->u.ar.dimen + ref->u.ar.codimen; n++) - if (ref->u.ar.dimen_type[n] != DIMEN_THIS_IMAGE) - { - coindexed = true; - break; - } - } - - if (ref->next != NULL) - pointer = 0; - break; - - case REF_COMPONENT: - /* F2008, C644. */ - if (coindexed) - { - gfc_error ("Coindexed allocatable object at %L", - &e->where); - goto failure; - } - - c = ref->u.c.component; - if (c->ts.type == BT_CLASS) - { - allocatable = CLASS_DATA (c)->attr.allocatable; - pointer = CLASS_DATA (c)->attr.class_pointer; - dimension = CLASS_DATA (c)->attr.dimension; - codimension = CLASS_DATA (c)->attr.codimension; - is_abstract = CLASS_DATA (c)->attr.abstract; - } - else - { - allocatable = c->attr.allocatable; - pointer = c->attr.pointer; - dimension = c->attr.dimension; - codimension = c->attr.codimension; - is_abstract = c->attr.abstract; - } - break; - - case REF_SUBSTRING: - case REF_INQUIRY: - allocatable = 0; - pointer = 0; - break; - } - } - } - - /* Check for F08:C628 (F2018:C932). Each allocate-object shall be a data - pointer or an allocatable variable. */ - if (allocatable == 0 && pointer == 0) - { - gfc_error ("Allocate-object at %L must be ALLOCATABLE or a POINTER", - &e->where); - goto failure; - } - - /* Some checks for the SOURCE tag. */ - if (code->expr3) - { - /* Check F03:C631. */ - if (!gfc_type_compatible (&e->ts, &code->expr3->ts)) - { - gfc_error ("Type of entity at %L is type incompatible with " - "source-expr at %L", &e->where, &code->expr3->where); - goto failure; - } - - /* Check F03:C632 and restriction following Note 6.18. */ - if (code->expr3->rank > 0 && !conformable_arrays (code->expr3, e)) - goto failure; - - /* Check F03:C633. */ - if (code->expr3->ts.kind != e->ts.kind && !unlimited) - { - gfc_error ("The allocate-object at %L and the source-expr at %L " - "shall have the same kind type parameter", - &e->where, &code->expr3->where); - goto failure; - } - - /* Check F2008, C642. */ - if (code->expr3->ts.type == BT_DERIVED - && ((codimension && gfc_expr_attr (code->expr3).lock_comp) - || (code->expr3->ts.u.derived->from_intmod - == INTMOD_ISO_FORTRAN_ENV - && code->expr3->ts.u.derived->intmod_sym_id - == ISOFORTRAN_LOCK_TYPE))) - { - gfc_error ("The source-expr at %L shall neither be of type " - "LOCK_TYPE nor have a LOCK_TYPE component if " - "allocate-object at %L is a coarray", - &code->expr3->where, &e->where); - goto failure; - } - - /* Check TS18508, C702/C703. */ - if (code->expr3->ts.type == BT_DERIVED - && ((codimension && gfc_expr_attr (code->expr3).event_comp) - || (code->expr3->ts.u.derived->from_intmod - == INTMOD_ISO_FORTRAN_ENV - && code->expr3->ts.u.derived->intmod_sym_id - == ISOFORTRAN_EVENT_TYPE))) - { - gfc_error ("The source-expr at %L shall neither be of type " - "EVENT_TYPE nor have a EVENT_TYPE component if " - "allocate-object at %L is a coarray", - &code->expr3->where, &e->where); - goto failure; - } - } - - /* Check F08:C629. */ - if (is_abstract && code->ext.alloc.ts.type == BT_UNKNOWN - && !code->expr3) - { - gcc_assert (e->ts.type == BT_CLASS); - gfc_error ("Allocating %s of ABSTRACT base type at %L requires a " - "type-spec or source-expr", sym->name, &e->where); - goto failure; - } - - /* Check F08:C632. */ - if (code->ext.alloc.ts.type == BT_CHARACTER && !e->ts.deferred - && !UNLIMITED_POLY (e)) - { - int cmp; - - if (!e->ts.u.cl->length) - goto failure; - - cmp = gfc_dep_compare_expr (e->ts.u.cl->length, - code->ext.alloc.ts.u.cl->length); - if (cmp == 1 || cmp == -1 || cmp == -3) - { - gfc_error ("Allocating %s at %L with type-spec requires the same " - "character-length parameter as in the declaration", - sym->name, &e->where); - goto failure; - } - } - - /* In the variable definition context checks, gfc_expr_attr is used - on the expression. This is fooled by the array specification - present in e, thus we have to eliminate that one temporarily. */ - e2 = remove_last_array_ref (e); - t = true; - if (t && pointer) - t = gfc_check_vardef_context (e2, true, true, false, - _("ALLOCATE object")); - if (t) - t = gfc_check_vardef_context (e2, false, true, false, - _("ALLOCATE object")); - gfc_free_expr (e2); - if (!t) - goto failure; - - if (e->ts.type == BT_CLASS && CLASS_DATA (e)->attr.dimension - && !code->expr3 && code->ext.alloc.ts.type == BT_DERIVED) - { - /* For class arrays, the initialization with SOURCE is done - using _copy and trans_call. It is convenient to exploit that - when the allocated type is different from the declared type but - no SOURCE exists by setting expr3. */ - code->expr3 = gfc_default_initializer (&code->ext.alloc.ts); - } - else if (flag_coarray != GFC_FCOARRAY_LIB && e->ts.type == BT_DERIVED - && e->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV - && e->ts.u.derived->intmod_sym_id == ISOFORTRAN_EVENT_TYPE) - { - /* We have to zero initialize the integer variable. */ - code->expr3 = gfc_get_int_expr (gfc_default_integer_kind, &e->where, 0); - } - - if (e->ts.type == BT_CLASS && !unlimited && !UNLIMITED_POLY (code->expr3)) - { - /* Make sure the vtab symbol is present when - the module variables are generated. */ - gfc_typespec ts = e->ts; - if (code->expr3) - ts = code->expr3->ts; - else if (code->ext.alloc.ts.type == BT_DERIVED) - ts = code->ext.alloc.ts; - - /* Finding the vtab also publishes the type's symbol. Therefore this - statement is necessary. */ - gfc_find_derived_vtab (ts.u.derived); - } - else if (unlimited && !UNLIMITED_POLY (code->expr3)) - { - /* Again, make sure the vtab symbol is present when - the module variables are generated. */ - gfc_typespec *ts = NULL; - if (code->expr3) - ts = &code->expr3->ts; - else - ts = &code->ext.alloc.ts; - - gcc_assert (ts); - - /* Finding the vtab also publishes the type's symbol. Therefore this - statement is necessary. */ - gfc_find_vtab (ts); - } - - if (dimension == 0 && codimension == 0) - goto success; - - /* Make sure the last reference node is an array specification. */ - - if (!ref2 || ref2->type != REF_ARRAY || ref2->u.ar.type == AR_FULL - || (dimension && ref2->u.ar.dimen == 0)) - { - /* F08:C633. */ - if (code->expr3) - { - if (!gfc_notify_std (GFC_STD_F2008, "Array specification required " - "in ALLOCATE statement at %L", &e->where)) - goto failure; - if (code->expr3->rank != 0) - *array_alloc_wo_spec = true; - else - { - gfc_error ("Array specification or array-valued SOURCE= " - "expression required in ALLOCATE statement at %L", - &e->where); - goto failure; - } - } - else - { - gfc_error ("Array specification required in ALLOCATE statement " - "at %L", &e->where); - goto failure; - } - } - - /* Make sure that the array section reference makes sense in the - context of an ALLOCATE specification. */ - - ar = &ref2->u.ar; - - if (codimension) - for (i = ar->dimen; i < ar->dimen + ar->codimen; i++) - { - switch (ar->dimen_type[i]) - { - case DIMEN_THIS_IMAGE: - gfc_error ("Coarray specification required in ALLOCATE statement " - "at %L", &e->where); - goto failure; - - case DIMEN_RANGE: - if (ar->start[i] == 0 || ar->end[i] == 0) - { - /* If ar->stride[i] is NULL, we issued a previous error. */ - if (ar->stride[i] == NULL) - gfc_error ("Bad array specification in ALLOCATE statement " - "at %L", &e->where); - goto failure; - } - else if (gfc_dep_compare_expr (ar->start[i], ar->end[i]) == 1) - { - gfc_error ("Upper cobound is less than lower cobound at %L", - &ar->start[i]->where); - goto failure; - } - break; - - case DIMEN_ELEMENT: - if (ar->start[i]->expr_type == EXPR_CONSTANT) - { - gcc_assert (ar->start[i]->ts.type == BT_INTEGER); - if (mpz_cmp_si (ar->start[i]->value.integer, 1) < 0) - { - gfc_error ("Upper cobound is less than lower cobound " - "of 1 at %L", &ar->start[i]->where); - goto failure; - } - } - break; - - case DIMEN_STAR: - break; - - default: - gfc_error ("Bad array specification in ALLOCATE statement at %L", - &e->where); - goto failure; - - } - } - for (i = 0; i < ar->dimen; i++) - { - if (ar->type == AR_ELEMENT || ar->type == AR_FULL) - goto check_symbols; - - switch (ar->dimen_type[i]) - { - case DIMEN_ELEMENT: - break; - - case DIMEN_RANGE: - if (ar->start[i] != NULL - && ar->end[i] != NULL - && ar->stride[i] == NULL) - break; - - /* Fall through. */ - - case DIMEN_UNKNOWN: - case DIMEN_VECTOR: - case DIMEN_STAR: - case DIMEN_THIS_IMAGE: - gfc_error ("Bad array specification in ALLOCATE statement at %L", - &e->where); - goto failure; - } - -check_symbols: - for (a = code->ext.alloc.list; a; a = a->next) - { - sym = a->expr->symtree->n.sym; - - /* TODO - check derived type components. */ - if (gfc_bt_struct (sym->ts.type) || sym->ts.type == BT_CLASS) - continue; - - if ((ar->start[i] != NULL - && gfc_find_sym_in_expr (sym, ar->start[i])) - || (ar->end[i] != NULL - && gfc_find_sym_in_expr (sym, ar->end[i]))) - { - gfc_error ("%qs must not appear in the array specification at " - "%L in the same ALLOCATE statement where it is " - "itself allocated", sym->name, &ar->where); - goto failure; - } - } - } - - for (i = ar->dimen; i < ar->codimen + ar->dimen; i++) - { - if (ar->dimen_type[i] == DIMEN_ELEMENT - || ar->dimen_type[i] == DIMEN_RANGE) - { - if (i == (ar->dimen + ar->codimen - 1)) - { - gfc_error ("Expected '*' in coindex specification in ALLOCATE " - "statement at %L", &e->where); - goto failure; - } - continue; - } - - if (ar->dimen_type[i] == DIMEN_STAR && i == (ar->dimen + ar->codimen - 1) - && ar->stride[i] == NULL) - break; - - gfc_error ("Bad coarray specification in ALLOCATE statement at %L", - &e->where); - goto failure; - } - -success: - return true; - -failure: - return false; -} - - -static void -resolve_allocate_deallocate (gfc_code *code, const char *fcn) -{ - gfc_expr *stat, *errmsg, *pe, *qe; - gfc_alloc *a, *p, *q; - - stat = code->expr1; - errmsg = code->expr2; - - /* Check the stat variable. */ - if (stat) - { - if (!gfc_check_vardef_context (stat, false, false, false, - _("STAT variable"))) - goto done_stat; - - if (stat->ts.type != BT_INTEGER - || stat->rank > 0) - gfc_error ("Stat-variable at %L must be a scalar INTEGER " - "variable", &stat->where); - - if (stat->expr_type == EXPR_CONSTANT || stat->symtree == NULL) - goto done_stat; - - /* F2018:9.7.4: The stat-variable shall not be allocated or deallocated - * within the ALLOCATE or DEALLOCATE statement in which it appears ... - */ - for (p = code->ext.alloc.list; p; p = p->next) - if (p->expr->symtree->n.sym->name == stat->symtree->n.sym->name) - { - gfc_ref *ref1, *ref2; - bool found = true; - - for (ref1 = p->expr->ref, ref2 = stat->ref; ref1 && ref2; - ref1 = ref1->next, ref2 = ref2->next) - { - if (ref1->type != REF_COMPONENT || ref2->type != REF_COMPONENT) - continue; - if (ref1->u.c.component->name != ref2->u.c.component->name) - { - found = false; - break; - } - } - - if (found) - { - gfc_error ("Stat-variable at %L shall not be %sd within " - "the same %s statement", &stat->where, fcn, fcn); - break; - } - } - } - -done_stat: - - /* Check the errmsg variable. */ - if (errmsg) - { - if (!stat) - gfc_warning (0, "ERRMSG at %L is useless without a STAT tag", - &errmsg->where); - - if (!gfc_check_vardef_context (errmsg, false, false, false, - _("ERRMSG variable"))) - goto done_errmsg; - - /* F18:R928 alloc-opt is ERRMSG = errmsg-variable - F18:R930 errmsg-variable is scalar-default-char-variable - F18:R906 default-char-variable is variable - F18:C906 default-char-variable shall be default character. */ - if (errmsg->ts.type != BT_CHARACTER - || errmsg->rank > 0 - || errmsg->ts.kind != gfc_default_character_kind) - gfc_error ("ERRMSG variable at %L shall be a scalar default CHARACTER " - "variable", &errmsg->where); - - if (errmsg->expr_type == EXPR_CONSTANT || errmsg->symtree == NULL) - goto done_errmsg; - - /* F2018:9.7.5: The errmsg-variable shall not be allocated or deallocated - * within the ALLOCATE or DEALLOCATE statement in which it appears ... - */ - for (p = code->ext.alloc.list; p; p = p->next) - if (p->expr->symtree->n.sym->name == errmsg->symtree->n.sym->name) - { - gfc_ref *ref1, *ref2; - bool found = true; - - for (ref1 = p->expr->ref, ref2 = errmsg->ref; ref1 && ref2; - ref1 = ref1->next, ref2 = ref2->next) - { - if (ref1->type != REF_COMPONENT || ref2->type != REF_COMPONENT) - continue; - if (ref1->u.c.component->name != ref2->u.c.component->name) - { - found = false; - break; - } - } - - if (found) - { - gfc_error ("Errmsg-variable at %L shall not be %sd within " - "the same %s statement", &errmsg->where, fcn, fcn); - break; - } - } - } - -done_errmsg: - - /* Check that an allocate-object appears only once in the statement. */ - - for (p = code->ext.alloc.list; p; p = p->next) - { - pe = p->expr; - for (q = p->next; q; q = q->next) - { - qe = q->expr; - if (pe->symtree->n.sym->name == qe->symtree->n.sym->name) - { - /* This is a potential collision. */ - gfc_ref *pr = pe->ref; - gfc_ref *qr = qe->ref; - - /* Follow the references until - a) They start to differ, in which case there is no error; - you can deallocate a%b and a%c in a single statement - b) Both of them stop, which is an error - c) One of them stops, which is also an error. */ - while (1) - { - if (pr == NULL && qr == NULL) - { - gfc_error ("Allocate-object at %L also appears at %L", - &pe->where, &qe->where); - break; - } - else if (pr != NULL && qr == NULL) - { - gfc_error ("Allocate-object at %L is subobject of" - " object at %L", &pe->where, &qe->where); - break; - } - else if (pr == NULL && qr != NULL) - { - gfc_error ("Allocate-object at %L is subobject of" - " object at %L", &qe->where, &pe->where); - break; - } - /* Here, pr != NULL && qr != NULL */ - gcc_assert(pr->type == qr->type); - if (pr->type == REF_ARRAY) - { - /* Handle cases like allocate(v(3)%x(3), v(2)%x(3)), - which are legal. */ - gcc_assert (qr->type == REF_ARRAY); - - if (pr->next && qr->next) - { - int i; - gfc_array_ref *par = &(pr->u.ar); - gfc_array_ref *qar = &(qr->u.ar); - - for (i=0; i<par->dimen; i++) - { - if ((par->start[i] != NULL - || qar->start[i] != NULL) - && gfc_dep_compare_expr (par->start[i], - qar->start[i]) != 0) - goto break_label; - } - } - } - else - { - if (pr->u.c.component->name != qr->u.c.component->name) - break; - } - - pr = pr->next; - qr = qr->next; - } - break_label: - ; - } - } - } - - if (strcmp (fcn, "ALLOCATE") == 0) - { - bool arr_alloc_wo_spec = false; - - /* Resolving the expr3 in the loop over all objects to allocate would - execute loop invariant code for each loop item. Therefore do it just - once here. */ - if (code->expr3 && code->expr3->mold - && code->expr3->ts.type == BT_DERIVED) - { - /* Default initialization via MOLD (non-polymorphic). */ - gfc_expr *rhs = gfc_default_initializer (&code->expr3->ts); - if (rhs != NULL) - { - gfc_resolve_expr (rhs); - gfc_free_expr (code->expr3); - code->expr3 = rhs; - } - } - for (a = code->ext.alloc.list; a; a = a->next) - resolve_allocate_expr (a->expr, code, &arr_alloc_wo_spec); - - if (arr_alloc_wo_spec && code->expr3) - { - /* Mark the allocate to have to take the array specification - from the expr3. */ - code->ext.alloc.arr_spec_from_expr3 = 1; - } - } - else - { - for (a = code->ext.alloc.list; a; a = a->next) - resolve_deallocate_expr (a->expr); - } -} - - -/************ SELECT CASE resolution subroutines ************/ - -/* Callback function for our mergesort variant. Determines interval - overlaps for CASEs. Return <0 if op1 < op2, 0 for overlap, >0 for - op1 > op2. Assumes we're not dealing with the default case. - We have op1 = (:L), (K:L) or (K:) and op2 = (:N), (M:N) or (M:). - There are nine situations to check. */ - -static int -compare_cases (const gfc_case *op1, const gfc_case *op2) -{ - int retval; - - if (op1->low == NULL) /* op1 = (:L) */ - { - /* op2 = (:N), so overlap. */ - retval = 0; - /* op2 = (M:) or (M:N), L < M */ - if (op2->low != NULL - && gfc_compare_expr (op1->high, op2->low, INTRINSIC_LT) < 0) - retval = -1; - } - else if (op1->high == NULL) /* op1 = (K:) */ - { - /* op2 = (M:), so overlap. */ - retval = 0; - /* op2 = (:N) or (M:N), K > N */ - if (op2->high != NULL - && gfc_compare_expr (op1->low, op2->high, INTRINSIC_GT) > 0) - retval = 1; - } - else /* op1 = (K:L) */ - { - if (op2->low == NULL) /* op2 = (:N), K > N */ - retval = (gfc_compare_expr (op1->low, op2->high, INTRINSIC_GT) > 0) - ? 1 : 0; - else if (op2->high == NULL) /* op2 = (M:), L < M */ - retval = (gfc_compare_expr (op1->high, op2->low, INTRINSIC_LT) < 0) - ? -1 : 0; - else /* op2 = (M:N) */ - { - retval = 0; - /* L < M */ - if (gfc_compare_expr (op1->high, op2->low, INTRINSIC_LT) < 0) - retval = -1; - /* K > N */ - else if (gfc_compare_expr (op1->low, op2->high, INTRINSIC_GT) > 0) - retval = 1; - } - } - - return retval; -} - - -/* Merge-sort a double linked case list, detecting overlap in the - process. LIST is the head of the double linked case list before it - is sorted. Returns the head of the sorted list if we don't see any - overlap, or NULL otherwise. */ - -static gfc_case * -check_case_overlap (gfc_case *list) -{ - gfc_case *p, *q, *e, *tail; - int insize, nmerges, psize, qsize, cmp, overlap_seen; - - /* If the passed list was empty, return immediately. */ - if (!list) - return NULL; - - overlap_seen = 0; - insize = 1; - - /* Loop unconditionally. The only exit from this loop is a return - statement, when we've finished sorting the case list. */ - for (;;) - { - p = list; - list = NULL; - tail = NULL; - - /* Count the number of merges we do in this pass. */ - nmerges = 0; - - /* Loop while there exists a merge to be done. */ - while (p) - { - int i; - - /* Count this merge. */ - nmerges++; - - /* Cut the list in two pieces by stepping INSIZE places - forward in the list, starting from P. */ - psize = 0; - q = p; - for (i = 0; i < insize; i++) - { - psize++; - q = q->right; - if (!q) - break; - } - qsize = insize; - - /* Now we have two lists. Merge them! */ - while (psize > 0 || (qsize > 0 && q != NULL)) - { - /* See from which the next case to merge comes from. */ - if (psize == 0) - { - /* P is empty so the next case must come from Q. */ - e = q; - q = q->right; - qsize--; - } - else if (qsize == 0 || q == NULL) - { - /* Q is empty. */ - e = p; - p = p->right; - psize--; - } - else - { - cmp = compare_cases (p, q); - if (cmp < 0) - { - /* The whole case range for P is less than the - one for Q. */ - e = p; - p = p->right; - psize--; - } - else if (cmp > 0) - { - /* The whole case range for Q is greater than - the case range for P. */ - e = q; - q = q->right; - qsize--; - } - else - { - /* The cases overlap, or they are the same - element in the list. Either way, we must - issue an error and get the next case from P. */ - /* FIXME: Sort P and Q by line number. */ - gfc_error ("CASE label at %L overlaps with CASE " - "label at %L", &p->where, &q->where); - overlap_seen = 1; - e = p; - p = p->right; - psize--; - } - } - - /* Add the next element to the merged list. */ - if (tail) - tail->right = e; - else - list = e; - e->left = tail; - tail = e; - } - - /* P has now stepped INSIZE places along, and so has Q. So - they're the same. */ - p = q; - } - tail->right = NULL; - - /* If we have done only one merge or none at all, we've - finished sorting the cases. */ - if (nmerges <= 1) - { - if (!overlap_seen) - return list; - else - return NULL; - } - - /* Otherwise repeat, merging lists twice the size. */ - insize *= 2; - } -} - - -/* Check to see if an expression is suitable for use in a CASE statement. - Makes sure that all case expressions are scalar constants of the same - type. Return false if anything is wrong. */ - -static bool -validate_case_label_expr (gfc_expr *e, gfc_expr *case_expr) -{ - if (e == NULL) return true; - - if (e->ts.type != case_expr->ts.type) - { - gfc_error ("Expression in CASE statement at %L must be of type %s", - &e->where, gfc_basic_typename (case_expr->ts.type)); - return false; - } - - /* C805 (R808) For a given case-construct, each case-value shall be of - the same type as case-expr. For character type, length differences - are allowed, but the kind type parameters shall be the same. */ - - if (case_expr->ts.type == BT_CHARACTER && e->ts.kind != case_expr->ts.kind) - { - gfc_error ("Expression in CASE statement at %L must be of kind %d", - &e->where, case_expr->ts.kind); - return false; - } - - /* Convert the case value kind to that of case expression kind, - if needed */ - - if (e->ts.kind != case_expr->ts.kind) - gfc_convert_type_warn (e, &case_expr->ts, 2, 0); - - if (e->rank != 0) - { - gfc_error ("Expression in CASE statement at %L must be scalar", - &e->where); - return false; - } - - return true; -} - - -/* Given a completely parsed select statement, we: - - - Validate all expressions and code within the SELECT. - - Make sure that the selection expression is not of the wrong type. - - Make sure that no case ranges overlap. - - Eliminate unreachable cases and unreachable code resulting from - removing case labels. - - The standard does allow unreachable cases, e.g. CASE (5:3). But - they are a hassle for code generation, and to prevent that, we just - cut them out here. This is not necessary for overlapping cases - because they are illegal and we never even try to generate code. - - We have the additional caveat that a SELECT construct could have - been a computed GOTO in the source code. Fortunately we can fairly - easily work around that here: The case_expr for a "real" SELECT CASE - is in code->expr1, but for a computed GOTO it is in code->expr2. All - we have to do is make sure that the case_expr is a scalar integer - expression. */ - -static void -resolve_select (gfc_code *code, bool select_type) -{ - gfc_code *body; - gfc_expr *case_expr; - gfc_case *cp, *default_case, *tail, *head; - int seen_unreachable; - int seen_logical; - int ncases; - bt type; - bool t; - - if (code->expr1 == NULL) - { - /* This was actually a computed GOTO statement. */ - case_expr = code->expr2; - if (case_expr->ts.type != BT_INTEGER|| case_expr->rank != 0) - gfc_error ("Selection expression in computed GOTO statement " - "at %L must be a scalar integer expression", - &case_expr->where); - - /* Further checking is not necessary because this SELECT was built - by the compiler, so it should always be OK. Just move the - case_expr from expr2 to expr so that we can handle computed - GOTOs as normal SELECTs from here on. */ - code->expr1 = code->expr2; - code->expr2 = NULL; - return; - } - - case_expr = code->expr1; - type = case_expr->ts.type; - - /* F08:C830. */ - if (type != BT_LOGICAL && type != BT_INTEGER && type != BT_CHARACTER) - { - gfc_error ("Argument of SELECT statement at %L cannot be %s", - &case_expr->where, gfc_typename (case_expr)); - - /* Punt. Going on here just produce more garbage error messages. */ - return; - } - - /* F08:R842. */ - if (!select_type && case_expr->rank != 0) - { - gfc_error ("Argument of SELECT statement at %L must be a scalar " - "expression", &case_expr->where); - - /* Punt. */ - return; - } - - /* Raise a warning if an INTEGER case value exceeds the range of - the case-expr. Later, all expressions will be promoted to the - largest kind of all case-labels. */ - - if (type == BT_INTEGER) - for (body = code->block; body; body = body->block) - for (cp = body->ext.block.case_list; cp; cp = cp->next) - { - if (cp->low - && gfc_check_integer_range (cp->low->value.integer, - case_expr->ts.kind) != ARITH_OK) - gfc_warning (0, "Expression in CASE statement at %L is " - "not in the range of %s", &cp->low->where, - gfc_typename (case_expr)); - - if (cp->high - && cp->low != cp->high - && gfc_check_integer_range (cp->high->value.integer, - case_expr->ts.kind) != ARITH_OK) - gfc_warning (0, "Expression in CASE statement at %L is " - "not in the range of %s", &cp->high->where, - gfc_typename (case_expr)); - } - - /* PR 19168 has a long discussion concerning a mismatch of the kinds - of the SELECT CASE expression and its CASE values. Walk the lists - of case values, and if we find a mismatch, promote case_expr to - the appropriate kind. */ - - if (type == BT_LOGICAL || type == BT_INTEGER) - { - for (body = code->block; body; body = body->block) - { - /* Walk the case label list. */ - for (cp = body->ext.block.case_list; cp; cp = cp->next) - { - /* Intercept the DEFAULT case. It does not have a kind. */ - if (cp->low == NULL && cp->high == NULL) - continue; - - /* Unreachable case ranges are discarded, so ignore. */ - if (cp->low != NULL && cp->high != NULL - && cp->low != cp->high - && gfc_compare_expr (cp->low, cp->high, INTRINSIC_GT) > 0) - continue; - - if (cp->low != NULL - && case_expr->ts.kind != gfc_kind_max(case_expr, cp->low)) - gfc_convert_type_warn (case_expr, &cp->low->ts, 1, 0); - - if (cp->high != NULL - && case_expr->ts.kind != gfc_kind_max(case_expr, cp->high)) - gfc_convert_type_warn (case_expr, &cp->high->ts, 1, 0); - } - } - } - - /* Assume there is no DEFAULT case. */ - default_case = NULL; - head = tail = NULL; - ncases = 0; - seen_logical = 0; - - for (body = code->block; body; body = body->block) - { - /* Assume the CASE list is OK, and all CASE labels can be matched. */ - t = true; - seen_unreachable = 0; - - /* Walk the case label list, making sure that all case labels - are legal. */ - for (cp = body->ext.block.case_list; cp; cp = cp->next) - { - /* Count the number of cases in the whole construct. */ - ncases++; - - /* Intercept the DEFAULT case. */ - if (cp->low == NULL && cp->high == NULL) - { - if (default_case != NULL) - { - gfc_error ("The DEFAULT CASE at %L cannot be followed " - "by a second DEFAULT CASE at %L", - &default_case->where, &cp->where); - t = false; - break; - } - else - { - default_case = cp; - continue; - } - } - - /* Deal with single value cases and case ranges. Errors are - issued from the validation function. */ - if (!validate_case_label_expr (cp->low, case_expr) - || !validate_case_label_expr (cp->high, case_expr)) - { - t = false; - break; - } - - if (type == BT_LOGICAL - && ((cp->low == NULL || cp->high == NULL) - || cp->low != cp->high)) - { - gfc_error ("Logical range in CASE statement at %L is not " - "allowed", - cp->low ? &cp->low->where : &cp->high->where); - t = false; - break; - } - - if (type == BT_LOGICAL && cp->low->expr_type == EXPR_CONSTANT) - { - int value; - value = cp->low->value.logical == 0 ? 2 : 1; - if (value & seen_logical) - { - gfc_error ("Constant logical value in CASE statement " - "is repeated at %L", - &cp->low->where); - t = false; - break; - } - seen_logical |= value; - } - - if (cp->low != NULL && cp->high != NULL - && cp->low != cp->high - && gfc_compare_expr (cp->low, cp->high, INTRINSIC_GT) > 0) - { - if (warn_surprising) - gfc_warning (OPT_Wsurprising, - "Range specification at %L can never be matched", - &cp->where); - - cp->unreachable = 1; - seen_unreachable = 1; - } - else - { - /* If the case range can be matched, it can also overlap with - other cases. To make sure it does not, we put it in a - double linked list here. We sort that with a merge sort - later on to detect any overlapping cases. */ - if (!head) - { - head = tail = cp; - head->right = head->left = NULL; - } - else - { - tail->right = cp; - tail->right->left = tail; - tail = tail->right; - tail->right = NULL; - } - } - } - - /* It there was a failure in the previous case label, give up - for this case label list. Continue with the next block. */ - if (!t) - continue; - - /* See if any case labels that are unreachable have been seen. - If so, we eliminate them. This is a bit of a kludge because - the case lists for a single case statement (label) is a - single forward linked lists. */ - if (seen_unreachable) - { - /* Advance until the first case in the list is reachable. */ - while (body->ext.block.case_list != NULL - && body->ext.block.case_list->unreachable) - { - gfc_case *n = body->ext.block.case_list; - body->ext.block.case_list = body->ext.block.case_list->next; - n->next = NULL; - gfc_free_case_list (n); - } - - /* Strip all other unreachable cases. */ - if (body->ext.block.case_list) - { - for (cp = body->ext.block.case_list; cp && cp->next; cp = cp->next) - { - if (cp->next->unreachable) - { - gfc_case *n = cp->next; - cp->next = cp->next->next; - n->next = NULL; - gfc_free_case_list (n); - } - } - } - } - } - - /* See if there were overlapping cases. If the check returns NULL, - there was overlap. In that case we don't do anything. If head - is non-NULL, we prepend the DEFAULT case. The sorted list can - then used during code generation for SELECT CASE constructs with - a case expression of a CHARACTER type. */ - if (head) - { - head = check_case_overlap (head); - - /* Prepend the default_case if it is there. */ - if (head != NULL && default_case) - { - default_case->left = NULL; - default_case->right = head; - head->left = default_case; - } - } - - /* Eliminate dead blocks that may be the result if we've seen - unreachable case labels for a block. */ - for (body = code; body && body->block; body = body->block) - { - if (body->block->ext.block.case_list == NULL) - { - /* Cut the unreachable block from the code chain. */ - gfc_code *c = body->block; - body->block = c->block; - - /* Kill the dead block, but not the blocks below it. */ - c->block = NULL; - gfc_free_statements (c); - } - } - - /* More than two cases is legal but insane for logical selects. - Issue a warning for it. */ - if (warn_surprising && type == BT_LOGICAL && ncases > 2) - gfc_warning (OPT_Wsurprising, - "Logical SELECT CASE block at %L has more that two cases", - &code->loc); -} - - -/* Check if a derived type is extensible. */ - -bool -gfc_type_is_extensible (gfc_symbol *sym) -{ - return !(sym->attr.is_bind_c || sym->attr.sequence - || (sym->attr.is_class - && sym->components->ts.u.derived->attr.unlimited_polymorphic)); -} - - -static void -resolve_types (gfc_namespace *ns); - -/* Resolve an associate-name: Resolve target and ensure the type-spec is - correct as well as possibly the array-spec. */ - -static void -resolve_assoc_var (gfc_symbol* sym, bool resolve_target) -{ - gfc_expr* target; - - gcc_assert (sym->assoc); - gcc_assert (sym->attr.flavor == FL_VARIABLE); - - /* If this is for SELECT TYPE, the target may not yet be set. In that - case, return. Resolution will be called later manually again when - this is done. */ - target = sym->assoc->target; - if (!target) - return; - gcc_assert (!sym->assoc->dangling); - - if (resolve_target && !gfc_resolve_expr (target)) - return; - - /* For variable targets, we get some attributes from the target. */ - if (target->expr_type == EXPR_VARIABLE) - { - gfc_symbol *tsym, *dsym; - - gcc_assert (target->symtree); - tsym = target->symtree->n.sym; - - if (gfc_expr_attr (target).proc_pointer) - { - gfc_error ("Associating entity %qs at %L is a procedure pointer", - tsym->name, &target->where); - return; - } - - if (tsym->attr.flavor == FL_PROCEDURE && tsym->generic - && (dsym = gfc_find_dt_in_generic (tsym)) != NULL - && dsym->attr.flavor == FL_DERIVED) - { - gfc_error ("Derived type %qs cannot be used as a variable at %L", - tsym->name, &target->where); - return; - } - - if (tsym->attr.flavor == FL_PROCEDURE) - { - bool is_error = true; - if (tsym->attr.function && tsym->result == tsym) - for (gfc_namespace *ns = sym->ns; ns; ns = ns->parent) - if (tsym == ns->proc_name) - { - is_error = false; - break; - } - if (is_error) - { - gfc_error ("Associating entity %qs at %L is a procedure name", - tsym->name, &target->where); - return; - } - } - - sym->attr.asynchronous = tsym->attr.asynchronous; - sym->attr.volatile_ = tsym->attr.volatile_; - - sym->attr.target = tsym->attr.target - || gfc_expr_attr (target).pointer; - if (is_subref_array (target)) - sym->attr.subref_array_pointer = 1; - } - else if (target->ts.type == BT_PROCEDURE) - { - gfc_error ("Associating selector-expression at %L yields a procedure", - &target->where); - return; - } - - if (target->expr_type == EXPR_NULL) - { - gfc_error ("Selector at %L cannot be NULL()", &target->where); - return; - } - else if (target->ts.type == BT_UNKNOWN) - { - gfc_error ("Selector at %L has no type", &target->where); - return; - } - - /* Get type if this was not already set. Note that it can be - some other type than the target in case this is a SELECT TYPE - selector! So we must not update when the type is already there. */ - if (sym->ts.type == BT_UNKNOWN) - sym->ts = target->ts; - - gcc_assert (sym->ts.type != BT_UNKNOWN); - - /* See if this is a valid association-to-variable. */ - sym->assoc->variable = (target->expr_type == EXPR_VARIABLE - && !gfc_has_vector_subscript (target)); - - /* Finally resolve if this is an array or not. */ - if (sym->attr.dimension && target->rank == 0) - { - /* primary.c makes the assumption that a reference to an associate - name followed by a left parenthesis is an array reference. */ - if (sym->ts.type != BT_CHARACTER) - gfc_error ("Associate-name %qs at %L is used as array", - sym->name, &sym->declared_at); - sym->attr.dimension = 0; - return; - } - - - /* We cannot deal with class selectors that need temporaries. */ - if (target->ts.type == BT_CLASS - && gfc_ref_needs_temporary_p (target->ref)) - { - gfc_error ("CLASS selector at %L needs a temporary which is not " - "yet implemented", &target->where); - return; - } - - if (target->ts.type == BT_CLASS) - gfc_fix_class_refs (target); - - if (target->rank != 0 && !sym->attr.select_rank_temporary) - { - gfc_array_spec *as; - /* The rank may be incorrectly guessed at parsing, therefore make sure - it is corrected now. */ - if (sym->ts.type != BT_CLASS && (!sym->as || sym->assoc->rankguessed)) - { - if (!sym->as) - sym->as = gfc_get_array_spec (); - as = sym->as; - as->rank = target->rank; - as->type = AS_DEFERRED; - as->corank = gfc_get_corank (target); - sym->attr.dimension = 1; - if (as->corank != 0) - sym->attr.codimension = 1; - } - else if (sym->ts.type == BT_CLASS - && CLASS_DATA (sym) - && (!CLASS_DATA (sym)->as || sym->assoc->rankguessed)) - { - if (!CLASS_DATA (sym)->as) - CLASS_DATA (sym)->as = gfc_get_array_spec (); - as = CLASS_DATA (sym)->as; - as->rank = target->rank; - as->type = AS_DEFERRED; - as->corank = gfc_get_corank (target); - CLASS_DATA (sym)->attr.dimension = 1; - if (as->corank != 0) - CLASS_DATA (sym)->attr.codimension = 1; - } - } - else if (!sym->attr.select_rank_temporary) - { - /* target's rank is 0, but the type of the sym is still array valued, - which has to be corrected. */ - if (sym->ts.type == BT_CLASS && sym->ts.u.derived - && CLASS_DATA (sym) && CLASS_DATA (sym)->as) - { - gfc_array_spec *as; - symbol_attribute attr; - /* The associated variable's type is still the array type - correct this now. */ - gfc_typespec *ts = &target->ts; - gfc_ref *ref; - gfc_component *c; - for (ref = target->ref; ref != NULL; ref = ref->next) - { - switch (ref->type) - { - case REF_COMPONENT: - ts = &ref->u.c.component->ts; - break; - case REF_ARRAY: - if (ts->type == BT_CLASS) - ts = &ts->u.derived->components->ts; - break; - default: - break; - } - } - /* Create a scalar instance of the current class type. Because the - rank of a class array goes into its name, the type has to be - rebuild. The alternative of (re-)setting just the attributes - and as in the current type, destroys the type also in other - places. */ - as = NULL; - sym->ts = *ts; - sym->ts.type = BT_CLASS; - attr = CLASS_DATA (sym) ? CLASS_DATA (sym)->attr : sym->attr; - attr.class_ok = 0; - attr.associate_var = 1; - attr.dimension = attr.codimension = 0; - attr.class_pointer = 1; - if (!gfc_build_class_symbol (&sym->ts, &attr, &as)) - gcc_unreachable (); - /* Make sure the _vptr is set. */ - c = gfc_find_component (sym->ts.u.derived, "_vptr", true, true, NULL); - if (c->ts.u.derived == NULL) - c->ts.u.derived = gfc_find_derived_vtab (sym->ts.u.derived); - CLASS_DATA (sym)->attr.pointer = 1; - CLASS_DATA (sym)->attr.class_pointer = 1; - gfc_set_sym_referenced (sym->ts.u.derived); - gfc_commit_symbol (sym->ts.u.derived); - /* _vptr now has the _vtab in it, change it to the _vtype. */ - if (c->ts.u.derived->attr.vtab) - c->ts.u.derived = c->ts.u.derived->ts.u.derived; - c->ts.u.derived->ns->types_resolved = 0; - resolve_types (c->ts.u.derived->ns); - } - } - - /* Mark this as an associate variable. */ - sym->attr.associate_var = 1; - - /* Fix up the type-spec for CHARACTER types. */ - if (sym->ts.type == BT_CHARACTER && !sym->attr.select_type_temporary) - { - if (!sym->ts.u.cl) - sym->ts.u.cl = target->ts.u.cl; - - if (sym->ts.deferred && target->expr_type == EXPR_VARIABLE - && target->symtree->n.sym->attr.dummy - && sym->ts.u.cl == target->ts.u.cl) - { - sym->ts.u.cl = gfc_new_charlen (sym->ns, NULL); - sym->ts.deferred = 1; - } - - if (!sym->ts.u.cl->length - && !sym->ts.deferred - && target->expr_type == EXPR_CONSTANT) - { - sym->ts.u.cl->length = - gfc_get_int_expr (gfc_charlen_int_kind, NULL, - target->value.character.length); - } - else if ((!sym->ts.u.cl->length - || sym->ts.u.cl->length->expr_type != EXPR_CONSTANT) - && target->expr_type != EXPR_VARIABLE) - { - sym->ts.u.cl = gfc_new_charlen (sym->ns, NULL); - sym->ts.deferred = 1; - - /* This is reset in trans-stmt.c after the assignment - of the target expression to the associate name. */ - sym->attr.allocatable = 1; - } - } - - /* If the target is a good class object, so is the associate variable. */ - if (sym->ts.type == BT_CLASS && gfc_expr_attr (target).class_ok) - sym->attr.class_ok = 1; -} - - -/* Ensure that SELECT TYPE expressions have the correct rank and a full - array reference, where necessary. The symbols are artificial and so - the dimension attribute and arrayspec can also be set. In addition, - sometimes the expr1 arrives as BT_DERIVED, when the symbol is BT_CLASS. - This is corrected here as well.*/ - -static void -fixup_array_ref (gfc_expr **expr1, gfc_expr *expr2, - int rank, gfc_ref *ref) -{ - gfc_ref *nref = (*expr1)->ref; - gfc_symbol *sym1 = (*expr1)->symtree->n.sym; - gfc_symbol *sym2 = expr2 ? expr2->symtree->n.sym : NULL; - (*expr1)->rank = rank; - if (sym1->ts.type == BT_CLASS) - { - if ((*expr1)->ts.type != BT_CLASS) - (*expr1)->ts = sym1->ts; - - CLASS_DATA (sym1)->attr.dimension = 1; - if (CLASS_DATA (sym1)->as == NULL && sym2) - CLASS_DATA (sym1)->as - = gfc_copy_array_spec (CLASS_DATA (sym2)->as); - } - else - { - sym1->attr.dimension = 1; - if (sym1->as == NULL && sym2) - sym1->as = gfc_copy_array_spec (sym2->as); - } - - for (; nref; nref = nref->next) - if (nref->next == NULL) - break; - - if (ref && nref && nref->type != REF_ARRAY) - nref->next = gfc_copy_ref (ref); - else if (ref && !nref) - (*expr1)->ref = gfc_copy_ref (ref); -} - - -static gfc_expr * -build_loc_call (gfc_expr *sym_expr) -{ - gfc_expr *loc_call; - loc_call = gfc_get_expr (); - loc_call->expr_type = EXPR_FUNCTION; - gfc_get_sym_tree ("_loc", gfc_current_ns, &loc_call->symtree, false); - loc_call->symtree->n.sym->attr.flavor = FL_PROCEDURE; - loc_call->symtree->n.sym->attr.intrinsic = 1; - loc_call->symtree->n.sym->result = loc_call->symtree->n.sym; - gfc_commit_symbol (loc_call->symtree->n.sym); - loc_call->ts.type = BT_INTEGER; - loc_call->ts.kind = gfc_index_integer_kind; - loc_call->value.function.isym = gfc_intrinsic_function_by_id (GFC_ISYM_LOC); - loc_call->value.function.actual = gfc_get_actual_arglist (); - loc_call->value.function.actual->expr = sym_expr; - loc_call->where = sym_expr->where; - return loc_call; -} - -/* Resolve a SELECT TYPE statement. */ - -static void -resolve_select_type (gfc_code *code, gfc_namespace *old_ns) -{ - gfc_symbol *selector_type; - gfc_code *body, *new_st, *if_st, *tail; - gfc_code *class_is = NULL, *default_case = NULL; - gfc_case *c; - gfc_symtree *st; - char name[GFC_MAX_SYMBOL_LEN + 12 + 1]; - gfc_namespace *ns; - int error = 0; - int rank = 0; - gfc_ref* ref = NULL; - gfc_expr *selector_expr = NULL; - - ns = code->ext.block.ns; - gfc_resolve (ns); - - /* Check for F03:C813. */ - if (code->expr1->ts.type != BT_CLASS - && !(code->expr2 && code->expr2->ts.type == BT_CLASS)) - { - gfc_error ("Selector shall be polymorphic in SELECT TYPE statement " - "at %L", &code->loc); - return; - } - - if (!code->expr1->symtree->n.sym->attr.class_ok) - return; - - if (code->expr2) - { - gfc_ref *ref2 = NULL; - for (ref = code->expr2->ref; ref != NULL; ref = ref->next) - if (ref->type == REF_COMPONENT - && ref->u.c.component->ts.type == BT_CLASS) - ref2 = ref; - - if (ref2) - { - if (code->expr1->symtree->n.sym->attr.untyped) - code->expr1->symtree->n.sym->ts = ref2->u.c.component->ts; - selector_type = CLASS_DATA (ref2->u.c.component)->ts.u.derived; - } - else - { - if (code->expr1->symtree->n.sym->attr.untyped) - code->expr1->symtree->n.sym->ts = code->expr2->ts; - selector_type = CLASS_DATA (code->expr2) - ? CLASS_DATA (code->expr2)->ts.u.derived : code->expr2->ts.u.derived; - } - - if (code->expr2->rank - && code->expr1->ts.type == BT_CLASS - && CLASS_DATA (code->expr1)->as) - CLASS_DATA (code->expr1)->as->rank = code->expr2->rank; - - /* F2008: C803 The selector expression must not be coindexed. */ - if (gfc_is_coindexed (code->expr2)) - { - gfc_error ("Selector at %L must not be coindexed", - &code->expr2->where); - return; - } - - } - else - { - selector_type = CLASS_DATA (code->expr1)->ts.u.derived; - - if (gfc_is_coindexed (code->expr1)) - { - gfc_error ("Selector at %L must not be coindexed", - &code->expr1->where); - return; - } - } - - /* Loop over TYPE IS / CLASS IS cases. */ - for (body = code->block; body; body = body->block) - { - c = body->ext.block.case_list; - - if (!error) - { - /* Check for repeated cases. */ - for (tail = code->block; tail; tail = tail->block) - { - gfc_case *d = tail->ext.block.case_list; - if (tail == body) - break; - - if (c->ts.type == d->ts.type - && ((c->ts.type == BT_DERIVED - && c->ts.u.derived && d->ts.u.derived - && !strcmp (c->ts.u.derived->name, - d->ts.u.derived->name)) - || c->ts.type == BT_UNKNOWN - || (!(c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS) - && c->ts.kind == d->ts.kind))) - { - gfc_error ("TYPE IS at %L overlaps with TYPE IS at %L", - &c->where, &d->where); - return; - } - } - } - - /* Check F03:C815. */ - if ((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS) - && selector_type - && !selector_type->attr.unlimited_polymorphic - && !gfc_type_is_extensible (c->ts.u.derived)) - { - gfc_error ("Derived type %qs at %L must be extensible", - c->ts.u.derived->name, &c->where); - error++; - continue; - } - - /* Check F03:C816. */ - if (c->ts.type != BT_UNKNOWN - && selector_type && !selector_type->attr.unlimited_polymorphic - && ((c->ts.type != BT_DERIVED && c->ts.type != BT_CLASS) - || !gfc_type_is_extension_of (selector_type, c->ts.u.derived))) - { - if (c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS) - gfc_error ("Derived type %qs at %L must be an extension of %qs", - c->ts.u.derived->name, &c->where, selector_type->name); - else - gfc_error ("Unexpected intrinsic type %qs at %L", - gfc_basic_typename (c->ts.type), &c->where); - error++; - continue; - } - - /* Check F03:C814. */ - if (c->ts.type == BT_CHARACTER - && (c->ts.u.cl->length != NULL || c->ts.deferred)) - { - gfc_error ("The type-spec at %L shall specify that each length " - "type parameter is assumed", &c->where); - error++; - continue; - } - - /* Intercept the DEFAULT case. */ - if (c->ts.type == BT_UNKNOWN) - { - /* Check F03:C818. */ - if (default_case) - { - gfc_error ("The DEFAULT CASE at %L cannot be followed " - "by a second DEFAULT CASE at %L", - &default_case->ext.block.case_list->where, &c->where); - error++; - continue; - } - - default_case = body; - } - } - - if (error > 0) - return; - - /* Transform SELECT TYPE statement to BLOCK and associate selector to - target if present. If there are any EXIT statements referring to the - SELECT TYPE construct, this is no problem because the gfc_code - reference stays the same and EXIT is equally possible from the BLOCK - it is changed to. */ - code->op = EXEC_BLOCK; - if (code->expr2) - { - gfc_association_list* assoc; - - assoc = gfc_get_association_list (); - assoc->st = code->expr1->symtree; - assoc->target = gfc_copy_expr (code->expr2); - assoc->target->where = code->expr2->where; - /* assoc->variable will be set by resolve_assoc_var. */ - - code->ext.block.assoc = assoc; - code->expr1->symtree->n.sym->assoc = assoc; - - resolve_assoc_var (code->expr1->symtree->n.sym, false); - } - else - code->ext.block.assoc = NULL; - - /* Ensure that the selector rank and arrayspec are available to - correct expressions in which they might be missing. */ - if (code->expr2 && code->expr2->rank) - { - rank = code->expr2->rank; - for (ref = code->expr2->ref; ref; ref = ref->next) - if (ref->next == NULL) - break; - if (ref && ref->type == REF_ARRAY) - ref = gfc_copy_ref (ref); - - /* Fixup expr1 if necessary. */ - if (rank) - fixup_array_ref (&code->expr1, code->expr2, rank, ref); - } - else if (code->expr1->rank) - { - rank = code->expr1->rank; - for (ref = code->expr1->ref; ref; ref = ref->next) - if (ref->next == NULL) - break; - if (ref && ref->type == REF_ARRAY) - ref = gfc_copy_ref (ref); - } - - /* Add EXEC_SELECT to switch on type. */ - new_st = gfc_get_code (code->op); - new_st->expr1 = code->expr1; - new_st->expr2 = code->expr2; - new_st->block = code->block; - code->expr1 = code->expr2 = NULL; - code->block = NULL; - if (!ns->code) - ns->code = new_st; - else - ns->code->next = new_st; - code = new_st; - code->op = EXEC_SELECT_TYPE; - - /* Use the intrinsic LOC function to generate an integer expression - for the vtable of the selector. Note that the rank of the selector - expression has to be set to zero. */ - gfc_add_vptr_component (code->expr1); - code->expr1->rank = 0; - code->expr1 = build_loc_call (code->expr1); - selector_expr = code->expr1->value.function.actual->expr; - - /* Loop over TYPE IS / CLASS IS cases. */ - for (body = code->block; body; body = body->block) - { - gfc_symbol *vtab; - gfc_expr *e; - c = body->ext.block.case_list; - - /* Generate an index integer expression for address of the - TYPE/CLASS vtable and store it in c->low. The hash expression - is stored in c->high and is used to resolve intrinsic cases. */ - if (c->ts.type != BT_UNKNOWN) - { - if (c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS) - { - vtab = gfc_find_derived_vtab (c->ts.u.derived); - gcc_assert (vtab); - c->high = gfc_get_int_expr (gfc_integer_4_kind, NULL, - c->ts.u.derived->hash_value); - } - else - { - vtab = gfc_find_vtab (&c->ts); - gcc_assert (vtab && CLASS_DATA (vtab)->initializer); - e = CLASS_DATA (vtab)->initializer; - c->high = gfc_copy_expr (e); - if (c->high->ts.kind != gfc_integer_4_kind) - { - gfc_typespec ts; - ts.kind = gfc_integer_4_kind; - ts.type = BT_INTEGER; - gfc_convert_type_warn (c->high, &ts, 2, 0); - } - } - - e = gfc_lval_expr_from_sym (vtab); - c->low = build_loc_call (e); - } - else - continue; - - /* Associate temporary to selector. This should only be done - when this case is actually true, so build a new ASSOCIATE - that does precisely this here (instead of using the - 'global' one). */ - - if (c->ts.type == BT_CLASS) - sprintf (name, "__tmp_class_%s", c->ts.u.derived->name); - else if (c->ts.type == BT_DERIVED) - sprintf (name, "__tmp_type_%s", c->ts.u.derived->name); - else if (c->ts.type == BT_CHARACTER) - { - HOST_WIDE_INT charlen = 0; - if (c->ts.u.cl && c->ts.u.cl->length - && c->ts.u.cl->length->expr_type == EXPR_CONSTANT) - charlen = gfc_mpz_get_hwi (c->ts.u.cl->length->value.integer); - snprintf (name, sizeof (name), - "__tmp_%s_" HOST_WIDE_INT_PRINT_DEC "_%d", - gfc_basic_typename (c->ts.type), charlen, c->ts.kind); - } - else - sprintf (name, "__tmp_%s_%d", gfc_basic_typename (c->ts.type), - c->ts.kind); - - st = gfc_find_symtree (ns->sym_root, name); - gcc_assert (st->n.sym->assoc); - st->n.sym->assoc->target = gfc_get_variable_expr (selector_expr->symtree); - st->n.sym->assoc->target->where = selector_expr->where; - if (c->ts.type != BT_CLASS && c->ts.type != BT_UNKNOWN) - { - gfc_add_data_component (st->n.sym->assoc->target); - /* Fixup the target expression if necessary. */ - if (rank) - fixup_array_ref (&st->n.sym->assoc->target, NULL, rank, ref); - } - - new_st = gfc_get_code (EXEC_BLOCK); - new_st->ext.block.ns = gfc_build_block_ns (ns); - new_st->ext.block.ns->code = body->next; - body->next = new_st; - - /* Chain in the new list only if it is marked as dangling. Otherwise - there is a CASE label overlap and this is already used. Just ignore, - the error is diagnosed elsewhere. */ - if (st->n.sym->assoc->dangling) - { - new_st->ext.block.assoc = st->n.sym->assoc; - st->n.sym->assoc->dangling = 0; - } - - resolve_assoc_var (st->n.sym, false); - } - - /* Take out CLASS IS cases for separate treatment. */ - body = code; - while (body && body->block) - { - if (body->block->ext.block.case_list->ts.type == BT_CLASS) - { - /* Add to class_is list. */ - if (class_is == NULL) - { - class_is = body->block; - tail = class_is; - } - else - { - for (tail = class_is; tail->block; tail = tail->block) ; - tail->block = body->block; - tail = tail->block; - } - /* Remove from EXEC_SELECT list. */ - body->block = body->block->block; - tail->block = NULL; - } - else - body = body->block; - } - - if (class_is) - { - gfc_symbol *vtab; - - if (!default_case) - { - /* Add a default case to hold the CLASS IS cases. */ - for (tail = code; tail->block; tail = tail->block) ; - tail->block = gfc_get_code (EXEC_SELECT_TYPE); - tail = tail->block; - tail->ext.block.case_list = gfc_get_case (); - tail->ext.block.case_list->ts.type = BT_UNKNOWN; - tail->next = NULL; - default_case = tail; - } - - /* More than one CLASS IS block? */ - if (class_is->block) - { - gfc_code **c1,*c2; - bool swapped; - /* Sort CLASS IS blocks by extension level. */ - do - { - swapped = false; - for (c1 = &class_is; (*c1) && (*c1)->block; c1 = &((*c1)->block)) - { - c2 = (*c1)->block; - /* F03:C817 (check for doubles). */ - if ((*c1)->ext.block.case_list->ts.u.derived->hash_value - == c2->ext.block.case_list->ts.u.derived->hash_value) - { - gfc_error ("Double CLASS IS block in SELECT TYPE " - "statement at %L", - &c2->ext.block.case_list->where); - return; - } - if ((*c1)->ext.block.case_list->ts.u.derived->attr.extension - < c2->ext.block.case_list->ts.u.derived->attr.extension) - { - /* Swap. */ - (*c1)->block = c2->block; - c2->block = *c1; - *c1 = c2; - swapped = true; - } - } - } - while (swapped); - } - - /* Generate IF chain. */ - if_st = gfc_get_code (EXEC_IF); - new_st = if_st; - for (body = class_is; body; body = body->block) - { - new_st->block = gfc_get_code (EXEC_IF); - new_st = new_st->block; - /* Set up IF condition: Call _gfortran_is_extension_of. */ - new_st->expr1 = gfc_get_expr (); - new_st->expr1->expr_type = EXPR_FUNCTION; - new_st->expr1->ts.type = BT_LOGICAL; - new_st->expr1->ts.kind = 4; - new_st->expr1->value.function.name = gfc_get_string (PREFIX ("is_extension_of")); - new_st->expr1->value.function.isym = XCNEW (gfc_intrinsic_sym); - new_st->expr1->value.function.isym->id = GFC_ISYM_EXTENDS_TYPE_OF; - /* Set up arguments. */ - new_st->expr1->value.function.actual = gfc_get_actual_arglist (); - new_st->expr1->value.function.actual->expr = gfc_get_variable_expr (selector_expr->symtree); - new_st->expr1->value.function.actual->expr->where = code->loc; - new_st->expr1->where = code->loc; - gfc_add_vptr_component (new_st->expr1->value.function.actual->expr); - vtab = gfc_find_derived_vtab (body->ext.block.case_list->ts.u.derived); - st = gfc_find_symtree (vtab->ns->sym_root, vtab->name); - new_st->expr1->value.function.actual->next = gfc_get_actual_arglist (); - new_st->expr1->value.function.actual->next->expr = gfc_get_variable_expr (st); - new_st->expr1->value.function.actual->next->expr->where = code->loc; - /* Set up types in formal arg list. */ - new_st->expr1->value.function.isym->formal = XCNEW (gfc_intrinsic_arg); - new_st->expr1->value.function.isym->formal->ts = new_st->expr1->value.function.actual->expr->ts; - new_st->expr1->value.function.isym->formal->next = XCNEW (gfc_intrinsic_arg); - new_st->expr1->value.function.isym->formal->next->ts = new_st->expr1->value.function.actual->next->expr->ts; - - new_st->next = body->next; - } - if (default_case->next) - { - new_st->block = gfc_get_code (EXEC_IF); - new_st = new_st->block; - new_st->next = default_case->next; - } - - /* Replace CLASS DEFAULT code by the IF chain. */ - default_case->next = if_st; - } - - /* Resolve the internal code. This cannot be done earlier because - it requires that the sym->assoc of selectors is set already. */ - gfc_current_ns = ns; - gfc_resolve_blocks (code->block, gfc_current_ns); - gfc_current_ns = old_ns; - - if (ref) - free (ref); -} - - -/* Resolve a SELECT RANK statement. */ - -static void -resolve_select_rank (gfc_code *code, gfc_namespace *old_ns) -{ - gfc_namespace *ns; - gfc_code *body, *new_st, *tail; - gfc_case *c; - char tname[GFC_MAX_SYMBOL_LEN + 7]; - char name[2 * GFC_MAX_SYMBOL_LEN]; - gfc_symtree *st; - gfc_expr *selector_expr = NULL; - int case_value; - HOST_WIDE_INT charlen = 0; - - ns = code->ext.block.ns; - gfc_resolve (ns); - - code->op = EXEC_BLOCK; - if (code->expr2) - { - gfc_association_list* assoc; - - assoc = gfc_get_association_list (); - assoc->st = code->expr1->symtree; - assoc->target = gfc_copy_expr (code->expr2); - assoc->target->where = code->expr2->where; - /* assoc->variable will be set by resolve_assoc_var. */ - - code->ext.block.assoc = assoc; - code->expr1->symtree->n.sym->assoc = assoc; - - resolve_assoc_var (code->expr1->symtree->n.sym, false); - } - else - code->ext.block.assoc = NULL; - - /* Loop over RANK cases. Note that returning on the errors causes a - cascade of further errors because the case blocks do not compile - correctly. */ - for (body = code->block; body; body = body->block) - { - c = body->ext.block.case_list; - if (c->low) - case_value = (int) mpz_get_si (c->low->value.integer); - else - case_value = -2; - - /* Check for repeated cases. */ - for (tail = code->block; tail; tail = tail->block) - { - gfc_case *d = tail->ext.block.case_list; - int case_value2; - - if (tail == body) - break; - - /* Check F2018: C1153. */ - if (!c->low && !d->low) - gfc_error ("RANK DEFAULT at %L is repeated at %L", - &c->where, &d->where); - - if (!c->low || !d->low) - continue; - - /* Check F2018: C1153. */ - case_value2 = (int) mpz_get_si (d->low->value.integer); - if ((case_value == case_value2) && case_value == -1) - gfc_error ("RANK (*) at %L is repeated at %L", - &c->where, &d->where); - else if (case_value == case_value2) - gfc_error ("RANK (%i) at %L is repeated at %L", - case_value, &c->where, &d->where); - } - - if (!c->low) - continue; - - /* Check F2018: C1155. */ - if (case_value == -1 && (gfc_expr_attr (code->expr1).allocatable - || gfc_expr_attr (code->expr1).pointer)) - gfc_error ("RANK (*) at %L cannot be used with the pointer or " - "allocatable selector at %L", &c->where, &code->expr1->where); - - if (case_value == -1 && (gfc_expr_attr (code->expr1).allocatable - || gfc_expr_attr (code->expr1).pointer)) - gfc_error ("RANK (*) at %L cannot be used with the pointer or " - "allocatable selector at %L", &c->where, &code->expr1->where); - } - - /* Add EXEC_SELECT to switch on rank. */ - new_st = gfc_get_code (code->op); - new_st->expr1 = code->expr1; - new_st->expr2 = code->expr2; - new_st->block = code->block; - code->expr1 = code->expr2 = NULL; - code->block = NULL; - if (!ns->code) - ns->code = new_st; - else - ns->code->next = new_st; - code = new_st; - code->op = EXEC_SELECT_RANK; - - selector_expr = code->expr1; - - /* Loop over SELECT RANK cases. */ - for (body = code->block; body; body = body->block) - { - c = body->ext.block.case_list; - int case_value; - - /* Pass on the default case. */ - if (c->low == NULL) - continue; - - /* Associate temporary to selector. This should only be done - when this case is actually true, so build a new ASSOCIATE - that does precisely this here (instead of using the - 'global' one). */ - if (c->ts.type == BT_CHARACTER && c->ts.u.cl && c->ts.u.cl->length - && c->ts.u.cl->length->expr_type == EXPR_CONSTANT) - charlen = gfc_mpz_get_hwi (c->ts.u.cl->length->value.integer); - - if (c->ts.type == BT_CLASS) - sprintf (tname, "class_%s", c->ts.u.derived->name); - else if (c->ts.type == BT_DERIVED) - sprintf (tname, "type_%s", c->ts.u.derived->name); - else if (c->ts.type != BT_CHARACTER) - sprintf (tname, "%s_%d", gfc_basic_typename (c->ts.type), c->ts.kind); - else - sprintf (tname, "%s_" HOST_WIDE_INT_PRINT_DEC "_%d", - gfc_basic_typename (c->ts.type), charlen, c->ts.kind); - - case_value = (int) mpz_get_si (c->low->value.integer); - if (case_value >= 0) - sprintf (name, "__tmp_%s_rank_%d", tname, case_value); - else - sprintf (name, "__tmp_%s_rank_m%d", tname, -case_value); - - st = gfc_find_symtree (ns->sym_root, name); - gcc_assert (st->n.sym->assoc); - - st->n.sym->assoc->target = gfc_get_variable_expr (selector_expr->symtree); - st->n.sym->assoc->target->where = selector_expr->where; - - new_st = gfc_get_code (EXEC_BLOCK); - new_st->ext.block.ns = gfc_build_block_ns (ns); - new_st->ext.block.ns->code = body->next; - body->next = new_st; - - /* Chain in the new list only if it is marked as dangling. Otherwise - there is a CASE label overlap and this is already used. Just ignore, - the error is diagnosed elsewhere. */ - if (st->n.sym->assoc->dangling) - { - new_st->ext.block.assoc = st->n.sym->assoc; - st->n.sym->assoc->dangling = 0; - } - - resolve_assoc_var (st->n.sym, false); - } - - gfc_current_ns = ns; - gfc_resolve_blocks (code->block, gfc_current_ns); - gfc_current_ns = old_ns; -} - - -/* Resolve a transfer statement. This is making sure that: - -- a derived type being transferred has only non-pointer components - -- a derived type being transferred doesn't have private components, unless - it's being transferred from the module where the type was defined - -- we're not trying to transfer a whole assumed size array. */ - -static void -resolve_transfer (gfc_code *code) -{ - gfc_symbol *sym, *derived; - gfc_ref *ref; - gfc_expr *exp; - bool write = false; - bool formatted = false; - gfc_dt *dt = code->ext.dt; - gfc_symbol *dtio_sub = NULL; - - exp = code->expr1; - - while (exp != NULL && exp->expr_type == EXPR_OP - && exp->value.op.op == INTRINSIC_PARENTHESES) - exp = exp->value.op.op1; - - if (exp && exp->expr_type == EXPR_NULL - && code->ext.dt) - { - gfc_error ("Invalid context for NULL () intrinsic at %L", - &exp->where); - return; - } - - if (exp == NULL || (exp->expr_type != EXPR_VARIABLE - && exp->expr_type != EXPR_FUNCTION - && exp->expr_type != EXPR_STRUCTURE)) - return; - - /* If we are reading, the variable will be changed. Note that - code->ext.dt may be NULL if the TRANSFER is related to - an INQUIRE statement -- but in this case, we are not reading, either. */ - if (dt && dt->dt_io_kind->value.iokind == M_READ - && !gfc_check_vardef_context (exp, false, false, false, - _("item in READ"))) - return; - - const gfc_typespec *ts = exp->expr_type == EXPR_STRUCTURE - || exp->expr_type == EXPR_FUNCTION - ? &exp->ts : &exp->symtree->n.sym->ts; - - /* Go to actual component transferred. */ - for (ref = exp->ref; ref; ref = ref->next) - if (ref->type == REF_COMPONENT) - ts = &ref->u.c.component->ts; - - if (dt && dt->dt_io_kind->value.iokind != M_INQUIRE - && (ts->type == BT_DERIVED || ts->type == BT_CLASS)) - { - derived = ts->u.derived; - - /* Determine when to use the formatted DTIO procedure. */ - if (dt && (dt->format_expr || dt->format_label)) - formatted = true; - - write = dt->dt_io_kind->value.iokind == M_WRITE - || dt->dt_io_kind->value.iokind == M_PRINT; - dtio_sub = gfc_find_specific_dtio_proc (derived, write, formatted); - - if (dtio_sub != NULL && exp->expr_type == EXPR_VARIABLE) - { - dt->udtio = exp; - sym = exp->symtree->n.sym->ns->proc_name; - /* Check to see if this is a nested DTIO call, with the - dummy as the io-list object. */ - if (sym && sym == dtio_sub && sym->formal - && sym->formal->sym == exp->symtree->n.sym - && exp->ref == NULL) - { - if (!sym->attr.recursive) - { - gfc_error ("DTIO %s procedure at %L must be recursive", - sym->name, &sym->declared_at); - return; - } - } - } - } - - if (ts->type == BT_CLASS && dtio_sub == NULL) - { - gfc_error ("Data transfer element at %L cannot be polymorphic unless " - "it is processed by a defined input/output procedure", - &code->loc); - return; - } - - if (ts->type == BT_DERIVED) - { - /* Check that transferred derived type doesn't contain POINTER - components unless it is processed by a defined input/output - procedure". */ - if (ts->u.derived->attr.pointer_comp && dtio_sub == NULL) - { - gfc_error ("Data transfer element at %L cannot have POINTER " - "components unless it is processed by a defined " - "input/output procedure", &code->loc); - return; - } - - /* F08:C935. */ - if (ts->u.derived->attr.proc_pointer_comp) - { - gfc_error ("Data transfer element at %L cannot have " - "procedure pointer components", &code->loc); - return; - } - - if (ts->u.derived->attr.alloc_comp && dtio_sub == NULL) - { - gfc_error ("Data transfer element at %L cannot have ALLOCATABLE " - "components unless it is processed by a defined " - "input/output procedure", &code->loc); - return; - } - - /* C_PTR and C_FUNPTR have private components which means they cannot - be printed. However, if -std=gnu and not -pedantic, allow - the component to be printed to help debugging. */ - if (ts->u.derived->ts.f90_type == BT_VOID) - { - if (!gfc_notify_std (GFC_STD_GNU, "Data transfer element at %L " - "cannot have PRIVATE components", &code->loc)) - return; - } - else if (derived_inaccessible (ts->u.derived) && dtio_sub == NULL) - { - gfc_error ("Data transfer element at %L cannot have " - "PRIVATE components unless it is processed by " - "a defined input/output procedure", &code->loc); - return; - } - } - - if (exp->expr_type == EXPR_STRUCTURE) - return; - - sym = exp->symtree->n.sym; - - if (sym->as != NULL && sym->as->type == AS_ASSUMED_SIZE && exp->ref - && exp->ref->type == REF_ARRAY && exp->ref->u.ar.type == AR_FULL) - { - gfc_error ("Data transfer element at %L cannot be a full reference to " - "an assumed-size array", &code->loc); - return; - } -} - - -/*********** Toplevel code resolution subroutines ***********/ - -/* Find the set of labels that are reachable from this block. We also - record the last statement in each block. */ - -static void -find_reachable_labels (gfc_code *block) -{ - gfc_code *c; - - if (!block) - return; - - cs_base->reachable_labels = bitmap_alloc (&labels_obstack); - - /* Collect labels in this block. We don't keep those corresponding - to END {IF|SELECT}, these are checked in resolve_branch by going - up through the code_stack. */ - for (c = block; c; c = c->next) - { - if (c->here && c->op != EXEC_END_NESTED_BLOCK) - bitmap_set_bit (cs_base->reachable_labels, c->here->value); - } - - /* Merge with labels from parent block. */ - if (cs_base->prev) - { - gcc_assert (cs_base->prev->reachable_labels); - bitmap_ior_into (cs_base->reachable_labels, - cs_base->prev->reachable_labels); - } -} - - -static void -resolve_lock_unlock_event (gfc_code *code) -{ - if (code->expr1->expr_type == EXPR_FUNCTION - && code->expr1->value.function.isym - && code->expr1->value.function.isym->id == GFC_ISYM_CAF_GET) - remove_caf_get_intrinsic (code->expr1); - - if ((code->op == EXEC_LOCK || code->op == EXEC_UNLOCK) - && (code->expr1->ts.type != BT_DERIVED - || code->expr1->expr_type != EXPR_VARIABLE - || code->expr1->ts.u.derived->from_intmod != INTMOD_ISO_FORTRAN_ENV - || code->expr1->ts.u.derived->intmod_sym_id != ISOFORTRAN_LOCK_TYPE - || code->expr1->rank != 0 - || (!gfc_is_coarray (code->expr1) && - !gfc_is_coindexed (code->expr1)))) - gfc_error ("Lock variable at %L must be a scalar of type LOCK_TYPE", - &code->expr1->where); - else if ((code->op == EXEC_EVENT_POST || code->op == EXEC_EVENT_WAIT) - && (code->expr1->ts.type != BT_DERIVED - || code->expr1->expr_type != EXPR_VARIABLE - || code->expr1->ts.u.derived->from_intmod - != INTMOD_ISO_FORTRAN_ENV - || code->expr1->ts.u.derived->intmod_sym_id - != ISOFORTRAN_EVENT_TYPE - || code->expr1->rank != 0)) - gfc_error ("Event variable at %L must be a scalar of type EVENT_TYPE", - &code->expr1->where); - else if (code->op == EXEC_EVENT_POST && !gfc_is_coarray (code->expr1) - && !gfc_is_coindexed (code->expr1)) - gfc_error ("Event variable argument at %L must be a coarray or coindexed", - &code->expr1->where); - else if (code->op == EXEC_EVENT_WAIT && !gfc_is_coarray (code->expr1)) - gfc_error ("Event variable argument at %L must be a coarray but not " - "coindexed", &code->expr1->where); - - /* Check STAT. */ - if (code->expr2 - && (code->expr2->ts.type != BT_INTEGER || code->expr2->rank != 0 - || code->expr2->expr_type != EXPR_VARIABLE)) - gfc_error ("STAT= argument at %L must be a scalar INTEGER variable", - &code->expr2->where); - - if (code->expr2 - && !gfc_check_vardef_context (code->expr2, false, false, false, - _("STAT variable"))) - return; - - /* Check ERRMSG. */ - if (code->expr3 - && (code->expr3->ts.type != BT_CHARACTER || code->expr3->rank != 0 - || code->expr3->expr_type != EXPR_VARIABLE)) - gfc_error ("ERRMSG= argument at %L must be a scalar CHARACTER variable", - &code->expr3->where); - - if (code->expr3 - && !gfc_check_vardef_context (code->expr3, false, false, false, - _("ERRMSG variable"))) - return; - - /* Check for LOCK the ACQUIRED_LOCK. */ - if (code->op != EXEC_EVENT_WAIT && code->expr4 - && (code->expr4->ts.type != BT_LOGICAL || code->expr4->rank != 0 - || code->expr4->expr_type != EXPR_VARIABLE)) - gfc_error ("ACQUIRED_LOCK= argument at %L must be a scalar LOGICAL " - "variable", &code->expr4->where); - - if (code->op != EXEC_EVENT_WAIT && code->expr4 - && !gfc_check_vardef_context (code->expr4, false, false, false, - _("ACQUIRED_LOCK variable"))) - return; - - /* Check for EVENT WAIT the UNTIL_COUNT. */ - if (code->op == EXEC_EVENT_WAIT && code->expr4) - { - if (!gfc_resolve_expr (code->expr4) || code->expr4->ts.type != BT_INTEGER - || code->expr4->rank != 0) - gfc_error ("UNTIL_COUNT= argument at %L must be a scalar INTEGER " - "expression", &code->expr4->where); - } -} - - -static void -resolve_critical (gfc_code *code) -{ - gfc_symtree *symtree; - gfc_symbol *lock_type; - char name[GFC_MAX_SYMBOL_LEN]; - static int serial = 0; - - if (flag_coarray != GFC_FCOARRAY_LIB) - return; - - symtree = gfc_find_symtree (gfc_current_ns->sym_root, - GFC_PREFIX ("lock_type")); - if (symtree) - lock_type = symtree->n.sym; - else - { - if (gfc_get_sym_tree (GFC_PREFIX ("lock_type"), gfc_current_ns, &symtree, - false) != 0) - gcc_unreachable (); - lock_type = symtree->n.sym; - lock_type->attr.flavor = FL_DERIVED; - lock_type->attr.zero_comp = 1; - lock_type->from_intmod = INTMOD_ISO_FORTRAN_ENV; - lock_type->intmod_sym_id = ISOFORTRAN_LOCK_TYPE; - } - - sprintf(name, GFC_PREFIX ("lock_var") "%d",serial++); - if (gfc_get_sym_tree (name, gfc_current_ns, &symtree, false) != 0) - gcc_unreachable (); - - code->resolved_sym = symtree->n.sym; - symtree->n.sym->attr.flavor = FL_VARIABLE; - symtree->n.sym->attr.referenced = 1; - symtree->n.sym->attr.artificial = 1; - symtree->n.sym->attr.codimension = 1; - symtree->n.sym->ts.type = BT_DERIVED; - symtree->n.sym->ts.u.derived = lock_type; - symtree->n.sym->as = gfc_get_array_spec (); - symtree->n.sym->as->corank = 1; - symtree->n.sym->as->type = AS_EXPLICIT; - symtree->n.sym->as->cotype = AS_EXPLICIT; - symtree->n.sym->as->lower[0] = gfc_get_int_expr (gfc_default_integer_kind, - NULL, 1); - gfc_commit_symbols(); -} - - -static void -resolve_sync (gfc_code *code) -{ - /* Check imageset. The * case matches expr1 == NULL. */ - if (code->expr1) - { - if (code->expr1->ts.type != BT_INTEGER || code->expr1->rank > 1) - gfc_error ("Imageset argument at %L must be a scalar or rank-1 " - "INTEGER expression", &code->expr1->where); - if (code->expr1->expr_type == EXPR_CONSTANT && code->expr1->rank == 0 - && mpz_cmp_si (code->expr1->value.integer, 1) < 0) - gfc_error ("Imageset argument at %L must between 1 and num_images()", - &code->expr1->where); - else if (code->expr1->expr_type == EXPR_ARRAY - && gfc_simplify_expr (code->expr1, 0)) - { - gfc_constructor *cons; - cons = gfc_constructor_first (code->expr1->value.constructor); - for (; cons; cons = gfc_constructor_next (cons)) - if (cons->expr->expr_type == EXPR_CONSTANT - && mpz_cmp_si (cons->expr->value.integer, 1) < 0) - gfc_error ("Imageset argument at %L must between 1 and " - "num_images()", &cons->expr->where); - } - } - - /* Check STAT. */ - gfc_resolve_expr (code->expr2); - if (code->expr2) - { - if (code->expr2->ts.type != BT_INTEGER || code->expr2->rank != 0) - gfc_error ("STAT= argument at %L must be a scalar INTEGER variable", - &code->expr2->where); - else - gfc_check_vardef_context (code->expr2, false, false, false, - _("STAT variable")); - } - - /* Check ERRMSG. */ - gfc_resolve_expr (code->expr3); - if (code->expr3) - { - if (code->expr3->ts.type != BT_CHARACTER || code->expr3->rank != 0) - gfc_error ("ERRMSG= argument at %L must be a scalar CHARACTER variable", - &code->expr3->where); - else - gfc_check_vardef_context (code->expr3, false, false, false, - _("ERRMSG variable")); - } -} - - -/* Given a branch to a label, see if the branch is conforming. - The code node describes where the branch is located. */ - -static void -resolve_branch (gfc_st_label *label, gfc_code *code) -{ - code_stack *stack; - - if (label == NULL) - return; - - /* Step one: is this a valid branching target? */ - - if (label->defined == ST_LABEL_UNKNOWN) - { - gfc_error ("Label %d referenced at %L is never defined", label->value, - &code->loc); - return; - } - - if (label->defined != ST_LABEL_TARGET && label->defined != ST_LABEL_DO_TARGET) - { - gfc_error ("Statement at %L is not a valid branch target statement " - "for the branch statement at %L", &label->where, &code->loc); - return; - } - - /* Step two: make sure this branch is not a branch to itself ;-) */ - - if (code->here == label) - { - gfc_warning (0, - "Branch at %L may result in an infinite loop", &code->loc); - return; - } - - /* Step three: See if the label is in the same block as the - branching statement. The hard work has been done by setting up - the bitmap reachable_labels. */ - - if (bitmap_bit_p (cs_base->reachable_labels, label->value)) - { - /* Check now whether there is a CRITICAL construct; if so, check - whether the label is still visible outside of the CRITICAL block, - which is invalid. */ - for (stack = cs_base; stack; stack = stack->prev) - { - if (stack->current->op == EXEC_CRITICAL - && bitmap_bit_p (stack->reachable_labels, label->value)) - gfc_error ("GOTO statement at %L leaves CRITICAL construct for " - "label at %L", &code->loc, &label->where); - else if (stack->current->op == EXEC_DO_CONCURRENT - && bitmap_bit_p (stack->reachable_labels, label->value)) - gfc_error ("GOTO statement at %L leaves DO CONCURRENT construct " - "for label at %L", &code->loc, &label->where); - } - - return; - } - - /* Step four: If we haven't found the label in the bitmap, it may - still be the label of the END of the enclosing block, in which - case we find it by going up the code_stack. */ - - for (stack = cs_base; stack; stack = stack->prev) - { - if (stack->current->next && stack->current->next->here == label) - break; - if (stack->current->op == EXEC_CRITICAL) - { - /* Note: A label at END CRITICAL does not leave the CRITICAL - construct as END CRITICAL is still part of it. */ - gfc_error ("GOTO statement at %L leaves CRITICAL construct for label" - " at %L", &code->loc, &label->where); - return; - } - else if (stack->current->op == EXEC_DO_CONCURRENT) - { - gfc_error ("GOTO statement at %L leaves DO CONCURRENT construct for " - "label at %L", &code->loc, &label->where); - return; - } - } - - if (stack) - { - gcc_assert (stack->current->next->op == EXEC_END_NESTED_BLOCK); - return; - } - - /* The label is not in an enclosing block, so illegal. This was - allowed in Fortran 66, so we allow it as extension. No - further checks are necessary in this case. */ - gfc_notify_std (GFC_STD_LEGACY, "Label at %L is not in the same block " - "as the GOTO statement at %L", &label->where, - &code->loc); - return; -} - - -/* Check whether EXPR1 has the same shape as EXPR2. */ - -static bool -resolve_where_shape (gfc_expr *expr1, gfc_expr *expr2) -{ - mpz_t shape[GFC_MAX_DIMENSIONS]; - mpz_t shape2[GFC_MAX_DIMENSIONS]; - bool result = false; - int i; - - /* Compare the rank. */ - if (expr1->rank != expr2->rank) - return result; - - /* Compare the size of each dimension. */ - for (i=0; i<expr1->rank; i++) - { - if (!gfc_array_dimen_size (expr1, i, &shape[i])) - goto ignore; - - if (!gfc_array_dimen_size (expr2, i, &shape2[i])) - goto ignore; - - if (mpz_cmp (shape[i], shape2[i])) - goto over; - } - - /* When either of the two expression is an assumed size array, we - ignore the comparison of dimension sizes. */ -ignore: - result = true; - -over: - gfc_clear_shape (shape, i); - gfc_clear_shape (shape2, i); - return result; -} - - -/* Check whether a WHERE assignment target or a WHERE mask expression - has the same shape as the outmost WHERE mask expression. */ - -static void -resolve_where (gfc_code *code, gfc_expr *mask) -{ - gfc_code *cblock; - gfc_code *cnext; - gfc_expr *e = NULL; - - cblock = code->block; - - /* Store the first WHERE mask-expr of the WHERE statement or construct. - In case of nested WHERE, only the outmost one is stored. */ - if (mask == NULL) /* outmost WHERE */ - e = cblock->expr1; - else /* inner WHERE */ - e = mask; - - while (cblock) - { - if (cblock->expr1) - { - /* Check if the mask-expr has a consistent shape with the - outmost WHERE mask-expr. */ - if (!resolve_where_shape (cblock->expr1, e)) - gfc_error ("WHERE mask at %L has inconsistent shape", - &cblock->expr1->where); - } - - /* the assignment statement of a WHERE statement, or the first - statement in where-body-construct of a WHERE construct */ - cnext = cblock->next; - while (cnext) - { - switch (cnext->op) - { - /* WHERE assignment statement */ - case EXEC_ASSIGN: - - /* Check shape consistent for WHERE assignment target. */ - if (e && !resolve_where_shape (cnext->expr1, e)) - gfc_error ("WHERE assignment target at %L has " - "inconsistent shape", &cnext->expr1->where); - break; - - - case EXEC_ASSIGN_CALL: - resolve_call (cnext); - if (!cnext->resolved_sym->attr.elemental) - gfc_error("Non-ELEMENTAL user-defined assignment in WHERE at %L", - &cnext->ext.actual->expr->where); - break; - - /* WHERE or WHERE construct is part of a where-body-construct */ - case EXEC_WHERE: - resolve_where (cnext, e); - break; - - default: - gfc_error ("Unsupported statement inside WHERE at %L", - &cnext->loc); - } - /* the next statement within the same where-body-construct */ - cnext = cnext->next; - } - /* the next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt */ - cblock = cblock->block; - } -} - - -/* Resolve assignment in FORALL construct. - NVAR is the number of FORALL index variables, and VAR_EXPR records the - FORALL index variables. */ - -static void -gfc_resolve_assign_in_forall (gfc_code *code, int nvar, gfc_expr **var_expr) -{ - int n; - - for (n = 0; n < nvar; n++) - { - gfc_symbol *forall_index; - - forall_index = var_expr[n]->symtree->n.sym; - - /* Check whether the assignment target is one of the FORALL index - variable. */ - if ((code->expr1->expr_type == EXPR_VARIABLE) - && (code->expr1->symtree->n.sym == forall_index)) - gfc_error ("Assignment to a FORALL index variable at %L", - &code->expr1->where); - else - { - /* If one of the FORALL index variables doesn't appear in the - assignment variable, then there could be a many-to-one - assignment. Emit a warning rather than an error because the - mask could be resolving this problem. */ - if (!find_forall_index (code->expr1, forall_index, 0)) - gfc_warning (0, "The FORALL with index %qs is not used on the " - "left side of the assignment at %L and so might " - "cause multiple assignment to this object", - var_expr[n]->symtree->name, &code->expr1->where); - } - } -} - - -/* Resolve WHERE statement in FORALL construct. */ - -static void -gfc_resolve_where_code_in_forall (gfc_code *code, int nvar, - gfc_expr **var_expr) -{ - gfc_code *cblock; - gfc_code *cnext; - - cblock = code->block; - while (cblock) - { - /* the assignment statement of a WHERE statement, or the first - statement in where-body-construct of a WHERE construct */ - cnext = cblock->next; - while (cnext) - { - switch (cnext->op) - { - /* WHERE assignment statement */ - case EXEC_ASSIGN: - gfc_resolve_assign_in_forall (cnext, nvar, var_expr); - break; - - /* WHERE operator assignment statement */ - case EXEC_ASSIGN_CALL: - resolve_call (cnext); - if (!cnext->resolved_sym->attr.elemental) - gfc_error("Non-ELEMENTAL user-defined assignment in WHERE at %L", - &cnext->ext.actual->expr->where); - break; - - /* WHERE or WHERE construct is part of a where-body-construct */ - case EXEC_WHERE: - gfc_resolve_where_code_in_forall (cnext, nvar, var_expr); - break; - - default: - gfc_error ("Unsupported statement inside WHERE at %L", - &cnext->loc); - } - /* the next statement within the same where-body-construct */ - cnext = cnext->next; - } - /* the next masked-elsewhere-stmt, elsewhere-stmt, or end-where-stmt */ - cblock = cblock->block; - } -} - - -/* Traverse the FORALL body to check whether the following errors exist: - 1. For assignment, check if a many-to-one assignment happens. - 2. For WHERE statement, check the WHERE body to see if there is any - many-to-one assignment. */ - -static void -gfc_resolve_forall_body (gfc_code *code, int nvar, gfc_expr **var_expr) -{ - gfc_code *c; - - c = code->block->next; - while (c) - { - switch (c->op) - { - case EXEC_ASSIGN: - case EXEC_POINTER_ASSIGN: - gfc_resolve_assign_in_forall (c, nvar, var_expr); - break; - - case EXEC_ASSIGN_CALL: - resolve_call (c); - break; - - /* Because the gfc_resolve_blocks() will handle the nested FORALL, - there is no need to handle it here. */ - case EXEC_FORALL: - break; - case EXEC_WHERE: - gfc_resolve_where_code_in_forall(c, nvar, var_expr); - break; - default: - break; - } - /* The next statement in the FORALL body. */ - c = c->next; - } -} - - -/* Counts the number of iterators needed inside a forall construct, including - nested forall constructs. This is used to allocate the needed memory - in gfc_resolve_forall. */ - -static int -gfc_count_forall_iterators (gfc_code *code) -{ - int max_iters, sub_iters, current_iters; - gfc_forall_iterator *fa; - - gcc_assert(code->op == EXEC_FORALL); - max_iters = 0; - current_iters = 0; - - for (fa = code->ext.forall_iterator; fa; fa = fa->next) - current_iters ++; - - code = code->block->next; - - while (code) - { - if (code->op == EXEC_FORALL) - { - sub_iters = gfc_count_forall_iterators (code); - if (sub_iters > max_iters) - max_iters = sub_iters; - } - code = code->next; - } - - return current_iters + max_iters; -} - - -/* Given a FORALL construct, first resolve the FORALL iterator, then call - gfc_resolve_forall_body to resolve the FORALL body. */ - -static void -gfc_resolve_forall (gfc_code *code, gfc_namespace *ns, int forall_save) -{ - static gfc_expr **var_expr; - static int total_var = 0; - static int nvar = 0; - int i, old_nvar, tmp; - gfc_forall_iterator *fa; - - old_nvar = nvar; - - if (!gfc_notify_std (GFC_STD_F2018_OBS, "FORALL construct at %L", &code->loc)) - return; - - /* Start to resolve a FORALL construct */ - if (forall_save == 0) - { - /* Count the total number of FORALL indices in the nested FORALL - construct in order to allocate the VAR_EXPR with proper size. */ - total_var = gfc_count_forall_iterators (code); - - /* Allocate VAR_EXPR with NUMBER_OF_FORALL_INDEX elements. */ - var_expr = XCNEWVEC (gfc_expr *, total_var); - } - - /* The information about FORALL iterator, including FORALL indices start, end - and stride. An outer FORALL indice cannot appear in start, end or stride. */ - for (fa = code->ext.forall_iterator; fa; fa = fa->next) - { - /* Fortran 20008: C738 (R753). */ - if (fa->var->ref && fa->var->ref->type == REF_ARRAY) - { - gfc_error ("FORALL index-name at %L must be a scalar variable " - "of type integer", &fa->var->where); - continue; - } - - /* Check if any outer FORALL index name is the same as the current - one. */ - for (i = 0; i < nvar; i++) - { - if (fa->var->symtree->n.sym == var_expr[i]->symtree->n.sym) - gfc_error ("An outer FORALL construct already has an index " - "with this name %L", &fa->var->where); - } - - /* Record the current FORALL index. */ - var_expr[nvar] = gfc_copy_expr (fa->var); - - nvar++; - - /* No memory leak. */ - gcc_assert (nvar <= total_var); - } - - /* Resolve the FORALL body. */ - gfc_resolve_forall_body (code, nvar, var_expr); - - /* May call gfc_resolve_forall to resolve the inner FORALL loop. */ - gfc_resolve_blocks (code->block, ns); - - tmp = nvar; - nvar = old_nvar; - /* Free only the VAR_EXPRs allocated in this frame. */ - for (i = nvar; i < tmp; i++) - gfc_free_expr (var_expr[i]); - - if (nvar == 0) - { - /* We are in the outermost FORALL construct. */ - gcc_assert (forall_save == 0); - - /* VAR_EXPR is not needed any more. */ - free (var_expr); - total_var = 0; - } -} - - -/* Resolve a BLOCK construct statement. */ - -static void -resolve_block_construct (gfc_code* code) -{ - /* Resolve the BLOCK's namespace. */ - gfc_resolve (code->ext.block.ns); - - /* For an ASSOCIATE block, the associations (and their targets) are already - resolved during resolve_symbol. */ -} - - -/* Resolve lists of blocks found in IF, SELECT CASE, WHERE, FORALL, GOTO and - DO code nodes. */ - -void -gfc_resolve_blocks (gfc_code *b, gfc_namespace *ns) -{ - bool t; - - for (; b; b = b->block) - { - t = gfc_resolve_expr (b->expr1); - if (!gfc_resolve_expr (b->expr2)) - t = false; - - switch (b->op) - { - case EXEC_IF: - if (t && b->expr1 != NULL - && (b->expr1->ts.type != BT_LOGICAL || b->expr1->rank != 0)) - gfc_error ("IF clause at %L requires a scalar LOGICAL expression", - &b->expr1->where); - break; - - case EXEC_WHERE: - if (t - && b->expr1 != NULL - && (b->expr1->ts.type != BT_LOGICAL || b->expr1->rank == 0)) - gfc_error ("WHERE/ELSEWHERE clause at %L requires a LOGICAL array", - &b->expr1->where); - break; - - case EXEC_GOTO: - resolve_branch (b->label1, b); - break; - - case EXEC_BLOCK: - resolve_block_construct (b); - break; - - case EXEC_SELECT: - case EXEC_SELECT_TYPE: - case EXEC_SELECT_RANK: - case EXEC_FORALL: - case EXEC_DO: - case EXEC_DO_WHILE: - case EXEC_DO_CONCURRENT: - case EXEC_CRITICAL: - case EXEC_READ: - case EXEC_WRITE: - case EXEC_IOLENGTH: - case EXEC_WAIT: - break; - - case EXEC_OMP_ATOMIC: - case EXEC_OACC_ATOMIC: - { - /* Verify this before calling gfc_resolve_code, which might - change it. */ - gcc_assert (b->op == EXEC_OMP_ATOMIC - || (b->next && b->next->op == EXEC_ASSIGN)); - } - break; - - case EXEC_OACC_PARALLEL_LOOP: - case EXEC_OACC_PARALLEL: - case EXEC_OACC_KERNELS_LOOP: - case EXEC_OACC_KERNELS: - case EXEC_OACC_SERIAL_LOOP: - case EXEC_OACC_SERIAL: - case EXEC_OACC_DATA: - case EXEC_OACC_HOST_DATA: - case EXEC_OACC_LOOP: - case EXEC_OACC_UPDATE: - case EXEC_OACC_WAIT: - case EXEC_OACC_CACHE: - case EXEC_OACC_ENTER_DATA: - case EXEC_OACC_EXIT_DATA: - case EXEC_OACC_ROUTINE: - case EXEC_OMP_CRITICAL: - case EXEC_OMP_DISTRIBUTE: - case EXEC_OMP_DISTRIBUTE_PARALLEL_DO: - case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD: - case EXEC_OMP_DISTRIBUTE_SIMD: - case EXEC_OMP_DO: - case EXEC_OMP_DO_SIMD: - case EXEC_OMP_ERROR: - case EXEC_OMP_LOOP: - case EXEC_OMP_MASKED: - case EXEC_OMP_MASKED_TASKLOOP: - case EXEC_OMP_MASKED_TASKLOOP_SIMD: - case EXEC_OMP_MASTER: - case EXEC_OMP_MASTER_TASKLOOP: - case EXEC_OMP_MASTER_TASKLOOP_SIMD: - case EXEC_OMP_ORDERED: - case EXEC_OMP_PARALLEL: - case EXEC_OMP_PARALLEL_DO: - case EXEC_OMP_PARALLEL_DO_SIMD: - case EXEC_OMP_PARALLEL_LOOP: - case EXEC_OMP_PARALLEL_MASKED: - case EXEC_OMP_PARALLEL_MASKED_TASKLOOP: - case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD: - case EXEC_OMP_PARALLEL_MASTER: - case EXEC_OMP_PARALLEL_MASTER_TASKLOOP: - case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD: - case EXEC_OMP_PARALLEL_SECTIONS: - case EXEC_OMP_PARALLEL_WORKSHARE: - case EXEC_OMP_SECTIONS: - case EXEC_OMP_SIMD: - case EXEC_OMP_SCOPE: - case EXEC_OMP_SINGLE: - case EXEC_OMP_TARGET: - case EXEC_OMP_TARGET_DATA: - case EXEC_OMP_TARGET_ENTER_DATA: - case EXEC_OMP_TARGET_EXIT_DATA: - case EXEC_OMP_TARGET_PARALLEL: - case EXEC_OMP_TARGET_PARALLEL_DO: - case EXEC_OMP_TARGET_PARALLEL_DO_SIMD: - case EXEC_OMP_TARGET_PARALLEL_LOOP: - case EXEC_OMP_TARGET_SIMD: - case EXEC_OMP_TARGET_TEAMS: - case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE: - case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO: - case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: - case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD: - case EXEC_OMP_TARGET_TEAMS_LOOP: - case EXEC_OMP_TARGET_UPDATE: - case EXEC_OMP_TASK: - case EXEC_OMP_TASKGROUP: - case EXEC_OMP_TASKLOOP: - case EXEC_OMP_TASKLOOP_SIMD: - case EXEC_OMP_TASKWAIT: - case EXEC_OMP_TASKYIELD: - case EXEC_OMP_TEAMS: - case EXEC_OMP_TEAMS_DISTRIBUTE: - case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO: - case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: - case EXEC_OMP_TEAMS_LOOP: - case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD: - case EXEC_OMP_WORKSHARE: - break; - - default: - gfc_internal_error ("gfc_resolve_blocks(): Bad block type"); - } - - gfc_resolve_code (b->next, ns); - } -} - - -/* Does everything to resolve an ordinary assignment. Returns true - if this is an interface assignment. */ -static bool -resolve_ordinary_assign (gfc_code *code, gfc_namespace *ns) -{ - bool rval = false; - gfc_expr *lhs; - gfc_expr *rhs; - int n; - gfc_ref *ref; - symbol_attribute attr; - - if (gfc_extend_assign (code, ns)) - { - gfc_expr** rhsptr; - - if (code->op == EXEC_ASSIGN_CALL) - { - lhs = code->ext.actual->expr; - rhsptr = &code->ext.actual->next->expr; - } - else - { - gfc_actual_arglist* args; - gfc_typebound_proc* tbp; - - gcc_assert (code->op == EXEC_COMPCALL); - - args = code->expr1->value.compcall.actual; - lhs = args->expr; - rhsptr = &args->next->expr; - - tbp = code->expr1->value.compcall.tbp; - gcc_assert (!tbp->is_generic); - } - - /* Make a temporary rhs when there is a default initializer - and rhs is the same symbol as the lhs. */ - if ((*rhsptr)->expr_type == EXPR_VARIABLE - && (*rhsptr)->symtree->n.sym->ts.type == BT_DERIVED - && gfc_has_default_initializer ((*rhsptr)->symtree->n.sym->ts.u.derived) - && (lhs->symtree->n.sym == (*rhsptr)->symtree->n.sym)) - *rhsptr = gfc_get_parentheses (*rhsptr); - - return true; - } - - lhs = code->expr1; - rhs = code->expr2; - - if ((gfc_numeric_ts (&lhs->ts) || lhs->ts.type == BT_LOGICAL) - && rhs->ts.type == BT_CHARACTER - && (rhs->expr_type != EXPR_CONSTANT || !flag_dec_char_conversions)) - { - /* Use of -fdec-char-conversions allows assignment of character data - to non-character variables. This not permited for nonconstant - strings. */ - gfc_error ("Cannot convert %s to %s at %L", gfc_typename (rhs), - gfc_typename (lhs), &rhs->where); - return false; - } - - /* Handle the case of a BOZ literal on the RHS. */ - if (rhs->ts.type == BT_BOZ) - { - if (gfc_invalid_boz ("BOZ literal constant at %L is neither a DATA " - "statement value nor an actual argument of " - "INT/REAL/DBLE/CMPLX intrinsic subprogram", - &rhs->where)) - return false; - - switch (lhs->ts.type) - { - case BT_INTEGER: - if (!gfc_boz2int (rhs, lhs->ts.kind)) - return false; - break; - case BT_REAL: - if (!gfc_boz2real (rhs, lhs->ts.kind)) - return false; - break; - default: - gfc_error ("Invalid use of BOZ literal constant at %L", &rhs->where); - return false; - } - } - - if (lhs->ts.type == BT_CHARACTER && warn_character_truncation) - { - HOST_WIDE_INT llen = 0, rlen = 0; - if (lhs->ts.u.cl != NULL - && lhs->ts.u.cl->length != NULL - && lhs->ts.u.cl->length->expr_type == EXPR_CONSTANT) - llen = gfc_mpz_get_hwi (lhs->ts.u.cl->length->value.integer); - - if (rhs->expr_type == EXPR_CONSTANT) - rlen = rhs->value.character.length; - - else if (rhs->ts.u.cl != NULL - && rhs->ts.u.cl->length != NULL - && rhs->ts.u.cl->length->expr_type == EXPR_CONSTANT) - rlen = gfc_mpz_get_hwi (rhs->ts.u.cl->length->value.integer); - - if (rlen && llen && rlen > llen) - gfc_warning_now (OPT_Wcharacter_truncation, - "CHARACTER expression will be truncated " - "in assignment (%ld/%ld) at %L", - (long) llen, (long) rlen, &code->loc); - } - - /* Ensure that a vector index expression for the lvalue is evaluated - to a temporary if the lvalue symbol is referenced in it. */ - if (lhs->rank) - { - for (ref = lhs->ref; ref; ref= ref->next) - if (ref->type == REF_ARRAY) - { - for (n = 0; n < ref->u.ar.dimen; n++) - if (ref->u.ar.dimen_type[n] == DIMEN_VECTOR - && gfc_find_sym_in_expr (lhs->symtree->n.sym, - ref->u.ar.start[n])) - ref->u.ar.start[n] - = gfc_get_parentheses (ref->u.ar.start[n]); - } - } - - if (gfc_pure (NULL)) - { - if (lhs->ts.type == BT_DERIVED - && lhs->expr_type == EXPR_VARIABLE - && lhs->ts.u.derived->attr.pointer_comp - && rhs->expr_type == EXPR_VARIABLE - && (gfc_impure_variable (rhs->symtree->n.sym) - || gfc_is_coindexed (rhs))) - { - /* F2008, C1283. */ - if (gfc_is_coindexed (rhs)) - gfc_error ("Coindexed expression at %L is assigned to " - "a derived type variable with a POINTER " - "component in a PURE procedure", - &rhs->where); - else - /* F2008, C1283 (4). */ - gfc_error ("In a pure subprogram an INTENT(IN) dummy argument " - "shall not be used as the expr at %L of an intrinsic " - "assignment statement in which the variable is of a " - "derived type if the derived type has a pointer " - "component at any level of component selection.", - &rhs->where); - return rval; - } - - /* Fortran 2008, C1283. */ - if (gfc_is_coindexed (lhs)) - { - gfc_error ("Assignment to coindexed variable at %L in a PURE " - "procedure", &rhs->where); - return rval; - } - } - - if (gfc_implicit_pure (NULL)) - { - if (lhs->expr_type == EXPR_VARIABLE - && lhs->symtree->n.sym != gfc_current_ns->proc_name - && lhs->symtree->n.sym->ns != gfc_current_ns) - gfc_unset_implicit_pure (NULL); - - if (lhs->ts.type == BT_DERIVED - && lhs->expr_type == EXPR_VARIABLE - && lhs->ts.u.derived->attr.pointer_comp - && rhs->expr_type == EXPR_VARIABLE - && (gfc_impure_variable (rhs->symtree->n.sym) - || gfc_is_coindexed (rhs))) - gfc_unset_implicit_pure (NULL); - - /* Fortran 2008, C1283. */ - if (gfc_is_coindexed (lhs)) - gfc_unset_implicit_pure (NULL); - } - - /* F2008, 7.2.1.2. */ - attr = gfc_expr_attr (lhs); - if (lhs->ts.type == BT_CLASS && attr.allocatable) - { - if (attr.codimension) - { - gfc_error ("Assignment to polymorphic coarray at %L is not " - "permitted", &lhs->where); - return false; - } - if (!gfc_notify_std (GFC_STD_F2008, "Assignment to an allocatable " - "polymorphic variable at %L", &lhs->where)) - return false; - if (!flag_realloc_lhs) - { - gfc_error ("Assignment to an allocatable polymorphic variable at %L " - "requires %<-frealloc-lhs%>", &lhs->where); - return false; - } - } - else if (lhs->ts.type == BT_CLASS) - { - gfc_error ("Nonallocatable variable must not be polymorphic in intrinsic " - "assignment at %L - check that there is a matching specific " - "subroutine for '=' operator", &lhs->where); - return false; - } - - bool lhs_coindexed = gfc_is_coindexed (lhs); - - /* F2008, Section 7.2.1.2. */ - if (lhs_coindexed && gfc_has_ultimate_allocatable (lhs)) - { - gfc_error ("Coindexed variable must not have an allocatable ultimate " - "component in assignment at %L", &lhs->where); - return false; - } - - /* Assign the 'data' of a class object to a derived type. */ - if (lhs->ts.type == BT_DERIVED - && rhs->ts.type == BT_CLASS - && rhs->expr_type != EXPR_ARRAY) - gfc_add_data_component (rhs); - - /* Make sure there is a vtable and, in particular, a _copy for the - rhs type. */ - if (lhs->ts.type == BT_CLASS && rhs->ts.type != BT_CLASS) - gfc_find_vtab (&rhs->ts); - - bool caf_convert_to_send = flag_coarray == GFC_FCOARRAY_LIB - && (lhs_coindexed - || (code->expr2->expr_type == EXPR_FUNCTION - && code->expr2->value.function.isym - && code->expr2->value.function.isym->id == GFC_ISYM_CAF_GET - && (code->expr1->rank == 0 || code->expr2->rank != 0) - && !gfc_expr_attr (rhs).allocatable - && !gfc_has_vector_subscript (rhs))); - - gfc_check_assign (lhs, rhs, 1, !caf_convert_to_send); - - /* Insert a GFC_ISYM_CAF_SEND intrinsic, when the LHS is a coindexed variable. - Additionally, insert this code when the RHS is a CAF as we then use the - GFC_ISYM_CAF_SEND intrinsic just to avoid a temporary; but do not do so if - the LHS is (re)allocatable or has a vector subscript. If the LHS is a - noncoindexed array and the RHS is a coindexed scalar, use the normal code - path. */ - if (caf_convert_to_send) - { - if (code->expr2->expr_type == EXPR_FUNCTION - && code->expr2->value.function.isym - && code->expr2->value.function.isym->id == GFC_ISYM_CAF_GET) - remove_caf_get_intrinsic (code->expr2); - code->op = EXEC_CALL; - gfc_get_sym_tree (GFC_PREFIX ("caf_send"), ns, &code->symtree, true); - code->resolved_sym = code->symtree->n.sym; - code->resolved_sym->attr.flavor = FL_PROCEDURE; - code->resolved_sym->attr.intrinsic = 1; - code->resolved_sym->attr.subroutine = 1; - code->resolved_isym = gfc_intrinsic_subroutine_by_id (GFC_ISYM_CAF_SEND); - gfc_commit_symbol (code->resolved_sym); - code->ext.actual = gfc_get_actual_arglist (); - code->ext.actual->expr = lhs; - code->ext.actual->next = gfc_get_actual_arglist (); - code->ext.actual->next->expr = rhs; - code->expr1 = NULL; - code->expr2 = NULL; - } - - return false; -} - - -/* Add a component reference onto an expression. */ - -static void -add_comp_ref (gfc_expr *e, gfc_component *c) -{ - gfc_ref **ref; - ref = &(e->ref); - while (*ref) - ref = &((*ref)->next); - *ref = gfc_get_ref (); - (*ref)->type = REF_COMPONENT; - (*ref)->u.c.sym = e->ts.u.derived; - (*ref)->u.c.component = c; - e->ts = c->ts; - - /* Add a full array ref, as necessary. */ - if (c->as) - { - gfc_add_full_array_ref (e, c->as); - e->rank = c->as->rank; - } -} - - -/* Build an assignment. Keep the argument 'op' for future use, so that - pointer assignments can be made. */ - -static gfc_code * -build_assignment (gfc_exec_op op, gfc_expr *expr1, gfc_expr *expr2, - gfc_component *comp1, gfc_component *comp2, locus loc) -{ - gfc_code *this_code; - - this_code = gfc_get_code (op); - this_code->next = NULL; - this_code->expr1 = gfc_copy_expr (expr1); - this_code->expr2 = gfc_copy_expr (expr2); - this_code->loc = loc; - if (comp1 && comp2) - { - add_comp_ref (this_code->expr1, comp1); - add_comp_ref (this_code->expr2, comp2); - } - - return this_code; -} - - -/* Makes a temporary variable expression based on the characteristics of - a given variable expression. */ - -static gfc_expr* -get_temp_from_expr (gfc_expr *e, gfc_namespace *ns) -{ - static int serial = 0; - char name[GFC_MAX_SYMBOL_LEN]; - gfc_symtree *tmp; - gfc_array_spec *as; - gfc_array_ref *aref; - gfc_ref *ref; - - sprintf (name, GFC_PREFIX("DA%d"), serial++); - gfc_get_sym_tree (name, ns, &tmp, false); - gfc_add_type (tmp->n.sym, &e->ts, NULL); - - if (e->expr_type == EXPR_CONSTANT && e->ts.type == BT_CHARACTER) - tmp->n.sym->ts.u.cl->length = gfc_get_int_expr (gfc_charlen_int_kind, - NULL, - e->value.character.length); - - as = NULL; - ref = NULL; - aref = NULL; - - /* Obtain the arrayspec for the temporary. */ - if (e->rank && e->expr_type != EXPR_ARRAY - && e->expr_type != EXPR_FUNCTION - && e->expr_type != EXPR_OP) - { - aref = gfc_find_array_ref (e); - if (e->expr_type == EXPR_VARIABLE - && e->symtree->n.sym->as == aref->as) - as = aref->as; - else - { - for (ref = e->ref; ref; ref = ref->next) - if (ref->type == REF_COMPONENT - && ref->u.c.component->as == aref->as) - { - as = aref->as; - break; - } - } - } - - /* Add the attributes and the arrayspec to the temporary. */ - tmp->n.sym->attr = gfc_expr_attr (e); - tmp->n.sym->attr.function = 0; - tmp->n.sym->attr.proc_pointer = 0; - tmp->n.sym->attr.result = 0; - tmp->n.sym->attr.flavor = FL_VARIABLE; - tmp->n.sym->attr.dummy = 0; - tmp->n.sym->attr.use_assoc = 0; - tmp->n.sym->attr.intent = INTENT_UNKNOWN; - - if (as) - { - tmp->n.sym->as = gfc_copy_array_spec (as); - if (!ref) - ref = e->ref; - if (as->type == AS_DEFERRED) - tmp->n.sym->attr.allocatable = 1; - } - else if (e->rank && (e->expr_type == EXPR_ARRAY - || e->expr_type == EXPR_FUNCTION - || e->expr_type == EXPR_OP)) - { - tmp->n.sym->as = gfc_get_array_spec (); - tmp->n.sym->as->type = AS_DEFERRED; - tmp->n.sym->as->rank = e->rank; - tmp->n.sym->attr.allocatable = 1; - tmp->n.sym->attr.dimension = 1; - } - else - tmp->n.sym->attr.dimension = 0; - - gfc_set_sym_referenced (tmp->n.sym); - gfc_commit_symbol (tmp->n.sym); - e = gfc_lval_expr_from_sym (tmp->n.sym); - - /* Should the lhs be a section, use its array ref for the - temporary expression. */ - if (aref && aref->type != AR_FULL) - { - gfc_free_ref_list (e->ref); - e->ref = gfc_copy_ref (ref); - } - return e; -} - - -/* Add one line of code to the code chain, making sure that 'head' and - 'tail' are appropriately updated. */ - -static void -add_code_to_chain (gfc_code **this_code, gfc_code **head, gfc_code **tail) -{ - gcc_assert (this_code); - if (*head == NULL) - *head = *tail = *this_code; - else - *tail = gfc_append_code (*tail, *this_code); - *this_code = NULL; -} - - -/* Counts the potential number of part array references that would - result from resolution of typebound defined assignments. */ - -static int -nonscalar_typebound_assign (gfc_symbol *derived, int depth) -{ - gfc_component *c; - int c_depth = 0, t_depth; - - for (c= derived->components; c; c = c->next) - { - if ((!gfc_bt_struct (c->ts.type) - || c->attr.pointer - || c->attr.allocatable - || c->attr.proc_pointer_comp - || c->attr.class_pointer - || c->attr.proc_pointer) - && !c->attr.defined_assign_comp) - continue; - - if (c->as && c_depth == 0) - c_depth = 1; - - if (c->ts.u.derived->attr.defined_assign_comp) - t_depth = nonscalar_typebound_assign (c->ts.u.derived, - c->as ? 1 : 0); - else - t_depth = 0; - - c_depth = t_depth > c_depth ? t_depth : c_depth; - } - return depth + c_depth; -} - - -/* Implement 7.2.1.3 of the F08 standard: - "An intrinsic assignment where the variable is of derived type is - performed as if each component of the variable were assigned from the - corresponding component of expr using pointer assignment (7.2.2) for - each pointer component, defined assignment for each nonpointer - nonallocatable component of a type that has a type-bound defined - assignment consistent with the component, intrinsic assignment for - each other nonpointer nonallocatable component, ..." - - The pointer assignments are taken care of by the intrinsic - assignment of the structure itself. This function recursively adds - defined assignments where required. The recursion is accomplished - by calling gfc_resolve_code. - - When the lhs in a defined assignment has intent INOUT, we need a - temporary for the lhs. In pseudo-code: - - ! Only call function lhs once. - if (lhs is not a constant or an variable) - temp_x = expr2 - expr2 => temp_x - ! Do the intrinsic assignment - expr1 = expr2 - ! Now do the defined assignments - do over components with typebound defined assignment [%cmp] - #if one component's assignment procedure is INOUT - t1 = expr1 - #if expr2 non-variable - temp_x = expr2 - expr2 => temp_x - # endif - expr1 = expr2 - # for each cmp - t1%cmp {defined=} expr2%cmp - expr1%cmp = t1%cmp - #else - expr1 = expr2 - - # for each cmp - expr1%cmp {defined=} expr2%cmp - #endif - */ - -/* The temporary assignments have to be put on top of the additional - code to avoid the result being changed by the intrinsic assignment. - */ -static int component_assignment_level = 0; -static gfc_code *tmp_head = NULL, *tmp_tail = NULL; - -static void -generate_component_assignments (gfc_code **code, gfc_namespace *ns) -{ - gfc_component *comp1, *comp2; - gfc_code *this_code = NULL, *head = NULL, *tail = NULL; - gfc_expr *t1; - int error_count, depth; - - gfc_get_errors (NULL, &error_count); - - /* Filter out continuing processing after an error. */ - if (error_count - || (*code)->expr1->ts.type != BT_DERIVED - || (*code)->expr2->ts.type != BT_DERIVED) - return; - - /* TODO: Handle more than one part array reference in assignments. */ - depth = nonscalar_typebound_assign ((*code)->expr1->ts.u.derived, - (*code)->expr1->rank ? 1 : 0); - if (depth > 1) - { - gfc_warning (0, "TODO: type-bound defined assignment(s) at %L not " - "done because multiple part array references would " - "occur in intermediate expressions.", &(*code)->loc); - return; - } - - component_assignment_level++; - - /* Create a temporary so that functions get called only once. */ - if ((*code)->expr2->expr_type != EXPR_VARIABLE - && (*code)->expr2->expr_type != EXPR_CONSTANT) - { - gfc_expr *tmp_expr; - - /* Assign the rhs to the temporary. */ - tmp_expr = get_temp_from_expr ((*code)->expr1, ns); - this_code = build_assignment (EXEC_ASSIGN, - tmp_expr, (*code)->expr2, - NULL, NULL, (*code)->loc); - /* Add the code and substitute the rhs expression. */ - add_code_to_chain (&this_code, &tmp_head, &tmp_tail); - gfc_free_expr ((*code)->expr2); - (*code)->expr2 = tmp_expr; - } - - /* Do the intrinsic assignment. This is not needed if the lhs is one - of the temporaries generated here, since the intrinsic assignment - to the final result already does this. */ - if ((*code)->expr1->symtree->n.sym->name[2] != '@') - { - this_code = build_assignment (EXEC_ASSIGN, - (*code)->expr1, (*code)->expr2, - NULL, NULL, (*code)->loc); - add_code_to_chain (&this_code, &head, &tail); - } - - comp1 = (*code)->expr1->ts.u.derived->components; - comp2 = (*code)->expr2->ts.u.derived->components; - - t1 = NULL; - for (; comp1; comp1 = comp1->next, comp2 = comp2->next) - { - bool inout = false; - - /* The intrinsic assignment does the right thing for pointers - of all kinds and allocatable components. */ - if (!gfc_bt_struct (comp1->ts.type) - || comp1->attr.pointer - || comp1->attr.allocatable - || comp1->attr.proc_pointer_comp - || comp1->attr.class_pointer - || comp1->attr.proc_pointer) - continue; - - /* Make an assigment for this component. */ - this_code = build_assignment (EXEC_ASSIGN, - (*code)->expr1, (*code)->expr2, - comp1, comp2, (*code)->loc); - - /* Convert the assignment if there is a defined assignment for - this type. Otherwise, using the call from gfc_resolve_code, - recurse into its components. */ - gfc_resolve_code (this_code, ns); - - if (this_code->op == EXEC_ASSIGN_CALL) - { - gfc_formal_arglist *dummy_args; - gfc_symbol *rsym; - /* Check that there is a typebound defined assignment. If not, - then this must be a module defined assignment. We cannot - use the defined_assign_comp attribute here because it must - be this derived type that has the defined assignment and not - a parent type. */ - if (!(comp1->ts.u.derived->f2k_derived - && comp1->ts.u.derived->f2k_derived - ->tb_op[INTRINSIC_ASSIGN])) - { - gfc_free_statements (this_code); - this_code = NULL; - continue; - } - - /* If the first argument of the subroutine has intent INOUT - a temporary must be generated and used instead. */ - rsym = this_code->resolved_sym; - dummy_args = gfc_sym_get_dummy_args (rsym); - if (dummy_args - && dummy_args->sym->attr.intent == INTENT_INOUT) - { - gfc_code *temp_code; - inout = true; - - /* Build the temporary required for the assignment and put - it at the head of the generated code. */ - if (!t1) - { - t1 = get_temp_from_expr ((*code)->expr1, ns); - temp_code = build_assignment (EXEC_ASSIGN, - t1, (*code)->expr1, - NULL, NULL, (*code)->loc); - - /* For allocatable LHS, check whether it is allocated. Note - that allocatable components with defined assignment are - not yet support. See PR 57696. */ - if ((*code)->expr1->symtree->n.sym->attr.allocatable) - { - gfc_code *block; - gfc_expr *e = - gfc_lval_expr_from_sym ((*code)->expr1->symtree->n.sym); - block = gfc_get_code (EXEC_IF); - block->block = gfc_get_code (EXEC_IF); - block->block->expr1 - = gfc_build_intrinsic_call (ns, - GFC_ISYM_ALLOCATED, "allocated", - (*code)->loc, 1, e); - block->block->next = temp_code; - temp_code = block; - } - add_code_to_chain (&temp_code, &tmp_head, &tmp_tail); - } - - /* Replace the first actual arg with the component of the - temporary. */ - gfc_free_expr (this_code->ext.actual->expr); - this_code->ext.actual->expr = gfc_copy_expr (t1); - add_comp_ref (this_code->ext.actual->expr, comp1); - - /* If the LHS variable is allocatable and wasn't allocated and - the temporary is allocatable, pointer assign the address of - the freshly allocated LHS to the temporary. */ - if ((*code)->expr1->symtree->n.sym->attr.allocatable - && gfc_expr_attr ((*code)->expr1).allocatable) - { - gfc_code *block; - gfc_expr *cond; - - cond = gfc_get_expr (); - cond->ts.type = BT_LOGICAL; - cond->ts.kind = gfc_default_logical_kind; - cond->expr_type = EXPR_OP; - cond->where = (*code)->loc; - cond->value.op.op = INTRINSIC_NOT; - cond->value.op.op1 = gfc_build_intrinsic_call (ns, - GFC_ISYM_ALLOCATED, "allocated", - (*code)->loc, 1, gfc_copy_expr (t1)); - block = gfc_get_code (EXEC_IF); - block->block = gfc_get_code (EXEC_IF); - block->block->expr1 = cond; - block->block->next = build_assignment (EXEC_POINTER_ASSIGN, - t1, (*code)->expr1, - NULL, NULL, (*code)->loc); - add_code_to_chain (&block, &head, &tail); - } - } - } - else if (this_code->op == EXEC_ASSIGN && !this_code->next) - { - /* Don't add intrinsic assignments since they are already - effected by the intrinsic assignment of the structure. */ - gfc_free_statements (this_code); - this_code = NULL; - continue; - } - - add_code_to_chain (&this_code, &head, &tail); - - if (t1 && inout) - { - /* Transfer the value to the final result. */ - this_code = build_assignment (EXEC_ASSIGN, - (*code)->expr1, t1, - comp1, comp2, (*code)->loc); - add_code_to_chain (&this_code, &head, &tail); - } - } - - /* Put the temporary assignments at the top of the generated code. */ - if (tmp_head && component_assignment_level == 1) - { - gfc_append_code (tmp_head, head); - head = tmp_head; - tmp_head = tmp_tail = NULL; - } - - // If we did a pointer assignment - thus, we need to ensure that the LHS is - // not accidentally deallocated. Hence, nullify t1. - if (t1 && (*code)->expr1->symtree->n.sym->attr.allocatable - && gfc_expr_attr ((*code)->expr1).allocatable) - { - gfc_code *block; - gfc_expr *cond; - gfc_expr *e; - - e = gfc_lval_expr_from_sym ((*code)->expr1->symtree->n.sym); - cond = gfc_build_intrinsic_call (ns, GFC_ISYM_ASSOCIATED, "associated", - (*code)->loc, 2, gfc_copy_expr (t1), e); - block = gfc_get_code (EXEC_IF); - block->block = gfc_get_code (EXEC_IF); - block->block->expr1 = cond; - block->block->next = build_assignment (EXEC_POINTER_ASSIGN, - t1, gfc_get_null_expr (&(*code)->loc), - NULL, NULL, (*code)->loc); - gfc_append_code (tail, block); - tail = block; - } - - /* Now attach the remaining code chain to the input code. Step on - to the end of the new code since resolution is complete. */ - gcc_assert ((*code)->op == EXEC_ASSIGN); - tail->next = (*code)->next; - /* Overwrite 'code' because this would place the intrinsic assignment - before the temporary for the lhs is created. */ - gfc_free_expr ((*code)->expr1); - gfc_free_expr ((*code)->expr2); - **code = *head; - if (head != tail) - free (head); - *code = tail; - - component_assignment_level--; -} - - -/* F2008: Pointer function assignments are of the form: - ptr_fcn (args) = expr - This function breaks these assignments into two statements: - temporary_pointer => ptr_fcn(args) - temporary_pointer = expr */ - -static bool -resolve_ptr_fcn_assign (gfc_code **code, gfc_namespace *ns) -{ - gfc_expr *tmp_ptr_expr; - gfc_code *this_code; - gfc_component *comp; - gfc_symbol *s; - - if ((*code)->expr1->expr_type != EXPR_FUNCTION) - return false; - - /* Even if standard does not support this feature, continue to build - the two statements to avoid upsetting frontend_passes.c. */ - gfc_notify_std (GFC_STD_F2008, "Pointer procedure assignment at " - "%L", &(*code)->loc); - - comp = gfc_get_proc_ptr_comp ((*code)->expr1); - - if (comp) - s = comp->ts.interface; - else - s = (*code)->expr1->symtree->n.sym; - - if (s == NULL || !s->result->attr.pointer) - { - gfc_error ("The function result on the lhs of the assignment at " - "%L must have the pointer attribute.", - &(*code)->expr1->where); - (*code)->op = EXEC_NOP; - return false; - } - - tmp_ptr_expr = get_temp_from_expr ((*code)->expr1, ns); - - /* get_temp_from_expression is set up for ordinary assignments. To that - end, where array bounds are not known, arrays are made allocatable. - Change the temporary to a pointer here. */ - tmp_ptr_expr->symtree->n.sym->attr.pointer = 1; - tmp_ptr_expr->symtree->n.sym->attr.allocatable = 0; - tmp_ptr_expr->where = (*code)->loc; - - this_code = build_assignment (EXEC_ASSIGN, - tmp_ptr_expr, (*code)->expr2, - NULL, NULL, (*code)->loc); - this_code->next = (*code)->next; - (*code)->next = this_code; - (*code)->op = EXEC_POINTER_ASSIGN; - (*code)->expr2 = (*code)->expr1; - (*code)->expr1 = tmp_ptr_expr; - - return true; -} - - -/* Deferred character length assignments from an operator expression - require a temporary because the character length of the lhs can - change in the course of the assignment. */ - -static bool -deferred_op_assign (gfc_code **code, gfc_namespace *ns) -{ - gfc_expr *tmp_expr; - gfc_code *this_code; - - if (!((*code)->expr1->ts.type == BT_CHARACTER - && (*code)->expr1->ts.deferred && (*code)->expr1->rank - && (*code)->expr2->expr_type == EXPR_OP)) - return false; - - if (!gfc_check_dependency ((*code)->expr1, (*code)->expr2, 1)) - return false; - - if (gfc_expr_attr ((*code)->expr1).pointer) - return false; - - tmp_expr = get_temp_from_expr ((*code)->expr1, ns); - tmp_expr->where = (*code)->loc; - - /* A new charlen is required to ensure that the variable string - length is different to that of the original lhs. */ - tmp_expr->ts.u.cl = gfc_get_charlen(); - tmp_expr->symtree->n.sym->ts.u.cl = tmp_expr->ts.u.cl; - tmp_expr->ts.u.cl->next = (*code)->expr2->ts.u.cl->next; - (*code)->expr2->ts.u.cl->next = tmp_expr->ts.u.cl; - - tmp_expr->symtree->n.sym->ts.deferred = 1; - - this_code = build_assignment (EXEC_ASSIGN, - (*code)->expr1, - gfc_copy_expr (tmp_expr), - NULL, NULL, (*code)->loc); - - (*code)->expr1 = tmp_expr; - - this_code->next = (*code)->next; - (*code)->next = this_code; - - return true; -} - - -/* Given a block of code, recursively resolve everything pointed to by this - code block. */ - -void -gfc_resolve_code (gfc_code *code, gfc_namespace *ns) -{ - int omp_workshare_save; - int forall_save, do_concurrent_save; - code_stack frame; - bool t; - - frame.prev = cs_base; - frame.head = code; - cs_base = &frame; - - find_reachable_labels (code); - - for (; code; code = code->next) - { - frame.current = code; - forall_save = forall_flag; - do_concurrent_save = gfc_do_concurrent_flag; - - if (code->op == EXEC_FORALL) - { - forall_flag = 1; - gfc_resolve_forall (code, ns, forall_save); - forall_flag = 2; - } - else if (code->block) - { - omp_workshare_save = -1; - switch (code->op) - { - case EXEC_OACC_PARALLEL_LOOP: - case EXEC_OACC_PARALLEL: - case EXEC_OACC_KERNELS_LOOP: - case EXEC_OACC_KERNELS: - case EXEC_OACC_SERIAL_LOOP: - case EXEC_OACC_SERIAL: - case EXEC_OACC_DATA: - case EXEC_OACC_HOST_DATA: - case EXEC_OACC_LOOP: - gfc_resolve_oacc_blocks (code, ns); - break; - case EXEC_OMP_PARALLEL_WORKSHARE: - omp_workshare_save = omp_workshare_flag; - omp_workshare_flag = 1; - gfc_resolve_omp_parallel_blocks (code, ns); - break; - case EXEC_OMP_DISTRIBUTE_PARALLEL_DO: - case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD: - case EXEC_OMP_PARALLEL: - case EXEC_OMP_PARALLEL_DO: - case EXEC_OMP_PARALLEL_DO_SIMD: - case EXEC_OMP_PARALLEL_MASKED: - case EXEC_OMP_PARALLEL_MASKED_TASKLOOP: - case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD: - case EXEC_OMP_PARALLEL_MASTER: - case EXEC_OMP_PARALLEL_MASTER_TASKLOOP: - case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD: - case EXEC_OMP_PARALLEL_SECTIONS: - case EXEC_OMP_TARGET_PARALLEL: - case EXEC_OMP_TARGET_PARALLEL_DO: - case EXEC_OMP_TARGET_PARALLEL_DO_SIMD: - case EXEC_OMP_TARGET_TEAMS: - case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE: - case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO: - case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: - case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD: - case EXEC_OMP_TASK: - case EXEC_OMP_TASKLOOP: - case EXEC_OMP_TASKLOOP_SIMD: - case EXEC_OMP_TEAMS: - case EXEC_OMP_TEAMS_DISTRIBUTE: - case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO: - case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: - case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD: - omp_workshare_save = omp_workshare_flag; - omp_workshare_flag = 0; - gfc_resolve_omp_parallel_blocks (code, ns); - break; - case EXEC_OMP_DISTRIBUTE: - case EXEC_OMP_DISTRIBUTE_SIMD: - case EXEC_OMP_DO: - case EXEC_OMP_DO_SIMD: - case EXEC_OMP_SIMD: - case EXEC_OMP_TARGET_SIMD: - gfc_resolve_omp_do_blocks (code, ns); - break; - case EXEC_SELECT_TYPE: - case EXEC_SELECT_RANK: - /* Blocks are handled in resolve_select_type/rank because we - have to transform the SELECT TYPE into ASSOCIATE first. */ - break; - case EXEC_DO_CONCURRENT: - gfc_do_concurrent_flag = 1; - gfc_resolve_blocks (code->block, ns); - gfc_do_concurrent_flag = 2; - break; - case EXEC_OMP_WORKSHARE: - omp_workshare_save = omp_workshare_flag; - omp_workshare_flag = 1; - /* FALL THROUGH */ - default: - gfc_resolve_blocks (code->block, ns); - break; - } - - if (omp_workshare_save != -1) - omp_workshare_flag = omp_workshare_save; - } -start: - t = true; - if (code->op != EXEC_COMPCALL && code->op != EXEC_CALL_PPC) - t = gfc_resolve_expr (code->expr1); - forall_flag = forall_save; - gfc_do_concurrent_flag = do_concurrent_save; - - if (!gfc_resolve_expr (code->expr2)) - t = false; - - if (code->op == EXEC_ALLOCATE - && !gfc_resolve_expr (code->expr3)) - t = false; - - switch (code->op) - { - case EXEC_NOP: - case EXEC_END_BLOCK: - case EXEC_END_NESTED_BLOCK: - case EXEC_CYCLE: - case EXEC_PAUSE: - case EXEC_STOP: - case EXEC_ERROR_STOP: - case EXEC_EXIT: - case EXEC_CONTINUE: - case EXEC_DT_END: - case EXEC_ASSIGN_CALL: - break; - - case EXEC_CRITICAL: - resolve_critical (code); - break; - - case EXEC_SYNC_ALL: - case EXEC_SYNC_IMAGES: - case EXEC_SYNC_MEMORY: - resolve_sync (code); - break; - - case EXEC_LOCK: - case EXEC_UNLOCK: - case EXEC_EVENT_POST: - case EXEC_EVENT_WAIT: - resolve_lock_unlock_event (code); - break; - - case EXEC_FAIL_IMAGE: - case EXEC_FORM_TEAM: - case EXEC_CHANGE_TEAM: - case EXEC_END_TEAM: - case EXEC_SYNC_TEAM: - break; - - case EXEC_ENTRY: - /* Keep track of which entry we are up to. */ - current_entry_id = code->ext.entry->id; - break; - - case EXEC_WHERE: - resolve_where (code, NULL); - break; - - case EXEC_GOTO: - if (code->expr1 != NULL) - { - if (code->expr1->expr_type != EXPR_VARIABLE - || code->expr1->ts.type != BT_INTEGER - || (code->expr1->ref - && code->expr1->ref->type == REF_ARRAY) - || code->expr1->symtree == NULL - || (code->expr1->symtree->n.sym - && (code->expr1->symtree->n.sym->attr.flavor - == FL_PARAMETER))) - gfc_error ("ASSIGNED GOTO statement at %L requires a " - "scalar INTEGER variable", &code->expr1->where); - else if (code->expr1->symtree->n.sym - && code->expr1->symtree->n.sym->attr.assign != 1) - gfc_error ("Variable %qs has not been assigned a target " - "label at %L", code->expr1->symtree->n.sym->name, - &code->expr1->where); - } - else - resolve_branch (code->label1, code); - break; - - case EXEC_RETURN: - if (code->expr1 != NULL - && (code->expr1->ts.type != BT_INTEGER || code->expr1->rank)) - gfc_error ("Alternate RETURN statement at %L requires a SCALAR-" - "INTEGER return specifier", &code->expr1->where); - break; - - case EXEC_INIT_ASSIGN: - case EXEC_END_PROCEDURE: - break; - - case EXEC_ASSIGN: - if (!t) - break; - - if (code->expr1->ts.type == BT_CLASS) - gfc_find_vtab (&code->expr2->ts); - - /* Remove a GFC_ISYM_CAF_GET inserted for a coindexed variable on - the LHS. */ - if (code->expr1->expr_type == EXPR_FUNCTION - && code->expr1->value.function.isym - && code->expr1->value.function.isym->id == GFC_ISYM_CAF_GET) - remove_caf_get_intrinsic (code->expr1); - - /* If this is a pointer function in an lvalue variable context, - the new code will have to be resolved afresh. This is also the - case with an error, where the code is transformed into NOP to - prevent ICEs downstream. */ - if (resolve_ptr_fcn_assign (&code, ns) - || code->op == EXEC_NOP) - goto start; - - if (!gfc_check_vardef_context (code->expr1, false, false, false, - _("assignment"))) - break; - - if (resolve_ordinary_assign (code, ns)) - { - if (omp_workshare_flag) - { - gfc_error ("Expected intrinsic assignment in OMP WORKSHARE " - "at %L", &code->loc); - break; - } - if (code->op == EXEC_COMPCALL) - goto compcall; - else - goto call; - } - - /* Check for dependencies in deferred character length array - assignments and generate a temporary, if necessary. */ - if (code->op == EXEC_ASSIGN && deferred_op_assign (&code, ns)) - break; - - /* F03 7.4.1.3 for non-allocatable, non-pointer components. */ - if (code->op != EXEC_CALL && code->expr1->ts.type == BT_DERIVED - && code->expr1->ts.u.derived - && code->expr1->ts.u.derived->attr.defined_assign_comp) - generate_component_assignments (&code, ns); - - break; - - case EXEC_LABEL_ASSIGN: - if (code->label1->defined == ST_LABEL_UNKNOWN) - gfc_error ("Label %d referenced at %L is never defined", - code->label1->value, &code->label1->where); - if (t - && (code->expr1->expr_type != EXPR_VARIABLE - || code->expr1->symtree->n.sym->ts.type != BT_INTEGER - || code->expr1->symtree->n.sym->ts.kind - != gfc_default_integer_kind - || code->expr1->symtree->n.sym->attr.flavor == FL_PARAMETER - || code->expr1->symtree->n.sym->as != NULL)) - gfc_error ("ASSIGN statement at %L requires a scalar " - "default INTEGER variable", &code->expr1->where); - break; - - case EXEC_POINTER_ASSIGN: - { - gfc_expr* e; - - if (!t) - break; - - /* This is both a variable definition and pointer assignment - context, so check both of them. For rank remapping, a final - array ref may be present on the LHS and fool gfc_expr_attr - used in gfc_check_vardef_context. Remove it. */ - e = remove_last_array_ref (code->expr1); - t = gfc_check_vardef_context (e, true, false, false, - _("pointer assignment")); - if (t) - t = gfc_check_vardef_context (e, false, false, false, - _("pointer assignment")); - gfc_free_expr (e); - - t = gfc_check_pointer_assign (code->expr1, code->expr2, !t) && t; - - if (!t) - break; - - /* Assigning a class object always is a regular assign. */ - if (code->expr2->ts.type == BT_CLASS - && code->expr1->ts.type == BT_CLASS - && CLASS_DATA (code->expr2) - && !CLASS_DATA (code->expr2)->attr.dimension - && !(gfc_expr_attr (code->expr1).proc_pointer - && code->expr2->expr_type == EXPR_VARIABLE - && code->expr2->symtree->n.sym->attr.flavor - == FL_PROCEDURE)) - code->op = EXEC_ASSIGN; - break; - } - - case EXEC_ARITHMETIC_IF: - { - gfc_expr *e = code->expr1; - - gfc_resolve_expr (e); - if (e->expr_type == EXPR_NULL) - gfc_error ("Invalid NULL at %L", &e->where); - - if (t && (e->rank > 0 - || !(e->ts.type == BT_REAL || e->ts.type == BT_INTEGER))) - gfc_error ("Arithmetic IF statement at %L requires a scalar " - "REAL or INTEGER expression", &e->where); - - resolve_branch (code->label1, code); - resolve_branch (code->label2, code); - resolve_branch (code->label3, code); - } - break; - - case EXEC_IF: - if (t && code->expr1 != NULL - && (code->expr1->ts.type != BT_LOGICAL - || code->expr1->rank != 0)) - gfc_error ("IF clause at %L requires a scalar LOGICAL expression", - &code->expr1->where); - break; - - case EXEC_CALL: - call: - resolve_call (code); - break; - - case EXEC_COMPCALL: - compcall: - resolve_typebound_subroutine (code); - break; - - case EXEC_CALL_PPC: - resolve_ppc_call (code); - break; - - case EXEC_SELECT: - /* Select is complicated. Also, a SELECT construct could be - a transformed computed GOTO. */ - resolve_select (code, false); - break; - - case EXEC_SELECT_TYPE: - resolve_select_type (code, ns); - break; - - case EXEC_SELECT_RANK: - resolve_select_rank (code, ns); - break; - - case EXEC_BLOCK: - resolve_block_construct (code); - break; - - case EXEC_DO: - if (code->ext.iterator != NULL) - { - gfc_iterator *iter = code->ext.iterator; - if (gfc_resolve_iterator (iter, true, false)) - gfc_resolve_do_iterator (code, iter->var->symtree->n.sym, - true); - } - break; - - case EXEC_DO_WHILE: - if (code->expr1 == NULL) - gfc_internal_error ("gfc_resolve_code(): No expression on " - "DO WHILE"); - if (t - && (code->expr1->rank != 0 - || code->expr1->ts.type != BT_LOGICAL)) - gfc_error ("Exit condition of DO WHILE loop at %L must be " - "a scalar LOGICAL expression", &code->expr1->where); - break; - - case EXEC_ALLOCATE: - if (t) - resolve_allocate_deallocate (code, "ALLOCATE"); - - break; - - case EXEC_DEALLOCATE: - if (t) - resolve_allocate_deallocate (code, "DEALLOCATE"); - - break; - - case EXEC_OPEN: - if (!gfc_resolve_open (code->ext.open, &code->loc)) - break; - - resolve_branch (code->ext.open->err, code); - break; - - case EXEC_CLOSE: - if (!gfc_resolve_close (code->ext.close, &code->loc)) - break; - - resolve_branch (code->ext.close->err, code); - break; - - case EXEC_BACKSPACE: - case EXEC_ENDFILE: - case EXEC_REWIND: - case EXEC_FLUSH: - if (!gfc_resolve_filepos (code->ext.filepos, &code->loc)) - break; - - resolve_branch (code->ext.filepos->err, code); - break; - - case EXEC_INQUIRE: - if (!gfc_resolve_inquire (code->ext.inquire)) - break; - - resolve_branch (code->ext.inquire->err, code); - break; - - case EXEC_IOLENGTH: - gcc_assert (code->ext.inquire != NULL); - if (!gfc_resolve_inquire (code->ext.inquire)) - break; - - resolve_branch (code->ext.inquire->err, code); - break; - - case EXEC_WAIT: - if (!gfc_resolve_wait (code->ext.wait)) - break; - - resolve_branch (code->ext.wait->err, code); - resolve_branch (code->ext.wait->end, code); - resolve_branch (code->ext.wait->eor, code); - break; - - case EXEC_READ: - case EXEC_WRITE: - if (!gfc_resolve_dt (code, code->ext.dt, &code->loc)) - break; - - resolve_branch (code->ext.dt->err, code); - resolve_branch (code->ext.dt->end, code); - resolve_branch (code->ext.dt->eor, code); - break; - - case EXEC_TRANSFER: - resolve_transfer (code); - break; - - case EXEC_DO_CONCURRENT: - case EXEC_FORALL: - resolve_forall_iterators (code->ext.forall_iterator); - - if (code->expr1 != NULL - && (code->expr1->ts.type != BT_LOGICAL || code->expr1->rank)) - gfc_error ("FORALL mask clause at %L requires a scalar LOGICAL " - "expression", &code->expr1->where); - break; - - case EXEC_OACC_PARALLEL_LOOP: - case EXEC_OACC_PARALLEL: - case EXEC_OACC_KERNELS_LOOP: - case EXEC_OACC_KERNELS: - case EXEC_OACC_SERIAL_LOOP: - case EXEC_OACC_SERIAL: - case EXEC_OACC_DATA: - case EXEC_OACC_HOST_DATA: - case EXEC_OACC_LOOP: - case EXEC_OACC_UPDATE: - case EXEC_OACC_WAIT: - case EXEC_OACC_CACHE: - case EXEC_OACC_ENTER_DATA: - case EXEC_OACC_EXIT_DATA: - case EXEC_OACC_ATOMIC: - case EXEC_OACC_DECLARE: - gfc_resolve_oacc_directive (code, ns); - break; - - case EXEC_OMP_ATOMIC: - case EXEC_OMP_BARRIER: - case EXEC_OMP_CANCEL: - case EXEC_OMP_CANCELLATION_POINT: - case EXEC_OMP_CRITICAL: - case EXEC_OMP_FLUSH: - case EXEC_OMP_DEPOBJ: - case EXEC_OMP_DISTRIBUTE: - case EXEC_OMP_DISTRIBUTE_PARALLEL_DO: - case EXEC_OMP_DISTRIBUTE_PARALLEL_DO_SIMD: - case EXEC_OMP_DISTRIBUTE_SIMD: - case EXEC_OMP_DO: - case EXEC_OMP_DO_SIMD: - case EXEC_OMP_ERROR: - case EXEC_OMP_LOOP: - case EXEC_OMP_MASTER: - case EXEC_OMP_MASTER_TASKLOOP: - case EXEC_OMP_MASTER_TASKLOOP_SIMD: - case EXEC_OMP_MASKED: - case EXEC_OMP_MASKED_TASKLOOP: - case EXEC_OMP_MASKED_TASKLOOP_SIMD: - case EXEC_OMP_ORDERED: - case EXEC_OMP_SCAN: - case EXEC_OMP_SCOPE: - case EXEC_OMP_SECTIONS: - case EXEC_OMP_SIMD: - case EXEC_OMP_SINGLE: - case EXEC_OMP_TARGET: - case EXEC_OMP_TARGET_DATA: - case EXEC_OMP_TARGET_ENTER_DATA: - case EXEC_OMP_TARGET_EXIT_DATA: - case EXEC_OMP_TARGET_PARALLEL: - case EXEC_OMP_TARGET_PARALLEL_DO: - case EXEC_OMP_TARGET_PARALLEL_DO_SIMD: - case EXEC_OMP_TARGET_PARALLEL_LOOP: - case EXEC_OMP_TARGET_SIMD: - case EXEC_OMP_TARGET_TEAMS: - case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE: - case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO: - case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: - case EXEC_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD: - case EXEC_OMP_TARGET_TEAMS_LOOP: - case EXEC_OMP_TARGET_UPDATE: - case EXEC_OMP_TASK: - case EXEC_OMP_TASKGROUP: - case EXEC_OMP_TASKLOOP: - case EXEC_OMP_TASKLOOP_SIMD: - case EXEC_OMP_TASKWAIT: - case EXEC_OMP_TASKYIELD: - case EXEC_OMP_TEAMS: - case EXEC_OMP_TEAMS_DISTRIBUTE: - case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO: - case EXEC_OMP_TEAMS_DISTRIBUTE_PARALLEL_DO_SIMD: - case EXEC_OMP_TEAMS_DISTRIBUTE_SIMD: - case EXEC_OMP_TEAMS_LOOP: - case EXEC_OMP_WORKSHARE: - gfc_resolve_omp_directive (code, ns); - break; - - case EXEC_OMP_PARALLEL: - case EXEC_OMP_PARALLEL_DO: - case EXEC_OMP_PARALLEL_DO_SIMD: - case EXEC_OMP_PARALLEL_LOOP: - case EXEC_OMP_PARALLEL_MASKED: - case EXEC_OMP_PARALLEL_MASKED_TASKLOOP: - case EXEC_OMP_PARALLEL_MASKED_TASKLOOP_SIMD: - case EXEC_OMP_PARALLEL_MASTER: - case EXEC_OMP_PARALLEL_MASTER_TASKLOOP: - case EXEC_OMP_PARALLEL_MASTER_TASKLOOP_SIMD: - case EXEC_OMP_PARALLEL_SECTIONS: - case EXEC_OMP_PARALLEL_WORKSHARE: - omp_workshare_save = omp_workshare_flag; - omp_workshare_flag = 0; - gfc_resolve_omp_directive (code, ns); - omp_workshare_flag = omp_workshare_save; - break; - - default: - gfc_internal_error ("gfc_resolve_code(): Bad statement code"); - } - } - - cs_base = frame.prev; -} - - -/* Resolve initial values and make sure they are compatible with - the variable. */ - -static void -resolve_values (gfc_symbol *sym) -{ - bool t; - - if (sym->value == NULL) - return; - - if (sym->attr.ext_attr & (1 << EXT_ATTR_DEPRECATED) && sym->attr.referenced) - gfc_warning (OPT_Wdeprecated_declarations, - "Using parameter %qs declared at %L is deprecated", - sym->name, &sym->declared_at); - - if (sym->value->expr_type == EXPR_STRUCTURE) - t= resolve_structure_cons (sym->value, 1); - else - t = gfc_resolve_expr (sym->value); - - if (!t) - return; - - gfc_check_assign_symbol (sym, NULL, sym->value); -} - - -/* Verify any BIND(C) derived types in the namespace so we can report errors - for them once, rather than for each variable declared of that type. */ - -static void -resolve_bind_c_derived_types (gfc_symbol *derived_sym) -{ - if (derived_sym != NULL && derived_sym->attr.flavor == FL_DERIVED - && derived_sym->attr.is_bind_c == 1) - verify_bind_c_derived_type (derived_sym); - - return; -} - - -/* Check the interfaces of DTIO procedures associated with derived - type 'sym'. These procedures can either have typebound bindings or - can appear in DTIO generic interfaces. */ - -static void -gfc_verify_DTIO_procedures (gfc_symbol *sym) -{ - if (!sym || sym->attr.flavor != FL_DERIVED) - return; - - gfc_check_dtio_interfaces (sym); - - return; -} - -/* Verify that any binding labels used in a given namespace do not collide - with the names or binding labels of any global symbols. Multiple INTERFACE - for the same procedure are permitted. */ - -static void -gfc_verify_binding_labels (gfc_symbol *sym) -{ - gfc_gsymbol *gsym; - const char *module; - - if (!sym || !sym->attr.is_bind_c || sym->attr.is_iso_c - || sym->attr.flavor == FL_DERIVED || !sym->binding_label) - return; - - gsym = gfc_find_case_gsymbol (gfc_gsym_root, sym->binding_label); - - if (sym->module) - module = sym->module; - else if (sym->ns && sym->ns->proc_name - && sym->ns->proc_name->attr.flavor == FL_MODULE) - module = sym->ns->proc_name->name; - else if (sym->ns && sym->ns->parent - && sym->ns && sym->ns->parent->proc_name - && sym->ns->parent->proc_name->attr.flavor == FL_MODULE) - module = sym->ns->parent->proc_name->name; - else - module = NULL; - - if (!gsym - || (!gsym->defined - && (gsym->type == GSYM_FUNCTION || gsym->type == GSYM_SUBROUTINE))) - { - if (!gsym) - gsym = gfc_get_gsymbol (sym->binding_label, true); - gsym->where = sym->declared_at; - gsym->sym_name = sym->name; - gsym->binding_label = sym->binding_label; - gsym->ns = sym->ns; - gsym->mod_name = module; - if (sym->attr.function) - gsym->type = GSYM_FUNCTION; - else if (sym->attr.subroutine) - gsym->type = GSYM_SUBROUTINE; - /* Mark as variable/procedure as defined, unless its an INTERFACE. */ - gsym->defined = sym->attr.if_source != IFSRC_IFBODY; - return; - } - - if (sym->attr.flavor == FL_VARIABLE && gsym->type != GSYM_UNKNOWN) - { - gfc_error ("Variable %qs with binding label %qs at %L uses the same global " - "identifier as entity at %L", sym->name, - sym->binding_label, &sym->declared_at, &gsym->where); - /* Clear the binding label to prevent checking multiple times. */ - sym->binding_label = NULL; - return; - } - - if (sym->attr.flavor == FL_VARIABLE && module - && (strcmp (module, gsym->mod_name) != 0 - || strcmp (sym->name, gsym->sym_name) != 0)) - { - /* This can only happen if the variable is defined in a module - if it - isn't the same module, reject it. */ - gfc_error ("Variable %qs from module %qs with binding label %qs at %L " - "uses the same global identifier as entity at %L from module %qs", - sym->name, module, sym->binding_label, - &sym->declared_at, &gsym->where, gsym->mod_name); - sym->binding_label = NULL; - return; - } - - if ((sym->attr.function || sym->attr.subroutine) - && ((gsym->type != GSYM_SUBROUTINE && gsym->type != GSYM_FUNCTION) - || (gsym->defined && sym->attr.if_source != IFSRC_IFBODY)) - && (sym != gsym->ns->proc_name && sym->attr.entry == 0) - && (module != gsym->mod_name - || strcmp (gsym->sym_name, sym->name) != 0 - || (module && strcmp (module, gsym->mod_name) != 0))) - { - /* Print an error if the procedure is defined multiple times; we have to - exclude references to the same procedure via module association or - multiple checks for the same procedure. */ - gfc_error ("Procedure %qs with binding label %qs at %L uses the same " - "global identifier as entity at %L", sym->name, - sym->binding_label, &sym->declared_at, &gsym->where); - sym->binding_label = NULL; - } -} - - -/* Resolve an index expression. */ - -static bool -resolve_index_expr (gfc_expr *e) -{ - if (!gfc_resolve_expr (e)) - return false; - - if (!gfc_simplify_expr (e, 0)) - return false; - - if (!gfc_specification_expr (e)) - return false; - - return true; -} - - -/* Resolve a charlen structure. */ - -static bool -resolve_charlen (gfc_charlen *cl) -{ - int k; - bool saved_specification_expr; - - if (cl->resolved) - return true; - - cl->resolved = 1; - saved_specification_expr = specification_expr; - specification_expr = true; - - if (cl->length_from_typespec) - { - if (!gfc_resolve_expr (cl->length)) - { - specification_expr = saved_specification_expr; - return false; - } - - if (!gfc_simplify_expr (cl->length, 0)) - { - specification_expr = saved_specification_expr; - return false; - } - - /* cl->length has been resolved. It should have an integer type. */ - if (cl->length - && (cl->length->ts.type != BT_INTEGER || cl->length->rank != 0)) - { - gfc_error ("Scalar INTEGER expression expected at %L", - &cl->length->where); - return false; - } - } - else - { - if (!resolve_index_expr (cl->length)) - { - specification_expr = saved_specification_expr; - return false; - } - } - - /* F2008, 4.4.3.2: If the character length parameter value evaluates to - a negative value, the length of character entities declared is zero. */ - if (cl->length && cl->length->expr_type == EXPR_CONSTANT - && mpz_sgn (cl->length->value.integer) < 0) - gfc_replace_expr (cl->length, - gfc_get_int_expr (gfc_charlen_int_kind, NULL, 0)); - - /* Check that the character length is not too large. */ - k = gfc_validate_kind (BT_INTEGER, gfc_charlen_int_kind, false); - if (cl->length && cl->length->expr_type == EXPR_CONSTANT - && cl->length->ts.type == BT_INTEGER - && mpz_cmp (cl->length->value.integer, gfc_integer_kinds[k].huge) > 0) - { - gfc_error ("String length at %L is too large", &cl->length->where); - specification_expr = saved_specification_expr; - return false; - } - - specification_expr = saved_specification_expr; - return true; -} - - -/* Test for non-constant shape arrays. */ - -static bool -is_non_constant_shape_array (gfc_symbol *sym) -{ - gfc_expr *e; - int i; - bool not_constant; - - not_constant = false; - if (sym->as != NULL) - { - /* Unfortunately, !gfc_is_compile_time_shape hits a legal case that - has not been simplified; parameter array references. Do the - simplification now. */ - for (i = 0; i < sym->as->rank + sym->as->corank; i++) - { - if (i == GFC_MAX_DIMENSIONS) - break; - - e = sym->as->lower[i]; - if (e && (!resolve_index_expr(e) - || !gfc_is_constant_expr (e))) - not_constant = true; - e = sym->as->upper[i]; - if (e && (!resolve_index_expr(e) - || !gfc_is_constant_expr (e))) - not_constant = true; - } - } - return not_constant; -} - -/* Given a symbol and an initialization expression, add code to initialize - the symbol to the function entry. */ -static void -build_init_assign (gfc_symbol *sym, gfc_expr *init) -{ - gfc_expr *lval; - gfc_code *init_st; - gfc_namespace *ns = sym->ns; - - /* Search for the function namespace if this is a contained - function without an explicit result. */ - if (sym->attr.function && sym == sym->result - && sym->name != sym->ns->proc_name->name) - { - ns = ns->contained; - for (;ns; ns = ns->sibling) - if (strcmp (ns->proc_name->name, sym->name) == 0) - break; - } - - if (ns == NULL) - { - gfc_free_expr (init); - return; - } - - /* Build an l-value expression for the result. */ - lval = gfc_lval_expr_from_sym (sym); - - /* Add the code at scope entry. */ - init_st = gfc_get_code (EXEC_INIT_ASSIGN); - init_st->next = ns->code; - ns->code = init_st; - - /* Assign the default initializer to the l-value. */ - init_st->loc = sym->declared_at; - init_st->expr1 = lval; - init_st->expr2 = init; -} - - -/* Whether or not we can generate a default initializer for a symbol. */ - -static bool -can_generate_init (gfc_symbol *sym) -{ - symbol_attribute *a; - if (!sym) - return false; - a = &sym->attr; - - /* These symbols should never have a default initialization. */ - return !( - a->allocatable - || a->external - || a->pointer - || (sym->ts.type == BT_CLASS && CLASS_DATA (sym) - && (CLASS_DATA (sym)->attr.class_pointer - || CLASS_DATA (sym)->attr.proc_pointer)) - || a->in_equivalence - || a->in_common - || a->data - || sym->module - || a->cray_pointee - || a->cray_pointer - || sym->assoc - || (!a->referenced && !a->result) - || (a->dummy && (a->intent != INTENT_OUT - || sym->ns->proc_name->attr.if_source == IFSRC_IFBODY)) - || (a->function && sym != sym->result) - ); -} - - -/* Assign the default initializer to a derived type variable or result. */ - -static void -apply_default_init (gfc_symbol *sym) -{ - gfc_expr *init = NULL; - - if (sym->attr.flavor != FL_VARIABLE && !sym->attr.function) - return; - - if (sym->ts.type == BT_DERIVED && sym->ts.u.derived) - init = gfc_generate_initializer (&sym->ts, can_generate_init (sym)); - - if (init == NULL && sym->ts.type != BT_CLASS) - return; - - build_init_assign (sym, init); - sym->attr.referenced = 1; -} - - -/* Build an initializer for a local. Returns null if the symbol should not have - a default initialization. */ - -static gfc_expr * -build_default_init_expr (gfc_symbol *sym) -{ - /* These symbols should never have a default initialization. */ - if (sym->attr.allocatable - || sym->attr.external - || sym->attr.dummy - || sym->attr.pointer - || sym->attr.in_equivalence - || sym->attr.in_common - || sym->attr.data - || sym->module - || sym->attr.cray_pointee - || sym->attr.cray_pointer - || sym->assoc) - return NULL; - - /* Get the appropriate init expression. */ - return gfc_build_default_init_expr (&sym->ts, &sym->declared_at); -} - -/* Add an initialization expression to a local variable. */ -static void -apply_default_init_local (gfc_symbol *sym) -{ - gfc_expr *init = NULL; - - /* The symbol should be a variable or a function return value. */ - if ((sym->attr.flavor != FL_VARIABLE && !sym->attr.function) - || (sym->attr.function && sym->result != sym)) - return; - - /* Try to build the initializer expression. If we can't initialize - this symbol, then init will be NULL. */ - init = build_default_init_expr (sym); - if (init == NULL) - return; - - /* For saved variables, we don't want to add an initializer at function - entry, so we just add a static initializer. Note that automatic variables - are stack allocated even with -fno-automatic; we have also to exclude - result variable, which are also nonstatic. */ - if (!sym->attr.automatic - && (sym->attr.save || sym->ns->save_all - || (flag_max_stack_var_size == 0 && !sym->attr.result - && (sym->ns->proc_name && !sym->ns->proc_name->attr.recursive) - && (!sym->attr.dimension || !is_non_constant_shape_array (sym))))) - { - /* Don't clobber an existing initializer! */ - gcc_assert (sym->value == NULL); - sym->value = init; - return; - } - - build_init_assign (sym, init); -} - - -/* Resolution of common features of flavors variable and procedure. */ - -static bool -resolve_fl_var_and_proc (gfc_symbol *sym, int mp_flag) -{ - gfc_array_spec *as; - - if (sym->ts.type == BT_CLASS && sym->attr.class_ok - && sym->ts.u.derived && CLASS_DATA (sym)) - as = CLASS_DATA (sym)->as; - else - as = sym->as; - - /* Constraints on deferred shape variable. */ - if (as == NULL || as->type != AS_DEFERRED) - { - bool pointer, allocatable, dimension; - - if (sym->ts.type == BT_CLASS && sym->attr.class_ok - && sym->ts.u.derived && CLASS_DATA (sym)) - { - pointer = CLASS_DATA (sym)->attr.class_pointer; - allocatable = CLASS_DATA (sym)->attr.allocatable; - dimension = CLASS_DATA (sym)->attr.dimension; - } - else - { - pointer = sym->attr.pointer && !sym->attr.select_type_temporary; - allocatable = sym->attr.allocatable; - dimension = sym->attr.dimension; - } - - if (allocatable) - { - if (dimension && as->type != AS_ASSUMED_RANK) - { - gfc_error ("Allocatable array %qs at %L must have a deferred " - "shape or assumed rank", sym->name, &sym->declared_at); - return false; - } - else if (!gfc_notify_std (GFC_STD_F2003, "Scalar object " - "%qs at %L may not be ALLOCATABLE", - sym->name, &sym->declared_at)) - return false; - } - - if (pointer && dimension && as->type != AS_ASSUMED_RANK) - { - gfc_error ("Array pointer %qs at %L must have a deferred shape or " - "assumed rank", sym->name, &sym->declared_at); - sym->error = 1; - return false; - } - } - else - { - if (!mp_flag && !sym->attr.allocatable && !sym->attr.pointer - && sym->ts.type != BT_CLASS && !sym->assoc) - { - gfc_error ("Array %qs at %L cannot have a deferred shape", - sym->name, &sym->declared_at); - return false; - } - } - - /* Constraints on polymorphic variables. */ - if (sym->ts.type == BT_CLASS && !(sym->result && sym->result != sym)) - { - /* F03:C502. */ - if (sym->attr.class_ok - && sym->ts.u.derived - && !sym->attr.select_type_temporary - && !UNLIMITED_POLY (sym) - && !gfc_type_is_extensible (CLASS_DATA (sym)->ts.u.derived)) - { - gfc_error ("Type %qs of CLASS variable %qs at %L is not extensible", - CLASS_DATA (sym)->ts.u.derived->name, sym->name, - &sym->declared_at); - return false; - } - - /* F03:C509. */ - /* Assume that use associated symbols were checked in the module ns. - Class-variables that are associate-names are also something special - and excepted from the test. */ - if (!sym->attr.class_ok && !sym->attr.use_assoc && !sym->assoc) - { - gfc_error ("CLASS variable %qs at %L must be dummy, allocatable " - "or pointer", sym->name, &sym->declared_at); - return false; - } - } - - return true; -} - - -/* Additional checks for symbols with flavor variable and derived - type. To be called from resolve_fl_variable. */ - -static bool -resolve_fl_variable_derived (gfc_symbol *sym, int no_init_flag) -{ - gcc_assert (sym->ts.type == BT_DERIVED || sym->ts.type == BT_CLASS); - - /* Check to see if a derived type is blocked from being host - associated by the presence of another class I symbol in the same - namespace. 14.6.1.3 of the standard and the discussion on - comp.lang.fortran. */ - if (sym->ts.u.derived - && sym->ns != sym->ts.u.derived->ns - && !sym->ts.u.derived->attr.use_assoc - && sym->ns->proc_name->attr.if_source != IFSRC_IFBODY) - { - gfc_symbol *s; - gfc_find_symbol (sym->ts.u.derived->name, sym->ns, 0, &s); - if (s && s->attr.generic) - s = gfc_find_dt_in_generic (s); - if (s && !gfc_fl_struct (s->attr.flavor)) - { - gfc_error ("The type %qs cannot be host associated at %L " - "because it is blocked by an incompatible object " - "of the same name declared at %L", - sym->ts.u.derived->name, &sym->declared_at, - &s->declared_at); - return false; - } - } - - /* 4th constraint in section 11.3: "If an object of a type for which - component-initialization is specified (R429) appears in the - specification-part of a module and does not have the ALLOCATABLE - or POINTER attribute, the object shall have the SAVE attribute." - - The check for initializers is performed with - gfc_has_default_initializer because gfc_default_initializer generates - a hidden default for allocatable components. */ - if (!(sym->value || no_init_flag) && sym->ns->proc_name - && sym->ns->proc_name->attr.flavor == FL_MODULE - && !(sym->ns->save_all && !sym->attr.automatic) && !sym->attr.save - && !sym->attr.pointer && !sym->attr.allocatable - && gfc_has_default_initializer (sym->ts.u.derived) - && !gfc_notify_std (GFC_STD_F2008, "Implied SAVE for module variable " - "%qs at %L, needed due to the default " - "initialization", sym->name, &sym->declared_at)) - return false; - - /* Assign default initializer. */ - if (!(sym->value || sym->attr.pointer || sym->attr.allocatable) - && (!no_init_flag - || (sym->attr.intent == INTENT_OUT - && sym->ns->proc_name->attr.if_source != IFSRC_IFBODY))) - sym->value = gfc_generate_initializer (&sym->ts, can_generate_init (sym)); - - return true; -} - - -/* F2008, C402 (R401): A colon shall not be used as a type-param-value - except in the declaration of an entity or component that has the POINTER - or ALLOCATABLE attribute. */ - -static bool -deferred_requirements (gfc_symbol *sym) -{ - if (sym->ts.deferred - && !(sym->attr.pointer - || sym->attr.allocatable - || sym->attr.associate_var - || sym->attr.omp_udr_artificial_var)) - { - /* If a function has a result variable, only check the variable. */ - if (sym->result && sym->name != sym->result->name) - return true; - - gfc_error ("Entity %qs at %L has a deferred type parameter and " - "requires either the POINTER or ALLOCATABLE attribute", - sym->name, &sym->declared_at); - return false; - } - return true; -} - - -/* Resolve symbols with flavor variable. */ - -static bool -resolve_fl_variable (gfc_symbol *sym, int mp_flag) -{ - const char *auto_save_msg = "Automatic object %qs at %L cannot have the " - "SAVE attribute"; - - if (!resolve_fl_var_and_proc (sym, mp_flag)) - return false; - - /* Set this flag to check that variables are parameters of all entries. - This check is effected by the call to gfc_resolve_expr through - is_non_constant_shape_array. */ - bool saved_specification_expr = specification_expr; - specification_expr = true; - - if (sym->ns->proc_name - && (sym->ns->proc_name->attr.flavor == FL_MODULE - || sym->ns->proc_name->attr.is_main_program) - && !sym->attr.use_assoc - && !sym->attr.allocatable - && !sym->attr.pointer - && is_non_constant_shape_array (sym)) - { - /* F08:C541. The shape of an array defined in a main program or module - * needs to be constant. */ - gfc_error ("The module or main program array %qs at %L must " - "have constant shape", sym->name, &sym->declared_at); - specification_expr = saved_specification_expr; - return false; - } - - /* Constraints on deferred type parameter. */ - if (!deferred_requirements (sym)) - return false; - - if (sym->ts.type == BT_CHARACTER && !sym->attr.associate_var) - { - /* Make sure that character string variables with assumed length are - dummy arguments. */ - gfc_expr *e = NULL; - - if (sym->ts.u.cl) - e = sym->ts.u.cl->length; - else - return false; - - if (e == NULL && !sym->attr.dummy && !sym->attr.result - && !sym->ts.deferred && !sym->attr.select_type_temporary - && !sym->attr.omp_udr_artificial_var) - { - gfc_error ("Entity with assumed character length at %L must be a " - "dummy argument or a PARAMETER", &sym->declared_at); - specification_expr = saved_specification_expr; - return false; - } - - if (e && sym->attr.save == SAVE_EXPLICIT && !gfc_is_constant_expr (e)) - { - gfc_error (auto_save_msg, sym->name, &sym->declared_at); - specification_expr = saved_specification_expr; - return false; - } - - if (!gfc_is_constant_expr (e) - && !(e->expr_type == EXPR_VARIABLE - && e->symtree->n.sym->attr.flavor == FL_PARAMETER)) - { - if (!sym->attr.use_assoc && sym->ns->proc_name - && (sym->ns->proc_name->attr.flavor == FL_MODULE - || sym->ns->proc_name->attr.is_main_program)) - { - gfc_error ("%qs at %L must have constant character length " - "in this context", sym->name, &sym->declared_at); - specification_expr = saved_specification_expr; - return false; - } - if (sym->attr.in_common) - { - gfc_error ("COMMON variable %qs at %L must have constant " - "character length", sym->name, &sym->declared_at); - specification_expr = saved_specification_expr; - return false; - } - } - } - - if (sym->value == NULL && sym->attr.referenced) - apply_default_init_local (sym); /* Try to apply a default initialization. */ - - /* Determine if the symbol may not have an initializer. */ - int no_init_flag = 0, automatic_flag = 0; - if (sym->attr.allocatable || sym->attr.external || sym->attr.dummy - || sym->attr.intrinsic || sym->attr.result) - no_init_flag = 1; - else if ((sym->attr.dimension || sym->attr.codimension) && !sym->attr.pointer - && is_non_constant_shape_array (sym)) - { - no_init_flag = automatic_flag = 1; - - /* Also, they must not have the SAVE attribute. - SAVE_IMPLICIT is checked below. */ - if (sym->as && sym->attr.codimension) - { - int corank = sym->as->corank; - sym->as->corank = 0; - no_init_flag = automatic_flag = is_non_constant_shape_array (sym); - sym->as->corank = corank; - } - if (automatic_flag && sym->attr.save == SAVE_EXPLICIT) - { - gfc_error (auto_save_msg, sym->name, &sym->declared_at); - specification_expr = saved_specification_expr; - return false; - } - } - - /* Ensure that any initializer is simplified. */ - if (sym->value) - gfc_simplify_expr (sym->value, 1); - - /* Reject illegal initializers. */ - if (!sym->mark && sym->value) - { - if (sym->attr.allocatable || (sym->ts.type == BT_CLASS - && CLASS_DATA (sym)->attr.allocatable)) - gfc_error ("Allocatable %qs at %L cannot have an initializer", - sym->name, &sym->declared_at); - else if (sym->attr.external) - gfc_error ("External %qs at %L cannot have an initializer", - sym->name, &sym->declared_at); - else if (sym->attr.dummy) - gfc_error ("Dummy %qs at %L cannot have an initializer", - sym->name, &sym->declared_at); - else if (sym->attr.intrinsic) - gfc_error ("Intrinsic %qs at %L cannot have an initializer", - sym->name, &sym->declared_at); - else if (sym->attr.result) - gfc_error ("Function result %qs at %L cannot have an initializer", - sym->name, &sym->declared_at); - else if (automatic_flag) - gfc_error ("Automatic array %qs at %L cannot have an initializer", - sym->name, &sym->declared_at); - else - goto no_init_error; - specification_expr = saved_specification_expr; - return false; - } - -no_init_error: - if (sym->ts.type == BT_DERIVED || sym->ts.type == BT_CLASS) - { - bool res = resolve_fl_variable_derived (sym, no_init_flag); - specification_expr = saved_specification_expr; - return res; - } - - specification_expr = saved_specification_expr; - return true; -} - - -/* Compare the dummy characteristics of a module procedure interface - declaration with the corresponding declaration in a submodule. */ -static gfc_formal_arglist *new_formal; -static char errmsg[200]; - -static void -compare_fsyms (gfc_symbol *sym) -{ - gfc_symbol *fsym; - - if (sym == NULL || new_formal == NULL) - return; - - fsym = new_formal->sym; - - if (sym == fsym) - return; - - if (strcmp (sym->name, fsym->name) == 0) - { - if (!gfc_check_dummy_characteristics (fsym, sym, true, errmsg, 200)) - gfc_error ("%s at %L", errmsg, &fsym->declared_at); - } -} - - -/* Resolve a procedure. */ - -static bool -resolve_fl_procedure (gfc_symbol *sym, int mp_flag) -{ - gfc_formal_arglist *arg; - bool allocatable_or_pointer = false; - - if (sym->attr.function - && !resolve_fl_var_and_proc (sym, mp_flag)) - return false; - - /* Constraints on deferred type parameter. */ - if (!deferred_requirements (sym)) - return false; - - if (sym->ts.type == BT_CHARACTER) - { - gfc_charlen *cl = sym->ts.u.cl; - - if (cl && cl->length && gfc_is_constant_expr (cl->length) - && !resolve_charlen (cl)) - return false; - - if ((!cl || !cl->length || cl->length->expr_type != EXPR_CONSTANT) - && sym->attr.proc == PROC_ST_FUNCTION) - { - gfc_error ("Character-valued statement function %qs at %L must " - "have constant length", sym->name, &sym->declared_at); - return false; - } - } - - /* Ensure that derived type for are not of a private type. Internal - module procedures are excluded by 2.2.3.3 - i.e., they are not - externally accessible and can access all the objects accessible in - the host. */ - if (!(sym->ns->parent && sym->ns->parent->proc_name - && sym->ns->parent->proc_name->attr.flavor == FL_MODULE) - && gfc_check_symbol_access (sym)) - { - gfc_interface *iface; - - for (arg = gfc_sym_get_dummy_args (sym); arg; arg = arg->next) - { - if (arg->sym - && arg->sym->ts.type == BT_DERIVED - && arg->sym->ts.u.derived - && !arg->sym->ts.u.derived->attr.use_assoc - && !gfc_check_symbol_access (arg->sym->ts.u.derived) - && !gfc_notify_std (GFC_STD_F2003, "%qs is of a PRIVATE type " - "and cannot be a dummy argument" - " of %qs, which is PUBLIC at %L", - arg->sym->name, sym->name, - &sym->declared_at)) - { - /* Stop this message from recurring. */ - arg->sym->ts.u.derived->attr.access = ACCESS_PUBLIC; - return false; - } - } - - /* PUBLIC interfaces may expose PRIVATE procedures that take types - PRIVATE to the containing module. */ - for (iface = sym->generic; iface; iface = iface->next) - { - for (arg = gfc_sym_get_dummy_args (iface->sym); arg; arg = arg->next) - { - if (arg->sym - && arg->sym->ts.type == BT_DERIVED - && !arg->sym->ts.u.derived->attr.use_assoc - && !gfc_check_symbol_access (arg->sym->ts.u.derived) - && !gfc_notify_std (GFC_STD_F2003, "Procedure %qs in " - "PUBLIC interface %qs at %L " - "takes dummy arguments of %qs which " - "is PRIVATE", iface->sym->name, - sym->name, &iface->sym->declared_at, - gfc_typename(&arg->sym->ts))) - { - /* Stop this message from recurring. */ - arg->sym->ts.u.derived->attr.access = ACCESS_PUBLIC; - return false; - } - } - } - } - - if (sym->attr.function && sym->value && sym->attr.proc != PROC_ST_FUNCTION - && !sym->attr.proc_pointer) - { - gfc_error ("Function %qs at %L cannot have an initializer", - sym->name, &sym->declared_at); - - /* Make sure no second error is issued for this. */ - sym->value->error = 1; - return false; - } - - /* An external symbol may not have an initializer because it is taken to be - a procedure. Exception: Procedure Pointers. */ - if (sym->attr.external && sym->value && !sym->attr.proc_pointer) - { - gfc_error ("External object %qs at %L may not have an initializer", - sym->name, &sym->declared_at); - return false; - } - - /* An elemental function is required to return a scalar 12.7.1 */ - if (sym->attr.elemental && sym->attr.function - && (sym->as || (sym->ts.type == BT_CLASS && sym->attr.class_ok - && CLASS_DATA (sym)->as))) - { - gfc_error ("ELEMENTAL function %qs at %L must have a scalar " - "result", sym->name, &sym->declared_at); - /* Reset so that the error only occurs once. */ - sym->attr.elemental = 0; - return false; - } - - if (sym->attr.proc == PROC_ST_FUNCTION - && (sym->attr.allocatable || sym->attr.pointer)) - { - gfc_error ("Statement function %qs at %L may not have pointer or " - "allocatable attribute", sym->name, &sym->declared_at); - return false; - } - - /* 5.1.1.5 of the Standard: A function name declared with an asterisk - char-len-param shall not be array-valued, pointer-valued, recursive - or pure. ....snip... A character value of * may only be used in the - following ways: (i) Dummy arg of procedure - dummy associates with - actual length; (ii) To declare a named constant; or (iii) External - function - but length must be declared in calling scoping unit. */ - if (sym->attr.function - && sym->ts.type == BT_CHARACTER && !sym->ts.deferred - && sym->ts.u.cl && sym->ts.u.cl->length == NULL) - { - if ((sym->as && sym->as->rank) || (sym->attr.pointer) - || (sym->attr.recursive) || (sym->attr.pure)) - { - if (sym->as && sym->as->rank) - gfc_error ("CHARACTER(*) function %qs at %L cannot be " - "array-valued", sym->name, &sym->declared_at); - - if (sym->attr.pointer) - gfc_error ("CHARACTER(*) function %qs at %L cannot be " - "pointer-valued", sym->name, &sym->declared_at); - - if (sym->attr.pure) - gfc_error ("CHARACTER(*) function %qs at %L cannot be " - "pure", sym->name, &sym->declared_at); - - if (sym->attr.recursive) - gfc_error ("CHARACTER(*) function %qs at %L cannot be " - "recursive", sym->name, &sym->declared_at); - - return false; - } - - /* Appendix B.2 of the standard. Contained functions give an - error anyway. Deferred character length is an F2003 feature. - Don't warn on intrinsic conversion functions, which start - with two underscores. */ - if (!sym->attr.contained && !sym->ts.deferred - && (sym->name[0] != '_' || sym->name[1] != '_')) - gfc_notify_std (GFC_STD_F95_OBS, - "CHARACTER(*) function %qs at %L", - sym->name, &sym->declared_at); - } - - /* F2008, C1218. */ - if (sym->attr.elemental) - { - if (sym->attr.proc_pointer) - { - const char* name = (sym->attr.result ? sym->ns->proc_name->name - : sym->name); - gfc_error ("Procedure pointer %qs at %L shall not be elemental", - name, &sym->declared_at); - return false; - } - if (sym->attr.dummy) - { - gfc_error ("Dummy procedure %qs at %L shall not be elemental", - sym->name, &sym->declared_at); - return false; - } - } - - /* F2018, C15100: "The result of an elemental function shall be scalar, - and shall not have the POINTER or ALLOCATABLE attribute." The scalar - pointer is tested and caught elsewhere. */ - if (sym->result) - allocatable_or_pointer = sym->result->ts.type == BT_CLASS - && CLASS_DATA (sym->result) ? - (CLASS_DATA (sym->result)->attr.allocatable - || CLASS_DATA (sym->result)->attr.pointer) : - (sym->result->attr.allocatable - || sym->result->attr.pointer); - - if (sym->attr.elemental && sym->result - && allocatable_or_pointer) - { - gfc_error ("Function result variable %qs at %L of elemental " - "function %qs shall not have an ALLOCATABLE or POINTER " - "attribute", sym->result->name, - &sym->result->declared_at, sym->name); - return false; - } - - if (sym->attr.is_bind_c && sym->attr.is_c_interop != 1) - { - gfc_formal_arglist *curr_arg; - int has_non_interop_arg = 0; - - if (!verify_bind_c_sym (sym, &(sym->ts), sym->attr.in_common, - sym->common_block)) - { - /* Clear these to prevent looking at them again if there was an - error. */ - sym->attr.is_bind_c = 0; - sym->attr.is_c_interop = 0; - sym->ts.is_c_interop = 0; - } - else - { - /* So far, no errors have been found. */ - sym->attr.is_c_interop = 1; - sym->ts.is_c_interop = 1; - } - - curr_arg = gfc_sym_get_dummy_args (sym); - while (curr_arg != NULL) - { - /* Skip implicitly typed dummy args here. */ - if (curr_arg->sym && curr_arg->sym->attr.implicit_type == 0) - if (!gfc_verify_c_interop_param (curr_arg->sym)) - /* If something is found to fail, record the fact so we - can mark the symbol for the procedure as not being - BIND(C) to try and prevent multiple errors being - reported. */ - has_non_interop_arg = 1; - - curr_arg = curr_arg->next; - } - - /* See if any of the arguments were not interoperable and if so, clear - the procedure symbol to prevent duplicate error messages. */ - if (has_non_interop_arg != 0) - { - sym->attr.is_c_interop = 0; - sym->ts.is_c_interop = 0; - sym->attr.is_bind_c = 0; - } - } - - if (!sym->attr.proc_pointer) - { - if (sym->attr.save == SAVE_EXPLICIT) - { - gfc_error ("PROCEDURE attribute conflicts with SAVE attribute " - "in %qs at %L", sym->name, &sym->declared_at); - return false; - } - if (sym->attr.intent) - { - gfc_error ("PROCEDURE attribute conflicts with INTENT attribute " - "in %qs at %L", sym->name, &sym->declared_at); - return false; - } - if (sym->attr.subroutine && sym->attr.result) - { - gfc_error ("PROCEDURE attribute conflicts with RESULT attribute " - "in %qs at %L", sym->ns->proc_name->name, &sym->declared_at); - return false; - } - if (sym->attr.external && sym->attr.function && !sym->attr.module_procedure - && ((sym->attr.if_source == IFSRC_DECL && !sym->attr.procedure) - || sym->attr.contained)) - { - gfc_error ("EXTERNAL attribute conflicts with FUNCTION attribute " - "in %qs at %L", sym->name, &sym->declared_at); - return false; - } - if (strcmp ("ppr@", sym->name) == 0) - { - gfc_error ("Procedure pointer result %qs at %L " - "is missing the pointer attribute", - sym->ns->proc_name->name, &sym->declared_at); - return false; - } - } - - /* Assume that a procedure whose body is not known has references - to external arrays. */ - if (sym->attr.if_source != IFSRC_DECL) - sym->attr.array_outer_dependency = 1; - - /* Compare the characteristics of a module procedure with the - interface declaration. Ideally this would be done with - gfc_compare_interfaces but, at present, the formal interface - cannot be copied to the ts.interface. */ - if (sym->attr.module_procedure - && sym->attr.if_source == IFSRC_DECL) - { - gfc_symbol *iface; - char name[2*GFC_MAX_SYMBOL_LEN + 1]; - char *module_name; - char *submodule_name; - strcpy (name, sym->ns->proc_name->name); - module_name = strtok (name, "."); - submodule_name = strtok (NULL, "."); - - iface = sym->tlink; - sym->tlink = NULL; - - /* Make sure that the result uses the correct charlen for deferred - length results. */ - if (iface && sym->result - && iface->ts.type == BT_CHARACTER - && iface->ts.deferred) - sym->result->ts.u.cl = iface->ts.u.cl; - - if (iface == NULL) - goto check_formal; - - /* Check the procedure characteristics. */ - if (sym->attr.elemental != iface->attr.elemental) - { - gfc_error ("Mismatch in ELEMENTAL attribute between MODULE " - "PROCEDURE at %L and its interface in %s", - &sym->declared_at, module_name); - return false; - } - - if (sym->attr.pure != iface->attr.pure) - { - gfc_error ("Mismatch in PURE attribute between MODULE " - "PROCEDURE at %L and its interface in %s", - &sym->declared_at, module_name); - return false; - } - - if (sym->attr.recursive != iface->attr.recursive) - { - gfc_error ("Mismatch in RECURSIVE attribute between MODULE " - "PROCEDURE at %L and its interface in %s", - &sym->declared_at, module_name); - return false; - } - - /* Check the result characteristics. */ - if (!gfc_check_result_characteristics (sym, iface, errmsg, 200)) - { - gfc_error ("%s between the MODULE PROCEDURE declaration " - "in MODULE %qs and the declaration at %L in " - "(SUB)MODULE %qs", - errmsg, module_name, &sym->declared_at, - submodule_name ? submodule_name : module_name); - return false; - } - -check_formal: - /* Check the characteristics of the formal arguments. */ - if (sym->formal && sym->formal_ns) - { - for (arg = sym->formal; arg && arg->sym; arg = arg->next) - { - new_formal = arg; - gfc_traverse_ns (sym->formal_ns, compare_fsyms); - } - } - } - return true; -} - - -/* Resolve a list of finalizer procedures. That is, after they have hopefully - been defined and we now know their defined arguments, check that they fulfill - the requirements of the standard for procedures used as finalizers. */ - -static bool -gfc_resolve_finalizers (gfc_symbol* derived, bool *finalizable) -{ - gfc_finalizer* list; - gfc_finalizer** prev_link; /* For removing wrong entries from the list. */ - bool result = true; - bool seen_scalar = false; - gfc_symbol *vtab; - gfc_component *c; - gfc_symbol *parent = gfc_get_derived_super_type (derived); - - if (parent) - gfc_resolve_finalizers (parent, finalizable); - - /* Ensure that derived-type components have a their finalizers resolved. */ - bool has_final = derived->f2k_derived && derived->f2k_derived->finalizers; - for (c = derived->components; c; c = c->next) - if (c->ts.type == BT_DERIVED - && !c->attr.pointer && !c->attr.proc_pointer && !c->attr.allocatable) - { - bool has_final2 = false; - if (!gfc_resolve_finalizers (c->ts.u.derived, &has_final2)) - return false; /* Error. */ - has_final = has_final || has_final2; - } - /* Return early if not finalizable. */ - if (!has_final) - { - if (finalizable) - *finalizable = false; - return true; - } - - /* Walk over the list of finalizer-procedures, check them, and if any one - does not fit in with the standard's definition, print an error and remove - it from the list. */ - prev_link = &derived->f2k_derived->finalizers; - for (list = derived->f2k_derived->finalizers; list; list = *prev_link) - { - gfc_formal_arglist *dummy_args; - gfc_symbol* arg; - gfc_finalizer* i; - int my_rank; - - /* Skip this finalizer if we already resolved it. */ - if (list->proc_tree) - { - if (list->proc_tree->n.sym->formal->sym->as == NULL - || list->proc_tree->n.sym->formal->sym->as->rank == 0) - seen_scalar = true; - prev_link = &(list->next); - continue; - } - - /* Check this exists and is a SUBROUTINE. */ - if (!list->proc_sym->attr.subroutine) - { - gfc_error ("FINAL procedure %qs at %L is not a SUBROUTINE", - list->proc_sym->name, &list->where); - goto error; - } - - /* We should have exactly one argument. */ - dummy_args = gfc_sym_get_dummy_args (list->proc_sym); - if (!dummy_args || dummy_args->next) - { - gfc_error ("FINAL procedure at %L must have exactly one argument", - &list->where); - goto error; - } - arg = dummy_args->sym; - - /* This argument must be of our type. */ - if (arg->ts.type != BT_DERIVED || arg->ts.u.derived != derived) - { - gfc_error ("Argument of FINAL procedure at %L must be of type %qs", - &arg->declared_at, derived->name); - goto error; - } - - /* It must neither be a pointer nor allocatable nor optional. */ - if (arg->attr.pointer) - { - gfc_error ("Argument of FINAL procedure at %L must not be a POINTER", - &arg->declared_at); - goto error; - } - if (arg->attr.allocatable) - { - gfc_error ("Argument of FINAL procedure at %L must not be" - " ALLOCATABLE", &arg->declared_at); - goto error; - } - if (arg->attr.optional) - { - gfc_error ("Argument of FINAL procedure at %L must not be OPTIONAL", - &arg->declared_at); - goto error; - } - - /* It must not be INTENT(OUT). */ - if (arg->attr.intent == INTENT_OUT) - { - gfc_error ("Argument of FINAL procedure at %L must not be" - " INTENT(OUT)", &arg->declared_at); - goto error; - } - - /* Warn if the procedure is non-scalar and not assumed shape. */ - if (warn_surprising && arg->as && arg->as->rank != 0 - && arg->as->type != AS_ASSUMED_SHAPE) - gfc_warning (OPT_Wsurprising, - "Non-scalar FINAL procedure at %L should have assumed" - " shape argument", &arg->declared_at); - - /* Check that it does not match in kind and rank with a FINAL procedure - defined earlier. To really loop over the *earlier* declarations, - we need to walk the tail of the list as new ones were pushed at the - front. */ - /* TODO: Handle kind parameters once they are implemented. */ - my_rank = (arg->as ? arg->as->rank : 0); - for (i = list->next; i; i = i->next) - { - gfc_formal_arglist *dummy_args; - - /* Argument list might be empty; that is an error signalled earlier, - but we nevertheless continued resolving. */ - dummy_args = gfc_sym_get_dummy_args (i->proc_sym); - if (dummy_args) - { - gfc_symbol* i_arg = dummy_args->sym; - const int i_rank = (i_arg->as ? i_arg->as->rank : 0); - if (i_rank == my_rank) - { - gfc_error ("FINAL procedure %qs declared at %L has the same" - " rank (%d) as %qs", - list->proc_sym->name, &list->where, my_rank, - i->proc_sym->name); - goto error; - } - } - } - - /* Is this the/a scalar finalizer procedure? */ - if (my_rank == 0) - seen_scalar = true; - - /* Find the symtree for this procedure. */ - gcc_assert (!list->proc_tree); - list->proc_tree = gfc_find_sym_in_symtree (list->proc_sym); - - prev_link = &list->next; - continue; - - /* Remove wrong nodes immediately from the list so we don't risk any - troubles in the future when they might fail later expectations. */ -error: - i = list; - *prev_link = list->next; - gfc_free_finalizer (i); - result = false; - } - - if (result == false) - return false; - - /* Warn if we haven't seen a scalar finalizer procedure (but we know there - were nodes in the list, must have been for arrays. It is surely a good - idea to have a scalar version there if there's something to finalize. */ - if (warn_surprising && derived->f2k_derived->finalizers && !seen_scalar) - gfc_warning (OPT_Wsurprising, - "Only array FINAL procedures declared for derived type %qs" - " defined at %L, suggest also scalar one", - derived->name, &derived->declared_at); - - vtab = gfc_find_derived_vtab (derived); - c = vtab->ts.u.derived->components->next->next->next->next->next; - gfc_set_sym_referenced (c->initializer->symtree->n.sym); - - if (finalizable) - *finalizable = true; - - return true; -} - - -/* Check if two GENERIC targets are ambiguous and emit an error is they are. */ - -static bool -check_generic_tbp_ambiguity (gfc_tbp_generic* t1, gfc_tbp_generic* t2, - const char* generic_name, locus where) -{ - gfc_symbol *sym1, *sym2; - const char *pass1, *pass2; - gfc_formal_arglist *dummy_args; - - gcc_assert (t1->specific && t2->specific); - gcc_assert (!t1->specific->is_generic); - gcc_assert (!t2->specific->is_generic); - gcc_assert (t1->is_operator == t2->is_operator); - - sym1 = t1->specific->u.specific->n.sym; - sym2 = t2->specific->u.specific->n.sym; - - if (sym1 == sym2) - return true; - - /* Both must be SUBROUTINEs or both must be FUNCTIONs. */ - if (sym1->attr.subroutine != sym2->attr.subroutine - || sym1->attr.function != sym2->attr.function) - { - gfc_error ("%qs and %qs cannot be mixed FUNCTION/SUBROUTINE for" - " GENERIC %qs at %L", - sym1->name, sym2->name, generic_name, &where); - return false; - } - - /* Determine PASS arguments. */ - if (t1->specific->nopass) - pass1 = NULL; - else if (t1->specific->pass_arg) - pass1 = t1->specific->pass_arg; - else - { - dummy_args = gfc_sym_get_dummy_args (t1->specific->u.specific->n.sym); - if (dummy_args) - pass1 = dummy_args->sym->name; - else - pass1 = NULL; - } - if (t2->specific->nopass) - pass2 = NULL; - else if (t2->specific->pass_arg) - pass2 = t2->specific->pass_arg; - else - { - dummy_args = gfc_sym_get_dummy_args (t2->specific->u.specific->n.sym); - if (dummy_args) - pass2 = dummy_args->sym->name; - else - pass2 = NULL; - } - - /* Compare the interfaces. */ - if (gfc_compare_interfaces (sym1, sym2, sym2->name, !t1->is_operator, 0, - NULL, 0, pass1, pass2)) - { - gfc_error ("%qs and %qs for GENERIC %qs at %L are ambiguous", - sym1->name, sym2->name, generic_name, &where); - return false; - } - - return true; -} - - -/* Worker function for resolving a generic procedure binding; this is used to - resolve GENERIC as well as user and intrinsic OPERATOR typebound procedures. - - The difference between those cases is finding possible inherited bindings - that are overridden, as one has to look for them in tb_sym_root, - tb_uop_root or tb_op, respectively. Thus the caller must already find - the super-type and set p->overridden correctly. */ - -static bool -resolve_tb_generic_targets (gfc_symbol* super_type, - gfc_typebound_proc* p, const char* name) -{ - gfc_tbp_generic* target; - gfc_symtree* first_target; - gfc_symtree* inherited; - - gcc_assert (p && p->is_generic); - - /* Try to find the specific bindings for the symtrees in our target-list. */ - gcc_assert (p->u.generic); - for (target = p->u.generic; target; target = target->next) - if (!target->specific) - { - gfc_typebound_proc* overridden_tbp; - gfc_tbp_generic* g; - const char* target_name; - - target_name = target->specific_st->name; - - /* Defined for this type directly. */ - if (target->specific_st->n.tb && !target->specific_st->n.tb->error) - { - target->specific = target->specific_st->n.tb; - goto specific_found; - } - - /* Look for an inherited specific binding. */ - if (super_type) - { - inherited = gfc_find_typebound_proc (super_type, NULL, target_name, - true, NULL); - - if (inherited) - { - gcc_assert (inherited->n.tb); - target->specific = inherited->n.tb; - goto specific_found; - } - } - - gfc_error ("Undefined specific binding %qs as target of GENERIC %qs" - " at %L", target_name, name, &p->where); - return false; - - /* Once we've found the specific binding, check it is not ambiguous with - other specifics already found or inherited for the same GENERIC. */ -specific_found: - gcc_assert (target->specific); - - /* This must really be a specific binding! */ - if (target->specific->is_generic) - { - gfc_error ("GENERIC %qs at %L must target a specific binding," - " %qs is GENERIC, too", name, &p->where, target_name); - return false; - } - - /* Check those already resolved on this type directly. */ - for (g = p->u.generic; g; g = g->next) - if (g != target && g->specific - && !check_generic_tbp_ambiguity (target, g, name, p->where)) - return false; - - /* Check for ambiguity with inherited specific targets. */ - for (overridden_tbp = p->overridden; overridden_tbp; - overridden_tbp = overridden_tbp->overridden) - if (overridden_tbp->is_generic) - { - for (g = overridden_tbp->u.generic; g; g = g->next) - { - gcc_assert (g->specific); - if (!check_generic_tbp_ambiguity (target, g, name, p->where)) - return false; - } - } - } - - /* If we attempt to "overwrite" a specific binding, this is an error. */ - if (p->overridden && !p->overridden->is_generic) - { - gfc_error ("GENERIC %qs at %L cannot overwrite specific binding with" - " the same name", name, &p->where); - return false; - } - - /* Take the SUBROUTINE/FUNCTION attributes of the first specific target, as - all must have the same attributes here. */ - first_target = p->u.generic->specific->u.specific; - gcc_assert (first_target); - p->subroutine = first_target->n.sym->attr.subroutine; - p->function = first_target->n.sym->attr.function; - - return true; -} - - -/* Resolve a GENERIC procedure binding for a derived type. */ - -static bool -resolve_typebound_generic (gfc_symbol* derived, gfc_symtree* st) -{ - gfc_symbol* super_type; - - /* Find the overridden binding if any. */ - st->n.tb->overridden = NULL; - super_type = gfc_get_derived_super_type (derived); - if (super_type) - { - gfc_symtree* overridden; - overridden = gfc_find_typebound_proc (super_type, NULL, st->name, - true, NULL); - - if (overridden && overridden->n.tb) - st->n.tb->overridden = overridden->n.tb; - } - - /* Resolve using worker function. */ - return resolve_tb_generic_targets (super_type, st->n.tb, st->name); -} - - -/* Retrieve the target-procedure of an operator binding and do some checks in - common for intrinsic and user-defined type-bound operators. */ - -static gfc_symbol* -get_checked_tb_operator_target (gfc_tbp_generic* target, locus where) -{ - gfc_symbol* target_proc; - - gcc_assert (target->specific && !target->specific->is_generic); - target_proc = target->specific->u.specific->n.sym; - gcc_assert (target_proc); - - /* F08:C468. All operator bindings must have a passed-object dummy argument. */ - if (target->specific->nopass) - { - gfc_error ("Type-bound operator at %L cannot be NOPASS", &where); - return NULL; - } - - return target_proc; -} - - -/* Resolve a type-bound intrinsic operator. */ - -static bool -resolve_typebound_intrinsic_op (gfc_symbol* derived, gfc_intrinsic_op op, - gfc_typebound_proc* p) -{ - gfc_symbol* super_type; - gfc_tbp_generic* target; - - /* If there's already an error here, do nothing (but don't fail again). */ - if (p->error) - return true; - - /* Operators should always be GENERIC bindings. */ - gcc_assert (p->is_generic); - - /* Look for an overridden binding. */ - super_type = gfc_get_derived_super_type (derived); - if (super_type && super_type->f2k_derived) - p->overridden = gfc_find_typebound_intrinsic_op (super_type, NULL, - op, true, NULL); - else - p->overridden = NULL; - - /* Resolve general GENERIC properties using worker function. */ - if (!resolve_tb_generic_targets (super_type, p, gfc_op2string(op))) - goto error; - - /* Check the targets to be procedures of correct interface. */ - for (target = p->u.generic; target; target = target->next) - { - gfc_symbol* target_proc; - - target_proc = get_checked_tb_operator_target (target, p->where); - if (!target_proc) - goto error; - - if (!gfc_check_operator_interface (target_proc, op, p->where)) - goto error; - - /* Add target to non-typebound operator list. */ - if (!target->specific->deferred && !derived->attr.use_assoc - && p->access != ACCESS_PRIVATE && derived->ns == gfc_current_ns) - { - gfc_interface *head, *intr; - - /* Preempt 'gfc_check_new_interface' for submodules, where the - mechanism for handling module procedures winds up resolving - operator interfaces twice and would otherwise cause an error. */ - for (intr = derived->ns->op[op]; intr; intr = intr->next) - if (intr->sym == target_proc - && target_proc->attr.used_in_submodule) - return true; - - if (!gfc_check_new_interface (derived->ns->op[op], - target_proc, p->where)) - return false; - head = derived->ns->op[op]; - intr = gfc_get_interface (); - intr->sym = target_proc; - intr->where = p->where; - intr->next = head; - derived->ns->op[op] = intr; - } - } - - return true; - -error: - p->error = 1; - return false; -} - - -/* Resolve a type-bound user operator (tree-walker callback). */ - -static gfc_symbol* resolve_bindings_derived; -static bool resolve_bindings_result; - -static bool check_uop_procedure (gfc_symbol* sym, locus where); - -static void -resolve_typebound_user_op (gfc_symtree* stree) -{ - gfc_symbol* super_type; - gfc_tbp_generic* target; - - gcc_assert (stree && stree->n.tb); - - if (stree->n.tb->error) - return; - - /* Operators should always be GENERIC bindings. */ - gcc_assert (stree->n.tb->is_generic); - - /* Find overridden procedure, if any. */ - super_type = gfc_get_derived_super_type (resolve_bindings_derived); - if (super_type && super_type->f2k_derived) - { - gfc_symtree* overridden; - overridden = gfc_find_typebound_user_op (super_type, NULL, - stree->name, true, NULL); - - if (overridden && overridden->n.tb) - stree->n.tb->overridden = overridden->n.tb; - } - else - stree->n.tb->overridden = NULL; - - /* Resolve basically using worker function. */ - if (!resolve_tb_generic_targets (super_type, stree->n.tb, stree->name)) - goto error; - - /* Check the targets to be functions of correct interface. */ - for (target = stree->n.tb->u.generic; target; target = target->next) - { - gfc_symbol* target_proc; - - target_proc = get_checked_tb_operator_target (target, stree->n.tb->where); - if (!target_proc) - goto error; - - if (!check_uop_procedure (target_proc, stree->n.tb->where)) - goto error; - } - - return; - -error: - resolve_bindings_result = false; - stree->n.tb->error = 1; -} - - -/* Resolve the type-bound procedures for a derived type. */ - -static void -resolve_typebound_procedure (gfc_symtree* stree) -{ - gfc_symbol* proc; - locus where; - gfc_symbol* me_arg; - gfc_symbol* super_type; - gfc_component* comp; - - gcc_assert (stree); - - /* Undefined specific symbol from GENERIC target definition. */ - if (!stree->n.tb) - return; - - if (stree->n.tb->error) - return; - - /* If this is a GENERIC binding, use that routine. */ - if (stree->n.tb->is_generic) - { - if (!resolve_typebound_generic (resolve_bindings_derived, stree)) - goto error; - return; - } - - /* Get the target-procedure to check it. */ - gcc_assert (!stree->n.tb->is_generic); - gcc_assert (stree->n.tb->u.specific); - proc = stree->n.tb->u.specific->n.sym; - where = stree->n.tb->where; - - /* Default access should already be resolved from the parser. */ - gcc_assert (stree->n.tb->access != ACCESS_UNKNOWN); - - if (stree->n.tb->deferred) - { - if (!check_proc_interface (proc, &where)) - goto error; - } - else - { - /* If proc has not been resolved at this point, proc->name may - actually be a USE associated entity. See PR fortran/89647. */ - if (!proc->resolve_symbol_called - && proc->attr.function == 0 && proc->attr.subroutine == 0) - { - gfc_symbol *tmp; - gfc_find_symbol (proc->name, gfc_current_ns->parent, 1, &tmp); - if (tmp && tmp->attr.use_assoc) - { - proc->module = tmp->module; - proc->attr.proc = tmp->attr.proc; - proc->attr.function = tmp->attr.function; - proc->attr.subroutine = tmp->attr.subroutine; - proc->attr.use_assoc = tmp->attr.use_assoc; - proc->ts = tmp->ts; - proc->result = tmp->result; - } - } - - /* Check for F08:C465. */ - if ((!proc->attr.subroutine && !proc->attr.function) - || (proc->attr.proc != PROC_MODULE - && proc->attr.if_source != IFSRC_IFBODY - && !proc->attr.module_procedure) - || proc->attr.abstract) - { - gfc_error ("%qs must be a module procedure or an external " - "procedure with an explicit interface at %L", - proc->name, &where); - goto error; - } - } - - stree->n.tb->subroutine = proc->attr.subroutine; - stree->n.tb->function = proc->attr.function; - - /* Find the super-type of the current derived type. We could do this once and - store in a global if speed is needed, but as long as not I believe this is - more readable and clearer. */ - super_type = gfc_get_derived_super_type (resolve_bindings_derived); - - /* If PASS, resolve and check arguments if not already resolved / loaded - from a .mod file. */ - if (!stree->n.tb->nopass && stree->n.tb->pass_arg_num == 0) - { - gfc_formal_arglist *dummy_args; - - dummy_args = gfc_sym_get_dummy_args (proc); - if (stree->n.tb->pass_arg) - { - gfc_formal_arglist *i; - - /* If an explicit passing argument name is given, walk the arg-list - and look for it. */ - - me_arg = NULL; - stree->n.tb->pass_arg_num = 1; - for (i = dummy_args; i; i = i->next) - { - if (!strcmp (i->sym->name, stree->n.tb->pass_arg)) - { - me_arg = i->sym; - break; - } - ++stree->n.tb->pass_arg_num; - } - - if (!me_arg) - { - gfc_error ("Procedure %qs with PASS(%s) at %L has no" - " argument %qs", - proc->name, stree->n.tb->pass_arg, &where, - stree->n.tb->pass_arg); - goto error; - } - } - else - { - /* Otherwise, take the first one; there should in fact be at least - one. */ - stree->n.tb->pass_arg_num = 1; - if (!dummy_args) - { - gfc_error ("Procedure %qs with PASS at %L must have at" - " least one argument", proc->name, &where); - goto error; - } - me_arg = dummy_args->sym; - } - - /* Now check that the argument-type matches and the passed-object - dummy argument is generally fine. */ - - gcc_assert (me_arg); - - if (me_arg->ts.type != BT_CLASS) - { - gfc_error ("Non-polymorphic passed-object dummy argument of %qs" - " at %L", proc->name, &where); - goto error; - } - - if (CLASS_DATA (me_arg)->ts.u.derived - != resolve_bindings_derived) - { - gfc_error ("Argument %qs of %qs with PASS(%s) at %L must be of" - " the derived-type %qs", me_arg->name, proc->name, - me_arg->name, &where, resolve_bindings_derived->name); - goto error; - } - - gcc_assert (me_arg->ts.type == BT_CLASS); - if (CLASS_DATA (me_arg)->as && CLASS_DATA (me_arg)->as->rank != 0) - { - gfc_error ("Passed-object dummy argument of %qs at %L must be" - " scalar", proc->name, &where); - goto error; - } - if (CLASS_DATA (me_arg)->attr.allocatable) - { - gfc_error ("Passed-object dummy argument of %qs at %L must not" - " be ALLOCATABLE", proc->name, &where); - goto error; - } - if (CLASS_DATA (me_arg)->attr.class_pointer) - { - gfc_error ("Passed-object dummy argument of %qs at %L must not" - " be POINTER", proc->name, &where); - goto error; - } - } - - /* If we are extending some type, check that we don't override a procedure - flagged NON_OVERRIDABLE. */ - stree->n.tb->overridden = NULL; - if (super_type) - { - gfc_symtree* overridden; - overridden = gfc_find_typebound_proc (super_type, NULL, - stree->name, true, NULL); - - if (overridden) - { - if (overridden->n.tb) - stree->n.tb->overridden = overridden->n.tb; - - if (!gfc_check_typebound_override (stree, overridden)) - goto error; - } - } - - /* See if there's a name collision with a component directly in this type. */ - for (comp = resolve_bindings_derived->components; comp; comp = comp->next) - if (!strcmp (comp->name, stree->name)) - { - gfc_error ("Procedure %qs at %L has the same name as a component of" - " %qs", - stree->name, &where, resolve_bindings_derived->name); - goto error; - } - - /* Try to find a name collision with an inherited component. */ - if (super_type && gfc_find_component (super_type, stree->name, true, true, - NULL)) - { - gfc_error ("Procedure %qs at %L has the same name as an inherited" - " component of %qs", - stree->name, &where, resolve_bindings_derived->name); - goto error; - } - - stree->n.tb->error = 0; - return; - -error: - resolve_bindings_result = false; - stree->n.tb->error = 1; -} - - -static bool -resolve_typebound_procedures (gfc_symbol* derived) -{ - int op; - gfc_symbol* super_type; - - if (!derived->f2k_derived || !derived->f2k_derived->tb_sym_root) - return true; - - super_type = gfc_get_derived_super_type (derived); - if (super_type) - resolve_symbol (super_type); - - resolve_bindings_derived = derived; - resolve_bindings_result = true; - - if (derived->f2k_derived->tb_sym_root) - gfc_traverse_symtree (derived->f2k_derived->tb_sym_root, - &resolve_typebound_procedure); - - if (derived->f2k_derived->tb_uop_root) - gfc_traverse_symtree (derived->f2k_derived->tb_uop_root, - &resolve_typebound_user_op); - - for (op = 0; op != GFC_INTRINSIC_OPS; ++op) - { - gfc_typebound_proc* p = derived->f2k_derived->tb_op[op]; - if (p && !resolve_typebound_intrinsic_op (derived, - (gfc_intrinsic_op)op, p)) - resolve_bindings_result = false; - } - - return resolve_bindings_result; -} - - -/* Add a derived type to the dt_list. The dt_list is used in trans-types.c - to give all identical derived types the same backend_decl. */ -static void -add_dt_to_dt_list (gfc_symbol *derived) -{ - if (!derived->dt_next) - { - if (gfc_derived_types) - { - derived->dt_next = gfc_derived_types->dt_next; - gfc_derived_types->dt_next = derived; - } - else - { - derived->dt_next = derived; - } - gfc_derived_types = derived; - } -} - - -/* Ensure that a derived-type is really not abstract, meaning that every - inherited DEFERRED binding is overridden by a non-DEFERRED one. */ - -static bool -ensure_not_abstract_walker (gfc_symbol* sub, gfc_symtree* st) -{ - if (!st) - return true; - - if (!ensure_not_abstract_walker (sub, st->left)) - return false; - if (!ensure_not_abstract_walker (sub, st->right)) - return false; - - if (st->n.tb && st->n.tb->deferred) - { - gfc_symtree* overriding; - overriding = gfc_find_typebound_proc (sub, NULL, st->name, true, NULL); - if (!overriding) - return false; - gcc_assert (overriding->n.tb); - if (overriding->n.tb->deferred) - { - gfc_error ("Derived-type %qs declared at %L must be ABSTRACT because" - " %qs is DEFERRED and not overridden", - sub->name, &sub->declared_at, st->name); - return false; - } - } - - return true; -} - -static bool -ensure_not_abstract (gfc_symbol* sub, gfc_symbol* ancestor) -{ - /* The algorithm used here is to recursively travel up the ancestry of sub - and for each ancestor-type, check all bindings. If any of them is - DEFERRED, look it up starting from sub and see if the found (overriding) - binding is not DEFERRED. - This is not the most efficient way to do this, but it should be ok and is - clearer than something sophisticated. */ - - gcc_assert (ancestor && !sub->attr.abstract); - - if (!ancestor->attr.abstract) - return true; - - /* Walk bindings of this ancestor. */ - if (ancestor->f2k_derived) - { - bool t; - t = ensure_not_abstract_walker (sub, ancestor->f2k_derived->tb_sym_root); - if (!t) - return false; - } - - /* Find next ancestor type and recurse on it. */ - ancestor = gfc_get_derived_super_type (ancestor); - if (ancestor) - return ensure_not_abstract (sub, ancestor); - - return true; -} - - -/* This check for typebound defined assignments is done recursively - since the order in which derived types are resolved is not always in - order of the declarations. */ - -static void -check_defined_assignments (gfc_symbol *derived) -{ - gfc_component *c; - - for (c = derived->components; c; c = c->next) - { - if (!gfc_bt_struct (c->ts.type) - || c->attr.pointer - || c->attr.allocatable - || c->attr.proc_pointer_comp - || c->attr.class_pointer - || c->attr.proc_pointer) - continue; - - if (c->ts.u.derived->attr.defined_assign_comp - || (c->ts.u.derived->f2k_derived - && c->ts.u.derived->f2k_derived->tb_op[INTRINSIC_ASSIGN])) - { - derived->attr.defined_assign_comp = 1; - return; - } - - check_defined_assignments (c->ts.u.derived); - if (c->ts.u.derived->attr.defined_assign_comp) - { - derived->attr.defined_assign_comp = 1; - return; - } - } -} - - -/* Resolve a single component of a derived type or structure. */ - -static bool -resolve_component (gfc_component *c, gfc_symbol *sym) -{ - gfc_symbol *super_type; - symbol_attribute *attr; - - if (c->attr.artificial) - return true; - - /* Do not allow vtype components to be resolved in nameless namespaces - such as block data because the procedure pointers will cause ICEs - and vtables are not needed in these contexts. */ - if (sym->attr.vtype && sym->attr.use_assoc - && sym->ns->proc_name == NULL) - return true; - - /* F2008, C442. */ - if ((!sym->attr.is_class || c != sym->components) - && c->attr.codimension - && (!c->attr.allocatable || (c->as && c->as->type != AS_DEFERRED))) - { - gfc_error ("Coarray component %qs at %L must be allocatable with " - "deferred shape", c->name, &c->loc); - return false; - } - - /* F2008, C443. */ - if (c->attr.codimension && c->ts.type == BT_DERIVED - && c->ts.u.derived->ts.is_iso_c) - { - gfc_error ("Component %qs at %L of TYPE(C_PTR) or TYPE(C_FUNPTR) " - "shall not be a coarray", c->name, &c->loc); - return false; - } - - /* F2008, C444. */ - if (gfc_bt_struct (c->ts.type) && c->ts.u.derived->attr.coarray_comp - && (c->attr.codimension || c->attr.pointer || c->attr.dimension - || c->attr.allocatable)) - { - gfc_error ("Component %qs at %L with coarray component " - "shall be a nonpointer, nonallocatable scalar", - c->name, &c->loc); - return false; - } - - /* F2008, C448. */ - if (c->ts.type == BT_CLASS) - { - if (c->attr.class_ok && CLASS_DATA (c)) - { - attr = &(CLASS_DATA (c)->attr); - - /* Fix up contiguous attribute. */ - if (c->attr.contiguous) - attr->contiguous = 1; - } - else - attr = NULL; - } - else - attr = &c->attr; - - if (attr && attr->contiguous && (!attr->dimension || !attr->pointer)) - { - gfc_error ("Component %qs at %L has the CONTIGUOUS attribute but " - "is not an array pointer", c->name, &c->loc); - return false; - } - - /* F2003, 15.2.1 - length has to be one. */ - if (sym->attr.is_bind_c && c->ts.type == BT_CHARACTER - && (c->ts.u.cl == NULL || c->ts.u.cl->length == NULL - || !gfc_is_constant_expr (c->ts.u.cl->length) - || mpz_cmp_si (c->ts.u.cl->length->value.integer, 1) != 0)) - { - gfc_error ("Component %qs of BIND(C) type at %L must have length one", - c->name, &c->loc); - return false; - } - - if (c->attr.proc_pointer && c->ts.interface) - { - gfc_symbol *ifc = c->ts.interface; - - if (!sym->attr.vtype && !check_proc_interface (ifc, &c->loc)) - { - c->tb->error = 1; - return false; - } - - if (ifc->attr.if_source || ifc->attr.intrinsic) - { - /* Resolve interface and copy attributes. */ - if (ifc->formal && !ifc->formal_ns) - resolve_symbol (ifc); - if (ifc->attr.intrinsic) - gfc_resolve_intrinsic (ifc, &ifc->declared_at); - - if (ifc->result) - { - c->ts = ifc->result->ts; - c->attr.allocatable = ifc->result->attr.allocatable; - c->attr.pointer = ifc->result->attr.pointer; - c->attr.dimension = ifc->result->attr.dimension; - c->as = gfc_copy_array_spec (ifc->result->as); - c->attr.class_ok = ifc->result->attr.class_ok; - } - else - { - c->ts = ifc->ts; - c->attr.allocatable = ifc->attr.allocatable; - c->attr.pointer = ifc->attr.pointer; - c->attr.dimension = ifc->attr.dimension; - c->as = gfc_copy_array_spec (ifc->as); - c->attr.class_ok = ifc->attr.class_ok; - } - c->ts.interface = ifc; - c->attr.function = ifc->attr.function; - c->attr.subroutine = ifc->attr.subroutine; - - c->attr.pure = ifc->attr.pure; - c->attr.elemental = ifc->attr.elemental; - c->attr.recursive = ifc->attr.recursive; - c->attr.always_explicit = ifc->attr.always_explicit; - c->attr.ext_attr |= ifc->attr.ext_attr; - /* Copy char length. */ - if (ifc->ts.type == BT_CHARACTER && ifc->ts.u.cl) - { - gfc_charlen *cl = gfc_new_charlen (sym->ns, ifc->ts.u.cl); - if (cl->length && !cl->resolved - && !gfc_resolve_expr (cl->length)) - { - c->tb->error = 1; - return false; - } - c->ts.u.cl = cl; - } - } - } - else if (c->attr.proc_pointer && c->ts.type == BT_UNKNOWN) - { - /* Since PPCs are not implicitly typed, a PPC without an explicit - interface must be a subroutine. */ - gfc_add_subroutine (&c->attr, c->name, &c->loc); - } - - /* Procedure pointer components: Check PASS arg. */ - if (c->attr.proc_pointer && !c->tb->nopass && c->tb->pass_arg_num == 0 - && !sym->attr.vtype) - { - gfc_symbol* me_arg; - - if (c->tb->pass_arg) - { - gfc_formal_arglist* i; - - /* If an explicit passing argument name is given, walk the arg-list - and look for it. */ - - me_arg = NULL; - c->tb->pass_arg_num = 1; - for (i = c->ts.interface->formal; i; i = i->next) - { - if (!strcmp (i->sym->name, c->tb->pass_arg)) - { - me_arg = i->sym; - break; - } - c->tb->pass_arg_num++; - } - - if (!me_arg) - { - gfc_error ("Procedure pointer component %qs with PASS(%s) " - "at %L has no argument %qs", c->name, - c->tb->pass_arg, &c->loc, c->tb->pass_arg); - c->tb->error = 1; - return false; - } - } - else - { - /* Otherwise, take the first one; there should in fact be at least - one. */ - c->tb->pass_arg_num = 1; - if (!c->ts.interface->formal) - { - gfc_error ("Procedure pointer component %qs with PASS at %L " - "must have at least one argument", - c->name, &c->loc); - c->tb->error = 1; - return false; - } - me_arg = c->ts.interface->formal->sym; - } - - /* Now check that the argument-type matches. */ - gcc_assert (me_arg); - if ((me_arg->ts.type != BT_DERIVED && me_arg->ts.type != BT_CLASS) - || (me_arg->ts.type == BT_DERIVED && me_arg->ts.u.derived != sym) - || (me_arg->ts.type == BT_CLASS - && CLASS_DATA (me_arg)->ts.u.derived != sym)) - { - gfc_error ("Argument %qs of %qs with PASS(%s) at %L must be of" - " the derived type %qs", me_arg->name, c->name, - me_arg->name, &c->loc, sym->name); - c->tb->error = 1; - return false; - } - - /* Check for F03:C453. */ - if (CLASS_DATA (me_arg)->attr.dimension) - { - gfc_error ("Argument %qs of %qs with PASS(%s) at %L " - "must be scalar", me_arg->name, c->name, me_arg->name, - &c->loc); - c->tb->error = 1; - return false; - } - - if (CLASS_DATA (me_arg)->attr.class_pointer) - { - gfc_error ("Argument %qs of %qs with PASS(%s) at %L " - "may not have the POINTER attribute", me_arg->name, - c->name, me_arg->name, &c->loc); - c->tb->error = 1; - return false; - } - - if (CLASS_DATA (me_arg)->attr.allocatable) - { - gfc_error ("Argument %qs of %qs with PASS(%s) at %L " - "may not be ALLOCATABLE", me_arg->name, c->name, - me_arg->name, &c->loc); - c->tb->error = 1; - return false; - } - - if (gfc_type_is_extensible (sym) && me_arg->ts.type != BT_CLASS) - { - gfc_error ("Non-polymorphic passed-object dummy argument of %qs" - " at %L", c->name, &c->loc); - return false; - } - - } - - /* Check type-spec if this is not the parent-type component. */ - if (((sym->attr.is_class - && (!sym->components->ts.u.derived->attr.extension - || c != sym->components->ts.u.derived->components)) - || (!sym->attr.is_class - && (!sym->attr.extension || c != sym->components))) - && !sym->attr.vtype - && !resolve_typespec_used (&c->ts, &c->loc, c->name)) - return false; - - super_type = gfc_get_derived_super_type (sym); - - /* If this type is an extension, set the accessibility of the parent - component. */ - if (super_type - && ((sym->attr.is_class - && c == sym->components->ts.u.derived->components) - || (!sym->attr.is_class && c == sym->components)) - && strcmp (super_type->name, c->name) == 0) - c->attr.access = super_type->attr.access; - - /* If this type is an extension, see if this component has the same name - as an inherited type-bound procedure. */ - if (super_type && !sym->attr.is_class - && gfc_find_typebound_proc (super_type, NULL, c->name, true, NULL)) - { - gfc_error ("Component %qs of %qs at %L has the same name as an" - " inherited type-bound procedure", - c->name, sym->name, &c->loc); - return false; - } - - if (c->ts.type == BT_CHARACTER && !c->attr.proc_pointer - && !c->ts.deferred) - { - if (c->ts.u.cl->length == NULL - || (!resolve_charlen(c->ts.u.cl)) - || !gfc_is_constant_expr (c->ts.u.cl->length)) - { - gfc_error ("Character length of component %qs needs to " - "be a constant specification expression at %L", - c->name, - c->ts.u.cl->length ? &c->ts.u.cl->length->where : &c->loc); - return false; - } - } - - if (c->ts.type == BT_CHARACTER && c->ts.deferred - && !c->attr.pointer && !c->attr.allocatable) - { - gfc_error ("Character component %qs of %qs at %L with deferred " - "length must be a POINTER or ALLOCATABLE", - c->name, sym->name, &c->loc); - return false; - } - - /* Add the hidden deferred length field. */ - if (c->ts.type == BT_CHARACTER - && (c->ts.deferred || c->attr.pdt_string) - && !c->attr.function - && !sym->attr.is_class) - { - char name[GFC_MAX_SYMBOL_LEN+9]; - gfc_component *strlen; - sprintf (name, "_%s_length", c->name); - strlen = gfc_find_component (sym, name, true, true, NULL); - if (strlen == NULL) - { - if (!gfc_add_component (sym, name, &strlen)) - return false; - strlen->ts.type = BT_INTEGER; - strlen->ts.kind = gfc_charlen_int_kind; - strlen->attr.access = ACCESS_PRIVATE; - strlen->attr.artificial = 1; - } - } - - if (c->ts.type == BT_DERIVED - && sym->component_access != ACCESS_PRIVATE - && gfc_check_symbol_access (sym) - && !is_sym_host_assoc (c->ts.u.derived, sym->ns) - && !c->ts.u.derived->attr.use_assoc - && !gfc_check_symbol_access (c->ts.u.derived) - && !gfc_notify_std (GFC_STD_F2003, "the component %qs is a " - "PRIVATE type and cannot be a component of " - "%qs, which is PUBLIC at %L", c->name, - sym->name, &sym->declared_at)) - return false; - - if ((sym->attr.sequence || sym->attr.is_bind_c) && c->ts.type == BT_CLASS) - { - gfc_error ("Polymorphic component %s at %L in SEQUENCE or BIND(C) " - "type %s", c->name, &c->loc, sym->name); - return false; - } - - if (sym->attr.sequence) - { - if (c->ts.type == BT_DERIVED && c->ts.u.derived->attr.sequence == 0) - { - gfc_error ("Component %s of SEQUENCE type declared at %L does " - "not have the SEQUENCE attribute", - c->ts.u.derived->name, &sym->declared_at); - return false; - } - } - - if (c->ts.type == BT_DERIVED && c->ts.u.derived->attr.generic) - c->ts.u.derived = gfc_find_dt_in_generic (c->ts.u.derived); - else if (c->ts.type == BT_CLASS && c->attr.class_ok - && CLASS_DATA (c)->ts.u.derived->attr.generic) - CLASS_DATA (c)->ts.u.derived - = gfc_find_dt_in_generic (CLASS_DATA (c)->ts.u.derived); - - /* If an allocatable component derived type is of the same type as - the enclosing derived type, we need a vtable generating so that - the __deallocate procedure is created. */ - if ((c->ts.type == BT_DERIVED || c->ts.type == BT_CLASS) - && c->ts.u.derived == sym && c->attr.allocatable == 1) - gfc_find_vtab (&c->ts); - - /* Ensure that all the derived type components are put on the - derived type list; even in formal namespaces, where derived type - pointer components might not have been declared. */ - if (c->ts.type == BT_DERIVED - && c->ts.u.derived - && c->ts.u.derived->components - && c->attr.pointer - && sym != c->ts.u.derived) - add_dt_to_dt_list (c->ts.u.derived); - - if (c->as && c->as->type != AS_DEFERRED - && (c->attr.pointer || c->attr.allocatable)) - return false; - - if (!gfc_resolve_array_spec (c->as, - !(c->attr.pointer || c->attr.proc_pointer - || c->attr.allocatable))) - return false; - - if (c->initializer && !sym->attr.vtype - && !c->attr.pdt_kind && !c->attr.pdt_len - && !gfc_check_assign_symbol (sym, c, c->initializer)) - return false; - - return true; -} - - -/* Be nice about the locus for a structure expression - show the locus of the - first non-null sub-expression if we can. */ - -static locus * -cons_where (gfc_expr *struct_expr) -{ - gfc_constructor *cons; - - gcc_assert (struct_expr && struct_expr->expr_type == EXPR_STRUCTURE); - - cons = gfc_constructor_first (struct_expr->value.constructor); - for (; cons; cons = gfc_constructor_next (cons)) - { - if (cons->expr && cons->expr->expr_type != EXPR_NULL) - return &cons->expr->where; - } - - return &struct_expr->where; -} - -/* Resolve the components of a structure type. Much less work than derived - types. */ - -static bool -resolve_fl_struct (gfc_symbol *sym) -{ - gfc_component *c; - gfc_expr *init = NULL; - bool success; - - /* Make sure UNIONs do not have overlapping initializers. */ - if (sym->attr.flavor == FL_UNION) - { - for (c = sym->components; c; c = c->next) - { - if (init && c->initializer) - { - gfc_error ("Conflicting initializers in union at %L and %L", - cons_where (init), cons_where (c->initializer)); - gfc_free_expr (c->initializer); - c->initializer = NULL; - } - if (init == NULL) - init = c->initializer; - } - } - - success = true; - for (c = sym->components; c; c = c->next) - if (!resolve_component (c, sym)) - success = false; - - if (!success) - return false; - - if (sym->components) - add_dt_to_dt_list (sym); - - return true; -} - - -/* Resolve the components of a derived type. This does not have to wait until - resolution stage, but can be done as soon as the dt declaration has been - parsed. */ - -static bool -resolve_fl_derived0 (gfc_symbol *sym) -{ - gfc_symbol* super_type; - gfc_component *c; - gfc_formal_arglist *f; - bool success; - - if (sym->attr.unlimited_polymorphic) - return true; - - super_type = gfc_get_derived_super_type (sym); - - /* F2008, C432. */ - if (super_type && sym->attr.coarray_comp && !super_type->attr.coarray_comp) - { - gfc_error ("As extending type %qs at %L has a coarray component, " - "parent type %qs shall also have one", sym->name, - &sym->declared_at, super_type->name); - return false; - } - - /* Ensure the extended type gets resolved before we do. */ - if (super_type && !resolve_fl_derived0 (super_type)) - return false; - - /* An ABSTRACT type must be extensible. */ - if (sym->attr.abstract && !gfc_type_is_extensible (sym)) - { - gfc_error ("Non-extensible derived-type %qs at %L must not be ABSTRACT", - sym->name, &sym->declared_at); - return false; - } - - c = (sym->attr.is_class) ? sym->components->ts.u.derived->components - : sym->components; - - success = true; - for ( ; c != NULL; c = c->next) - if (!resolve_component (c, sym)) - success = false; - - if (!success) - return false; - - /* Now add the caf token field, where needed. */ - if (flag_coarray != GFC_FCOARRAY_NONE - && !sym->attr.is_class && !sym->attr.vtype) - { - for (c = sym->components; c; c = c->next) - if (!c->attr.dimension && !c->attr.codimension - && (c->attr.allocatable || c->attr.pointer)) - { - char name[GFC_MAX_SYMBOL_LEN+9]; - gfc_component *token; - sprintf (name, "_caf_%s", c->name); - token = gfc_find_component (sym, name, true, true, NULL); - if (token == NULL) - { - if (!gfc_add_component (sym, name, &token)) - return false; - token->ts.type = BT_VOID; - token->ts.kind = gfc_default_integer_kind; - token->attr.access = ACCESS_PRIVATE; - token->attr.artificial = 1; - token->attr.caf_token = 1; - } - } - } - - check_defined_assignments (sym); - - if (!sym->attr.defined_assign_comp && super_type) - sym->attr.defined_assign_comp - = super_type->attr.defined_assign_comp; - - /* If this is a non-ABSTRACT type extending an ABSTRACT one, ensure that - all DEFERRED bindings are overridden. */ - if (super_type && super_type->attr.abstract && !sym->attr.abstract - && !sym->attr.is_class - && !ensure_not_abstract (sym, super_type)) - return false; - - /* Check that there is a component for every PDT parameter. */ - if (sym->attr.pdt_template) - { - for (f = sym->formal; f; f = f->next) - { - if (!f->sym) - continue; - c = gfc_find_component (sym, f->sym->name, true, true, NULL); - if (c == NULL) - { - gfc_error ("Parameterized type %qs does not have a component " - "corresponding to parameter %qs at %L", sym->name, - f->sym->name, &sym->declared_at); - break; - } - } - } - - /* Add derived type to the derived type list. */ - add_dt_to_dt_list (sym); - - return true; -} - - -/* The following procedure does the full resolution of a derived type, - including resolution of all type-bound procedures (if present). In contrast - to 'resolve_fl_derived0' this can only be done after the module has been - parsed completely. */ - -static bool -resolve_fl_derived (gfc_symbol *sym) -{ - gfc_symbol *gen_dt = NULL; - - if (sym->attr.unlimited_polymorphic) - return true; - - if (!sym->attr.is_class) - gfc_find_symbol (sym->name, sym->ns, 0, &gen_dt); - if (gen_dt && gen_dt->generic && gen_dt->generic->next - && (!gen_dt->generic->sym->attr.use_assoc - || gen_dt->generic->sym->module != gen_dt->generic->next->sym->module) - && !gfc_notify_std (GFC_STD_F2003, "Generic name %qs of function " - "%qs at %L being the same name as derived " - "type at %L", sym->name, - gen_dt->generic->sym == sym - ? gen_dt->generic->next->sym->name - : gen_dt->generic->sym->name, - gen_dt->generic->sym == sym - ? &gen_dt->generic->next->sym->declared_at - : &gen_dt->generic->sym->declared_at, - &sym->declared_at)) - return false; - - if (sym->components == NULL && !sym->attr.zero_comp && !sym->attr.use_assoc) - { - gfc_error ("Derived type %qs at %L has not been declared", - sym->name, &sym->declared_at); - return false; - } - - /* Resolve the finalizer procedures. */ - if (!gfc_resolve_finalizers (sym, NULL)) - return false; - - if (sym->attr.is_class && sym->ts.u.derived == NULL) - { - /* Fix up incomplete CLASS symbols. */ - gfc_component *data = gfc_find_component (sym, "_data", true, true, NULL); - gfc_component *vptr = gfc_find_component (sym, "_vptr", true, true, NULL); - - /* Nothing more to do for unlimited polymorphic entities. */ - if (data->ts.u.derived->attr.unlimited_polymorphic) - return true; - else if (vptr->ts.u.derived == NULL) - { - gfc_symbol *vtab = gfc_find_derived_vtab (data->ts.u.derived); - gcc_assert (vtab); - vptr->ts.u.derived = vtab->ts.u.derived; - if (!resolve_fl_derived0 (vptr->ts.u.derived)) - return false; - } - } - - if (!resolve_fl_derived0 (sym)) - return false; - - /* Resolve the type-bound procedures. */ - if (!resolve_typebound_procedures (sym)) - return false; - - /* Generate module vtables subject to their accessibility and their not - being vtables or pdt templates. If this is not done class declarations - in external procedures wind up with their own version and so SELECT TYPE - fails because the vptrs do not have the same address. */ - if (gfc_option.allow_std & GFC_STD_F2003 - && sym->ns->proc_name - && sym->ns->proc_name->attr.flavor == FL_MODULE - && sym->attr.access != ACCESS_PRIVATE - && !(sym->attr.use_assoc || sym->attr.vtype || sym->attr.pdt_template)) - { - gfc_symbol *vtab = gfc_find_derived_vtab (sym); - gfc_set_sym_referenced (vtab); - } - - return true; -} - - -static bool -resolve_fl_namelist (gfc_symbol *sym) -{ - gfc_namelist *nl; - gfc_symbol *nlsym; - - for (nl = sym->namelist; nl; nl = nl->next) - { - /* Check again, the check in match only works if NAMELIST comes - after the decl. */ - if (nl->sym->as && nl->sym->as->type == AS_ASSUMED_SIZE) - { - gfc_error ("Assumed size array %qs in namelist %qs at %L is not " - "allowed", nl->sym->name, sym->name, &sym->declared_at); - return false; - } - - if (nl->sym->as && nl->sym->as->type == AS_ASSUMED_SHAPE - && !gfc_notify_std (GFC_STD_F2003, "NAMELIST array object %qs " - "with assumed shape in namelist %qs at %L", - nl->sym->name, sym->name, &sym->declared_at)) - return false; - - if (is_non_constant_shape_array (nl->sym) - && !gfc_notify_std (GFC_STD_F2003, "NAMELIST array object %qs " - "with nonconstant shape in namelist %qs at %L", - nl->sym->name, sym->name, &sym->declared_at)) - return false; - - if (nl->sym->ts.type == BT_CHARACTER - && (nl->sym->ts.u.cl->length == NULL - || !gfc_is_constant_expr (nl->sym->ts.u.cl->length)) - && !gfc_notify_std (GFC_STD_F2003, "NAMELIST object %qs with " - "nonconstant character length in " - "namelist %qs at %L", nl->sym->name, - sym->name, &sym->declared_at)) - return false; - - } - - /* Reject PRIVATE objects in a PUBLIC namelist. */ - if (gfc_check_symbol_access (sym)) - { - for (nl = sym->namelist; nl; nl = nl->next) - { - if (!nl->sym->attr.use_assoc - && !is_sym_host_assoc (nl->sym, sym->ns) - && !gfc_check_symbol_access (nl->sym)) - { - gfc_error ("NAMELIST object %qs was declared PRIVATE and " - "cannot be member of PUBLIC namelist %qs at %L", - nl->sym->name, sym->name, &sym->declared_at); - return false; - } - - if (nl->sym->ts.type == BT_DERIVED - && (nl->sym->ts.u.derived->attr.alloc_comp - || nl->sym->ts.u.derived->attr.pointer_comp)) - { - if (!gfc_notify_std (GFC_STD_F2003, "NAMELIST object %qs in " - "namelist %qs at %L with ALLOCATABLE " - "or POINTER components", nl->sym->name, - sym->name, &sym->declared_at)) - return false; - return true; - } - - /* Types with private components that came here by USE-association. */ - if (nl->sym->ts.type == BT_DERIVED - && derived_inaccessible (nl->sym->ts.u.derived)) - { - gfc_error ("NAMELIST object %qs has use-associated PRIVATE " - "components and cannot be member of namelist %qs at %L", - nl->sym->name, sym->name, &sym->declared_at); - return false; - } - - /* Types with private components that are defined in the same module. */ - if (nl->sym->ts.type == BT_DERIVED - && !is_sym_host_assoc (nl->sym->ts.u.derived, sym->ns) - && nl->sym->ts.u.derived->attr.private_comp) - { - gfc_error ("NAMELIST object %qs has PRIVATE components and " - "cannot be a member of PUBLIC namelist %qs at %L", - nl->sym->name, sym->name, &sym->declared_at); - return false; - } - } - } - - - /* 14.1.2 A module or internal procedure represent local entities - of the same type as a namelist member and so are not allowed. */ - for (nl = sym->namelist; nl; nl = nl->next) - { - if (nl->sym->ts.kind != 0 && nl->sym->attr.flavor == FL_VARIABLE) - continue; - - if (nl->sym->attr.function && nl->sym == nl->sym->result) - if ((nl->sym == sym->ns->proc_name) - || - (sym->ns->parent && nl->sym == sym->ns->parent->proc_name)) - continue; - - nlsym = NULL; - if (nl->sym->name) - gfc_find_symbol (nl->sym->name, sym->ns, 1, &nlsym); - if (nlsym && nlsym->attr.flavor == FL_PROCEDURE) - { - gfc_error ("PROCEDURE attribute conflicts with NAMELIST " - "attribute in %qs at %L", nlsym->name, - &sym->declared_at); - return false; - } - } - - return true; -} - - -static bool -resolve_fl_parameter (gfc_symbol *sym) -{ - /* A parameter array's shape needs to be constant. */ - if (sym->as != NULL - && (sym->as->type == AS_DEFERRED - || is_non_constant_shape_array (sym))) - { - gfc_error ("Parameter array %qs at %L cannot be automatic " - "or of deferred shape", sym->name, &sym->declared_at); - return false; - } - - /* Constraints on deferred type parameter. */ - if (!deferred_requirements (sym)) - return false; - - /* Make sure a parameter that has been implicitly typed still - matches the implicit type, since PARAMETER statements can precede - IMPLICIT statements. */ - if (sym->attr.implicit_type - && !gfc_compare_types (&sym->ts, gfc_get_default_type (sym->name, - sym->ns))) - { - gfc_error ("Implicitly typed PARAMETER %qs at %L doesn't match a " - "later IMPLICIT type", sym->name, &sym->declared_at); - return false; - } - - /* Make sure the types of derived parameters are consistent. This - type checking is deferred until resolution because the type may - refer to a derived type from the host. */ - if (sym->ts.type == BT_DERIVED - && !gfc_compare_types (&sym->ts, &sym->value->ts)) - { - gfc_error ("Incompatible derived type in PARAMETER at %L", - &sym->value->where); - return false; - } - - /* F03:C509,C514. */ - if (sym->ts.type == BT_CLASS) - { - gfc_error ("CLASS variable %qs at %L cannot have the PARAMETER attribute", - sym->name, &sym->declared_at); - return false; - } - - return true; -} - - -/* Called by resolve_symbol to check PDTs. */ - -static void -resolve_pdt (gfc_symbol* sym) -{ - gfc_symbol *derived = NULL; - gfc_actual_arglist *param; - gfc_component *c; - bool const_len_exprs = true; - bool assumed_len_exprs = false; - symbol_attribute *attr; - - if (sym->ts.type == BT_DERIVED) - { - derived = sym->ts.u.derived; - attr = &(sym->attr); - } - else if (sym->ts.type == BT_CLASS) - { - derived = CLASS_DATA (sym)->ts.u.derived; - attr = &(CLASS_DATA (sym)->attr); - } - else - gcc_unreachable (); - - gcc_assert (derived->attr.pdt_type); - - for (param = sym->param_list; param; param = param->next) - { - c = gfc_find_component (derived, param->name, false, true, NULL); - gcc_assert (c); - if (c->attr.pdt_kind) - continue; - - if (param->expr && !gfc_is_constant_expr (param->expr) - && c->attr.pdt_len) - const_len_exprs = false; - else if (param->spec_type == SPEC_ASSUMED) - assumed_len_exprs = true; - - if (param->spec_type == SPEC_DEFERRED - && !attr->allocatable && !attr->pointer) - gfc_error ("The object %qs at %L has a deferred LEN " - "parameter %qs and is neither allocatable " - "nor a pointer", sym->name, &sym->declared_at, - param->name); - - } - - if (!const_len_exprs - && (sym->ns->proc_name->attr.is_main_program - || sym->ns->proc_name->attr.flavor == FL_MODULE - || sym->attr.save != SAVE_NONE)) - gfc_error ("The AUTOMATIC object %qs at %L must not have the " - "SAVE attribute or be a variable declared in the " - "main program, a module or a submodule(F08/C513)", - sym->name, &sym->declared_at); - - if (assumed_len_exprs && !(sym->attr.dummy - || sym->attr.select_type_temporary || sym->attr.associate_var)) - gfc_error ("The object %qs at %L with ASSUMED type parameters " - "must be a dummy or a SELECT TYPE selector(F08/4.2)", - sym->name, &sym->declared_at); -} - - -/* Do anything necessary to resolve a symbol. Right now, we just - assume that an otherwise unknown symbol is a variable. This sort - of thing commonly happens for symbols in module. */ - -static void -resolve_symbol (gfc_symbol *sym) -{ - int check_constant, mp_flag; - gfc_symtree *symtree; - gfc_symtree *this_symtree; - gfc_namespace *ns; - gfc_component *c; - symbol_attribute class_attr; - gfc_array_spec *as; - bool saved_specification_expr; - - if (sym->resolve_symbol_called >= 1) - return; - sym->resolve_symbol_called = 1; - - /* No symbol will ever have union type; only components can be unions. - Union type declaration symbols have type BT_UNKNOWN but flavor FL_UNION - (just like derived type declaration symbols have flavor FL_DERIVED). */ - gcc_assert (sym->ts.type != BT_UNION); - - /* Coarrayed polymorphic objects with allocatable or pointer components are - yet unsupported for -fcoarray=lib. */ - if (flag_coarray == GFC_FCOARRAY_LIB && sym->ts.type == BT_CLASS - && sym->ts.u.derived && CLASS_DATA (sym) - && CLASS_DATA (sym)->attr.codimension - && CLASS_DATA (sym)->ts.u.derived - && (CLASS_DATA (sym)->ts.u.derived->attr.alloc_comp - || CLASS_DATA (sym)->ts.u.derived->attr.pointer_comp)) - { - gfc_error ("Sorry, allocatable/pointer components in polymorphic (CLASS) " - "type coarrays at %L are unsupported", &sym->declared_at); - return; - } - - if (sym->attr.artificial) - return; - - if (sym->attr.unlimited_polymorphic) - return; - - if (sym->attr.flavor == FL_UNKNOWN - || (sym->attr.flavor == FL_PROCEDURE && !sym->attr.intrinsic - && !sym->attr.generic && !sym->attr.external - && sym->attr.if_source == IFSRC_UNKNOWN - && sym->ts.type == BT_UNKNOWN)) - { - - /* If we find that a flavorless symbol is an interface in one of the - parent namespaces, find its symtree in this namespace, free the - symbol and set the symtree to point to the interface symbol. */ - for (ns = gfc_current_ns->parent; ns; ns = ns->parent) - { - symtree = gfc_find_symtree (ns->sym_root, sym->name); - if (symtree && (symtree->n.sym->generic || - (symtree->n.sym->attr.flavor == FL_PROCEDURE - && sym->ns->construct_entities))) - { - this_symtree = gfc_find_symtree (gfc_current_ns->sym_root, - sym->name); - if (this_symtree->n.sym == sym) - { - symtree->n.sym->refs++; - gfc_release_symbol (sym); - this_symtree->n.sym = symtree->n.sym; - return; - } - } - } - - /* Otherwise give it a flavor according to such attributes as - it has. */ - if (sym->attr.flavor == FL_UNKNOWN && sym->attr.external == 0 - && sym->attr.intrinsic == 0) - sym->attr.flavor = FL_VARIABLE; - else if (sym->attr.flavor == FL_UNKNOWN) - { - sym->attr.flavor = FL_PROCEDURE; - if (sym->attr.dimension) - sym->attr.function = 1; - } - } - - if (sym->attr.external && sym->ts.type != BT_UNKNOWN && !sym->attr.function) - gfc_add_function (&sym->attr, sym->name, &sym->declared_at); - - if (sym->attr.procedure && sym->attr.if_source != IFSRC_DECL - && !resolve_procedure_interface (sym)) - return; - - if (sym->attr.is_protected && !sym->attr.proc_pointer - && (sym->attr.procedure || sym->attr.external)) - { - if (sym->attr.external) - gfc_error ("PROTECTED attribute conflicts with EXTERNAL attribute " - "at %L", &sym->declared_at); - else - gfc_error ("PROCEDURE attribute conflicts with PROTECTED attribute " - "at %L", &sym->declared_at); - - return; - } - - if (sym->attr.flavor == FL_DERIVED && !resolve_fl_derived (sym)) - return; - - else if ((sym->attr.flavor == FL_STRUCT || sym->attr.flavor == FL_UNION) - && !resolve_fl_struct (sym)) - return; - - /* Symbols that are module procedures with results (functions) have - the types and array specification copied for type checking in - procedures that call them, as well as for saving to a module - file. These symbols can't stand the scrutiny that their results - can. */ - mp_flag = (sym->result != NULL && sym->result != sym); - - /* Make sure that the intrinsic is consistent with its internal - representation. This needs to be done before assigning a default - type to avoid spurious warnings. */ - if (sym->attr.flavor != FL_MODULE && sym->attr.intrinsic - && !gfc_resolve_intrinsic (sym, &sym->declared_at)) - return; - - /* Resolve associate names. */ - if (sym->assoc) - resolve_assoc_var (sym, true); - - /* Assign default type to symbols that need one and don't have one. */ - if (sym->ts.type == BT_UNKNOWN) - { - if (sym->attr.flavor == FL_VARIABLE || sym->attr.flavor == FL_PARAMETER) - { - gfc_set_default_type (sym, 1, NULL); - } - - if (sym->attr.flavor == FL_PROCEDURE && sym->attr.external - && !sym->attr.function && !sym->attr.subroutine - && gfc_get_default_type (sym->name, sym->ns)->type == BT_UNKNOWN) - gfc_add_subroutine (&sym->attr, sym->name, &sym->declared_at); - - if (sym->attr.flavor == FL_PROCEDURE && sym->attr.function) - { - /* The specific case of an external procedure should emit an error - in the case that there is no implicit type. */ - if (!mp_flag) - { - if (!sym->attr.mixed_entry_master) - gfc_set_default_type (sym, sym->attr.external, NULL); - } - else - { - /* Result may be in another namespace. */ - resolve_symbol (sym->result); - - if (!sym->result->attr.proc_pointer) - { - sym->ts = sym->result->ts; - sym->as = gfc_copy_array_spec (sym->result->as); - sym->attr.dimension = sym->result->attr.dimension; - sym->attr.pointer = sym->result->attr.pointer; - sym->attr.allocatable = sym->result->attr.allocatable; - sym->attr.contiguous = sym->result->attr.contiguous; - } - } - } - } - else if (mp_flag && sym->attr.flavor == FL_PROCEDURE && sym->attr.function) - { - bool saved_specification_expr = specification_expr; - bool saved_formal_arg_flag = formal_arg_flag; - - specification_expr = true; - formal_arg_flag = true; - gfc_resolve_array_spec (sym->result->as, false); - formal_arg_flag = saved_formal_arg_flag; - specification_expr = saved_specification_expr; - } - - if (sym->ts.type == BT_CLASS && sym->attr.class_ok && sym->ts.u.derived) - { - as = CLASS_DATA (sym)->as; - class_attr = CLASS_DATA (sym)->attr; - class_attr.pointer = class_attr.class_pointer; - } - else - { - class_attr = sym->attr; - as = sym->as; - } - - /* F2008, C530. */ - if (sym->attr.contiguous - && (!class_attr.dimension - || (as->type != AS_ASSUMED_SHAPE && as->type != AS_ASSUMED_RANK - && !class_attr.pointer))) - { - gfc_error ("%qs at %L has the CONTIGUOUS attribute but is not an " - "array pointer or an assumed-shape or assumed-rank array", - sym->name, &sym->declared_at); - return; - } - - /* Assumed size arrays and assumed shape arrays must be dummy - arguments. Array-spec's of implied-shape should have been resolved to - AS_EXPLICIT already. */ - - if (as) - { - /* If AS_IMPLIED_SHAPE makes it to here, it must be a bad - specification expression. */ - if (as->type == AS_IMPLIED_SHAPE) - { - int i; - for (i=0; i<as->rank; i++) - { - if (as->lower[i] != NULL && as->upper[i] == NULL) - { - gfc_error ("Bad specification for assumed size array at %L", - &as->lower[i]->where); - return; - } - } - gcc_unreachable(); - } - - if (((as->type == AS_ASSUMED_SIZE && !as->cp_was_assumed) - || as->type == AS_ASSUMED_SHAPE) - && !sym->attr.dummy && !sym->attr.select_type_temporary) - { - if (as->type == AS_ASSUMED_SIZE) - gfc_error ("Assumed size array at %L must be a dummy argument", - &sym->declared_at); - else - gfc_error ("Assumed shape array at %L must be a dummy argument", - &sym->declared_at); - return; - } - /* TS 29113, C535a. */ - if (as->type == AS_ASSUMED_RANK && !sym->attr.dummy - && !sym->attr.select_type_temporary - && !(cs_base && cs_base->current - && cs_base->current->op == EXEC_SELECT_RANK)) - { - gfc_error ("Assumed-rank array at %L must be a dummy argument", - &sym->declared_at); - return; - } - if (as->type == AS_ASSUMED_RANK - && (sym->attr.codimension || sym->attr.value)) - { - gfc_error ("Assumed-rank array at %L may not have the VALUE or " - "CODIMENSION attribute", &sym->declared_at); - return; - } - } - - /* Make sure symbols with known intent or optional are really dummy - variable. Because of ENTRY statement, this has to be deferred - until resolution time. */ - - if (!sym->attr.dummy - && (sym->attr.optional || sym->attr.intent != INTENT_UNKNOWN)) - { - gfc_error ("Symbol at %L is not a DUMMY variable", &sym->declared_at); - return; - } - - if (sym->attr.value && !sym->attr.dummy) - { - gfc_error ("%qs at %L cannot have the VALUE attribute because " - "it is not a dummy argument", sym->name, &sym->declared_at); - return; - } - - if (sym->attr.value && sym->ts.type == BT_CHARACTER) - { - gfc_charlen *cl = sym->ts.u.cl; - if (!cl || !cl->length || cl->length->expr_type != EXPR_CONSTANT) - { - gfc_error ("Character dummy variable %qs at %L with VALUE " - "attribute must have constant length", - sym->name, &sym->declared_at); - return; - } - - if (sym->ts.is_c_interop - && mpz_cmp_si (cl->length->value.integer, 1) != 0) - { - gfc_error ("C interoperable character dummy variable %qs at %L " - "with VALUE attribute must have length one", - sym->name, &sym->declared_at); - return; - } - } - - if (sym->ts.type == BT_DERIVED && !sym->attr.is_iso_c - && sym->ts.u.derived->attr.generic) - { - sym->ts.u.derived = gfc_find_dt_in_generic (sym->ts.u.derived); - if (!sym->ts.u.derived) - { - gfc_error ("The derived type %qs at %L is of type %qs, " - "which has not been defined", sym->name, - &sym->declared_at, sym->ts.u.derived->name); - sym->ts.type = BT_UNKNOWN; - return; - } - } - - /* Use the same constraints as TYPE(*), except for the type check - and that only scalars and assumed-size arrays are permitted. */ - if (sym->attr.ext_attr & (1 << EXT_ATTR_NO_ARG_CHECK)) - { - if (!sym->attr.dummy) - { - gfc_error ("Variable %s at %L with NO_ARG_CHECK attribute shall be " - "a dummy argument", sym->name, &sym->declared_at); - return; - } - - if (sym->ts.type != BT_ASSUMED && sym->ts.type != BT_INTEGER - && sym->ts.type != BT_REAL && sym->ts.type != BT_LOGICAL - && sym->ts.type != BT_COMPLEX) - { - gfc_error ("Variable %s at %L with NO_ARG_CHECK attribute shall be " - "of type TYPE(*) or of an numeric intrinsic type", - sym->name, &sym->declared_at); - return; - } - - if (sym->attr.allocatable || sym->attr.codimension - || sym->attr.pointer || sym->attr.value) - { - gfc_error ("Variable %s at %L with NO_ARG_CHECK attribute may not " - "have the ALLOCATABLE, CODIMENSION, POINTER or VALUE " - "attribute", sym->name, &sym->declared_at); - return; - } - - if (sym->attr.intent == INTENT_OUT) - { - gfc_error ("Variable %s at %L with NO_ARG_CHECK attribute may not " - "have the INTENT(OUT) attribute", - sym->name, &sym->declared_at); - return; - } - if (sym->attr.dimension && sym->as->type != AS_ASSUMED_SIZE) - { - gfc_error ("Variable %s at %L with NO_ARG_CHECK attribute shall " - "either be a scalar or an assumed-size array", - sym->name, &sym->declared_at); - return; - } - - /* Set the type to TYPE(*) and add a dimension(*) to ensure - NO_ARG_CHECK is correctly handled in trans*.c, e.g. with - packing. */ - sym->ts.type = BT_ASSUMED; - sym->as = gfc_get_array_spec (); - sym->as->type = AS_ASSUMED_SIZE; - sym->as->rank = 1; - sym->as->lower[0] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 1); - } - else if (sym->ts.type == BT_ASSUMED) - { - /* TS 29113, C407a. */ - if (!sym->attr.dummy) - { - gfc_error ("Assumed type of variable %s at %L is only permitted " - "for dummy variables", sym->name, &sym->declared_at); - return; - } - if (sym->attr.allocatable || sym->attr.codimension - || sym->attr.pointer || sym->attr.value) - { - gfc_error ("Assumed-type variable %s at %L may not have the " - "ALLOCATABLE, CODIMENSION, POINTER or VALUE attribute", - sym->name, &sym->declared_at); - return; - } - if (sym->attr.intent == INTENT_OUT) - { - gfc_error ("Assumed-type variable %s at %L may not have the " - "INTENT(OUT) attribute", - sym->name, &sym->declared_at); - return; - } - if (sym->attr.dimension && sym->as->type == AS_EXPLICIT) - { - gfc_error ("Assumed-type variable %s at %L shall not be an " - "explicit-shape array", sym->name, &sym->declared_at); - return; - } - } - - /* If the symbol is marked as bind(c), that it is declared at module level - scope and verify its type and kind. Do not do the latter for symbols - that are implicitly typed because that is handled in - gfc_set_default_type. Handle dummy arguments and procedure definitions - separately. Also, anything that is use associated is not handled here - but instead is handled in the module it is declared in. Finally, derived - type definitions are allowed to be BIND(C) since that only implies that - they're interoperable, and they are checked fully for interoperability - when a variable is declared of that type. */ - if (sym->attr.is_bind_c && sym->attr.use_assoc == 0 - && sym->attr.dummy == 0 && sym->attr.flavor != FL_PROCEDURE - && sym->attr.flavor != FL_DERIVED) - { - bool t = true; - - /* First, make sure the variable is declared at the - module-level scope (J3/04-007, Section 15.3). */ - if (sym->ns->proc_name->attr.flavor != FL_MODULE && - sym->attr.in_common == 0) - { - gfc_error ("Variable %qs at %L cannot be BIND(C) because it " - "is neither a COMMON block nor declared at the " - "module level scope", sym->name, &(sym->declared_at)); - t = false; - } - else if (sym->ts.type == BT_CHARACTER - && (sym->ts.u.cl == NULL || sym->ts.u.cl->length == NULL - || !gfc_is_constant_expr (sym->ts.u.cl->length) - || mpz_cmp_si (sym->ts.u.cl->length->value.integer, 1) != 0)) - { - gfc_error ("BIND(C) Variable %qs at %L must have length one", - sym->name, &sym->declared_at); - t = false; - } - else if (sym->common_head != NULL && sym->attr.implicit_type == 0) - { - t = verify_com_block_vars_c_interop (sym->common_head); - } - else if (sym->attr.implicit_type == 0) - { - /* If type() declaration, we need to verify that the components - of the given type are all C interoperable, etc. */ - if (sym->ts.type == BT_DERIVED && - sym->ts.u.derived->attr.is_c_interop != 1) - { - /* Make sure the user marked the derived type as BIND(C). If - not, call the verify routine. This could print an error - for the derived type more than once if multiple variables - of that type are declared. */ - if (sym->ts.u.derived->attr.is_bind_c != 1) - verify_bind_c_derived_type (sym->ts.u.derived); - t = false; - } - - /* Verify the variable itself as C interoperable if it - is BIND(C). It is not possible for this to succeed if - the verify_bind_c_derived_type failed, so don't have to handle - any error returned by verify_bind_c_derived_type. */ - t = verify_bind_c_sym (sym, &(sym->ts), sym->attr.in_common, - sym->common_block); - } - - if (!t) - { - /* clear the is_bind_c flag to prevent reporting errors more than - once if something failed. */ - sym->attr.is_bind_c = 0; - return; - } - } - - /* If a derived type symbol has reached this point, without its - type being declared, we have an error. Notice that most - conditions that produce undefined derived types have already - been dealt with. However, the likes of: - implicit type(t) (t) ..... call foo (t) will get us here if - the type is not declared in the scope of the implicit - statement. Change the type to BT_UNKNOWN, both because it is so - and to prevent an ICE. */ - if (sym->ts.type == BT_DERIVED && !sym->attr.is_iso_c - && sym->ts.u.derived->components == NULL - && !sym->ts.u.derived->attr.zero_comp) - { - gfc_error ("The derived type %qs at %L is of type %qs, " - "which has not been defined", sym->name, - &sym->declared_at, sym->ts.u.derived->name); - sym->ts.type = BT_UNKNOWN; - return; - } - - /* Make sure that the derived type has been resolved and that the - derived type is visible in the symbol's namespace, if it is a - module function and is not PRIVATE. */ - if (sym->ts.type == BT_DERIVED - && sym->ts.u.derived->attr.use_assoc - && sym->ns->proc_name - && sym->ns->proc_name->attr.flavor == FL_MODULE - && !resolve_fl_derived (sym->ts.u.derived)) - return; - - /* Unless the derived-type declaration is use associated, Fortran 95 - does not allow public entries of private derived types. - See 4.4.1 (F95) and 4.5.1.1 (F2003); and related interpretation - 161 in 95-006r3. */ - if (sym->ts.type == BT_DERIVED - && sym->ns->proc_name && sym->ns->proc_name->attr.flavor == FL_MODULE - && !sym->ts.u.derived->attr.use_assoc - && gfc_check_symbol_access (sym) - && !gfc_check_symbol_access (sym->ts.u.derived) - && !gfc_notify_std (GFC_STD_F2003, "PUBLIC %s %qs at %L of PRIVATE " - "derived type %qs", - (sym->attr.flavor == FL_PARAMETER) - ? "parameter" : "variable", - sym->name, &sym->declared_at, - sym->ts.u.derived->name)) - return; - - /* F2008, C1302. */ - if (sym->ts.type == BT_DERIVED - && ((sym->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV - && sym->ts.u.derived->intmod_sym_id == ISOFORTRAN_LOCK_TYPE) - || sym->ts.u.derived->attr.lock_comp) - && !sym->attr.codimension && !sym->ts.u.derived->attr.coarray_comp) - { - gfc_error ("Variable %s at %L of type LOCK_TYPE or with subcomponent of " - "type LOCK_TYPE must be a coarray", sym->name, - &sym->declared_at); - return; - } - - /* TS18508, C702/C703. */ - if (sym->ts.type == BT_DERIVED - && ((sym->ts.u.derived->from_intmod == INTMOD_ISO_FORTRAN_ENV - && sym->ts.u.derived->intmod_sym_id == ISOFORTRAN_EVENT_TYPE) - || sym->ts.u.derived->attr.event_comp) - && !sym->attr.codimension && !sym->ts.u.derived->attr.coarray_comp) - { - gfc_error ("Variable %s at %L of type EVENT_TYPE or with subcomponent of " - "type EVENT_TYPE must be a coarray", sym->name, - &sym->declared_at); - return; - } - - /* An assumed-size array with INTENT(OUT) shall not be of a type for which - default initialization is defined (5.1.2.4.4). */ - if (sym->ts.type == BT_DERIVED - && sym->attr.dummy - && sym->attr.intent == INTENT_OUT - && sym->as - && sym->as->type == AS_ASSUMED_SIZE) - { - for (c = sym->ts.u.derived->components; c; c = c->next) - { - if (c->initializer) - { - gfc_error ("The INTENT(OUT) dummy argument %qs at %L is " - "ASSUMED SIZE and so cannot have a default initializer", - sym->name, &sym->declared_at); - return; - } - } - } - - /* F2008, C542. */ - if (sym->ts.type == BT_DERIVED && sym->attr.dummy - && sym->attr.intent == INTENT_OUT && sym->attr.lock_comp) - { - gfc_error ("Dummy argument %qs at %L of LOCK_TYPE shall not be " - "INTENT(OUT)", sym->name, &sym->declared_at); - return; - } - - /* TS18508. */ - if (sym->ts.type == BT_DERIVED && sym->attr.dummy - && sym->attr.intent == INTENT_OUT && sym->attr.event_comp) - { - gfc_error ("Dummy argument %qs at %L of EVENT_TYPE shall not be " - "INTENT(OUT)", sym->name, &sym->declared_at); - return; - } - - /* F2008, C525. */ - if ((((sym->ts.type == BT_DERIVED && sym->ts.u.derived->attr.coarray_comp) - || (sym->ts.type == BT_CLASS && sym->attr.class_ok - && sym->ts.u.derived && CLASS_DATA (sym) - && CLASS_DATA (sym)->attr.coarray_comp)) - || class_attr.codimension) - && (sym->attr.result || sym->result == sym)) - { - gfc_error ("Function result %qs at %L shall not be a coarray or have " - "a coarray component", sym->name, &sym->declared_at); - return; - } - - /* F2008, C524. */ - if (sym->attr.codimension && sym->ts.type == BT_DERIVED - && sym->ts.u.derived->ts.is_iso_c) - { - gfc_error ("Variable %qs at %L of TYPE(C_PTR) or TYPE(C_FUNPTR) " - "shall not be a coarray", sym->name, &sym->declared_at); - return; - } - - /* F2008, C525. */ - if (((sym->ts.type == BT_DERIVED && sym->ts.u.derived->attr.coarray_comp) - || (sym->ts.type == BT_CLASS && sym->attr.class_ok - && sym->ts.u.derived && CLASS_DATA (sym) - && CLASS_DATA (sym)->attr.coarray_comp)) - && (class_attr.codimension || class_attr.pointer || class_attr.dimension - || class_attr.allocatable)) - { - gfc_error ("Variable %qs at %L with coarray component shall be a " - "nonpointer, nonallocatable scalar, which is not a coarray", - sym->name, &sym->declared_at); - return; - } - - /* F2008, C526. The function-result case was handled above. */ - if (class_attr.codimension - && !(class_attr.allocatable || sym->attr.dummy || sym->attr.save - || sym->attr.select_type_temporary - || sym->attr.associate_var - || (sym->ns->save_all && !sym->attr.automatic) - || sym->ns->proc_name->attr.flavor == FL_MODULE - || sym->ns->proc_name->attr.is_main_program - || sym->attr.function || sym->attr.result || sym->attr.use_assoc)) - { - gfc_error ("Variable %qs at %L is a coarray and is not ALLOCATABLE, SAVE " - "nor a dummy argument", sym->name, &sym->declared_at); - return; - } - /* F2008, C528. */ - else if (class_attr.codimension && !sym->attr.select_type_temporary - && !class_attr.allocatable && as && as->cotype == AS_DEFERRED) - { - gfc_error ("Coarray variable %qs at %L shall not have codimensions with " - "deferred shape", sym->name, &sym->declared_at); - return; - } - else if (class_attr.codimension && class_attr.allocatable && as - && (as->cotype != AS_DEFERRED || as->type != AS_DEFERRED)) - { - gfc_error ("Allocatable coarray variable %qs at %L must have " - "deferred shape", sym->name, &sym->declared_at); - return; - } - - /* F2008, C541. */ - if ((((sym->ts.type == BT_DERIVED && sym->ts.u.derived->attr.coarray_comp) - || (sym->ts.type == BT_CLASS && sym->attr.class_ok - && sym->ts.u.derived && CLASS_DATA (sym) - && CLASS_DATA (sym)->attr.coarray_comp)) - || (class_attr.codimension && class_attr.allocatable)) - && sym->attr.dummy && sym->attr.intent == INTENT_OUT) - { - gfc_error ("Variable %qs at %L is INTENT(OUT) and can thus not be an " - "allocatable coarray or have coarray components", - sym->name, &sym->declared_at); - return; - } - - if (class_attr.codimension && sym->attr.dummy - && sym->ns->proc_name && sym->ns->proc_name->attr.is_bind_c) - { - gfc_error ("Coarray dummy variable %qs at %L not allowed in BIND(C) " - "procedure %qs", sym->name, &sym->declared_at, - sym->ns->proc_name->name); - return; - } - - if (sym->ts.type == BT_LOGICAL - && ((sym->attr.function && sym->attr.is_bind_c && sym->result == sym) - || ((sym->attr.dummy || sym->attr.result) && sym->ns->proc_name - && sym->ns->proc_name->attr.is_bind_c))) - { - int i; - for (i = 0; gfc_logical_kinds[i].kind; i++) - if (gfc_logical_kinds[i].kind == sym->ts.kind) - break; - if (!gfc_logical_kinds[i].c_bool && sym->attr.dummy - && !gfc_notify_std (GFC_STD_GNU, "LOGICAL dummy argument %qs at " - "%L with non-C_Bool kind in BIND(C) procedure " - "%qs", sym->name, &sym->declared_at, - sym->ns->proc_name->name)) - return; - else if (!gfc_logical_kinds[i].c_bool - && !gfc_notify_std (GFC_STD_GNU, "LOGICAL result variable " - "%qs at %L with non-C_Bool kind in " - "BIND(C) procedure %qs", sym->name, - &sym->declared_at, - sym->attr.function ? sym->name - : sym->ns->proc_name->name)) - return; - } - - switch (sym->attr.flavor) - { - case FL_VARIABLE: - if (!resolve_fl_variable (sym, mp_flag)) - return; - break; - - case FL_PROCEDURE: - if (sym->formal && !sym->formal_ns) - { - /* Check that none of the arguments are a namelist. */ - gfc_formal_arglist *formal = sym->formal; - - for (; formal; formal = formal->next) - if (formal->sym && formal->sym->attr.flavor == FL_NAMELIST) - { - gfc_error ("Namelist %qs cannot be an argument to " - "subroutine or function at %L", - formal->sym->name, &sym->declared_at); - return; - } - } - - if (!resolve_fl_procedure (sym, mp_flag)) - return; - break; - - case FL_NAMELIST: - if (!resolve_fl_namelist (sym)) - return; - break; - - case FL_PARAMETER: - if (!resolve_fl_parameter (sym)) - return; - break; - - default: - break; - } - - /* Resolve array specifier. Check as well some constraints - on COMMON blocks. */ - - check_constant = sym->attr.in_common && !sym->attr.pointer; - - /* Set the formal_arg_flag so that check_conflict will not throw - an error for host associated variables in the specification - expression for an array_valued function. */ - if ((sym->attr.function || sym->attr.result) && sym->as) - formal_arg_flag = true; - - saved_specification_expr = specification_expr; - specification_expr = true; - gfc_resolve_array_spec (sym->as, check_constant); - specification_expr = saved_specification_expr; - - formal_arg_flag = false; - - /* Resolve formal namespaces. */ - if (sym->formal_ns && sym->formal_ns != gfc_current_ns - && !sym->attr.contained && !sym->attr.intrinsic) - gfc_resolve (sym->formal_ns); - - /* Make sure the formal namespace is present. */ - if (sym->formal && !sym->formal_ns) - { - gfc_formal_arglist *formal = sym->formal; - while (formal && !formal->sym) - formal = formal->next; - - if (formal) - { - sym->formal_ns = formal->sym->ns; - if (sym->formal_ns && sym->ns != formal->sym->ns) - sym->formal_ns->refs++; - } - } - - /* Check threadprivate restrictions. */ - if (sym->attr.threadprivate - && !(sym->attr.save || sym->attr.data || sym->attr.in_common) - && !(sym->ns->save_all && !sym->attr.automatic) - && sym->module == NULL - && (sym->ns->proc_name == NULL - || (sym->ns->proc_name->attr.flavor != FL_MODULE - && !sym->ns->proc_name->attr.is_main_program))) - gfc_error ("Threadprivate at %L isn't SAVEd", &sym->declared_at); - - /* Check omp declare target restrictions. */ - if (sym->attr.omp_declare_target - && sym->attr.flavor == FL_VARIABLE - && !sym->attr.save - && !(sym->ns->save_all && !sym->attr.automatic) - && (!sym->attr.in_common - && sym->module == NULL - && (sym->ns->proc_name == NULL - || (sym->ns->proc_name->attr.flavor != FL_MODULE - && !sym->ns->proc_name->attr.is_main_program)))) - gfc_error ("!$OMP DECLARE TARGET variable %qs at %L isn't SAVEd", - sym->name, &sym->declared_at); - - /* If we have come this far we can apply default-initializers, as - described in 14.7.5, to those variables that have not already - been assigned one. */ - if (sym->ts.type == BT_DERIVED - && !sym->value - && !sym->attr.allocatable - && !sym->attr.alloc_comp) - { - symbol_attribute *a = &sym->attr; - - if ((!a->save && !a->dummy && !a->pointer - && !a->in_common && !a->use_assoc - && a->referenced - && !((a->function || a->result) - && (!a->dimension - || sym->ts.u.derived->attr.alloc_comp - || sym->ts.u.derived->attr.pointer_comp)) - && !(a->function && sym != sym->result)) - || (a->dummy && !a->pointer && a->intent == INTENT_OUT - && sym->ns->proc_name->attr.if_source != IFSRC_IFBODY)) - apply_default_init (sym); - else if (a->function && sym->result && a->access != ACCESS_PRIVATE - && (sym->ts.u.derived->attr.alloc_comp - || sym->ts.u.derived->attr.pointer_comp)) - /* Mark the result symbol to be referenced, when it has allocatable - components. */ - sym->result->attr.referenced = 1; - } - - if (sym->ts.type == BT_CLASS && sym->ns == gfc_current_ns - && sym->attr.dummy && sym->attr.intent == INTENT_OUT - && sym->ns->proc_name->attr.if_source != IFSRC_IFBODY - && !CLASS_DATA (sym)->attr.class_pointer - && !CLASS_DATA (sym)->attr.allocatable) - apply_default_init (sym); - - /* If this symbol has a type-spec, check it. */ - if (sym->attr.flavor == FL_VARIABLE || sym->attr.flavor == FL_PARAMETER - || (sym->attr.flavor == FL_PROCEDURE && sym->attr.function)) - if (!resolve_typespec_used (&sym->ts, &sym->declared_at, sym->name)) - return; - - if (sym->param_list) - resolve_pdt (sym); -} - - -/************* Resolve DATA statements *************/ - -static struct -{ - gfc_data_value *vnode; - mpz_t left; -} -values; - - -/* Advance the values structure to point to the next value in the data list. */ - -static bool -next_data_value (void) -{ - while (mpz_cmp_ui (values.left, 0) == 0) - { - - if (values.vnode->next == NULL) - return false; - - values.vnode = values.vnode->next; - mpz_set (values.left, values.vnode->repeat); - } - - return true; -} - - -static bool -check_data_variable (gfc_data_variable *var, locus *where) -{ - gfc_expr *e; - mpz_t size; - mpz_t offset; - bool t; - ar_type mark = AR_UNKNOWN; - int i; - mpz_t section_index[GFC_MAX_DIMENSIONS]; - gfc_ref *ref; - gfc_array_ref *ar; - gfc_symbol *sym; - int has_pointer; - - if (!gfc_resolve_expr (var->expr)) - return false; - - ar = NULL; - mpz_init_set_si (offset, 0); - e = var->expr; - - if (e->expr_type == EXPR_FUNCTION && e->value.function.isym - && e->value.function.isym->id == GFC_ISYM_CAF_GET) - e = e->value.function.actual->expr; - - if (e->expr_type != EXPR_VARIABLE) - { - gfc_error ("Expecting definable entity near %L", where); - return false; - } - - sym = e->symtree->n.sym; - - if (sym->ns->is_block_data && !sym->attr.in_common) - { - gfc_error ("BLOCK DATA element %qs at %L must be in COMMON", - sym->name, &sym->declared_at); - return false; - } - - if (e->ref == NULL && sym->as) - { - gfc_error ("DATA array %qs at %L must be specified in a previous" - " declaration", sym->name, where); - return false; - } - - if (gfc_is_coindexed (e)) - { - gfc_error ("DATA element %qs at %L cannot have a coindex", sym->name, - where); - return false; - } - - has_pointer = sym->attr.pointer; - - for (ref = e->ref; ref; ref = ref->next) - { - if (ref->type == REF_COMPONENT && ref->u.c.component->attr.pointer) - has_pointer = 1; - - if (has_pointer) - { - if (ref->type == REF_ARRAY && ref->u.ar.type != AR_FULL) - { - gfc_error ("DATA element %qs at %L is a pointer and so must " - "be a full array", sym->name, where); - return false; - } - - if (values.vnode->expr->expr_type == EXPR_CONSTANT) - { - gfc_error ("DATA object near %L has the pointer attribute " - "and the corresponding DATA value is not a valid " - "initial-data-target", where); - return false; - } - } - - if (ref->type == REF_COMPONENT && ref->u.c.component->attr.allocatable) - { - gfc_error ("DATA element %qs at %L cannot have the ALLOCATABLE " - "attribute", ref->u.c.component->name, &e->where); - return false; - } - } - - if (e->rank == 0 || has_pointer) - { - mpz_init_set_ui (size, 1); - ref = NULL; - } - else - { - ref = e->ref; - - /* Find the array section reference. */ - for (ref = e->ref; ref; ref = ref->next) - { - if (ref->type != REF_ARRAY) - continue; - if (ref->u.ar.type == AR_ELEMENT) - continue; - break; - } - gcc_assert (ref); - - /* Set marks according to the reference pattern. */ - switch (ref->u.ar.type) - { - case AR_FULL: - mark = AR_FULL; - break; - - case AR_SECTION: - ar = &ref->u.ar; - /* Get the start position of array section. */ - gfc_get_section_index (ar, section_index, &offset); - mark = AR_SECTION; - break; - - default: - gcc_unreachable (); - } - - if (!gfc_array_size (e, &size)) - { - gfc_error ("Nonconstant array section at %L in DATA statement", - where); - mpz_clear (offset); - return false; - } - } - - t = true; - - while (mpz_cmp_ui (size, 0) > 0) - { - if (!next_data_value ()) - { - gfc_error ("DATA statement at %L has more variables than values", - where); - t = false; - break; - } - - t = gfc_check_assign (var->expr, values.vnode->expr, 0); - if (!t) - break; - - /* If we have more than one element left in the repeat count, - and we have more than one element left in the target variable, - then create a range assignment. */ - /* FIXME: Only done for full arrays for now, since array sections - seem tricky. */ - if (mark == AR_FULL && ref && ref->next == NULL - && mpz_cmp_ui (values.left, 1) > 0 && mpz_cmp_ui (size, 1) > 0) - { - mpz_t range; - - if (mpz_cmp (size, values.left) >= 0) - { - mpz_init_set (range, values.left); - mpz_sub (size, size, values.left); - mpz_set_ui (values.left, 0); - } - else - { - mpz_init_set (range, size); - mpz_sub (values.left, values.left, size); - mpz_set_ui (size, 0); - } - - t = gfc_assign_data_value (var->expr, values.vnode->expr, - offset, &range); - - mpz_add (offset, offset, range); - mpz_clear (range); - - if (!t) - break; - } - - /* Assign initial value to symbol. */ - else - { - mpz_sub_ui (values.left, values.left, 1); - mpz_sub_ui (size, size, 1); - - t = gfc_assign_data_value (var->expr, values.vnode->expr, - offset, NULL); - if (!t) - break; - - if (mark == AR_FULL) - mpz_add_ui (offset, offset, 1); - - /* Modify the array section indexes and recalculate the offset - for next element. */ - else if (mark == AR_SECTION) - gfc_advance_section (section_index, ar, &offset); - } - } - - if (mark == AR_SECTION) - { - for (i = 0; i < ar->dimen; i++) - mpz_clear (section_index[i]); - } - - mpz_clear (size); - mpz_clear (offset); - - return t; -} - - -static bool traverse_data_var (gfc_data_variable *, locus *); - -/* Iterate over a list of elements in a DATA statement. */ - -static bool -traverse_data_list (gfc_data_variable *var, locus *where) -{ - mpz_t trip; - iterator_stack frame; - gfc_expr *e, *start, *end, *step; - bool retval = true; - - mpz_init (frame.value); - mpz_init (trip); - - start = gfc_copy_expr (var->iter.start); - end = gfc_copy_expr (var->iter.end); - step = gfc_copy_expr (var->iter.step); - - if (!gfc_simplify_expr (start, 1) - || start->expr_type != EXPR_CONSTANT) - { - gfc_error ("start of implied-do loop at %L could not be " - "simplified to a constant value", &start->where); - retval = false; - goto cleanup; - } - if (!gfc_simplify_expr (end, 1) - || end->expr_type != EXPR_CONSTANT) - { - gfc_error ("end of implied-do loop at %L could not be " - "simplified to a constant value", &end->where); - retval = false; - goto cleanup; - } - if (!gfc_simplify_expr (step, 1) - || step->expr_type != EXPR_CONSTANT) - { - gfc_error ("step of implied-do loop at %L could not be " - "simplified to a constant value", &step->where); - retval = false; - goto cleanup; - } - if (mpz_cmp_si (step->value.integer, 0) == 0) - { - gfc_error ("step of implied-do loop at %L shall not be zero", - &step->where); - retval = false; - goto cleanup; - } - - mpz_set (trip, end->value.integer); - mpz_sub (trip, trip, start->value.integer); - mpz_add (trip, trip, step->value.integer); - - mpz_div (trip, trip, step->value.integer); - - mpz_set (frame.value, start->value.integer); - - frame.prev = iter_stack; - frame.variable = var->iter.var->symtree; - iter_stack = &frame; - - while (mpz_cmp_ui (trip, 0) > 0) - { - if (!traverse_data_var (var->list, where)) - { - retval = false; - goto cleanup; - } - - e = gfc_copy_expr (var->expr); - if (!gfc_simplify_expr (e, 1)) - { - gfc_free_expr (e); - retval = false; - goto cleanup; - } - - mpz_add (frame.value, frame.value, step->value.integer); - - mpz_sub_ui (trip, trip, 1); - } - -cleanup: - mpz_clear (frame.value); - mpz_clear (trip); - - gfc_free_expr (start); - gfc_free_expr (end); - gfc_free_expr (step); - - iter_stack = frame.prev; - return retval; -} - - -/* Type resolve variables in the variable list of a DATA statement. */ - -static bool -traverse_data_var (gfc_data_variable *var, locus *where) -{ - bool t; - - for (; var; var = var->next) - { - if (var->expr == NULL) - t = traverse_data_list (var, where); - else - t = check_data_variable (var, where); - - if (!t) - return false; - } - - return true; -} - - -/* Resolve the expressions and iterators associated with a data statement. - This is separate from the assignment checking because data lists should - only be resolved once. */ - -static bool -resolve_data_variables (gfc_data_variable *d) -{ - for (; d; d = d->next) - { - if (d->list == NULL) - { - if (!gfc_resolve_expr (d->expr)) - return false; - } - else - { - if (!gfc_resolve_iterator (&d->iter, false, true)) - return false; - - if (!resolve_data_variables (d->list)) - return false; - } - } - - return true; -} - - -/* Resolve a single DATA statement. We implement this by storing a pointer to - the value list into static variables, and then recursively traversing the - variables list, expanding iterators and such. */ - -static void -resolve_data (gfc_data *d) -{ - - if (!resolve_data_variables (d->var)) - return; - - values.vnode = d->value; - if (d->value == NULL) - mpz_set_ui (values.left, 0); - else - mpz_set (values.left, d->value->repeat); - - if (!traverse_data_var (d->var, &d->where)) - return; - - /* At this point, we better not have any values left. */ - - if (next_data_value ()) - gfc_error ("DATA statement at %L has more values than variables", - &d->where); -} - - -/* 12.6 Constraint: In a pure subprogram any variable which is in common or - accessed by host or use association, is a dummy argument to a pure function, - is a dummy argument with INTENT (IN) to a pure subroutine, or an object that - is storage associated with any such variable, shall not be used in the - following contexts: (clients of this function). */ - -/* Determines if a variable is not 'pure', i.e., not assignable within a pure - procedure. Returns zero if assignment is OK, nonzero if there is a - problem. */ -int -gfc_impure_variable (gfc_symbol *sym) -{ - gfc_symbol *proc; - gfc_namespace *ns; - - if (sym->attr.use_assoc || sym->attr.in_common) - return 1; - - /* Check if the symbol's ns is inside the pure procedure. */ - for (ns = gfc_current_ns; ns; ns = ns->parent) - { - if (ns == sym->ns) - break; - if (ns->proc_name->attr.flavor == FL_PROCEDURE && !sym->attr.function) - return 1; - } - - proc = sym->ns->proc_name; - if (sym->attr.dummy - && !sym->attr.value - && ((proc->attr.subroutine && sym->attr.intent == INTENT_IN) - || proc->attr.function)) - return 1; - - /* TODO: Sort out what can be storage associated, if anything, and include - it here. In principle equivalences should be scanned but it does not - seem to be possible to storage associate an impure variable this way. */ - return 0; -} - - -/* Test whether a symbol is pure or not. For a NULL pointer, checks if the - current namespace is inside a pure procedure. */ - -int -gfc_pure (gfc_symbol *sym) -{ - symbol_attribute attr; - gfc_namespace *ns; - - if (sym == NULL) - { - /* Check if the current namespace or one of its parents - belongs to a pure procedure. */ - for (ns = gfc_current_ns; ns; ns = ns->parent) - { - sym = ns->proc_name; - if (sym == NULL) - return 0; - attr = sym->attr; - if (attr.flavor == FL_PROCEDURE && attr.pure) - return 1; - } - return 0; - } - - attr = sym->attr; - - return attr.flavor == FL_PROCEDURE && attr.pure; -} - - -/* Test whether a symbol is implicitly pure or not. For a NULL pointer, - checks if the current namespace is implicitly pure. Note that this - function returns false for a PURE procedure. */ - -int -gfc_implicit_pure (gfc_symbol *sym) -{ - gfc_namespace *ns; - - if (sym == NULL) - { - /* Check if the current procedure is implicit_pure. Walk up - the procedure list until we find a procedure. */ - for (ns = gfc_current_ns; ns; ns = ns->parent) - { - sym = ns->proc_name; - if (sym == NULL) - return 0; - - if (sym->attr.flavor == FL_PROCEDURE) - break; - } - } - - return sym->attr.flavor == FL_PROCEDURE && sym->attr.implicit_pure - && !sym->attr.pure; -} - - -void -gfc_unset_implicit_pure (gfc_symbol *sym) -{ - gfc_namespace *ns; - - if (sym == NULL) - { - /* Check if the current procedure is implicit_pure. Walk up - the procedure list until we find a procedure. */ - for (ns = gfc_current_ns; ns; ns = ns->parent) - { - sym = ns->proc_name; - if (sym == NULL) - return; - - if (sym->attr.flavor == FL_PROCEDURE) - break; - } - } - - if (sym->attr.flavor == FL_PROCEDURE) - sym->attr.implicit_pure = 0; - else - sym->attr.pure = 0; -} - - -/* Test whether the current procedure is elemental or not. */ - -int -gfc_elemental (gfc_symbol *sym) -{ - symbol_attribute attr; - - if (sym == NULL) - sym = gfc_current_ns->proc_name; - if (sym == NULL) - return 0; - attr = sym->attr; - - return attr.flavor == FL_PROCEDURE && attr.elemental; -} - - -/* Warn about unused labels. */ - -static void -warn_unused_fortran_label (gfc_st_label *label) -{ - if (label == NULL) - return; - - warn_unused_fortran_label (label->left); - - if (label->defined == ST_LABEL_UNKNOWN) - return; - - switch (label->referenced) - { - case ST_LABEL_UNKNOWN: - gfc_warning (OPT_Wunused_label, "Label %d at %L defined but not used", - label->value, &label->where); - break; - - case ST_LABEL_BAD_TARGET: - gfc_warning (OPT_Wunused_label, - "Label %d at %L defined but cannot be used", - label->value, &label->where); - break; - - default: - break; - } - - warn_unused_fortran_label (label->right); -} - - -/* Returns the sequence type of a symbol or sequence. */ - -static seq_type -sequence_type (gfc_typespec ts) -{ - seq_type result; - gfc_component *c; - - switch (ts.type) - { - case BT_DERIVED: - - if (ts.u.derived->components == NULL) - return SEQ_NONDEFAULT; - - result = sequence_type (ts.u.derived->components->ts); - for (c = ts.u.derived->components->next; c; c = c->next) - if (sequence_type (c->ts) != result) - return SEQ_MIXED; - - return result; - - case BT_CHARACTER: - if (ts.kind != gfc_default_character_kind) - return SEQ_NONDEFAULT; - - return SEQ_CHARACTER; - - case BT_INTEGER: - if (ts.kind != gfc_default_integer_kind) - return SEQ_NONDEFAULT; - - return SEQ_NUMERIC; - - case BT_REAL: - if (!(ts.kind == gfc_default_real_kind - || ts.kind == gfc_default_double_kind)) - return SEQ_NONDEFAULT; - - return SEQ_NUMERIC; - - case BT_COMPLEX: - if (ts.kind != gfc_default_complex_kind) - return SEQ_NONDEFAULT; - - return SEQ_NUMERIC; - - case BT_LOGICAL: - if (ts.kind != gfc_default_logical_kind) - return SEQ_NONDEFAULT; - - return SEQ_NUMERIC; - - default: - return SEQ_NONDEFAULT; - } -} - - -/* Resolve derived type EQUIVALENCE object. */ - -static bool -resolve_equivalence_derived (gfc_symbol *derived, gfc_symbol *sym, gfc_expr *e) -{ - gfc_component *c = derived->components; - - if (!derived) - return true; - - /* Shall not be an object of nonsequence derived type. */ - if (!derived->attr.sequence) - { - gfc_error ("Derived type variable %qs at %L must have SEQUENCE " - "attribute to be an EQUIVALENCE object", sym->name, - &e->where); - return false; - } - - /* Shall not have allocatable components. */ - if (derived->attr.alloc_comp) - { - gfc_error ("Derived type variable %qs at %L cannot have ALLOCATABLE " - "components to be an EQUIVALENCE object",sym->name, - &e->where); - return false; - } - - if (sym->attr.in_common && gfc_has_default_initializer (sym->ts.u.derived)) - { - gfc_error ("Derived type variable %qs at %L with default " - "initialization cannot be in EQUIVALENCE with a variable " - "in COMMON", sym->name, &e->where); - return false; - } - - for (; c ; c = c->next) - { - if (gfc_bt_struct (c->ts.type) - && (!resolve_equivalence_derived(c->ts.u.derived, sym, e))) - return false; - - /* Shall not be an object of sequence derived type containing a pointer - in the structure. */ - if (c->attr.pointer) - { - gfc_error ("Derived type variable %qs at %L with pointer " - "component(s) cannot be an EQUIVALENCE object", - sym->name, &e->where); - return false; - } - } - return true; -} - - -/* Resolve equivalence object. - An EQUIVALENCE object shall not be a dummy argument, a pointer, a target, - an allocatable array, an object of nonsequence derived type, an object of - sequence derived type containing a pointer at any level of component - selection, an automatic object, a function name, an entry name, a result - name, a named constant, a structure component, or a subobject of any of - the preceding objects. A substring shall not have length zero. A - derived type shall not have components with default initialization nor - shall two objects of an equivalence group be initialized. - Either all or none of the objects shall have an protected attribute. - The simple constraints are done in symbol.c(check_conflict) and the rest - are implemented here. */ - -static void -resolve_equivalence (gfc_equiv *eq) -{ - gfc_symbol *sym; - gfc_symbol *first_sym; - gfc_expr *e; - gfc_ref *r; - locus *last_where = NULL; - seq_type eq_type, last_eq_type; - gfc_typespec *last_ts; - int object, cnt_protected; - const char *msg; - - last_ts = &eq->expr->symtree->n.sym->ts; - - first_sym = eq->expr->symtree->n.sym; - - cnt_protected = 0; - - for (object = 1; eq; eq = eq->eq, object++) - { - e = eq->expr; - - e->ts = e->symtree->n.sym->ts; - /* match_varspec might not know yet if it is seeing - array reference or substring reference, as it doesn't - know the types. */ - if (e->ref && e->ref->type == REF_ARRAY) - { - gfc_ref *ref = e->ref; - sym = e->symtree->n.sym; - - if (sym->attr.dimension) - { - ref->u.ar.as = sym->as; - ref = ref->next; - } - - /* For substrings, convert REF_ARRAY into REF_SUBSTRING. */ - if (e->ts.type == BT_CHARACTER - && ref - && ref->type == REF_ARRAY - && ref->u.ar.dimen == 1 - && ref->u.ar.dimen_type[0] == DIMEN_RANGE - && ref->u.ar.stride[0] == NULL) - { - gfc_expr *start = ref->u.ar.start[0]; - gfc_expr *end = ref->u.ar.end[0]; - void *mem = NULL; - - /* Optimize away the (:) reference. */ - if (start == NULL && end == NULL) - { - if (e->ref == ref) - e->ref = ref->next; - else - e->ref->next = ref->next; - mem = ref; - } - else - { - ref->type = REF_SUBSTRING; - if (start == NULL) - start = gfc_get_int_expr (gfc_charlen_int_kind, - NULL, 1); - ref->u.ss.start = start; - if (end == NULL && e->ts.u.cl) - end = gfc_copy_expr (e->ts.u.cl->length); - ref->u.ss.end = end; - ref->u.ss.length = e->ts.u.cl; - e->ts.u.cl = NULL; - } - ref = ref->next; - free (mem); - } - - /* Any further ref is an error. */ - if (ref) - { - gcc_assert (ref->type == REF_ARRAY); - gfc_error ("Syntax error in EQUIVALENCE statement at %L", - &ref->u.ar.where); - continue; - } - } - - if (!gfc_resolve_expr (e)) - continue; - - sym = e->symtree->n.sym; - - if (sym->attr.is_protected) - cnt_protected++; - if (cnt_protected > 0 && cnt_protected != object) - { - gfc_error ("Either all or none of the objects in the " - "EQUIVALENCE set at %L shall have the " - "PROTECTED attribute", - &e->where); - break; - } - - /* Shall not equivalence common block variables in a PURE procedure. */ - if (sym->ns->proc_name - && sym->ns->proc_name->attr.pure - && sym->attr.in_common) - { - /* Need to check for symbols that may have entered the pure - procedure via a USE statement. */ - bool saw_sym = false; - if (sym->ns->use_stmts) - { - gfc_use_rename *r; - for (r = sym->ns->use_stmts->rename; r; r = r->next) - if (strcmp(r->use_name, sym->name) == 0) saw_sym = true; - } - else - saw_sym = true; - - if (saw_sym) - gfc_error ("COMMON block member %qs at %L cannot be an " - "EQUIVALENCE object in the pure procedure %qs", - sym->name, &e->where, sym->ns->proc_name->name); - break; - } - - /* Shall not be a named constant. */ - if (e->expr_type == EXPR_CONSTANT) - { - gfc_error ("Named constant %qs at %L cannot be an EQUIVALENCE " - "object", sym->name, &e->where); - continue; - } - - if (e->ts.type == BT_DERIVED - && !resolve_equivalence_derived (e->ts.u.derived, sym, e)) - continue; - - /* Check that the types correspond correctly: - Note 5.28: - A numeric sequence structure may be equivalenced to another sequence - structure, an object of default integer type, default real type, double - precision real type, default logical type such that components of the - structure ultimately only become associated to objects of the same - kind. A character sequence structure may be equivalenced to an object - of default character kind or another character sequence structure. - Other objects may be equivalenced only to objects of the same type and - kind parameters. */ - - /* Identical types are unconditionally OK. */ - if (object == 1 || gfc_compare_types (last_ts, &sym->ts)) - goto identical_types; - - last_eq_type = sequence_type (*last_ts); - eq_type = sequence_type (sym->ts); - - /* Since the pair of objects is not of the same type, mixed or - non-default sequences can be rejected. */ - - msg = "Sequence %s with mixed components in EQUIVALENCE " - "statement at %L with different type objects"; - if ((object ==2 - && last_eq_type == SEQ_MIXED - && !gfc_notify_std (GFC_STD_GNU, msg, first_sym->name, last_where)) - || (eq_type == SEQ_MIXED - && !gfc_notify_std (GFC_STD_GNU, msg, sym->name, &e->where))) - continue; - - msg = "Non-default type object or sequence %s in EQUIVALENCE " - "statement at %L with objects of different type"; - if ((object ==2 - && last_eq_type == SEQ_NONDEFAULT - && !gfc_notify_std (GFC_STD_GNU, msg, first_sym->name, last_where)) - || (eq_type == SEQ_NONDEFAULT - && !gfc_notify_std (GFC_STD_GNU, msg, sym->name, &e->where))) - continue; - - msg ="Non-CHARACTER object %qs in default CHARACTER " - "EQUIVALENCE statement at %L"; - if (last_eq_type == SEQ_CHARACTER - && eq_type != SEQ_CHARACTER - && !gfc_notify_std (GFC_STD_GNU, msg, sym->name, &e->where)) - continue; - - msg ="Non-NUMERIC object %qs in default NUMERIC " - "EQUIVALENCE statement at %L"; - if (last_eq_type == SEQ_NUMERIC - && eq_type != SEQ_NUMERIC - && !gfc_notify_std (GFC_STD_GNU, msg, sym->name, &e->where)) - continue; - -identical_types: - - last_ts =&sym->ts; - last_where = &e->where; - - if (!e->ref) - continue; - - /* Shall not be an automatic array. */ - if (e->ref->type == REF_ARRAY && is_non_constant_shape_array (sym)) - { - gfc_error ("Array %qs at %L with non-constant bounds cannot be " - "an EQUIVALENCE object", sym->name, &e->where); - continue; - } - - r = e->ref; - while (r) - { - /* Shall not be a structure component. */ - if (r->type == REF_COMPONENT) - { - gfc_error ("Structure component %qs at %L cannot be an " - "EQUIVALENCE object", - r->u.c.component->name, &e->where); - break; - } - - /* A substring shall not have length zero. */ - if (r->type == REF_SUBSTRING) - { - if (compare_bound (r->u.ss.start, r->u.ss.end) == CMP_GT) - { - gfc_error ("Substring at %L has length zero", - &r->u.ss.start->where); - break; - } - } - r = r->next; - } - } -} - - -/* Function called by resolve_fntype to flag other symbols used in the - length type parameter specification of function results. */ - -static bool -flag_fn_result_spec (gfc_expr *expr, - gfc_symbol *sym, - int *f ATTRIBUTE_UNUSED) -{ - gfc_namespace *ns; - gfc_symbol *s; - - if (expr->expr_type == EXPR_VARIABLE) - { - s = expr->symtree->n.sym; - for (ns = s->ns; ns; ns = ns->parent) - if (!ns->parent) - break; - - if (sym == s) - { - gfc_error ("Self reference in character length expression " - "for %qs at %L", sym->name, &expr->where); - return true; - } - - if (!s->fn_result_spec - && s->attr.flavor == FL_PARAMETER) - { - /* Function contained in a module.... */ - if (ns->proc_name && ns->proc_name->attr.flavor == FL_MODULE) - { - gfc_symtree *st; - s->fn_result_spec = 1; - /* Make sure that this symbol is translated as a module - variable. */ - st = gfc_get_unique_symtree (ns); - st->n.sym = s; - s->refs++; - } - /* ... which is use associated and called. */ - else if (s->attr.use_assoc || s->attr.used_in_submodule - || - /* External function matched with an interface. */ - (s->ns->proc_name - && ((s->ns == ns - && s->ns->proc_name->attr.if_source == IFSRC_DECL) - || s->ns->proc_name->attr.if_source == IFSRC_IFBODY) - && s->ns->proc_name->attr.function)) - s->fn_result_spec = 1; - } - } - return false; -} - - -/* Resolve function and ENTRY types, issue diagnostics if needed. */ - -static void -resolve_fntype (gfc_namespace *ns) -{ - gfc_entry_list *el; - gfc_symbol *sym; - - if (ns->proc_name == NULL || !ns->proc_name->attr.function) - return; - - /* If there are any entries, ns->proc_name is the entry master - synthetic symbol and ns->entries->sym actual FUNCTION symbol. */ - if (ns->entries) - sym = ns->entries->sym; - else - sym = ns->proc_name; - if (sym->result == sym - && sym->ts.type == BT_UNKNOWN - && !gfc_set_default_type (sym, 0, NULL) - && !sym->attr.untyped) - { - gfc_error ("Function %qs at %L has no IMPLICIT type", - sym->name, &sym->declared_at); - sym->attr.untyped = 1; - } - - if (sym->ts.type == BT_DERIVED && !sym->ts.u.derived->attr.use_assoc - && !sym->attr.contained - && !gfc_check_symbol_access (sym->ts.u.derived) - && gfc_check_symbol_access (sym)) - { - gfc_notify_std (GFC_STD_F2003, "PUBLIC function %qs at " - "%L of PRIVATE type %qs", sym->name, - &sym->declared_at, sym->ts.u.derived->name); - } - - if (ns->entries) - for (el = ns->entries->next; el; el = el->next) - { - if (el->sym->result == el->sym - && el->sym->ts.type == BT_UNKNOWN - && !gfc_set_default_type (el->sym, 0, NULL) - && !el->sym->attr.untyped) - { - gfc_error ("ENTRY %qs at %L has no IMPLICIT type", - el->sym->name, &el->sym->declared_at); - el->sym->attr.untyped = 1; - } - } - - if (sym->ts.type == BT_CHARACTER) - gfc_traverse_expr (sym->ts.u.cl->length, sym, flag_fn_result_spec, 0); -} - - -/* 12.3.2.1.1 Defined operators. */ - -static bool -check_uop_procedure (gfc_symbol *sym, locus where) -{ - gfc_formal_arglist *formal; - - if (!sym->attr.function) - { - gfc_error ("User operator procedure %qs at %L must be a FUNCTION", - sym->name, &where); - return false; - } - - if (sym->ts.type == BT_CHARACTER - && !((sym->ts.u.cl && sym->ts.u.cl->length) || sym->ts.deferred) - && !(sym->result && ((sym->result->ts.u.cl - && sym->result->ts.u.cl->length) || sym->result->ts.deferred))) - { - gfc_error ("User operator procedure %qs at %L cannot be assumed " - "character length", sym->name, &where); - return false; - } - - formal = gfc_sym_get_dummy_args (sym); - if (!formal || !formal->sym) - { - gfc_error ("User operator procedure %qs at %L must have at least " - "one argument", sym->name, &where); - return false; - } - - if (formal->sym->attr.intent != INTENT_IN) - { - gfc_error ("First argument of operator interface at %L must be " - "INTENT(IN)", &where); - return false; - } - - if (formal->sym->attr.optional) - { - gfc_error ("First argument of operator interface at %L cannot be " - "optional", &where); - return false; - } - - formal = formal->next; - if (!formal || !formal->sym) - return true; - - if (formal->sym->attr.intent != INTENT_IN) - { - gfc_error ("Second argument of operator interface at %L must be " - "INTENT(IN)", &where); - return false; - } - - if (formal->sym->attr.optional) - { - gfc_error ("Second argument of operator interface at %L cannot be " - "optional", &where); - return false; - } - - if (formal->next) - { - gfc_error ("Operator interface at %L must have, at most, two " - "arguments", &where); - return false; - } - - return true; -} - -static void -gfc_resolve_uops (gfc_symtree *symtree) -{ - gfc_interface *itr; - - if (symtree == NULL) - return; - - gfc_resolve_uops (symtree->left); - gfc_resolve_uops (symtree->right); - - for (itr = symtree->n.uop->op; itr; itr = itr->next) - check_uop_procedure (itr->sym, itr->sym->declared_at); -} - - -/* Examine all of the expressions associated with a program unit, - assign types to all intermediate expressions, make sure that all - assignments are to compatible types and figure out which names - refer to which functions or subroutines. It doesn't check code - block, which is handled by gfc_resolve_code. */ - -static void -resolve_types (gfc_namespace *ns) -{ - gfc_namespace *n; - gfc_charlen *cl; - gfc_data *d; - gfc_equiv *eq; - gfc_namespace* old_ns = gfc_current_ns; - bool recursive = ns->proc_name && ns->proc_name->attr.recursive; - - if (ns->types_resolved) - return; - - /* Check that all IMPLICIT types are ok. */ - if (!ns->seen_implicit_none) - { - unsigned letter; - for (letter = 0; letter != GFC_LETTERS; ++letter) - if (ns->set_flag[letter] - && !resolve_typespec_used (&ns->default_type[letter], - &ns->implicit_loc[letter], NULL)) - return; - } - - gfc_current_ns = ns; - - resolve_entries (ns); - - resolve_common_vars (&ns->blank_common, false); - resolve_common_blocks (ns->common_root); - - resolve_contained_functions (ns); - - if (ns->proc_name && ns->proc_name->attr.flavor == FL_PROCEDURE - && ns->proc_name->attr.if_source == IFSRC_IFBODY) - gfc_resolve_formal_arglist (ns->proc_name); - - gfc_traverse_ns (ns, resolve_bind_c_derived_types); - - for (cl = ns->cl_list; cl; cl = cl->next) - resolve_charlen (cl); - - gfc_traverse_ns (ns, resolve_symbol); - - resolve_fntype (ns); - - for (n = ns->contained; n; n = n->sibling) - { - if (gfc_pure (ns->proc_name) && !gfc_pure (n->proc_name)) - gfc_error ("Contained procedure %qs at %L of a PURE procedure must " - "also be PURE", n->proc_name->name, - &n->proc_name->declared_at); - - resolve_types (n); - } - - forall_flag = 0; - gfc_do_concurrent_flag = 0; - gfc_check_interfaces (ns); - - gfc_traverse_ns (ns, resolve_values); - - if (ns->save_all || (!flag_automatic && !recursive)) - gfc_save_all (ns); - - iter_stack = NULL; - for (d = ns->data; d; d = d->next) - resolve_data (d); - - iter_stack = NULL; - gfc_traverse_ns (ns, gfc_formalize_init_value); - - gfc_traverse_ns (ns, gfc_verify_binding_labels); - - for (eq = ns->equiv; eq; eq = eq->next) - resolve_equivalence (eq); - - /* Warn about unused labels. */ - if (warn_unused_label) - warn_unused_fortran_label (ns->st_labels); - - gfc_resolve_uops (ns->uop_root); - - gfc_traverse_ns (ns, gfc_verify_DTIO_procedures); - - gfc_resolve_omp_declare_simd (ns); - - gfc_resolve_omp_udrs (ns->omp_udr_root); - - ns->types_resolved = 1; - - gfc_current_ns = old_ns; -} - - -/* Call gfc_resolve_code recursively. */ - -static void -resolve_codes (gfc_namespace *ns) -{ - gfc_namespace *n; - bitmap_obstack old_obstack; - - if (ns->resolved == 1) - return; - - for (n = ns->contained; n; n = n->sibling) - resolve_codes (n); - - gfc_current_ns = ns; - - /* Don't clear 'cs_base' if this is the namespace of a BLOCK construct. */ - if (!(ns->proc_name && ns->proc_name->attr.flavor == FL_LABEL)) - cs_base = NULL; - - /* Set to an out of range value. */ - current_entry_id = -1; - - old_obstack = labels_obstack; - bitmap_obstack_initialize (&labels_obstack); - - gfc_resolve_oacc_declare (ns); - gfc_resolve_oacc_routines (ns); - gfc_resolve_omp_local_vars (ns); - gfc_resolve_code (ns->code, ns); - - bitmap_obstack_release (&labels_obstack); - labels_obstack = old_obstack; -} - - -/* This function is called after a complete program unit has been compiled. - Its purpose is to examine all of the expressions associated with a program - unit, assign types to all intermediate expressions, make sure that all - assignments are to compatible types and figure out which names refer to - which functions or subroutines. */ - -void -gfc_resolve (gfc_namespace *ns) -{ - gfc_namespace *old_ns; - code_stack *old_cs_base; - struct gfc_omp_saved_state old_omp_state; - - if (ns->resolved) - return; - - ns->resolved = -1; - old_ns = gfc_current_ns; - old_cs_base = cs_base; - - /* As gfc_resolve can be called during resolution of an OpenMP construct - body, we should clear any state associated to it, so that say NS's - DO loops are not interpreted as OpenMP loops. */ - if (!ns->construct_entities) - gfc_omp_save_and_clear_state (&old_omp_state); - - resolve_types (ns); - component_assignment_level = 0; - resolve_codes (ns); - - gfc_current_ns = old_ns; - cs_base = old_cs_base; - ns->resolved = 1; - - gfc_run_passes (ns); - - if (!ns->construct_entities) - gfc_omp_restore_state (&old_omp_state); -} |