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/cp/semantics.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/cp/semantics.c')
-rw-r--r-- | gcc/cp/semantics.c | 12340 |
1 files changed, 0 insertions, 12340 deletions
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c deleted file mode 100644 index 089ea5f..0000000 --- a/gcc/cp/semantics.c +++ /dev/null @@ -1,12340 +0,0 @@ -/* Perform the semantic phase of parsing, i.e., the process of - building tree structure, checking semantic consistency, and - building RTL. These routines are used both during actual parsing - and during the instantiation of template functions. - - Copyright (C) 1998-2022 Free Software Foundation, Inc. - Written by Mark Mitchell (mmitchell@usa.net) based on code found - formerly in parse.y and pt.c. - - 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 "target.h" -#include "bitmap.h" -#include "cp-tree.h" -#include "stringpool.h" -#include "cgraph.h" -#include "stmt.h" -#include "varasm.h" -#include "stor-layout.h" -#include "c-family/c-objc.h" -#include "tree-inline.h" -#include "intl.h" -#include "tree-iterator.h" -#include "omp-general.h" -#include "convert.h" -#include "stringpool.h" -#include "attribs.h" -#include "gomp-constants.h" -#include "predict.h" -#include "memmodel.h" - -/* There routines provide a modular interface to perform many parsing - operations. They may therefore be used during actual parsing, or - during template instantiation, which may be regarded as a - degenerate form of parsing. */ - -static tree maybe_convert_cond (tree); -static tree finalize_nrv_r (tree *, int *, void *); -static tree capture_decltype (tree); - -/* Used for OpenMP non-static data member privatization. */ - -static hash_map<tree, tree> *omp_private_member_map; -static vec<tree> omp_private_member_vec; -static bool omp_private_member_ignore_next; - - -/* Deferred Access Checking Overview - --------------------------------- - - Most C++ expressions and declarations require access checking - to be performed during parsing. However, in several cases, - this has to be treated differently. - - For member declarations, access checking has to be deferred - until more information about the declaration is known. For - example: - - class A { - typedef int X; - public: - X f(); - }; - - A::X A::f(); - A::X g(); - - When we are parsing the function return type `A::X', we don't - really know if this is allowed until we parse the function name. - - Furthermore, some contexts require that access checking is - never performed at all. These include class heads, and template - instantiations. - - Typical use of access checking functions is described here: - - 1. When we enter a context that requires certain access checking - mode, the function `push_deferring_access_checks' is called with - DEFERRING argument specifying the desired mode. Access checking - may be performed immediately (dk_no_deferred), deferred - (dk_deferred), or not performed (dk_no_check). - - 2. When a declaration such as a type, or a variable, is encountered, - the function `perform_or_defer_access_check' is called. It - maintains a vector of all deferred checks. - - 3. The global `current_class_type' or `current_function_decl' is then - setup by the parser. `enforce_access' relies on these information - to check access. - - 4. Upon exiting the context mentioned in step 1, - `perform_deferred_access_checks' is called to check all declaration - stored in the vector. `pop_deferring_access_checks' is then - called to restore the previous access checking mode. - - In case of parsing error, we simply call `pop_deferring_access_checks' - without `perform_deferred_access_checks'. */ - -struct GTY(()) deferred_access { - /* A vector representing name-lookups for which we have deferred - checking access controls. We cannot check the accessibility of - names used in a decl-specifier-seq until we know what is being - declared because code like: - - class A { - class B {}; - B* f(); - } - - A::B* A::f() { return 0; } - - is valid, even though `A::B' is not generally accessible. */ - vec<deferred_access_check, va_gc> *deferred_access_checks; - - /* The current mode of access checks. */ - enum deferring_kind deferring_access_checks_kind; -}; - -/* Data for deferred access checking. */ -static GTY(()) vec<deferred_access, va_gc> *deferred_access_stack; -static GTY(()) unsigned deferred_access_no_check; - -/* Save the current deferred access states and start deferred - access checking iff DEFER_P is true. */ - -void -push_deferring_access_checks (deferring_kind deferring) -{ - /* For context like template instantiation, access checking - disabling applies to all nested context. */ - if (deferred_access_no_check || deferring == dk_no_check) - deferred_access_no_check++; - else - { - deferred_access e = {NULL, deferring}; - vec_safe_push (deferred_access_stack, e); - } -} - -/* Save the current deferred access states and start deferred access - checking, continuing the set of deferred checks in CHECKS. */ - -void -reopen_deferring_access_checks (vec<deferred_access_check, va_gc> * checks) -{ - push_deferring_access_checks (dk_deferred); - if (!deferred_access_no_check) - deferred_access_stack->last().deferred_access_checks = checks; -} - -/* Resume deferring access checks again after we stopped doing - this previously. */ - -void -resume_deferring_access_checks (void) -{ - if (!deferred_access_no_check) - deferred_access_stack->last().deferring_access_checks_kind = dk_deferred; -} - -/* Stop deferring access checks. */ - -void -stop_deferring_access_checks (void) -{ - if (!deferred_access_no_check) - deferred_access_stack->last().deferring_access_checks_kind = dk_no_deferred; -} - -/* Discard the current deferred access checks and restore the - previous states. */ - -void -pop_deferring_access_checks (void) -{ - if (deferred_access_no_check) - deferred_access_no_check--; - else - deferred_access_stack->pop (); -} - -/* Returns a TREE_LIST representing the deferred checks. - The TREE_PURPOSE of each node is the type through which the - access occurred; the TREE_VALUE is the declaration named. - */ - -vec<deferred_access_check, va_gc> * -get_deferred_access_checks (void) -{ - if (deferred_access_no_check) - return NULL; - else - return (deferred_access_stack->last().deferred_access_checks); -} - -/* Take current deferred checks and combine with the - previous states if we also defer checks previously. - Otherwise perform checks now. */ - -void -pop_to_parent_deferring_access_checks (void) -{ - if (deferred_access_no_check) - deferred_access_no_check--; - else - { - vec<deferred_access_check, va_gc> *checks; - deferred_access *ptr; - - checks = (deferred_access_stack->last ().deferred_access_checks); - - deferred_access_stack->pop (); - ptr = &deferred_access_stack->last (); - if (ptr->deferring_access_checks_kind == dk_no_deferred) - { - /* Check access. */ - perform_access_checks (checks, tf_warning_or_error); - } - else - { - /* Merge with parent. */ - int i, j; - deferred_access_check *chk, *probe; - - FOR_EACH_VEC_SAFE_ELT (checks, i, chk) - { - FOR_EACH_VEC_SAFE_ELT (ptr->deferred_access_checks, j, probe) - { - if (probe->binfo == chk->binfo && - probe->decl == chk->decl && - probe->diag_decl == chk->diag_decl) - goto found; - } - /* Insert into parent's checks. */ - vec_safe_push (ptr->deferred_access_checks, *chk); - found:; - } - } - } -} - -/* Called from enforce_access. A class has attempted (but failed) to access - DECL. It is already established that a baseclass of that class, - PARENT_BINFO, has private access to DECL. Examine certain special cases - to find a decl that accurately describes the source of the problem. If - none of the special cases apply, simply return DECL as the source of the - problem. */ - -static tree -get_class_access_diagnostic_decl (tree parent_binfo, tree decl) -{ - /* When a class is denied access to a decl in a baseclass, most of the - time it is because the decl itself was declared as private at the point - of declaration. - - However, in C++, there are (at least) two situations in which a decl - can be private even though it was not originally defined as such. - These two situations only apply if a baseclass had private access to - DECL (this function is only called if that is the case). */ - - /* We should first check whether the reason the parent had private access - to DECL was simply because DECL was created and declared as private in - the parent. If it was, then DECL is definitively the source of the - problem. */ - if (SAME_BINFO_TYPE_P (context_for_name_lookup (decl), - BINFO_TYPE (parent_binfo))) - return decl; - - /* 1. If the "using" keyword is used to inherit DECL within the parent, - this may cause DECL to be private, so we should return the using - statement as the source of the problem. - - Scan the fields of PARENT_BINFO and see if there are any using decls. If - there are, see if they inherit DECL. If they do, that's where DECL must - have been declared private. */ - - for (tree parent_field = TYPE_FIELDS (BINFO_TYPE (parent_binfo)); - parent_field; - parent_field = DECL_CHAIN (parent_field)) - /* Not necessary, but also check TREE_PRIVATE for the sake of - eliminating obviously non-relevant using decls. */ - if (TREE_CODE (parent_field) == USING_DECL - && TREE_PRIVATE (parent_field)) - { - tree decl_stripped = strip_using_decl (parent_field); - - /* The using statement might be overloaded. If so, we need to - check all of the overloads. */ - for (ovl_iterator iter (decl_stripped); iter; ++iter) - /* If equal, the using statement inherits DECL, and so is the - source of the access failure, so return it. */ - if (*iter == decl) - return parent_field; - } - - /* 2. If DECL was privately inherited by the parent class, then DECL will - be inaccessible, even though it may originally have been accessible to - deriving classes. In that case, the fault lies with the parent, since it - used a private inheritance, so we return the parent as the source of the - problem. - - Since this is the last check, we just assume it's true. At worst, it - will simply point to the class that failed to give access, which is - technically true. */ - return TYPE_NAME (BINFO_TYPE (parent_binfo)); -} - -/* If the current scope isn't allowed to access DECL along - BASETYPE_PATH, give an error, or if we're parsing a function or class - template, defer the access check to be performed at instantiation time. - The most derived class in BASETYPE_PATH is the one used to qualify DECL. - DIAG_DECL is the declaration to use in the error diagnostic. */ - -static bool -enforce_access (tree basetype_path, tree decl, tree diag_decl, - tsubst_flags_t complain, access_failure_info *afi = NULL) -{ - gcc_assert (TREE_CODE (basetype_path) == TREE_BINFO); - - if (flag_new_inheriting_ctors - && DECL_INHERITED_CTOR (decl)) - { - /* 7.3.3/18: The additional constructors are accessible if they would be - accessible when used to construct an object of the corresponding base - class. */ - decl = strip_inheriting_ctors (decl); - basetype_path = lookup_base (basetype_path, DECL_CONTEXT (decl), - ba_any, NULL, complain); - } - - tree cs = current_scope (); - if (processing_template_decl - && (CLASS_TYPE_P (cs) || TREE_CODE (cs) == FUNCTION_DECL)) - if (tree template_info = get_template_info (cs)) - { - /* When parsing a function or class template, we in general need to - defer access checks until template instantiation time, since a friend - declaration may grant access only to a particular specialization of - the template. */ - - if (accessible_p (basetype_path, decl, /*consider_local_p=*/true)) - /* But if the member is deemed accessible at parse time, then we can - assume it'll be accessible at instantiation time. */ - return true; - - /* Access of a dependent decl should be rechecked after tsubst'ing - into the user of the decl, rather than explicitly deferring the - check here. */ - gcc_assert (!uses_template_parms (decl)); - if (TREE_CODE (decl) == FIELD_DECL) - gcc_assert (!uses_template_parms (DECL_CONTEXT (decl))); - - /* Defer this access check until instantiation time. */ - deferred_access_check access_check; - access_check.binfo = basetype_path; - access_check.decl = decl; - access_check.diag_decl = diag_decl; - access_check.loc = input_location; - vec_safe_push (TI_DEFERRED_ACCESS_CHECKS (template_info), access_check); - return true; - } - - if (!accessible_p (basetype_path, decl, /*consider_local_p=*/true)) - { - if (flag_new_inheriting_ctors) - diag_decl = strip_inheriting_ctors (diag_decl); - if (complain & tf_error) - { - access_kind access_failure_reason = ak_none; - - /* By default, using the decl as the source of the problem will - usually give correct results. */ - tree diag_location = diag_decl; - - /* However, if a parent of BASETYPE_PATH had private access to decl, - then it actually might be the case that the source of the problem - is not DECL. */ - tree parent_binfo = get_parent_with_private_access (decl, - basetype_path); - - /* So if a parent did have private access, then we need to do - special checks to obtain the best diagnostic location decl. */ - if (parent_binfo != NULL_TREE) - { - diag_location = get_class_access_diagnostic_decl (parent_binfo, - diag_decl); - - /* We also at this point know that the reason access failed was - because decl was private. */ - access_failure_reason = ak_private; - } - - /* Finally, generate an error message. */ - complain_about_access (decl, diag_decl, diag_location, true, - access_failure_reason); - } - if (afi) - afi->record_access_failure (basetype_path, decl, diag_decl); - return false; - } - - return true; -} - -/* Perform the access checks in CHECKS. The TREE_PURPOSE of each node - is the BINFO indicating the qualifying scope used to access the - DECL node stored in the TREE_VALUE of the node. If CHECKS is empty - or we aren't in SFINAE context or all the checks succeed return TRUE, - otherwise FALSE. */ - -bool -perform_access_checks (vec<deferred_access_check, va_gc> *checks, - tsubst_flags_t complain) -{ - int i; - deferred_access_check *chk; - location_t loc = input_location; - bool ok = true; - - if (!checks) - return true; - - FOR_EACH_VEC_SAFE_ELT (checks, i, chk) - { - input_location = chk->loc; - ok &= enforce_access (chk->binfo, chk->decl, chk->diag_decl, complain); - } - - input_location = loc; - return (complain & tf_error) ? true : ok; -} - -/* Perform the deferred access checks. - - After performing the checks, we still have to keep the list - `deferred_access_stack->deferred_access_checks' since we may want - to check access for them again later in a different context. - For example: - - class A { - typedef int X; - static X a; - }; - A::X A::a, x; // No error for `A::a', error for `x' - - We have to perform deferred access of `A::X', first with `A::a', - next with `x'. Return value like perform_access_checks above. */ - -bool -perform_deferred_access_checks (tsubst_flags_t complain) -{ - return perform_access_checks (get_deferred_access_checks (), complain); -} - -/* Defer checking the accessibility of DECL, when looked up in - BINFO. DIAG_DECL is the declaration to use to print diagnostics. - Return value like perform_access_checks above. - If non-NULL, report failures to AFI. */ - -bool -perform_or_defer_access_check (tree binfo, tree decl, tree diag_decl, - tsubst_flags_t complain, - access_failure_info *afi) -{ - int i; - deferred_access *ptr; - deferred_access_check *chk; - - /* Exit if we are in a context that no access checking is performed. */ - if (deferred_access_no_check) - return true; - - gcc_assert (TREE_CODE (binfo) == TREE_BINFO); - - ptr = &deferred_access_stack->last (); - - /* If we are not supposed to defer access checks, just check now. */ - if (ptr->deferring_access_checks_kind == dk_no_deferred) - { - bool ok = enforce_access (binfo, decl, diag_decl, complain, afi); - return (complain & tf_error) ? true : ok; - } - - /* See if we are already going to perform this check. */ - FOR_EACH_VEC_SAFE_ELT (ptr->deferred_access_checks, i, chk) - { - if (chk->decl == decl && chk->binfo == binfo && - chk->diag_decl == diag_decl) - { - return true; - } - } - /* If not, record the check. */ - deferred_access_check new_access = {binfo, decl, diag_decl, input_location}; - vec_safe_push (ptr->deferred_access_checks, new_access); - - return true; -} - -/* Returns nonzero if the current statement is a full expression, - i.e. temporaries created during that statement should be destroyed - at the end of the statement. */ - -int -stmts_are_full_exprs_p (void) -{ - return current_stmt_tree ()->stmts_are_full_exprs_p; -} - -/* T is a statement. Add it to the statement-tree. This is the C++ - version. The C/ObjC frontends have a slightly different version of - this function. */ - -tree -add_stmt (tree t) -{ - enum tree_code code = TREE_CODE (t); - - if (EXPR_P (t) && code != LABEL_EXPR) - { - if (!EXPR_HAS_LOCATION (t)) - SET_EXPR_LOCATION (t, input_location); - - /* When we expand a statement-tree, we must know whether or not the - statements are full-expressions. We record that fact here. */ - if (STATEMENT_CODE_P (TREE_CODE (t))) - STMT_IS_FULL_EXPR_P (t) = stmts_are_full_exprs_p (); - } - - if (code == LABEL_EXPR || code == CASE_LABEL_EXPR) - STATEMENT_LIST_HAS_LABEL (cur_stmt_list) = 1; - - /* Add T to the statement-tree. Non-side-effect statements need to be - recorded during statement expressions. */ - gcc_checking_assert (!stmt_list_stack->is_empty ()); - append_to_statement_list_force (t, &cur_stmt_list); - - return t; -} - -/* Returns the stmt_tree to which statements are currently being added. */ - -stmt_tree -current_stmt_tree (void) -{ - return (cfun - ? &cfun->language->base.x_stmt_tree - : &scope_chain->x_stmt_tree); -} - -/* If statements are full expressions, wrap STMT in a CLEANUP_POINT_EXPR. */ - -static tree -maybe_cleanup_point_expr (tree expr) -{ - if (!processing_template_decl && stmts_are_full_exprs_p ()) - expr = fold_build_cleanup_point_expr (TREE_TYPE (expr), expr); - return expr; -} - -/* Like maybe_cleanup_point_expr except have the type of the new expression be - void so we don't need to create a temporary variable to hold the inner - expression. The reason why we do this is because the original type might be - an aggregate and we cannot create a temporary variable for that type. */ - -tree -maybe_cleanup_point_expr_void (tree expr) -{ - if (!processing_template_decl && stmts_are_full_exprs_p ()) - expr = fold_build_cleanup_point_expr (void_type_node, expr); - return expr; -} - - - -/* Create a declaration statement for the declaration given by the DECL. */ - -void -add_decl_expr (tree decl) -{ - tree r = build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl); - if (DECL_INITIAL (decl) - || (DECL_SIZE (decl) && TREE_SIDE_EFFECTS (DECL_SIZE (decl)))) - r = maybe_cleanup_point_expr_void (r); - add_stmt (r); -} - -/* Set EXPR_LOCATION of the cleanups of any CLEANUP_STMT in STMTS to LOC. */ - -static void -set_cleanup_locs (tree stmts, location_t loc) -{ - if (TREE_CODE (stmts) == CLEANUP_STMT) - { - protected_set_expr_location (CLEANUP_EXPR (stmts), loc); - set_cleanup_locs (CLEANUP_BODY (stmts), loc); - } - else if (TREE_CODE (stmts) == STATEMENT_LIST) - for (tree stmt : tsi_range (stmts)) - set_cleanup_locs (stmt, loc); -} - -/* Finish a scope. */ - -tree -do_poplevel (tree stmt_list) -{ - tree block = NULL; - - maybe_splice_retval_cleanup (stmt_list); - - if (stmts_are_full_exprs_p ()) - block = poplevel (kept_level_p (), 1, 0); - - stmt_list = pop_stmt_list (stmt_list); - - /* input_location is the last token of the scope, usually a }. */ - set_cleanup_locs (stmt_list, input_location); - - if (!processing_template_decl) - { - stmt_list = c_build_bind_expr (input_location, block, stmt_list); - /* ??? See c_end_compound_stmt re statement expressions. */ - } - - return stmt_list; -} - -/* Begin a new scope. */ - -static tree -do_pushlevel (scope_kind sk) -{ - tree ret = push_stmt_list (); - if (stmts_are_full_exprs_p ()) - begin_scope (sk, NULL); - return ret; -} - -/* Queue a cleanup. CLEANUP is an expression/statement to be executed - when the current scope is exited. EH_ONLY is true when this is not - meant to apply to normal control flow transfer. */ - -void -push_cleanup (tree decl, tree cleanup, bool eh_only) -{ - tree stmt = build_stmt (input_location, CLEANUP_STMT, NULL, cleanup, decl); - CLEANUP_EH_ONLY (stmt) = eh_only; - add_stmt (stmt); - CLEANUP_BODY (stmt) = push_stmt_list (); -} - -/* Simple infinite loop tracking for -Wreturn-type. We keep a stack of all - the current loops, represented by 'NULL_TREE' if we've seen a possible - exit, and 'error_mark_node' if not. This is currently used only to - suppress the warning about a function with no return statements, and - therefore we don't bother noting returns as possible exits. We also - don't bother with gotos. */ - -static void -begin_maybe_infinite_loop (tree cond) -{ - /* Only track this while parsing a function, not during instantiation. */ - if (!cfun || (DECL_TEMPLATE_INSTANTIATION (current_function_decl) - && !processing_template_decl)) - return; - bool maybe_infinite = true; - if (cond) - { - cond = fold_non_dependent_expr (cond); - maybe_infinite = integer_nonzerop (cond); - } - vec_safe_push (cp_function_chain->infinite_loops, - maybe_infinite ? error_mark_node : NULL_TREE); - -} - -/* A break is a possible exit for the current loop. */ - -void -break_maybe_infinite_loop (void) -{ - if (!cfun) - return; - cp_function_chain->infinite_loops->last() = NULL_TREE; -} - -/* If we reach the end of the loop without seeing a possible exit, we have - an infinite loop. */ - -static void -end_maybe_infinite_loop (tree cond) -{ - if (!cfun || (DECL_TEMPLATE_INSTANTIATION (current_function_decl) - && !processing_template_decl)) - return; - tree current = cp_function_chain->infinite_loops->pop(); - if (current != NULL_TREE) - { - cond = fold_non_dependent_expr (cond); - if (integer_nonzerop (cond)) - current_function_infinite_loop = 1; - } -} - - -/* Begin a conditional that might contain a declaration. When generating - normal code, we want the declaration to appear before the statement - containing the conditional. When generating template code, we want the - conditional to be rendered as the raw DECL_EXPR. */ - -static void -begin_cond (tree *cond_p) -{ - if (processing_template_decl) - *cond_p = push_stmt_list (); -} - -/* Finish such a conditional. */ - -static void -finish_cond (tree *cond_p, tree expr) -{ - if (processing_template_decl) - { - tree cond = pop_stmt_list (*cond_p); - - if (expr == NULL_TREE) - /* Empty condition in 'for'. */ - gcc_assert (empty_expr_stmt_p (cond)); - else if (check_for_bare_parameter_packs (expr)) - expr = error_mark_node; - else if (!empty_expr_stmt_p (cond)) - expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr), cond, expr); - } - *cond_p = expr; -} - -/* If *COND_P specifies a conditional with a declaration, transform the - loop such that - while (A x = 42) { } - for (; A x = 42;) { } - becomes - while (true) { A x = 42; if (!x) break; } - for (;;) { A x = 42; if (!x) break; } - The statement list for BODY will be empty if the conditional did - not declare anything. */ - -static void -simplify_loop_decl_cond (tree *cond_p, tree body) -{ - tree cond, if_stmt; - - if (!TREE_SIDE_EFFECTS (body)) - return; - - cond = *cond_p; - *cond_p = boolean_true_node; - - if_stmt = begin_if_stmt (); - cond = cp_build_unary_op (TRUTH_NOT_EXPR, cond, false, tf_warning_or_error); - finish_if_stmt_cond (cond, if_stmt); - finish_break_stmt (); - finish_then_clause (if_stmt); - finish_if_stmt (if_stmt); -} - -/* Finish a goto-statement. */ - -tree -finish_goto_stmt (tree destination) -{ - if (identifier_p (destination)) - destination = lookup_label (destination); - - /* We warn about unused labels with -Wunused. That means we have to - mark the used labels as used. */ - if (TREE_CODE (destination) == LABEL_DECL) - TREE_USED (destination) = 1; - else - { - destination = mark_rvalue_use (destination); - if (!processing_template_decl) - { - destination = cp_convert (ptr_type_node, destination, - tf_warning_or_error); - if (error_operand_p (destination)) - return NULL_TREE; - destination - = fold_build_cleanup_point_expr (TREE_TYPE (destination), - destination); - } - } - - check_goto (destination); - - add_stmt (build_predict_expr (PRED_GOTO, NOT_TAKEN)); - return add_stmt (build_stmt (input_location, GOTO_EXPR, destination)); -} - -/* COND is the condition-expression for an if, while, etc., - statement. Convert it to a boolean value, if appropriate. - In addition, verify sequence points if -Wsequence-point is enabled. */ - -static tree -maybe_convert_cond (tree cond) -{ - /* Empty conditions remain empty. */ - if (!cond) - return NULL_TREE; - - /* Wait until we instantiate templates before doing conversion. */ - if (type_dependent_expression_p (cond)) - return cond; - - if (warn_sequence_point && !processing_template_decl) - verify_sequence_points (cond); - - /* Do the conversion. */ - cond = convert_from_reference (cond); - - if (TREE_CODE (cond) == MODIFY_EXPR - && warn_parentheses - && !warning_suppressed_p (cond, OPT_Wparentheses) - && warning_at (cp_expr_loc_or_input_loc (cond), - OPT_Wparentheses, "suggest parentheses around " - "assignment used as truth value")) - suppress_warning (cond, OPT_Wparentheses); - - return condition_conversion (cond); -} - -/* Finish an expression-statement, whose EXPRESSION is as indicated. */ - -tree -finish_expr_stmt (tree expr) -{ - tree r = NULL_TREE; - location_t loc = EXPR_LOCATION (expr); - - if (expr != NULL_TREE) - { - /* If we ran into a problem, make sure we complained. */ - gcc_assert (expr != error_mark_node || seen_error ()); - - if (!processing_template_decl) - { - if (warn_sequence_point) - verify_sequence_points (expr); - expr = convert_to_void (expr, ICV_STATEMENT, tf_warning_or_error); - } - else if (!type_dependent_expression_p (expr)) - convert_to_void (build_non_dependent_expr (expr), ICV_STATEMENT, - tf_warning_or_error); - - if (check_for_bare_parameter_packs (expr)) - expr = error_mark_node; - - /* Simplification of inner statement expressions, compound exprs, - etc can result in us already having an EXPR_STMT. */ - if (TREE_CODE (expr) != CLEANUP_POINT_EXPR) - { - if (TREE_CODE (expr) != EXPR_STMT) - expr = build_stmt (loc, EXPR_STMT, expr); - expr = maybe_cleanup_point_expr_void (expr); - } - - r = add_stmt (expr); - } - - return r; -} - - -/* Begin an if-statement. Returns a newly created IF_STMT if - appropriate. */ - -tree -begin_if_stmt (void) -{ - tree r, scope; - scope = do_pushlevel (sk_cond); - r = build_stmt (input_location, IF_STMT, NULL_TREE, - NULL_TREE, NULL_TREE, scope); - current_binding_level->this_entity = r; - begin_cond (&IF_COND (r)); - return r; -} - -/* Returns true if FN, a CALL_EXPR, is a call to - std::is_constant_evaluated or __builtin_is_constant_evaluated. */ - -static bool -is_std_constant_evaluated_p (tree fn) -{ - /* std::is_constant_evaluated takes no arguments. */ - if (call_expr_nargs (fn) != 0) - return false; - - tree fndecl = cp_get_callee_fndecl_nofold (fn); - if (fndecl == NULL_TREE) - return false; - - if (fndecl_built_in_p (fndecl, CP_BUILT_IN_IS_CONSTANT_EVALUATED, - BUILT_IN_FRONTEND)) - return true; - - if (!decl_in_std_namespace_p (fndecl)) - return false; - - tree name = DECL_NAME (fndecl); - return name && id_equal (name, "is_constant_evaluated"); -} - -/* Callback function for maybe_warn_for_constant_evaluated that looks - for calls to std::is_constant_evaluated in TP. */ - -static tree -find_std_constant_evaluated_r (tree *tp, int *walk_subtrees, void *) -{ - tree t = *tp; - - if (TYPE_P (t) || TREE_CONSTANT (t)) - { - *walk_subtrees = false; - return NULL_TREE; - } - - switch (TREE_CODE (t)) - { - case CALL_EXPR: - if (is_std_constant_evaluated_p (t)) - return t; - break; - case EXPR_STMT: - /* Don't warn in statement expressions. */ - *walk_subtrees = false; - return NULL_TREE; - default: - break; - } - - return NULL_TREE; -} - -/* In certain contexts, std::is_constant_evaluated() is always true (for - instance, in a consteval function or in a constexpr if), or always false - (e.g., in a non-constexpr non-consteval function) so give the user a clue. */ - -static void -maybe_warn_for_constant_evaluated (tree cond, bool constexpr_if) -{ - if (!warn_tautological_compare) - return; - - /* Suppress warning for std::is_constant_evaluated if the conditional - comes from a macro. */ - if (from_macro_expansion_at (EXPR_LOCATION (cond))) - return; - - cond = cp_walk_tree_without_duplicates (&cond, find_std_constant_evaluated_r, - NULL); - if (cond) - { - if (constexpr_if) - warning_at (EXPR_LOCATION (cond), OPT_Wtautological_compare, - "%<std::is_constant_evaluated%> always evaluates to " - "true in %<if constexpr%>"); - else if (!maybe_constexpr_fn (current_function_decl)) - warning_at (EXPR_LOCATION (cond), OPT_Wtautological_compare, - "%<std::is_constant_evaluated%> always evaluates to " - "false in a non-%<constexpr%> function"); - else if (DECL_IMMEDIATE_FUNCTION_P (current_function_decl)) - warning_at (EXPR_LOCATION (cond), OPT_Wtautological_compare, - "%<std::is_constant_evaluated%> always evaluates to " - "true in a %<consteval%> function"); - } -} - -/* Process the COND of an if-statement, which may be given by - IF_STMT. */ - -tree -finish_if_stmt_cond (tree cond, tree if_stmt) -{ - cond = maybe_convert_cond (cond); - if (IF_STMT_CONSTEXPR_P (if_stmt) - && !type_dependent_expression_p (cond) - && require_constant_expression (cond) - && !instantiation_dependent_expression_p (cond) - /* Wait until instantiation time, since only then COND has been - converted to bool. */ - && TYPE_MAIN_VARIANT (TREE_TYPE (cond)) == boolean_type_node) - { - maybe_warn_for_constant_evaluated (cond, /*constexpr_if=*/true); - cond = instantiate_non_dependent_expr (cond); - cond = cxx_constant_value (cond, NULL_TREE); - } - else - maybe_warn_for_constant_evaluated (cond, /*constexpr_if=*/false); - finish_cond (&IF_COND (if_stmt), cond); - add_stmt (if_stmt); - THEN_CLAUSE (if_stmt) = push_stmt_list (); - return cond; -} - -/* Finish the then-clause of an if-statement, which may be given by - IF_STMT. */ - -tree -finish_then_clause (tree if_stmt) -{ - THEN_CLAUSE (if_stmt) = pop_stmt_list (THEN_CLAUSE (if_stmt)); - return if_stmt; -} - -/* Begin the else-clause of an if-statement. */ - -void -begin_else_clause (tree if_stmt) -{ - ELSE_CLAUSE (if_stmt) = push_stmt_list (); -} - -/* Finish the else-clause of an if-statement, which may be given by - IF_STMT. */ - -void -finish_else_clause (tree if_stmt) -{ - ELSE_CLAUSE (if_stmt) = pop_stmt_list (ELSE_CLAUSE (if_stmt)); -} - -/* Callback for cp_walk_tree to mark all {VAR,PARM}_DECLs in a tree as - read. */ - -static tree -maybe_mark_exp_read_r (tree *tp, int *, void *) -{ - tree t = *tp; - if (VAR_P (t) || TREE_CODE (t) == PARM_DECL) - mark_exp_read (t); - return NULL_TREE; -} - -/* Finish an if-statement. */ - -void -finish_if_stmt (tree if_stmt) -{ - tree scope = IF_SCOPE (if_stmt); - IF_SCOPE (if_stmt) = NULL; - if (IF_STMT_CONSTEXPR_P (if_stmt)) - { - /* Prevent various -Wunused warnings. We might not instantiate - either of these branches, so we would not mark the variables - used in that branch as read. */ - cp_walk_tree_without_duplicates (&THEN_CLAUSE (if_stmt), - maybe_mark_exp_read_r, NULL); - cp_walk_tree_without_duplicates (&ELSE_CLAUSE (if_stmt), - maybe_mark_exp_read_r, NULL); - } - add_stmt (do_poplevel (scope)); -} - -/* Begin a while-statement. Returns a newly created WHILE_STMT if - appropriate. */ - -tree -begin_while_stmt (void) -{ - tree r; - r = build_stmt (input_location, WHILE_STMT, NULL_TREE, NULL_TREE); - add_stmt (r); - WHILE_BODY (r) = do_pushlevel (sk_block); - begin_cond (&WHILE_COND (r)); - return r; -} - -/* Process the COND of a while-statement, which may be given by - WHILE_STMT. */ - -void -finish_while_stmt_cond (tree cond, tree while_stmt, bool ivdep, - unsigned short unroll) -{ - cond = maybe_convert_cond (cond); - finish_cond (&WHILE_COND (while_stmt), cond); - begin_maybe_infinite_loop (cond); - if (ivdep && cond != error_mark_node) - WHILE_COND (while_stmt) = build3 (ANNOTATE_EXPR, - TREE_TYPE (WHILE_COND (while_stmt)), - WHILE_COND (while_stmt), - build_int_cst (integer_type_node, - annot_expr_ivdep_kind), - integer_zero_node); - if (unroll && cond != error_mark_node) - WHILE_COND (while_stmt) = build3 (ANNOTATE_EXPR, - TREE_TYPE (WHILE_COND (while_stmt)), - WHILE_COND (while_stmt), - build_int_cst (integer_type_node, - annot_expr_unroll_kind), - build_int_cst (integer_type_node, - unroll)); - simplify_loop_decl_cond (&WHILE_COND (while_stmt), WHILE_BODY (while_stmt)); -} - -/* Finish a while-statement, which may be given by WHILE_STMT. */ - -void -finish_while_stmt (tree while_stmt) -{ - end_maybe_infinite_loop (boolean_true_node); - WHILE_BODY (while_stmt) = do_poplevel (WHILE_BODY (while_stmt)); -} - -/* Begin a do-statement. Returns a newly created DO_STMT if - appropriate. */ - -tree -begin_do_stmt (void) -{ - tree r = build_stmt (input_location, DO_STMT, NULL_TREE, NULL_TREE); - begin_maybe_infinite_loop (boolean_true_node); - add_stmt (r); - DO_BODY (r) = push_stmt_list (); - return r; -} - -/* Finish the body of a do-statement, which may be given by DO_STMT. */ - -void -finish_do_body (tree do_stmt) -{ - tree body = DO_BODY (do_stmt) = pop_stmt_list (DO_BODY (do_stmt)); - - if (TREE_CODE (body) == STATEMENT_LIST && STATEMENT_LIST_TAIL (body)) - body = STATEMENT_LIST_TAIL (body)->stmt; - - if (IS_EMPTY_STMT (body)) - warning (OPT_Wempty_body, - "suggest explicit braces around empty body in %<do%> statement"); -} - -/* Finish a do-statement, which may be given by DO_STMT, and whose - COND is as indicated. */ - -void -finish_do_stmt (tree cond, tree do_stmt, bool ivdep, unsigned short unroll) -{ - cond = maybe_convert_cond (cond); - end_maybe_infinite_loop (cond); - /* Unlike other iteration statements, the condition may not contain - a declaration, so we don't call finish_cond which checks for - unexpanded parameter packs. */ - if (check_for_bare_parameter_packs (cond)) - cond = error_mark_node; - if (ivdep && cond != error_mark_node) - cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, - build_int_cst (integer_type_node, annot_expr_ivdep_kind), - integer_zero_node); - if (unroll && cond != error_mark_node) - cond = build3 (ANNOTATE_EXPR, TREE_TYPE (cond), cond, - build_int_cst (integer_type_node, annot_expr_unroll_kind), - build_int_cst (integer_type_node, unroll)); - DO_COND (do_stmt) = cond; -} - -/* Finish a return-statement. The EXPRESSION returned, if any, is as - indicated. */ - -tree -finish_return_stmt (tree expr) -{ - tree r; - bool no_warning; - - expr = check_return_expr (expr, &no_warning); - - if (error_operand_p (expr) - || (flag_openmp && !check_omp_return ())) - { - /* Suppress -Wreturn-type for this function. */ - if (warn_return_type) - suppress_warning (current_function_decl, OPT_Wreturn_type); - return error_mark_node; - } - - if (!processing_template_decl) - { - if (warn_sequence_point) - verify_sequence_points (expr); - - if (DECL_DESTRUCTOR_P (current_function_decl) - || (DECL_CONSTRUCTOR_P (current_function_decl) - && targetm.cxx.cdtor_returns_this ())) - { - /* Similarly, all destructors must run destructors for - base-classes before returning. So, all returns in a - destructor get sent to the DTOR_LABEL; finish_function emits - code to return a value there. */ - return finish_goto_stmt (cdtor_label); - } - } - - r = build_stmt (input_location, RETURN_EXPR, expr); - if (no_warning) - suppress_warning (r, OPT_Wreturn_type); - r = maybe_cleanup_point_expr_void (r); - r = add_stmt (r); - - return r; -} - -/* Begin the scope of a for-statement or a range-for-statement. - Both the returned trees are to be used in a call to - begin_for_stmt or begin_range_for_stmt. */ - -tree -begin_for_scope (tree *init) -{ - tree scope = do_pushlevel (sk_for); - - if (processing_template_decl) - *init = push_stmt_list (); - else - *init = NULL_TREE; - - return scope; -} - -/* Begin a for-statement. Returns a new FOR_STMT. - SCOPE and INIT should be the return of begin_for_scope, - or both NULL_TREE */ - -tree -begin_for_stmt (tree scope, tree init) -{ - tree r; - - r = build_stmt (input_location, FOR_STMT, NULL_TREE, NULL_TREE, - NULL_TREE, NULL_TREE, NULL_TREE); - - if (scope == NULL_TREE) - { - gcc_assert (!init); - scope = begin_for_scope (&init); - } - - FOR_INIT_STMT (r) = init; - FOR_SCOPE (r) = scope; - - return r; -} - -/* Finish the init-statement of a for-statement, which may be - given by FOR_STMT. */ - -void -finish_init_stmt (tree for_stmt) -{ - if (processing_template_decl) - FOR_INIT_STMT (for_stmt) = pop_stmt_list (FOR_INIT_STMT (for_stmt)); - add_stmt (for_stmt); - FOR_BODY (for_stmt) = do_pushlevel (sk_block); - begin_cond (&FOR_COND (for_stmt)); -} - -/* Finish the COND of a for-statement, which may be given by - FOR_STMT. */ - -void -finish_for_cond (tree cond, tree for_stmt, bool ivdep, unsigned short unroll) -{ - cond = maybe_convert_cond (cond); - finish_cond (&FOR_COND (for_stmt), cond); - begin_maybe_infinite_loop (cond); - if (ivdep && cond != error_mark_node) - FOR_COND (for_stmt) = build3 (ANNOTATE_EXPR, - TREE_TYPE (FOR_COND (for_stmt)), - FOR_COND (for_stmt), - build_int_cst (integer_type_node, - annot_expr_ivdep_kind), - integer_zero_node); - if (unroll && cond != error_mark_node) - FOR_COND (for_stmt) = build3 (ANNOTATE_EXPR, - TREE_TYPE (FOR_COND (for_stmt)), - FOR_COND (for_stmt), - build_int_cst (integer_type_node, - annot_expr_unroll_kind), - build_int_cst (integer_type_node, - unroll)); - simplify_loop_decl_cond (&FOR_COND (for_stmt), FOR_BODY (for_stmt)); -} - -/* Finish the increment-EXPRESSION in a for-statement, which may be - given by FOR_STMT. */ - -void -finish_for_expr (tree expr, tree for_stmt) -{ - if (!expr) - return; - /* If EXPR is an overloaded function, issue an error; there is no - context available to use to perform overload resolution. */ - if (type_unknown_p (expr)) - { - cxx_incomplete_type_error (expr, TREE_TYPE (expr)); - expr = error_mark_node; - } - if (!processing_template_decl) - { - if (warn_sequence_point) - verify_sequence_points (expr); - expr = convert_to_void (expr, ICV_THIRD_IN_FOR, - tf_warning_or_error); - } - else if (!type_dependent_expression_p (expr)) - convert_to_void (build_non_dependent_expr (expr), ICV_THIRD_IN_FOR, - tf_warning_or_error); - expr = maybe_cleanup_point_expr_void (expr); - if (check_for_bare_parameter_packs (expr)) - expr = error_mark_node; - FOR_EXPR (for_stmt) = expr; -} - -/* Finish the body of a for-statement, which may be given by - FOR_STMT. The increment-EXPR for the loop must be - provided. - It can also finish RANGE_FOR_STMT. */ - -void -finish_for_stmt (tree for_stmt) -{ - end_maybe_infinite_loop (boolean_true_node); - - if (TREE_CODE (for_stmt) == RANGE_FOR_STMT) - RANGE_FOR_BODY (for_stmt) = do_poplevel (RANGE_FOR_BODY (for_stmt)); - else - FOR_BODY (for_stmt) = do_poplevel (FOR_BODY (for_stmt)); - - /* Pop the scope for the body of the loop. */ - tree *scope_ptr = (TREE_CODE (for_stmt) == RANGE_FOR_STMT - ? &RANGE_FOR_SCOPE (for_stmt) - : &FOR_SCOPE (for_stmt)); - tree scope = *scope_ptr; - *scope_ptr = NULL; - - /* During parsing of the body, range for uses "__for_{range,begin,end} " - decl names to make those unaccessible by code in the body. - Change it to ones with underscore instead of space, so that it can - be inspected in the debugger. */ - tree range_for_decl[3] = { NULL_TREE, NULL_TREE, NULL_TREE }; - gcc_assert (CPTI_FOR_BEGIN__IDENTIFIER == CPTI_FOR_RANGE__IDENTIFIER + 1 - && CPTI_FOR_END__IDENTIFIER == CPTI_FOR_RANGE__IDENTIFIER + 2 - && CPTI_FOR_RANGE_IDENTIFIER == CPTI_FOR_RANGE__IDENTIFIER + 3 - && CPTI_FOR_BEGIN_IDENTIFIER == CPTI_FOR_BEGIN__IDENTIFIER + 3 - && CPTI_FOR_END_IDENTIFIER == CPTI_FOR_END__IDENTIFIER + 3); - for (int i = 0; i < 3; i++) - { - tree id = cp_global_trees[CPTI_FOR_RANGE__IDENTIFIER + i]; - if (IDENTIFIER_BINDING (id) - && IDENTIFIER_BINDING (id)->scope == current_binding_level) - { - range_for_decl[i] = IDENTIFIER_BINDING (id)->value; - gcc_assert (VAR_P (range_for_decl[i]) - && DECL_ARTIFICIAL (range_for_decl[i])); - } - } - - add_stmt (do_poplevel (scope)); - - for (int i = 0; i < 3; i++) - if (range_for_decl[i]) - DECL_NAME (range_for_decl[i]) - = cp_global_trees[CPTI_FOR_RANGE_IDENTIFIER + i]; -} - -/* Begin a range-for-statement. Returns a new RANGE_FOR_STMT. - SCOPE and INIT should be the return of begin_for_scope, - or both NULL_TREE . - To finish it call finish_for_stmt(). */ - -tree -begin_range_for_stmt (tree scope, tree init) -{ - begin_maybe_infinite_loop (boolean_false_node); - - tree r = build_stmt (input_location, RANGE_FOR_STMT, NULL_TREE, NULL_TREE, - NULL_TREE, NULL_TREE, NULL_TREE, NULL_TREE); - - if (scope == NULL_TREE) - { - gcc_assert (!init); - scope = begin_for_scope (&init); - } - - /* Since C++20, RANGE_FOR_STMTs can use the init tree, so save it. */ - RANGE_FOR_INIT_STMT (r) = init; - RANGE_FOR_SCOPE (r) = scope; - - return r; -} - -/* Finish the head of a range-based for statement, which may - be given by RANGE_FOR_STMT. DECL must be the declaration - and EXPR must be the loop expression. */ - -void -finish_range_for_decl (tree range_for_stmt, tree decl, tree expr) -{ - if (processing_template_decl) - RANGE_FOR_INIT_STMT (range_for_stmt) - = pop_stmt_list (RANGE_FOR_INIT_STMT (range_for_stmt)); - RANGE_FOR_DECL (range_for_stmt) = decl; - RANGE_FOR_EXPR (range_for_stmt) = expr; - add_stmt (range_for_stmt); - RANGE_FOR_BODY (range_for_stmt) = do_pushlevel (sk_block); -} - -/* Finish a break-statement. */ - -tree -finish_break_stmt (void) -{ - /* In switch statements break is sometimes stylistically used after - a return statement. This can lead to spurious warnings about - control reaching the end of a non-void function when it is - inlined. Note that we are calling block_may_fallthru with - language specific tree nodes; this works because - block_may_fallthru returns true when given something it does not - understand. */ - if (!block_may_fallthru (cur_stmt_list)) - return void_node; - note_break_stmt (); - return add_stmt (build_stmt (input_location, BREAK_STMT)); -} - -/* Finish a continue-statement. */ - -tree -finish_continue_stmt (void) -{ - return add_stmt (build_stmt (input_location, CONTINUE_STMT)); -} - -/* Begin a switch-statement. Returns a new SWITCH_STMT if - appropriate. */ - -tree -begin_switch_stmt (void) -{ - tree r, scope; - - scope = do_pushlevel (sk_cond); - r = build_stmt (input_location, SWITCH_STMT, NULL_TREE, NULL_TREE, NULL_TREE, scope); - - begin_cond (&SWITCH_STMT_COND (r)); - - return r; -} - -/* Finish the cond of a switch-statement. */ - -void -finish_switch_cond (tree cond, tree switch_stmt) -{ - tree orig_type = NULL; - - if (!processing_template_decl) - { - /* Convert the condition to an integer or enumeration type. */ - tree orig_cond = cond; - cond = build_expr_type_conversion (WANT_INT | WANT_ENUM, cond, true); - if (cond == NULL_TREE) - { - error_at (cp_expr_loc_or_input_loc (orig_cond), - "switch quantity not an integer"); - cond = error_mark_node; - } - /* We want unlowered type here to handle enum bit-fields. */ - orig_type = unlowered_expr_type (cond); - if (TREE_CODE (orig_type) != ENUMERAL_TYPE) - orig_type = TREE_TYPE (cond); - if (cond != error_mark_node) - { - /* [stmt.switch] - - Integral promotions are performed. */ - cond = perform_integral_promotions (cond); - cond = maybe_cleanup_point_expr (cond); - } - } - if (check_for_bare_parameter_packs (cond)) - cond = error_mark_node; - else if (!processing_template_decl && warn_sequence_point) - verify_sequence_points (cond); - - finish_cond (&SWITCH_STMT_COND (switch_stmt), cond); - SWITCH_STMT_TYPE (switch_stmt) = orig_type; - add_stmt (switch_stmt); - push_switch (switch_stmt); - SWITCH_STMT_BODY (switch_stmt) = push_stmt_list (); -} - -/* Finish the body of a switch-statement, which may be given by - SWITCH_STMT. The COND to switch on is indicated. */ - -void -finish_switch_stmt (tree switch_stmt) -{ - tree scope; - - SWITCH_STMT_BODY (switch_stmt) = - pop_stmt_list (SWITCH_STMT_BODY (switch_stmt)); - pop_switch (); - - scope = SWITCH_STMT_SCOPE (switch_stmt); - SWITCH_STMT_SCOPE (switch_stmt) = NULL; - add_stmt (do_poplevel (scope)); -} - -/* Begin a try-block. Returns a newly-created TRY_BLOCK if - appropriate. */ - -tree -begin_try_block (void) -{ - tree r = build_stmt (input_location, TRY_BLOCK, NULL_TREE, NULL_TREE); - add_stmt (r); - TRY_STMTS (r) = push_stmt_list (); - return r; -} - -/* Likewise, for a function-try-block. The block returned in - *COMPOUND_STMT is an artificial outer scope, containing the - function-try-block. */ - -tree -begin_function_try_block (tree *compound_stmt) -{ - tree r; - /* This outer scope does not exist in the C++ standard, but we need - a place to put __FUNCTION__ and similar variables. */ - *compound_stmt = begin_compound_stmt (0); - r = begin_try_block (); - FN_TRY_BLOCK_P (r) = 1; - return r; -} - -/* Finish a try-block, which may be given by TRY_BLOCK. */ - -void -finish_try_block (tree try_block) -{ - TRY_STMTS (try_block) = pop_stmt_list (TRY_STMTS (try_block)); - TRY_HANDLERS (try_block) = push_stmt_list (); -} - -/* Finish the body of a cleanup try-block, which may be given by - TRY_BLOCK. */ - -void -finish_cleanup_try_block (tree try_block) -{ - TRY_STMTS (try_block) = pop_stmt_list (TRY_STMTS (try_block)); -} - -/* Finish an implicitly generated try-block, with a cleanup is given - by CLEANUP. */ - -void -finish_cleanup (tree cleanup, tree try_block) -{ - TRY_HANDLERS (try_block) = cleanup; - CLEANUP_P (try_block) = 1; -} - -/* Likewise, for a function-try-block. */ - -void -finish_function_try_block (tree try_block) -{ - finish_try_block (try_block); - /* FIXME : something queer about CTOR_INITIALIZER somehow following - the try block, but moving it inside. */ - in_function_try_handler = 1; -} - -/* Finish a handler-sequence for a try-block, which may be given by - TRY_BLOCK. */ - -void -finish_handler_sequence (tree try_block) -{ - TRY_HANDLERS (try_block) = pop_stmt_list (TRY_HANDLERS (try_block)); - check_handlers (TRY_HANDLERS (try_block)); -} - -/* Finish the handler-seq for a function-try-block, given by - TRY_BLOCK. COMPOUND_STMT is the outer block created by - begin_function_try_block. */ - -void -finish_function_handler_sequence (tree try_block, tree compound_stmt) -{ - in_function_try_handler = 0; - finish_handler_sequence (try_block); - finish_compound_stmt (compound_stmt); -} - -/* Begin a handler. Returns a HANDLER if appropriate. */ - -tree -begin_handler (void) -{ - tree r; - - r = build_stmt (input_location, HANDLER, NULL_TREE, NULL_TREE); - add_stmt (r); - - /* Create a binding level for the eh_info and the exception object - cleanup. */ - HANDLER_BODY (r) = do_pushlevel (sk_catch); - - return r; -} - -/* Finish the handler-parameters for a handler, which may be given by - HANDLER. DECL is the declaration for the catch parameter, or NULL - if this is a `catch (...)' clause. */ - -void -finish_handler_parms (tree decl, tree handler) -{ - tree type = NULL_TREE; - if (processing_template_decl) - { - if (decl) - { - decl = pushdecl (decl); - decl = push_template_decl (decl); - HANDLER_PARMS (handler) = decl; - type = TREE_TYPE (decl); - } - } - else - { - type = expand_start_catch_block (decl); - if (warn_catch_value - && type != NULL_TREE - && type != error_mark_node - && !TYPE_REF_P (TREE_TYPE (decl))) - { - tree orig_type = TREE_TYPE (decl); - if (CLASS_TYPE_P (orig_type)) - { - if (TYPE_POLYMORPHIC_P (orig_type)) - warning_at (DECL_SOURCE_LOCATION (decl), - OPT_Wcatch_value_, - "catching polymorphic type %q#T by value", - orig_type); - else if (warn_catch_value > 1) - warning_at (DECL_SOURCE_LOCATION (decl), - OPT_Wcatch_value_, - "catching type %q#T by value", orig_type); - } - else if (warn_catch_value > 2) - warning_at (DECL_SOURCE_LOCATION (decl), - OPT_Wcatch_value_, - "catching non-reference type %q#T", orig_type); - } - } - HANDLER_TYPE (handler) = type; -} - -/* Finish a handler, which may be given by HANDLER. The BLOCKs are - the return value from the matching call to finish_handler_parms. */ - -void -finish_handler (tree handler) -{ - if (!processing_template_decl) - expand_end_catch_block (); - HANDLER_BODY (handler) = do_poplevel (HANDLER_BODY (handler)); -} - -/* Begin a compound statement. FLAGS contains some bits that control the - behavior and context. If BCS_NO_SCOPE is set, the compound statement - does not define a scope. If BCS_FN_BODY is set, this is the outermost - block of a function. If BCS_TRY_BLOCK is set, this is the block - created on behalf of a TRY statement. Returns a token to be passed to - finish_compound_stmt. */ - -tree -begin_compound_stmt (unsigned int flags) -{ - tree r; - - if (flags & BCS_NO_SCOPE) - { - r = push_stmt_list (); - STATEMENT_LIST_NO_SCOPE (r) = 1; - - /* Normally, we try hard to keep the BLOCK for a statement-expression. - But, if it's a statement-expression with a scopeless block, there's - nothing to keep, and we don't want to accidentally keep a block - *inside* the scopeless block. */ - keep_next_level (false); - } - else - { - scope_kind sk = sk_block; - if (flags & BCS_TRY_BLOCK) - sk = sk_try; - else if (flags & BCS_TRANSACTION) - sk = sk_transaction; - r = do_pushlevel (sk); - } - - /* When processing a template, we need to remember where the braces were, - so that we can set up identical scopes when instantiating the template - later. BIND_EXPR is a handy candidate for this. - Note that do_poplevel won't create a BIND_EXPR itself here (and thus - result in nested BIND_EXPRs), since we don't build BLOCK nodes when - processing templates. */ - if (processing_template_decl) - { - r = build3 (BIND_EXPR, NULL, NULL, r, NULL); - BIND_EXPR_TRY_BLOCK (r) = (flags & BCS_TRY_BLOCK) != 0; - BIND_EXPR_BODY_BLOCK (r) = (flags & BCS_FN_BODY) != 0; - TREE_SIDE_EFFECTS (r) = 1; - } - - return r; -} - -/* Finish a compound-statement, which is given by STMT. */ - -void -finish_compound_stmt (tree stmt) -{ - if (TREE_CODE (stmt) == BIND_EXPR) - { - tree body = do_poplevel (BIND_EXPR_BODY (stmt)); - /* If the STATEMENT_LIST is empty and this BIND_EXPR isn't special, - discard the BIND_EXPR so it can be merged with the containing - STATEMENT_LIST. */ - if (TREE_CODE (body) == STATEMENT_LIST - && STATEMENT_LIST_HEAD (body) == NULL - && !BIND_EXPR_BODY_BLOCK (stmt) - && !BIND_EXPR_TRY_BLOCK (stmt)) - stmt = body; - else - BIND_EXPR_BODY (stmt) = body; - } - else if (STATEMENT_LIST_NO_SCOPE (stmt)) - stmt = pop_stmt_list (stmt); - else - { - /* Destroy any ObjC "super" receivers that may have been - created. */ - objc_clear_super_receiver (); - - stmt = do_poplevel (stmt); - } - - /* ??? See c_end_compound_stmt wrt statement expressions. */ - add_stmt (stmt); -} - -/* Finish an asm-statement, whose components are a STRING, some - OUTPUT_OPERANDS, some INPUT_OPERANDS, some CLOBBERS and some - LABELS. Also note whether the asm-statement should be - considered volatile, and whether it is asm inline. */ - -tree -finish_asm_stmt (location_t loc, int volatile_p, tree string, - tree output_operands, tree input_operands, tree clobbers, - tree labels, bool inline_p) -{ - tree r; - tree t; - int ninputs = list_length (input_operands); - int noutputs = list_length (output_operands); - - if (!processing_template_decl) - { - const char *constraint; - const char **oconstraints; - bool allows_mem, allows_reg, is_inout; - tree operand; - int i; - - oconstraints = XALLOCAVEC (const char *, noutputs); - - string = resolve_asm_operand_names (string, output_operands, - input_operands, labels); - - for (i = 0, t = output_operands; t; t = TREE_CHAIN (t), ++i) - { - operand = TREE_VALUE (t); - - /* ??? Really, this should not be here. Users should be using a - proper lvalue, dammit. But there's a long history of using - casts in the output operands. In cases like longlong.h, this - becomes a primitive form of typechecking -- if the cast can be - removed, then the output operand had a type of the proper width; - otherwise we'll get an error. Gross, but ... */ - STRIP_NOPS (operand); - - operand = mark_lvalue_use (operand); - - if (!lvalue_or_else (operand, lv_asm, tf_warning_or_error)) - operand = error_mark_node; - - if (operand != error_mark_node - && (TREE_READONLY (operand) - || CP_TYPE_CONST_P (TREE_TYPE (operand)) - /* Functions are not modifiable, even though they are - lvalues. */ - || FUNC_OR_METHOD_TYPE_P (TREE_TYPE (operand)) - /* If it's an aggregate and any field is const, then it is - effectively const. */ - || (CLASS_TYPE_P (TREE_TYPE (operand)) - && C_TYPE_FIELDS_READONLY (TREE_TYPE (operand))))) - cxx_readonly_error (loc, operand, lv_asm); - - tree *op = &operand; - while (TREE_CODE (*op) == COMPOUND_EXPR) - op = &TREE_OPERAND (*op, 1); - switch (TREE_CODE (*op)) - { - case PREINCREMENT_EXPR: - case PREDECREMENT_EXPR: - case MODIFY_EXPR: - *op = genericize_compound_lvalue (*op); - op = &TREE_OPERAND (*op, 1); - break; - default: - break; - } - - constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t))); - oconstraints[i] = constraint; - - if (parse_output_constraint (&constraint, i, ninputs, noutputs, - &allows_mem, &allows_reg, &is_inout)) - { - /* If the operand is going to end up in memory, - mark it addressable. */ - if (!allows_reg && !cxx_mark_addressable (*op)) - operand = error_mark_node; - } - else - operand = error_mark_node; - - TREE_VALUE (t) = operand; - } - - for (i = 0, t = input_operands; t; ++i, t = TREE_CHAIN (t)) - { - constraint = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (t))); - bool constraint_parsed - = parse_input_constraint (&constraint, i, ninputs, noutputs, 0, - oconstraints, &allows_mem, &allows_reg); - /* If the operand is going to end up in memory, don't call - decay_conversion. */ - if (constraint_parsed && !allows_reg && allows_mem) - operand = mark_lvalue_use (TREE_VALUE (t)); - else - operand = decay_conversion (TREE_VALUE (t), tf_warning_or_error); - - /* If the type of the operand hasn't been determined (e.g., - because it involves an overloaded function), then issue - an error message. There's no context available to - resolve the overloading. */ - if (TREE_TYPE (operand) == unknown_type_node) - { - error_at (loc, - "type of %<asm%> operand %qE could not be determined", - TREE_VALUE (t)); - operand = error_mark_node; - } - - if (constraint_parsed) - { - /* If the operand is going to end up in memory, - mark it addressable. */ - if (!allows_reg && allows_mem) - { - /* Strip the nops as we allow this case. FIXME, this really - should be rejected or made deprecated. */ - STRIP_NOPS (operand); - - tree *op = &operand; - while (TREE_CODE (*op) == COMPOUND_EXPR) - op = &TREE_OPERAND (*op, 1); - switch (TREE_CODE (*op)) - { - case PREINCREMENT_EXPR: - case PREDECREMENT_EXPR: - case MODIFY_EXPR: - *op = genericize_compound_lvalue (*op); - op = &TREE_OPERAND (*op, 1); - break; - default: - break; - } - - if (!cxx_mark_addressable (*op)) - operand = error_mark_node; - } - else if (!allows_reg && !allows_mem) - { - /* If constraint allows neither register nor memory, - try harder to get a constant. */ - tree constop = maybe_constant_value (operand); - if (TREE_CONSTANT (constop)) - operand = constop; - } - } - else - operand = error_mark_node; - - TREE_VALUE (t) = operand; - } - } - - r = build_stmt (loc, ASM_EXPR, string, - output_operands, input_operands, - clobbers, labels); - ASM_VOLATILE_P (r) = volatile_p || noutputs == 0; - ASM_INLINE_P (r) = inline_p; - r = maybe_cleanup_point_expr_void (r); - return add_stmt (r); -} - -/* Finish a label with the indicated NAME. Returns the new label. */ - -tree -finish_label_stmt (tree name) -{ - tree decl = define_label (input_location, name); - - if (decl == error_mark_node) - return error_mark_node; - - add_stmt (build_stmt (input_location, LABEL_EXPR, decl)); - - return decl; -} - -/* Finish a series of declarations for local labels. G++ allows users - to declare "local" labels, i.e., labels with scope. This extension - is useful when writing code involving statement-expressions. */ - -void -finish_label_decl (tree name) -{ - if (!at_function_scope_p ()) - { - error ("%<__label__%> declarations are only allowed in function scopes"); - return; - } - - add_decl_expr (declare_local_label (name)); -} - -/* When DECL goes out of scope, make sure that CLEANUP is executed. */ - -void -finish_decl_cleanup (tree decl, tree cleanup) -{ - push_cleanup (decl, cleanup, false); -} - -/* If the current scope exits with an exception, run CLEANUP. */ - -void -finish_eh_cleanup (tree cleanup) -{ - push_cleanup (NULL, cleanup, true); -} - -/* The MEM_INITS is a list of mem-initializers, in reverse of the - order they were written by the user. Each node is as for - emit_mem_initializers. */ - -void -finish_mem_initializers (tree mem_inits) -{ - /* Reorder the MEM_INITS so that they are in the order they appeared - in the source program. */ - mem_inits = nreverse (mem_inits); - - if (processing_template_decl) - { - tree mem; - - for (mem = mem_inits; mem; mem = TREE_CHAIN (mem)) - { - /* If the TREE_PURPOSE is a TYPE_PACK_EXPANSION, skip the - check for bare parameter packs in the TREE_VALUE, because - any parameter packs in the TREE_VALUE have already been - bound as part of the TREE_PURPOSE. See - make_pack_expansion for more information. */ - if (TREE_CODE (TREE_PURPOSE (mem)) != TYPE_PACK_EXPANSION - && check_for_bare_parameter_packs (TREE_VALUE (mem))) - TREE_VALUE (mem) = error_mark_node; - } - - add_stmt (build_min_nt_loc (UNKNOWN_LOCATION, - CTOR_INITIALIZER, mem_inits)); - } - else - emit_mem_initializers (mem_inits); -} - -/* Obfuscate EXPR if it looks like an id-expression or member access so - that the call to finish_decltype in do_auto_deduction will give the - right result. If EVEN_UNEVAL, do this even in unevaluated context. */ - -tree -force_paren_expr (tree expr, bool even_uneval) -{ - /* This is only needed for decltype(auto) in C++14. */ - if (cxx_dialect < cxx14) - return expr; - - /* If we're in unevaluated context, we can't be deducing a - return/initializer type, so we don't need to mess with this. */ - if (cp_unevaluated_operand && !even_uneval) - return expr; - - if (TREE_CODE (expr) == COMPONENT_REF - || TREE_CODE (expr) == SCOPE_REF - || REFERENCE_REF_P (expr)) - REF_PARENTHESIZED_P (expr) = true; - else if (DECL_P (tree_strip_any_location_wrapper (expr))) - { - location_t loc = cp_expr_location (expr); - const tree_code code = processing_template_decl ? PAREN_EXPR - : VIEW_CONVERT_EXPR; - expr = build1_loc (loc, code, TREE_TYPE (expr), expr); - REF_PARENTHESIZED_P (expr) = true; - } - return expr; -} - -/* If T is an id-expression obfuscated by force_paren_expr, undo the - obfuscation and return the underlying id-expression. Otherwise - return T. */ - -tree -maybe_undo_parenthesized_ref (tree t) -{ - if (cxx_dialect < cxx14) - return t; - - if ((TREE_CODE (t) == PAREN_EXPR || TREE_CODE (t) == VIEW_CONVERT_EXPR) - && REF_PARENTHESIZED_P (t)) - t = TREE_OPERAND (t, 0); - - return t; -} - -/* Finish a parenthesized expression EXPR. */ - -cp_expr -finish_parenthesized_expr (cp_expr expr) -{ - if (EXPR_P (expr)) - /* This inhibits warnings in c_common_truthvalue_conversion. */ - suppress_warning (expr, OPT_Wparentheses); - - if (TREE_CODE (expr) == OFFSET_REF - || TREE_CODE (expr) == SCOPE_REF) - /* [expr.unary.op]/3 The qualified id of a pointer-to-member must not be - enclosed in parentheses. */ - PTRMEM_OK_P (expr) = 0; - - tree stripped_expr = tree_strip_any_location_wrapper (expr); - if (TREE_CODE (stripped_expr) == STRING_CST) - PAREN_STRING_LITERAL_P (stripped_expr) = 1; - - expr = cp_expr (force_paren_expr (expr), expr.get_location ()); - - return expr; -} - -/* Finish a reference to a non-static data member (DECL) that is not - preceded by `.' or `->'. */ - -tree -finish_non_static_data_member (tree decl, tree object, tree qualifying_scope) -{ - gcc_assert (TREE_CODE (decl) == FIELD_DECL); - bool try_omp_private = !object && omp_private_member_map; - tree ret; - - if (!object) - { - tree scope = qualifying_scope; - if (scope == NULL_TREE) - { - scope = context_for_name_lookup (decl); - if (!TYPE_P (scope)) - { - /* Can happen during error recovery (c++/85014). */ - gcc_assert (seen_error ()); - return error_mark_node; - } - } - object = maybe_dummy_object (scope, NULL); - } - - object = maybe_resolve_dummy (object, true); - if (object == error_mark_node) - return error_mark_node; - - /* DR 613/850: Can use non-static data members without an associated - object in sizeof/decltype/alignof. */ - if (is_dummy_object (object) && cp_unevaluated_operand == 0 - && (!processing_template_decl || !current_class_ref)) - { - if (current_function_decl - && DECL_STATIC_FUNCTION_P (current_function_decl)) - error ("invalid use of member %qD in static member function", decl); - else - error ("invalid use of non-static data member %qD", decl); - inform (DECL_SOURCE_LOCATION (decl), "declared here"); - - return error_mark_node; - } - - if (current_class_ptr) - TREE_USED (current_class_ptr) = 1; - if (processing_template_decl) - { - tree type = TREE_TYPE (decl); - - if (TYPE_REF_P (type)) - /* Quals on the object don't matter. */; - else if (PACK_EXPANSION_P (type)) - /* Don't bother trying to represent this. */ - type = NULL_TREE; - else - { - /* Set the cv qualifiers. */ - int quals = cp_type_quals (TREE_TYPE (object)); - - if (DECL_MUTABLE_P (decl)) - quals &= ~TYPE_QUAL_CONST; - - quals |= cp_type_quals (TREE_TYPE (decl)); - type = cp_build_qualified_type (type, quals); - } - - if (qualifying_scope) - /* Wrap this in a SCOPE_REF for now. */ - ret = build_qualified_name (type, qualifying_scope, decl, - /*template_p=*/false); - else - ret = (convert_from_reference - (build_min (COMPONENT_REF, type, object, decl, NULL_TREE))); - } - /* If PROCESSING_TEMPLATE_DECL is nonzero here, then - QUALIFYING_SCOPE is also non-null. */ - else - { - tree access_type = TREE_TYPE (object); - - perform_or_defer_access_check (TYPE_BINFO (access_type), decl, - decl, tf_warning_or_error); - - /* If the data member was named `C::M', convert `*this' to `C' - first. */ - if (qualifying_scope) - { - tree binfo = NULL_TREE; - object = build_scoped_ref (object, qualifying_scope, - &binfo); - } - - ret = build_class_member_access_expr (object, decl, - /*access_path=*/NULL_TREE, - /*preserve_reference=*/false, - tf_warning_or_error); - } - if (try_omp_private) - { - tree *v = omp_private_member_map->get (decl); - if (v) - ret = convert_from_reference (*v); - } - return ret; -} - -/* DECL was the declaration to which a qualified-id resolved. Issue - an error message if it is not accessible. If OBJECT_TYPE is - non-NULL, we have just seen `x->' or `x.' and OBJECT_TYPE is the - type of `*x', or `x', respectively. If the DECL was named as - `A::B' then NESTED_NAME_SPECIFIER is `A'. Return value is like - perform_access_checks above. */ - -bool -check_accessibility_of_qualified_id (tree decl, - tree object_type, - tree nested_name_specifier, - tsubst_flags_t complain) -{ - /* If we're not checking, return immediately. */ - if (deferred_access_no_check) - return true; - - /* Determine the SCOPE of DECL. */ - tree scope = context_for_name_lookup (decl); - /* If the SCOPE is not a type, then DECL is not a member. */ - if (!TYPE_P (scope) - /* If SCOPE is dependent then we can't perform this access check now, - and since we'll perform this access check again after substitution - there's no need to explicitly defer it. */ - || dependent_type_p (scope)) - return true; - - tree qualifying_type = NULL_TREE; - /* Compute the scope through which DECL is being accessed. */ - if (object_type - /* OBJECT_TYPE might not be a class type; consider: - - class A { typedef int I; }; - I *p; - p->A::I::~I(); - - In this case, we will have "A::I" as the DECL, but "I" as the - OBJECT_TYPE. */ - && CLASS_TYPE_P (object_type) - && DERIVED_FROM_P (scope, object_type)) - /* If we are processing a `->' or `.' expression, use the type of the - left-hand side. */ - qualifying_type = object_type; - else if (nested_name_specifier) - { - /* If the reference is to a non-static member of the - current class, treat it as if it were referenced through - `this'. */ - if (DECL_NONSTATIC_MEMBER_P (decl) - && current_class_ptr) - if (tree current = current_nonlambda_class_type ()) - { - if (dependent_type_p (current)) - /* In general we can't know whether this access goes through - `this' until instantiation time. Punt now, or else we might - create a deferred access check that's not relative to `this' - when it ought to be. We'll check this access again after - substitution, e.g. from tsubst_qualified_id. */ - return true; - - if (DERIVED_FROM_P (scope, current)) - qualifying_type = current; - } - /* Otherwise, use the type indicated by the - nested-name-specifier. */ - if (!qualifying_type) - qualifying_type = nested_name_specifier; - } - else - /* Otherwise, the name must be from the current class or one of - its bases. */ - qualifying_type = currently_open_derived_class (scope); - - if (qualifying_type - /* It is possible for qualifying type to be a TEMPLATE_TYPE_PARM - or similar in a default argument value. */ - && CLASS_TYPE_P (qualifying_type)) - return perform_or_defer_access_check (TYPE_BINFO (qualifying_type), decl, - decl, complain); - - return true; -} - -/* EXPR is the result of a qualified-id. The QUALIFYING_CLASS was the - class named to the left of the "::" operator. DONE is true if this - expression is a complete postfix-expression; it is false if this - expression is followed by '->', '[', '(', etc. ADDRESS_P is true - iff this expression is the operand of '&'. TEMPLATE_P is true iff - the qualified-id was of the form "A::template B". TEMPLATE_ARG_P - is true iff this qualified name appears as a template argument. */ - -tree -finish_qualified_id_expr (tree qualifying_class, - tree expr, - bool done, - bool address_p, - bool template_p, - bool template_arg_p, - tsubst_flags_t complain) -{ - gcc_assert (TYPE_P (qualifying_class)); - - if (error_operand_p (expr)) - return error_mark_node; - - if ((DECL_P (expr) || BASELINK_P (expr)) - && !mark_used (expr, complain)) - return error_mark_node; - - if (template_p) - { - if (TREE_CODE (expr) == UNBOUND_CLASS_TEMPLATE) - { - /* cp_parser_lookup_name thought we were looking for a type, - but we're actually looking for a declaration. */ - qualifying_class = TYPE_CONTEXT (expr); - expr = TYPE_IDENTIFIER (expr); - } - else - check_template_keyword (expr); - } - - /* If EXPR occurs as the operand of '&', use special handling that - permits a pointer-to-member. */ - if (address_p && done) - { - if (TREE_CODE (expr) == SCOPE_REF) - expr = TREE_OPERAND (expr, 1); - expr = build_offset_ref (qualifying_class, expr, - /*address_p=*/true, complain); - return expr; - } - - /* No need to check access within an enum. */ - if (TREE_CODE (qualifying_class) == ENUMERAL_TYPE - && TREE_CODE (expr) != IDENTIFIER_NODE) - return expr; - - /* Within the scope of a class, turn references to non-static - members into expression of the form "this->...". */ - if (template_arg_p) - /* But, within a template argument, we do not want make the - transformation, as there is no "this" pointer. */ - ; - else if (TREE_CODE (expr) == FIELD_DECL) - { - push_deferring_access_checks (dk_no_check); - expr = finish_non_static_data_member (expr, NULL_TREE, - qualifying_class); - pop_deferring_access_checks (); - } - else if (BASELINK_P (expr)) - { - /* See if any of the functions are non-static members. */ - /* If so, the expression may be relative to 'this'. */ - if (!shared_member_p (expr) - && current_class_ptr - && DERIVED_FROM_P (qualifying_class, - current_nonlambda_class_type ())) - expr = (build_class_member_access_expr - (maybe_dummy_object (qualifying_class, NULL), - expr, - BASELINK_ACCESS_BINFO (expr), - /*preserve_reference=*/false, - complain)); - else if (done) - /* The expression is a qualified name whose address is not - being taken. */ - expr = build_offset_ref (qualifying_class, expr, /*address_p=*/false, - complain); - } - else if (!template_p - && TREE_CODE (expr) == TEMPLATE_DECL - && !DECL_FUNCTION_TEMPLATE_P (expr)) - { - if (complain & tf_error) - error ("%qE missing template arguments", expr); - return error_mark_node; - } - else - { - /* In a template, return a SCOPE_REF for most qualified-ids - so that we can check access at instantiation time. But if - we're looking at a member of the current instantiation, we - know we have access and building up the SCOPE_REF confuses - non-type template argument handling. */ - if (processing_template_decl - && (!currently_open_class (qualifying_class) - || TREE_CODE (expr) == IDENTIFIER_NODE - || TREE_CODE (expr) == TEMPLATE_ID_EXPR - || TREE_CODE (expr) == BIT_NOT_EXPR)) - expr = build_qualified_name (TREE_TYPE (expr), - qualifying_class, expr, - template_p); - else if (tree wrap = maybe_get_tls_wrapper_call (expr)) - expr = wrap; - - expr = convert_from_reference (expr); - } - - return expr; -} - -/* Begin a statement-expression. The value returned must be passed to - finish_stmt_expr. */ - -tree -begin_stmt_expr (void) -{ - return push_stmt_list (); -} - -/* Process the final expression of a statement expression. EXPR can be - NULL, if the final expression is empty. Return a STATEMENT_LIST - containing all the statements in the statement-expression, or - ERROR_MARK_NODE if there was an error. */ - -tree -finish_stmt_expr_expr (tree expr, tree stmt_expr) -{ - if (error_operand_p (expr)) - { - /* The type of the statement-expression is the type of the last - expression. */ - TREE_TYPE (stmt_expr) = error_mark_node; - return error_mark_node; - } - - /* If the last statement does not have "void" type, then the value - of the last statement is the value of the entire expression. */ - if (expr) - { - tree type = TREE_TYPE (expr); - - if (type && type_unknown_p (type)) - { - error ("a statement expression is an insufficient context" - " for overload resolution"); - TREE_TYPE (stmt_expr) = error_mark_node; - return error_mark_node; - } - else if (processing_template_decl) - { - expr = build_stmt (input_location, EXPR_STMT, expr); - expr = add_stmt (expr); - /* Mark the last statement so that we can recognize it as such at - template-instantiation time. */ - EXPR_STMT_STMT_EXPR_RESULT (expr) = 1; - } - else if (VOID_TYPE_P (type)) - { - /* Just treat this like an ordinary statement. */ - expr = finish_expr_stmt (expr); - } - else - { - /* It actually has a value we need to deal with. First, force it - to be an rvalue so that we won't need to build up a copy - constructor call later when we try to assign it to something. */ - expr = force_rvalue (expr, tf_warning_or_error); - if (error_operand_p (expr)) - return error_mark_node; - - /* Update for array-to-pointer decay. */ - type = TREE_TYPE (expr); - - /* Wrap it in a CLEANUP_POINT_EXPR and add it to the list like a - normal statement, but don't convert to void or actually add - the EXPR_STMT. */ - if (TREE_CODE (expr) != CLEANUP_POINT_EXPR) - expr = maybe_cleanup_point_expr (expr); - add_stmt (expr); - } - - /* The type of the statement-expression is the type of the last - expression. */ - TREE_TYPE (stmt_expr) = type; - } - - return stmt_expr; -} - -/* Finish a statement-expression. EXPR should be the value returned - by the previous begin_stmt_expr. Returns an expression - representing the statement-expression. */ - -tree -finish_stmt_expr (tree stmt_expr, bool has_no_scope) -{ - tree type; - tree result; - - if (error_operand_p (stmt_expr)) - { - pop_stmt_list (stmt_expr); - return error_mark_node; - } - - gcc_assert (TREE_CODE (stmt_expr) == STATEMENT_LIST); - - type = TREE_TYPE (stmt_expr); - result = pop_stmt_list (stmt_expr); - TREE_TYPE (result) = type; - - if (processing_template_decl) - { - result = build_min (STMT_EXPR, type, result); - TREE_SIDE_EFFECTS (result) = 1; - STMT_EXPR_NO_SCOPE (result) = has_no_scope; - } - else if (CLASS_TYPE_P (type)) - { - /* Wrap the statement-expression in a TARGET_EXPR so that the - temporary object created by the final expression is destroyed at - the end of the full-expression containing the - statement-expression. */ - result = force_target_expr (type, result, tf_warning_or_error); - } - - return result; -} - -/* Returns the expression which provides the value of STMT_EXPR. */ - -tree -stmt_expr_value_expr (tree stmt_expr) -{ - tree t = STMT_EXPR_STMT (stmt_expr); - - if (TREE_CODE (t) == BIND_EXPR) - t = BIND_EXPR_BODY (t); - - if (TREE_CODE (t) == STATEMENT_LIST && STATEMENT_LIST_TAIL (t)) - t = STATEMENT_LIST_TAIL (t)->stmt; - - if (TREE_CODE (t) == EXPR_STMT) - t = EXPR_STMT_EXPR (t); - - return t; -} - -/* Return TRUE iff EXPR_STMT is an empty list of - expression statements. */ - -bool -empty_expr_stmt_p (tree expr_stmt) -{ - tree body = NULL_TREE; - - if (expr_stmt == void_node) - return true; - - if (expr_stmt) - { - if (TREE_CODE (expr_stmt) == EXPR_STMT) - body = EXPR_STMT_EXPR (expr_stmt); - else if (TREE_CODE (expr_stmt) == STATEMENT_LIST) - body = expr_stmt; - } - - if (body) - { - if (TREE_CODE (body) == STATEMENT_LIST) - return tsi_end_p (tsi_start (body)); - else - return empty_expr_stmt_p (body); - } - return false; -} - -/* Perform Koenig lookup. FN_EXPR is the postfix-expression representing - the function (or functions) to call; ARGS are the arguments to the - call. Returns the functions to be considered by overload resolution. */ - -cp_expr -perform_koenig_lookup (cp_expr fn_expr, vec<tree, va_gc> *args, - tsubst_flags_t complain) -{ - tree identifier = NULL_TREE; - tree functions = NULL_TREE; - tree tmpl_args = NULL_TREE; - bool template_id = false; - location_t loc = fn_expr.get_location (); - tree fn = fn_expr.get_value (); - - STRIP_ANY_LOCATION_WRAPPER (fn); - - if (TREE_CODE (fn) == TEMPLATE_ID_EXPR) - { - /* Use a separate flag to handle null args. */ - template_id = true; - tmpl_args = TREE_OPERAND (fn, 1); - fn = TREE_OPERAND (fn, 0); - } - - /* Find the name of the overloaded function. */ - if (identifier_p (fn)) - identifier = fn; - else - { - functions = fn; - identifier = OVL_NAME (functions); - } - - /* A call to a namespace-scope function using an unqualified name. - - Do Koenig lookup -- unless any of the arguments are - type-dependent. */ - if (!any_type_dependent_arguments_p (args) - && !any_dependent_template_arguments_p (tmpl_args)) - { - fn = lookup_arg_dependent (identifier, functions, args); - if (!fn) - { - /* The unqualified name could not be resolved. */ - if (complain & tf_error) - fn = unqualified_fn_lookup_error (cp_expr (identifier, loc)); - else - fn = identifier; - } - } - - if (fn && template_id && fn != error_mark_node) - fn = build2 (TEMPLATE_ID_EXPR, unknown_type_node, fn, tmpl_args); - - return cp_expr (fn, loc); -} - -/* Generate an expression for `FN (ARGS)'. This may change the - contents of ARGS. - - If DISALLOW_VIRTUAL is true, the call to FN will be not generated - as a virtual call, even if FN is virtual. (This flag is set when - encountering an expression where the function name is explicitly - qualified. For example a call to `X::f' never generates a virtual - call.) - - Returns code for the call. */ - -tree -finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual, - bool koenig_p, tsubst_flags_t complain) -{ - tree result; - tree orig_fn; - vec<tree, va_gc> *orig_args = *args; - - if (fn == error_mark_node) - return error_mark_node; - - gcc_assert (!TYPE_P (fn)); - - /* If FN may be a FUNCTION_DECL obfuscated by force_paren_expr, undo - it so that we can tell this is a call to a known function. */ - fn = maybe_undo_parenthesized_ref (fn); - - STRIP_ANY_LOCATION_WRAPPER (fn); - - orig_fn = fn; - - if (processing_template_decl) - { - /* If FN is a local extern declaration or set thereof, look them up - again at instantiation time. */ - if (is_overloaded_fn (fn)) - { - tree ifn = get_first_fn (fn); - if (TREE_CODE (ifn) == FUNCTION_DECL - && DECL_LOCAL_DECL_P (ifn)) - orig_fn = DECL_NAME (ifn); - } - - /* If the call expression is dependent, build a CALL_EXPR node - with no type; type_dependent_expression_p recognizes - expressions with no type as being dependent. */ - if (type_dependent_expression_p (fn) - || any_type_dependent_arguments_p (*args)) - { - result = build_min_nt_call_vec (orig_fn, *args); - SET_EXPR_LOCATION (result, cp_expr_loc_or_input_loc (fn)); - KOENIG_LOOKUP_P (result) = koenig_p; - if (is_overloaded_fn (fn)) - fn = get_fns (fn); - - if (cfun) - { - bool abnormal = true; - for (lkp_iterator iter (fn); abnormal && iter; ++iter) - { - tree fndecl = STRIP_TEMPLATE (*iter); - if (TREE_CODE (fndecl) != FUNCTION_DECL - || !TREE_THIS_VOLATILE (fndecl)) - abnormal = false; - } - /* FIXME: Stop warning about falling off end of non-void - function. But this is wrong. Even if we only see - no-return fns at this point, we could select a - future-defined return fn during instantiation. Or - vice-versa. */ - if (abnormal) - current_function_returns_abnormally = 1; - } - return result; - } - orig_args = make_tree_vector_copy (*args); - if (!BASELINK_P (fn) - && TREE_CODE (fn) != PSEUDO_DTOR_EXPR - && TREE_TYPE (fn) != unknown_type_node) - fn = build_non_dependent_expr (fn); - make_args_non_dependent (*args); - } - - if (TREE_CODE (fn) == COMPONENT_REF) - { - tree member = TREE_OPERAND (fn, 1); - if (BASELINK_P (member)) - { - tree object = TREE_OPERAND (fn, 0); - return build_new_method_call (object, member, - args, NULL_TREE, - (disallow_virtual - ? LOOKUP_NORMAL | LOOKUP_NONVIRTUAL - : LOOKUP_NORMAL), - /*fn_p=*/NULL, - complain); - } - } - - /* Per 13.3.1.1, '(&f)(...)' is the same as '(f)(...)'. */ - if (TREE_CODE (fn) == ADDR_EXPR - && TREE_CODE (TREE_OPERAND (fn, 0)) == OVERLOAD) - fn = TREE_OPERAND (fn, 0); - - if (is_overloaded_fn (fn)) - fn = baselink_for_fns (fn); - - result = NULL_TREE; - if (BASELINK_P (fn)) - { - tree object; - - /* A call to a member function. From [over.call.func]: - - If the keyword this is in scope and refers to the class of - that member function, or a derived class thereof, then the - function call is transformed into a qualified function call - using (*this) as the postfix-expression to the left of the - . operator.... [Otherwise] a contrived object of type T - becomes the implied object argument. - - In this situation: - - struct A { void f(); }; - struct B : public A {}; - struct C : public A { void g() { B::f(); }}; - - "the class of that member function" refers to `A'. But 11.2 - [class.access.base] says that we need to convert 'this' to B* as - part of the access, so we pass 'B' to maybe_dummy_object. */ - - if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (get_first_fn (fn))) - { - /* A constructor call always uses a dummy object. (This constructor - call which has the form A::A () is actually invalid and we are - going to reject it later in build_new_method_call.) */ - object = build_dummy_object (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn))); - } - else - object = maybe_dummy_object (BINFO_TYPE (BASELINK_ACCESS_BINFO (fn)), - NULL); - - result = build_new_method_call (object, fn, args, NULL_TREE, - (disallow_virtual - ? LOOKUP_NORMAL|LOOKUP_NONVIRTUAL - : LOOKUP_NORMAL), - /*fn_p=*/NULL, - complain); - } - else if (concept_check_p (fn)) - { - /* FN is actually a template-id referring to a concept definition. */ - tree id = unpack_concept_check (fn); - tree tmpl = TREE_OPERAND (id, 0); - tree args = TREE_OPERAND (id, 1); - - if (!function_concept_p (tmpl)) - { - error_at (EXPR_LOC_OR_LOC (fn, input_location), - "cannot call a concept as a function"); - return error_mark_node; - } - - /* Ensure the result is wrapped as a call expression. */ - result = build_concept_check (tmpl, args, tf_warning_or_error); - } - else if (is_overloaded_fn (fn)) - { - /* If the function is an overloaded builtin, resolve it. */ - if (TREE_CODE (fn) == FUNCTION_DECL - && (DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL - || DECL_BUILT_IN_CLASS (fn) == BUILT_IN_MD)) - result = resolve_overloaded_builtin (input_location, fn, *args); - - if (!result) - { - if (warn_sizeof_pointer_memaccess - && (complain & tf_warning) - && !vec_safe_is_empty (*args) - && !processing_template_decl) - { - location_t sizeof_arg_loc[3]; - tree sizeof_arg[3]; - unsigned int i; - for (i = 0; i < 3; i++) - { - tree t; - - sizeof_arg_loc[i] = UNKNOWN_LOCATION; - sizeof_arg[i] = NULL_TREE; - if (i >= (*args)->length ()) - continue; - t = (**args)[i]; - if (TREE_CODE (t) != SIZEOF_EXPR) - continue; - if (SIZEOF_EXPR_TYPE_P (t)) - sizeof_arg[i] = TREE_TYPE (TREE_OPERAND (t, 0)); - else - sizeof_arg[i] = TREE_OPERAND (t, 0); - sizeof_arg_loc[i] = EXPR_LOCATION (t); - } - sizeof_pointer_memaccess_warning - (sizeof_arg_loc, fn, *args, - sizeof_arg, same_type_ignoring_top_level_qualifiers_p); - } - - if ((complain & tf_warning) - && TREE_CODE (fn) == FUNCTION_DECL - && fndecl_built_in_p (fn, BUILT_IN_MEMSET) - && vec_safe_length (*args) == 3 - && !any_type_dependent_arguments_p (*args)) - { - tree arg0 = (*orig_args)[0]; - tree arg1 = (*orig_args)[1]; - tree arg2 = (*orig_args)[2]; - int literal_mask = ((literal_integer_zerop (arg1) << 1) - | (literal_integer_zerop (arg2) << 2)); - warn_for_memset (input_location, arg0, arg2, literal_mask); - } - - /* A call to a namespace-scope function. */ - result = build_new_function_call (fn, args, complain); - } - } - else if (TREE_CODE (fn) == PSEUDO_DTOR_EXPR) - { - if (!vec_safe_is_empty (*args)) - error ("arguments to destructor are not allowed"); - /* C++20/DR: If the postfix-expression names a pseudo-destructor (in - which case the postfix-expression is a possibly-parenthesized class - member access), the function call destroys the object of scalar type - denoted by the object expression of the class member access. */ - tree ob = TREE_OPERAND (fn, 0); - if (obvalue_p (ob)) - result = build_trivial_dtor_call (ob, true); - else - /* No location to clobber. */ - result = convert_to_void (ob, ICV_STATEMENT, complain); - } - else if (CLASS_TYPE_P (TREE_TYPE (fn))) - /* If the "function" is really an object of class type, it might - have an overloaded `operator ()'. */ - result = build_op_call (fn, args, complain); - - if (!result) - /* A call where the function is unknown. */ - result = cp_build_function_call_vec (fn, args, complain); - - if (processing_template_decl && result != error_mark_node) - { - if (INDIRECT_REF_P (result)) - result = TREE_OPERAND (result, 0); - - /* Prune all but the selected function from the original overload - set so that we can avoid some duplicate work at instantiation time. */ - if (TREE_CODE (result) == CALL_EXPR - && really_overloaded_fn (orig_fn)) - { - orig_fn = CALL_EXPR_FN (result); - if (TREE_CODE (orig_fn) == COMPONENT_REF) - { - /* The non-dependent result of build_new_method_call. */ - orig_fn = TREE_OPERAND (orig_fn, 1); - gcc_assert (BASELINK_P (orig_fn)); - } - } - - result = build_call_vec (TREE_TYPE (result), orig_fn, orig_args); - SET_EXPR_LOCATION (result, input_location); - KOENIG_LOOKUP_P (result) = koenig_p; - release_tree_vector (orig_args); - result = convert_from_reference (result); - } - - return result; -} - -/* Finish a call to a postfix increment or decrement or EXPR. (Which - is indicated by CODE, which should be POSTINCREMENT_EXPR or - POSTDECREMENT_EXPR.) */ - -cp_expr -finish_increment_expr (cp_expr expr, enum tree_code code) -{ - /* input_location holds the location of the trailing operator token. - Build a location of the form: - expr++ - ~~~~^~ - with the caret at the operator token, ranging from the start - of EXPR to the end of the operator token. */ - location_t combined_loc = make_location (input_location, - expr.get_start (), - get_finish (input_location)); - cp_expr result = build_x_unary_op (combined_loc, code, expr, - NULL_TREE, tf_warning_or_error); - /* TODO: build_x_unary_op doesn't honor the location, so set it here. */ - result.set_location (combined_loc); - return result; -} - -/* Finish a use of `this'. Returns an expression for `this'. */ - -tree -finish_this_expr (void) -{ - tree result = NULL_TREE; - - if (current_class_ptr) - { - tree type = TREE_TYPE (current_class_ref); - - /* In a lambda expression, 'this' refers to the captured 'this'. */ - if (LAMBDA_TYPE_P (type)) - result = lambda_expr_this_capture (CLASSTYPE_LAMBDA_EXPR (type), true); - else - result = current_class_ptr; - } - - if (result) - /* The keyword 'this' is a prvalue expression. */ - return rvalue (result); - - tree fn = current_nonlambda_function (); - if (fn && DECL_STATIC_FUNCTION_P (fn)) - error ("%<this%> is unavailable for static member functions"); - else if (fn) - error ("invalid use of %<this%> in non-member function"); - else - error ("invalid use of %<this%> at top level"); - return error_mark_node; -} - -/* Finish a pseudo-destructor expression. If SCOPE is NULL, the - expression was of the form `OBJECT.~DESTRUCTOR' where DESTRUCTOR is - the TYPE for the type given. If SCOPE is non-NULL, the expression - was of the form `OBJECT.SCOPE::~DESTRUCTOR'. */ - -tree -finish_pseudo_destructor_expr (tree object, tree scope, tree destructor, - location_t loc) -{ - if (object == error_mark_node || destructor == error_mark_node) - return error_mark_node; - - gcc_assert (TYPE_P (destructor)); - - if (!processing_template_decl) - { - if (scope == error_mark_node) - { - error_at (loc, "invalid qualifying scope in pseudo-destructor name"); - return error_mark_node; - } - if (is_auto (destructor)) - destructor = TREE_TYPE (object); - if (scope && TYPE_P (scope) && !check_dtor_name (scope, destructor)) - { - error_at (loc, - "qualified type %qT does not match destructor name ~%qT", - scope, destructor); - return error_mark_node; - } - - - /* [expr.pseudo] says both: - - The type designated by the pseudo-destructor-name shall be - the same as the object type. - - and: - - The cv-unqualified versions of the object type and of the - type designated by the pseudo-destructor-name shall be the - same type. - - We implement the more generous second sentence, since that is - what most other compilers do. */ - if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (object), - destructor)) - { - error_at (loc, "%qE is not of type %qT", object, destructor); - return error_mark_node; - } - } - - tree type = (type_dependent_expression_p (object) - ? NULL_TREE : void_type_node); - - return build3_loc (loc, PSEUDO_DTOR_EXPR, type, object, - scope, destructor); -} - -/* Finish an expression of the form CODE EXPR. */ - -cp_expr -finish_unary_op_expr (location_t op_loc, enum tree_code code, cp_expr expr, - tsubst_flags_t complain) -{ - /* Build a location of the form: - ++expr - ^~~~~~ - with the caret at the operator token, ranging from the start - of the operator token to the end of EXPR. */ - location_t combined_loc = make_location (op_loc, - op_loc, expr.get_finish ()); - cp_expr result = build_x_unary_op (combined_loc, code, expr, - NULL_TREE, complain); - /* TODO: build_x_unary_op doesn't always honor the location. */ - result.set_location (combined_loc); - - if (result == error_mark_node) - return result; - - if (!(complain & tf_warning)) - return result; - - tree result_ovl = result; - tree expr_ovl = expr; - - if (!processing_template_decl) - expr_ovl = cp_fully_fold (expr_ovl); - - if (!CONSTANT_CLASS_P (expr_ovl) - || TREE_OVERFLOW_P (expr_ovl)) - return result; - - if (!processing_template_decl) - result_ovl = cp_fully_fold (result_ovl); - - if (CONSTANT_CLASS_P (result_ovl) && TREE_OVERFLOW_P (result_ovl)) - overflow_warning (combined_loc, result_ovl); - - return result; -} - -/* Return true if CONSTRUCTOR EXPR after pack expansion could have no - elements. */ - -static bool -maybe_zero_constructor_nelts (tree expr) -{ - if (CONSTRUCTOR_NELTS (expr) == 0) - return true; - if (!processing_template_decl) - return false; - for (constructor_elt &elt : CONSTRUCTOR_ELTS (expr)) - if (!PACK_EXPANSION_P (elt.value)) - return false; - return true; -} - -/* Finish a compound-literal expression or C++11 functional cast with aggregate - initializer. TYPE is the type to which the CONSTRUCTOR in COMPOUND_LITERAL - is being cast. */ - -tree -finish_compound_literal (tree type, tree compound_literal, - tsubst_flags_t complain, - fcl_t fcl_context) -{ - if (type == error_mark_node) - return error_mark_node; - - if (TYPE_REF_P (type)) - { - compound_literal - = finish_compound_literal (TREE_TYPE (type), compound_literal, - complain, fcl_context); - /* The prvalue is then used to direct-initialize the reference. */ - tree r = (perform_implicit_conversion_flags - (type, compound_literal, complain, LOOKUP_NORMAL)); - return convert_from_reference (r); - } - - if (!TYPE_OBJ_P (type)) - { - /* DR2351 */ - if (VOID_TYPE_P (type) && CONSTRUCTOR_NELTS (compound_literal) == 0) - return void_node; - else if (VOID_TYPE_P (type) - && processing_template_decl - && maybe_zero_constructor_nelts (compound_literal)) - /* If there are only packs in compound_literal, it could - be void{} after pack expansion. */; - else - { - if (complain & tf_error) - error ("compound literal of non-object type %qT", type); - return error_mark_node; - } - } - - if (template_placeholder_p (type)) - { - type = do_auto_deduction (type, compound_literal, type, complain, - adc_variable_type); - if (type == error_mark_node) - return error_mark_node; - } - /* C++23 auto{x}. */ - else if (is_auto (type) - && !AUTO_IS_DECLTYPE (type) - && CONSTRUCTOR_NELTS (compound_literal) == 1) - { - if (cxx_dialect < cxx23) - pedwarn (input_location, OPT_Wc__23_extensions, - "%<auto{x}%> only available with " - "%<-std=c++2b%> or %<-std=gnu++2b%>"); - type = do_auto_deduction (type, compound_literal, type, complain, - adc_variable_type); - if (type == error_mark_node) - return error_mark_node; - } - - /* Used to hold a copy of the compound literal in a template. */ - tree orig_cl = NULL_TREE; - - if (processing_template_decl) - { - const bool dependent_p - = (instantiation_dependent_expression_p (compound_literal) - || dependent_type_p (type)); - if (dependent_p) - /* We're about to return, no need to copy. */ - orig_cl = compound_literal; - else - /* We're going to need a copy. */ - orig_cl = unshare_constructor (compound_literal); - TREE_TYPE (orig_cl) = type; - /* Mark the expression as a compound literal. */ - TREE_HAS_CONSTRUCTOR (orig_cl) = 1; - /* And as instantiation-dependent. */ - CONSTRUCTOR_IS_DEPENDENT (orig_cl) = dependent_p; - if (fcl_context == fcl_c99) - CONSTRUCTOR_C99_COMPOUND_LITERAL (orig_cl) = 1; - /* If the compound literal is dependent, we're done for now. */ - if (dependent_p) - return orig_cl; - /* Otherwise, do go on to e.g. check narrowing. */ - } - - type = complete_type (type); - - if (TYPE_NON_AGGREGATE_CLASS (type)) - { - /* Trying to deal with a CONSTRUCTOR instead of a TREE_LIST - everywhere that deals with function arguments would be a pain, so - just wrap it in a TREE_LIST. The parser set a flag so we know - that it came from T{} rather than T({}). */ - CONSTRUCTOR_IS_DIRECT_INIT (compound_literal) = 1; - compound_literal = build_tree_list (NULL_TREE, compound_literal); - return build_functional_cast (input_location, type, - compound_literal, complain); - } - - if (TREE_CODE (type) == ARRAY_TYPE - && check_array_initializer (NULL_TREE, type, compound_literal)) - return error_mark_node; - compound_literal = reshape_init (type, compound_literal, complain); - if (SCALAR_TYPE_P (type) - && !BRACE_ENCLOSED_INITIALIZER_P (compound_literal)) - { - tree t = instantiate_non_dependent_expr_sfinae (compound_literal, - complain); - if (!check_narrowing (type, t, complain)) - return error_mark_node; - } - if (TREE_CODE (type) == ARRAY_TYPE - && TYPE_DOMAIN (type) == NULL_TREE) - { - cp_complete_array_type_or_error (&type, compound_literal, - false, complain); - if (type == error_mark_node) - return error_mark_node; - } - compound_literal = digest_init_flags (type, compound_literal, - LOOKUP_NORMAL | LOOKUP_NO_NARROWING, - complain); - if (compound_literal == error_mark_node) - return error_mark_node; - - /* If we're in a template, return the original compound literal. */ - if (orig_cl) - return orig_cl; - - if (TREE_CODE (compound_literal) == CONSTRUCTOR) - { - TREE_HAS_CONSTRUCTOR (compound_literal) = true; - if (fcl_context == fcl_c99) - CONSTRUCTOR_C99_COMPOUND_LITERAL (compound_literal) = 1; - } - - /* Put static/constant array temporaries in static variables. */ - /* FIXME all C99 compound literals should be variables rather than C++ - temporaries, unless they are used as an aggregate initializer. */ - if ((!at_function_scope_p () || CP_TYPE_CONST_P (type)) - && fcl_context == fcl_c99 - && TREE_CODE (type) == ARRAY_TYPE - && !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type) - && initializer_constant_valid_p (compound_literal, type)) - { - tree decl = create_temporary_var (type); - DECL_CONTEXT (decl) = NULL_TREE; - DECL_INITIAL (decl) = compound_literal; - TREE_STATIC (decl) = 1; - if (literal_type_p (type) && CP_TYPE_CONST_NON_VOLATILE_P (type)) - { - /* 5.19 says that a constant expression can include an - lvalue-rvalue conversion applied to "a glvalue of literal type - that refers to a non-volatile temporary object initialized - with a constant expression". Rather than try to communicate - that this VAR_DECL is a temporary, just mark it constexpr. */ - DECL_DECLARED_CONSTEXPR_P (decl) = true; - DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = true; - TREE_CONSTANT (decl) = true; - } - cp_apply_type_quals_to_decl (cp_type_quals (type), decl); - decl = pushdecl_top_level (decl); - DECL_NAME (decl) = make_anon_name (); - SET_DECL_ASSEMBLER_NAME (decl, DECL_NAME (decl)); - /* Make sure the destructor is callable. */ - tree clean = cxx_maybe_build_cleanup (decl, complain); - if (clean == error_mark_node) - return error_mark_node; - return decl; - } - - /* Represent other compound literals with TARGET_EXPR so we produce - a prvalue, and can elide copies. */ - if (!VECTOR_TYPE_P (type)) - { - /* The CONSTRUCTOR is now an initializer, not a compound literal. */ - TREE_HAS_CONSTRUCTOR (compound_literal) = false; - compound_literal = get_target_expr_sfinae (compound_literal, complain); - } - - return compound_literal; -} - -/* Return the declaration for the function-name variable indicated by - ID. */ - -tree -finish_fname (tree id) -{ - tree decl; - - decl = fname_decl (input_location, C_RID_CODE (id), id); - if (processing_template_decl && current_function_decl - && decl != error_mark_node) - decl = DECL_NAME (decl); - return decl; -} - -/* Finish a translation unit. */ - -void -finish_translation_unit (void) -{ - /* In case there were missing closebraces, - get us back to the global binding level. */ - pop_everything (); - while (current_namespace != global_namespace) - pop_namespace (); - - /* Do file scope __FUNCTION__ et al. */ - finish_fname_decls (); - - if (vec_safe_length (scope_chain->omp_declare_target_attribute)) - { - if (!errorcount) - error ("%<#pragma omp declare target%> without corresponding " - "%<#pragma omp end declare target%>"); - vec_safe_truncate (scope_chain->omp_declare_target_attribute, 0); - } -} - -/* Finish a template type parameter, specified as AGGR IDENTIFIER. - Returns the parameter. */ - -tree -finish_template_type_parm (tree aggr, tree identifier) -{ - if (aggr != class_type_node) - { - permerror (input_location, "template type parameters must use the keyword %<class%> or %<typename%>"); - aggr = class_type_node; - } - - return build_tree_list (aggr, identifier); -} - -/* Finish a template template parameter, specified as AGGR IDENTIFIER. - Returns the parameter. */ - -tree -finish_template_template_parm (tree aggr, tree identifier) -{ - tree decl = build_decl (input_location, - TYPE_DECL, identifier, NULL_TREE); - - tree tmpl = build_lang_decl (TEMPLATE_DECL, identifier, NULL_TREE); - DECL_TEMPLATE_PARMS (tmpl) = current_template_parms; - DECL_TEMPLATE_RESULT (tmpl) = decl; - DECL_ARTIFICIAL (decl) = 1; - - /* Associate the constraints with the underlying declaration, - not the template. */ - tree reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms); - tree constr = build_constraints (reqs, NULL_TREE); - set_constraints (decl, constr); - - end_template_decl (); - - gcc_assert (DECL_TEMPLATE_PARMS (tmpl)); - - check_default_tmpl_args (decl, DECL_TEMPLATE_PARMS (tmpl), - /*is_primary=*/true, /*is_partial=*/false, - /*is_friend=*/0); - - return finish_template_type_parm (aggr, tmpl); -} - -/* ARGUMENT is the default-argument value for a template template - parameter. If ARGUMENT is invalid, issue error messages and return - the ERROR_MARK_NODE. Otherwise, ARGUMENT itself is returned. */ - -tree -check_template_template_default_arg (tree argument) -{ - if (TREE_CODE (argument) != TEMPLATE_DECL - && TREE_CODE (argument) != TEMPLATE_TEMPLATE_PARM - && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE) - { - if (TREE_CODE (argument) == TYPE_DECL) - error ("invalid use of type %qT as a default value for a template " - "template-parameter", TREE_TYPE (argument)); - else - error ("invalid default argument for a template template parameter"); - return error_mark_node; - } - - return argument; -} - -/* Begin a class definition, as indicated by T. */ - -tree -begin_class_definition (tree t) -{ - if (error_operand_p (t) || error_operand_p (TYPE_MAIN_DECL (t))) - return error_mark_node; - - if (processing_template_parmlist && !LAMBDA_TYPE_P (t)) - { - error ("definition of %q#T inside template parameter list", t); - return error_mark_node; - } - - /* According to the C++ ABI, decimal classes defined in ISO/IEC TR 24733 - are passed the same as decimal scalar types. */ - if (TREE_CODE (t) == RECORD_TYPE - && !processing_template_decl) - { - tree ns = TYPE_CONTEXT (t); - if (ns && TREE_CODE (ns) == NAMESPACE_DECL - && DECL_CONTEXT (ns) == std_node - && DECL_NAME (ns) - && id_equal (DECL_NAME (ns), "decimal")) - { - const char *n = TYPE_NAME_STRING (t); - if ((strcmp (n, "decimal32") == 0) - || (strcmp (n, "decimal64") == 0) - || (strcmp (n, "decimal128") == 0)) - TYPE_TRANSPARENT_AGGR (t) = 1; - } - } - - /* A non-implicit typename comes from code like: - - template <typename T> struct A { - template <typename U> struct A<T>::B ... - - This is erroneous. */ - else if (TREE_CODE (t) == TYPENAME_TYPE) - { - error ("invalid definition of qualified type %qT", t); - t = error_mark_node; - } - - if (t == error_mark_node || ! MAYBE_CLASS_TYPE_P (t)) - { - t = make_class_type (RECORD_TYPE); - pushtag (make_anon_name (), t); - } - - if (TYPE_BEING_DEFINED (t)) - { - t = make_class_type (TREE_CODE (t)); - pushtag (TYPE_IDENTIFIER (t), t); - } - - if (modules_p ()) - { - if (!module_may_redeclare (TYPE_NAME (t))) - { - error ("cannot declare %qD in a different module", TYPE_NAME (t)); - inform (DECL_SOURCE_LOCATION (TYPE_NAME (t)), "declared here"); - return error_mark_node; - } - set_instantiating_module (TYPE_NAME (t)); - set_defining_module (TYPE_NAME (t)); - } - - maybe_process_partial_specialization (t); - pushclass (t); - TYPE_BEING_DEFINED (t) = 1; - class_binding_level->defining_class_p = 1; - - if (flag_pack_struct) - { - tree v; - TYPE_PACKED (t) = 1; - /* Even though the type is being defined for the first time - here, there might have been a forward declaration, so there - might be cv-qualified variants of T. */ - for (v = TYPE_NEXT_VARIANT (t); v; v = TYPE_NEXT_VARIANT (v)) - TYPE_PACKED (v) = 1; - } - /* Reset the interface data, at the earliest possible - moment, as it might have been set via a class foo; - before. */ - if (! TYPE_UNNAMED_P (t)) - { - struct c_fileinfo *finfo = \ - get_fileinfo (LOCATION_FILE (input_location)); - CLASSTYPE_INTERFACE_ONLY (t) = finfo->interface_only; - SET_CLASSTYPE_INTERFACE_UNKNOWN_X - (t, finfo->interface_unknown); - } - reset_specialization (); - - /* Make a declaration for this class in its own scope. */ - build_self_reference (); - - return t; -} - -/* Finish the member declaration given by DECL. */ - -void -finish_member_declaration (tree decl) -{ - if (decl == error_mark_node || decl == NULL_TREE) - return; - - if (decl == void_type_node) - /* The COMPONENT was a friend, not a member, and so there's - nothing for us to do. */ - return; - - /* We should see only one DECL at a time. */ - gcc_assert (DECL_CHAIN (decl) == NULL_TREE); - - /* Don't add decls after definition. */ - gcc_assert (TYPE_BEING_DEFINED (current_class_type) - /* We can add lambda types when late parsing default - arguments. */ - || LAMBDA_TYPE_P (TREE_TYPE (decl))); - - /* Set up access control for DECL. */ - TREE_PRIVATE (decl) - = (current_access_specifier == access_private_node); - TREE_PROTECTED (decl) - = (current_access_specifier == access_protected_node); - if (TREE_CODE (decl) == TEMPLATE_DECL) - { - TREE_PRIVATE (DECL_TEMPLATE_RESULT (decl)) = TREE_PRIVATE (decl); - TREE_PROTECTED (DECL_TEMPLATE_RESULT (decl)) = TREE_PROTECTED (decl); - } - - /* Mark the DECL as a member of the current class, unless it's - a member of an enumeration. */ - if (TREE_CODE (decl) != CONST_DECL) - DECL_CONTEXT (decl) = current_class_type; - - /* Remember the single FIELD_DECL an anonymous aggregate type is used for. */ - if (TREE_CODE (decl) == FIELD_DECL - && ANON_AGGR_TYPE_P (TREE_TYPE (decl))) - { - gcc_assert (!ANON_AGGR_TYPE_FIELD (TYPE_MAIN_VARIANT (TREE_TYPE (decl)))); - ANON_AGGR_TYPE_FIELD (TYPE_MAIN_VARIANT (TREE_TYPE (decl))) = decl; - } - - if (TREE_CODE (decl) == USING_DECL) - /* For now, ignore class-scope USING_DECLS, so that debugging - backends do not see them. */ - DECL_IGNORED_P (decl) = 1; - - /* Check for bare parameter packs in the non-static data member - declaration. */ - if (TREE_CODE (decl) == FIELD_DECL) - { - if (check_for_bare_parameter_packs (TREE_TYPE (decl))) - TREE_TYPE (decl) = error_mark_node; - if (check_for_bare_parameter_packs (DECL_ATTRIBUTES (decl))) - DECL_ATTRIBUTES (decl) = NULL_TREE; - } - - /* [dcl.link] - - A C language linkage is ignored for the names of class members - and the member function type of class member functions. */ - if (DECL_LANG_SPECIFIC (decl)) - SET_DECL_LANGUAGE (decl, lang_cplusplus); - - bool add = false; - - /* Functions and non-functions are added differently. */ - if (DECL_DECLARES_FUNCTION_P (decl)) - add = add_method (current_class_type, decl, false); - /* Enter the DECL into the scope of the class, if the class - isn't a closure (whose fields are supposed to be unnamed). */ - else if (CLASSTYPE_LAMBDA_EXPR (current_class_type) - || pushdecl_class_level (decl)) - add = true; - - if (add) - { - /* All TYPE_DECLs go at the end of TYPE_FIELDS. Ordinary fields - go at the beginning. The reason is that - legacy_nonfn_member_lookup searches the list in order, and we - want a field name to override a type name so that the "struct - stat hack" will work. In particular: - - struct S { enum E { }; static const int E = 5; int ary[S::E]; } s; - - is valid. */ - - if (TREE_CODE (decl) == TYPE_DECL) - TYPE_FIELDS (current_class_type) - = chainon (TYPE_FIELDS (current_class_type), decl); - else - { - DECL_CHAIN (decl) = TYPE_FIELDS (current_class_type); - TYPE_FIELDS (current_class_type) = decl; - } - - maybe_add_class_template_decl_list (current_class_type, decl, - /*friend_p=*/0); - } -} - -/* Finish processing a complete template declaration. The PARMS are - the template parameters. */ - -void -finish_template_decl (tree parms) -{ - if (parms) - end_template_decl (); - else - end_specialization (); -} - -// Returns the template type of the class scope being entered. If we're -// entering a constrained class scope. TYPE is the class template -// scope being entered and we may need to match the intended type with -// a constrained specialization. For example: -// -// template<Object T> -// struct S { void f(); }; #1 -// -// template<Object T> -// void S<T>::f() { } #2 -// -// We check, in #2, that S<T> refers precisely to the type declared by -// #1 (i.e., that the constraints match). Note that the following should -// be an error since there is no specialization of S<T> that is -// unconstrained, but this is not diagnosed here. -// -// template<typename T> -// void S<T>::f() { } -// -// We cannot diagnose this problem here since this function also matches -// qualified template names that are not part of a definition. For example: -// -// template<Integral T, Floating_point U> -// typename pair<T, U>::first_type void f(T, U); -// -// Here, it is unlikely that there is a partial specialization of -// pair constrained for for Integral and Floating_point arguments. -// -// The general rule is: if a constrained specialization with matching -// constraints is found return that type. Also note that if TYPE is not a -// class-type (e.g. a typename type), then no fixup is needed. - -static tree -fixup_template_type (tree type) -{ - // Find the template parameter list at the a depth appropriate to - // the scope we're trying to enter. - tree parms = current_template_parms; - int depth = template_class_depth (type); - for (int n = current_template_depth; n > depth && parms; --n) - parms = TREE_CHAIN (parms); - if (!parms) - return type; - tree cur_reqs = TEMPLATE_PARMS_CONSTRAINTS (parms); - tree cur_constr = build_constraints (cur_reqs, NULL_TREE); - - // Search for a specialization whose type and constraints match. - tree tmpl = CLASSTYPE_TI_TEMPLATE (type); - tree specs = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); - while (specs) - { - tree spec_constr = get_constraints (TREE_VALUE (specs)); - - // If the type and constraints match a specialization, then we - // are entering that type. - if (same_type_p (type, TREE_TYPE (specs)) - && equivalent_constraints (cur_constr, spec_constr)) - return TREE_TYPE (specs); - specs = TREE_CHAIN (specs); - } - - // If no specialization matches, then must return the type - // previously found. - return type; -} - -/* Finish processing a template-id (which names a type) of the form - NAME < ARGS >. Return the TYPE_DECL for the type named by the - template-id. If ENTERING_SCOPE is nonzero we are about to enter - the scope of template-id indicated. */ - -tree -finish_template_type (tree name, tree args, int entering_scope) -{ - tree type; - - type = lookup_template_class (name, args, - NULL_TREE, NULL_TREE, entering_scope, - tf_warning_or_error | tf_user); - - /* If we might be entering the scope of a partial specialization, - find the one with the right constraints. */ - if (flag_concepts - && entering_scope - && CLASS_TYPE_P (type) - && CLASSTYPE_TEMPLATE_INFO (type) - && dependent_type_p (type) - && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type))) - type = fixup_template_type (type); - - if (type == error_mark_node) - return type; - else if (CLASS_TYPE_P (type) && !alias_type_or_template_p (type)) - return TYPE_STUB_DECL (type); - else - return TYPE_NAME (type); -} - -/* Finish processing a BASE_CLASS with the indicated ACCESS_SPECIFIER. - Return a TREE_LIST containing the ACCESS_SPECIFIER and the - BASE_CLASS, or NULL_TREE if an error occurred. The - ACCESS_SPECIFIER is one of - access_{default,public,protected_private}_node. For a virtual base - we set TREE_TYPE. */ - -tree -finish_base_specifier (tree base, tree access, bool virtual_p) -{ - tree result; - - if (base == error_mark_node) - { - error ("invalid base-class specification"); - result = NULL_TREE; - } - else if (! MAYBE_CLASS_TYPE_P (base)) - { - error ("%qT is not a class type", base); - result = NULL_TREE; - } - else - { - if (cp_type_quals (base) != 0) - { - /* DR 484: Can a base-specifier name a cv-qualified - class type? */ - base = TYPE_MAIN_VARIANT (base); - } - result = build_tree_list (access, base); - if (virtual_p) - TREE_TYPE (result) = integer_type_node; - } - - return result; -} - -/* If FNS is a member function, a set of member functions, or a - template-id referring to one or more member functions, return a - BASELINK for FNS, incorporating the current access context. - Otherwise, return FNS unchanged. */ - -tree -baselink_for_fns (tree fns) -{ - tree scope; - tree cl; - - if (BASELINK_P (fns) - || error_operand_p (fns)) - return fns; - - scope = ovl_scope (fns); - if (!CLASS_TYPE_P (scope)) - return fns; - - cl = currently_open_derived_class (scope); - if (!cl) - cl = scope; - tree access_path = TYPE_BINFO (cl); - tree conv_path = (cl == scope ? access_path - : lookup_base (cl, scope, ba_any, NULL, tf_none)); - return build_baselink (conv_path, access_path, fns, /*optype=*/NULL_TREE); -} - -/* Returns true iff DECL is a variable from a function outside - the current one. */ - -static bool -outer_var_p (tree decl) -{ - return ((VAR_P (decl) || TREE_CODE (decl) == PARM_DECL) - && DECL_FUNCTION_SCOPE_P (decl) - /* Don't get confused by temporaries. */ - && DECL_NAME (decl) - && (DECL_CONTEXT (decl) != current_function_decl - || parsing_nsdmi ())); -} - -/* As above, but also checks that DECL is automatic. */ - -bool -outer_automatic_var_p (tree decl) -{ - return (outer_var_p (decl) - && !TREE_STATIC (decl)); -} - -/* DECL satisfies outer_automatic_var_p. Possibly complain about it or - rewrite it for lambda capture. - - If ODR_USE is true, we're being called from mark_use, and we complain about - use of constant variables. If ODR_USE is false, we're being called for the - id-expression, and we do lambda capture. */ - -tree -process_outer_var_ref (tree decl, tsubst_flags_t complain, bool odr_use) -{ - if (cp_unevaluated_operand) - { - tree type = TREE_TYPE (decl); - if (!dependent_type_p (type) - && variably_modified_type_p (type, NULL_TREE)) - /* VLAs are used even in unevaluated context. */; - else - /* It's not a use (3.2) if we're in an unevaluated context. */ - return decl; - } - if (decl == error_mark_node) - return decl; - - tree context = DECL_CONTEXT (decl); - tree containing_function = current_function_decl; - tree lambda_stack = NULL_TREE; - tree lambda_expr = NULL_TREE; - tree initializer = convert_from_reference (decl); - - /* Mark it as used now even if the use is ill-formed. */ - if (!mark_used (decl, complain)) - return error_mark_node; - - if (parsing_nsdmi ()) - containing_function = NULL_TREE; - - if (containing_function && LAMBDA_FUNCTION_P (containing_function)) - { - /* Check whether we've already built a proxy. */ - tree var = decl; - while (is_normal_capture_proxy (var)) - var = DECL_CAPTURED_VARIABLE (var); - tree d = retrieve_local_specialization (var); - - if (d && d != decl && is_capture_proxy (d)) - { - if (DECL_CONTEXT (d) == containing_function) - /* We already have an inner proxy. */ - return d; - else - /* We need to capture an outer proxy. */ - return process_outer_var_ref (d, complain, odr_use); - } - } - - /* If we are in a lambda function, we can move out until we hit - 1. the context, - 2. a non-lambda function, or - 3. a non-default capturing lambda function. */ - while (context != containing_function - /* containing_function can be null with invalid generic lambdas. */ - && containing_function - && LAMBDA_FUNCTION_P (containing_function)) - { - tree closure = DECL_CONTEXT (containing_function); - lambda_expr = CLASSTYPE_LAMBDA_EXPR (closure); - - if (TYPE_CLASS_SCOPE_P (closure)) - /* A lambda in an NSDMI (c++/64496). */ - break; - - if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) == CPLD_NONE) - break; - - lambda_stack = tree_cons (NULL_TREE, lambda_expr, lambda_stack); - - containing_function = decl_function_context (containing_function); - } - - /* In a lambda within a template, wait until instantiation time to implicitly - capture a parameter pack. We want to wait because we don't know if we're - capturing the whole pack or a single element, and it's OK to wait because - find_parameter_packs_r walks into the lambda body. */ - if (context == containing_function - && DECL_PACK_P (decl)) - return decl; - - if (lambda_expr && VAR_P (decl) && DECL_ANON_UNION_VAR_P (decl)) - { - if (complain & tf_error) - error ("cannot capture member %qD of anonymous union", decl); - return error_mark_node; - } - /* Do lambda capture when processing the id-expression, not when - odr-using a variable. */ - if (!odr_use && context == containing_function) - decl = add_default_capture (lambda_stack, - /*id=*/DECL_NAME (decl), initializer); - /* Only an odr-use of an outer automatic variable causes an - error, and a constant variable can decay to a prvalue - constant without odr-use. So don't complain yet. */ - else if (!odr_use && decl_constant_var_p (decl)) - return decl; - else if (lambda_expr) - { - if (complain & tf_error) - { - error ("%qD is not captured", decl); - tree closure = LAMBDA_EXPR_CLOSURE (lambda_expr); - if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) == CPLD_NONE) - inform (location_of (closure), - "the lambda has no capture-default"); - else if (TYPE_CLASS_SCOPE_P (closure)) - inform (UNKNOWN_LOCATION, "lambda in local class %q+T cannot " - "capture variables from the enclosing context", - TYPE_CONTEXT (closure)); - inform (DECL_SOURCE_LOCATION (decl), "%q#D declared here", decl); - } - return error_mark_node; - } - else - { - if (complain & tf_error) - { - error (VAR_P (decl) - ? G_("use of local variable with automatic storage from " - "containing function") - : G_("use of parameter from containing function")); - inform (DECL_SOURCE_LOCATION (decl), "%q#D declared here", decl); - } - return error_mark_node; - } - return decl; -} - -/* ID_EXPRESSION is a representation of parsed, but unprocessed, - id-expression. (See cp_parser_id_expression for details.) SCOPE, - if non-NULL, is the type or namespace used to explicitly qualify - ID_EXPRESSION. DECL is the entity to which that name has been - resolved. - - *CONSTANT_EXPRESSION_P is true if we are presently parsing a - constant-expression. In that case, *NON_CONSTANT_EXPRESSION_P will - be set to true if this expression isn't permitted in a - constant-expression, but it is otherwise not set by this function. - *ALLOW_NON_CONSTANT_EXPRESSION_P is true if we are parsing a - constant-expression, but a non-constant expression is also - permissible. - - DONE is true if this expression is a complete postfix-expression; - it is false if this expression is followed by '->', '[', '(', etc. - ADDRESS_P is true iff this expression is the operand of '&'. - TEMPLATE_P is true iff the qualified-id was of the form - "A::template B". TEMPLATE_ARG_P is true iff this qualified name - appears as a template argument. - - If an error occurs, and it is the kind of error that might cause - the parser to abort a tentative parse, *ERROR_MSG is filled in. It - is the caller's responsibility to issue the message. *ERROR_MSG - will be a string with static storage duration, so the caller need - not "free" it. - - Return an expression for the entity, after issuing appropriate - diagnostics. This function is also responsible for transforming a - reference to a non-static member into a COMPONENT_REF that makes - the use of "this" explicit. - - Upon return, *IDK will be filled in appropriately. */ -static cp_expr -finish_id_expression_1 (tree id_expression, - tree decl, - tree scope, - cp_id_kind *idk, - bool integral_constant_expression_p, - bool allow_non_integral_constant_expression_p, - bool *non_integral_constant_expression_p, - bool template_p, - bool done, - bool address_p, - bool template_arg_p, - const char **error_msg, - location_t location) -{ - decl = strip_using_decl (decl); - - /* Initialize the output parameters. */ - *idk = CP_ID_KIND_NONE; - *error_msg = NULL; - - if (id_expression == error_mark_node) - return error_mark_node; - /* If we have a template-id, then no further lookup is - required. If the template-id was for a template-class, we - will sometimes have a TYPE_DECL at this point. */ - else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR - || TREE_CODE (decl) == TYPE_DECL) - ; - /* Look up the name. */ - else - { - if (decl == error_mark_node) - { - /* Name lookup failed. */ - if (scope - && (!TYPE_P (scope) - || (!dependent_type_p (scope) - && !(identifier_p (id_expression) - && IDENTIFIER_CONV_OP_P (id_expression) - && dependent_type_p (TREE_TYPE (id_expression)))))) - { - /* If the qualifying type is non-dependent (and the name - does not name a conversion operator to a dependent - type), issue an error. */ - qualified_name_lookup_error (scope, id_expression, decl, location); - return error_mark_node; - } - else if (!scope) - { - /* It may be resolved via Koenig lookup. */ - *idk = CP_ID_KIND_UNQUALIFIED; - return id_expression; - } - else - decl = id_expression; - } - - /* Remember that the name was used in the definition of - the current class so that we can check later to see if - the meaning would have been different after the class - was entirely defined. */ - if (!scope && decl != error_mark_node && identifier_p (id_expression)) - maybe_note_name_used_in_class (id_expression, decl); - - /* A use in unevaluated operand might not be instantiated appropriately - if tsubst_copy builds a dummy parm, or if we never instantiate a - generic lambda, so mark it now. */ - if (processing_template_decl && cp_unevaluated_operand) - mark_type_use (decl); - - /* Disallow uses of local variables from containing functions, except - within lambda-expressions. */ - if (outer_automatic_var_p (decl)) - { - decl = process_outer_var_ref (decl, tf_warning_or_error); - if (decl == error_mark_node) - return error_mark_node; - } - - /* Also disallow uses of function parameters outside the function - body, except inside an unevaluated context (i.e. decltype). */ - if (TREE_CODE (decl) == PARM_DECL - && DECL_CONTEXT (decl) == NULL_TREE - && !cp_unevaluated_operand) - { - *error_msg = G_("use of parameter outside function body"); - return error_mark_node; - } - } - - /* If we didn't find anything, or what we found was a type, - then this wasn't really an id-expression. */ - if (TREE_CODE (decl) == TEMPLATE_DECL - && !DECL_FUNCTION_TEMPLATE_P (decl)) - { - *error_msg = G_("missing template arguments"); - return error_mark_node; - } - else if (TREE_CODE (decl) == TYPE_DECL - || TREE_CODE (decl) == NAMESPACE_DECL) - { - *error_msg = G_("expected primary-expression"); - return error_mark_node; - } - - /* If the name resolved to a template parameter, there is no - need to look it up again later. */ - if ((TREE_CODE (decl) == CONST_DECL && DECL_TEMPLATE_PARM_P (decl)) - || TREE_CODE (decl) == TEMPLATE_PARM_INDEX) - { - tree r; - - *idk = CP_ID_KIND_NONE; - if (TREE_CODE (decl) == TEMPLATE_PARM_INDEX) - decl = TEMPLATE_PARM_DECL (decl); - r = DECL_INITIAL (decl); - if (CLASS_TYPE_P (TREE_TYPE (r)) && !CP_TYPE_CONST_P (TREE_TYPE (r))) - { - /* If the entity is a template parameter object for a template - parameter of type T, the type of the expression is const T. */ - tree ctype = TREE_TYPE (r); - ctype = cp_build_qualified_type (ctype, (cp_type_quals (ctype) - | TYPE_QUAL_CONST)); - r = build1 (VIEW_CONVERT_EXPR, ctype, r); - } - r = convert_from_reference (r); - if (integral_constant_expression_p - && !dependent_type_p (TREE_TYPE (decl)) - && !(INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (r)))) - { - if (!allow_non_integral_constant_expression_p) - error ("template parameter %qD of type %qT is not allowed in " - "an integral constant expression because it is not of " - "integral or enumeration type", decl, TREE_TYPE (decl)); - *non_integral_constant_expression_p = true; - } - return r; - } - else - { - bool dependent_p = type_dependent_expression_p (decl); - - /* If the declaration was explicitly qualified indicate - that. The semantics of `A::f(3)' are different than - `f(3)' if `f' is virtual. */ - *idk = (scope - ? CP_ID_KIND_QUALIFIED - : (TREE_CODE (decl) == TEMPLATE_ID_EXPR - ? CP_ID_KIND_TEMPLATE_ID - : (dependent_p - ? CP_ID_KIND_UNQUALIFIED_DEPENDENT - : CP_ID_KIND_UNQUALIFIED))); - - if (dependent_p - && DECL_P (decl) - && any_dependent_type_attributes_p (DECL_ATTRIBUTES (decl))) - /* Dependent type attributes on the decl mean that the TREE_TYPE is - wrong, so just return the identifier. */ - return id_expression; - - if (DECL_CLASS_TEMPLATE_P (decl)) - { - error ("use of class template %qT as expression", decl); - return error_mark_node; - } - - if (TREE_CODE (decl) == TREE_LIST) - { - /* Ambiguous reference to base members. */ - error ("request for member %qD is ambiguous in " - "multiple inheritance lattice", id_expression); - print_candidates (decl); - return error_mark_node; - } - - /* Mark variable-like entities as used. Functions are similarly - marked either below or after overload resolution. */ - if ((VAR_P (decl) - || TREE_CODE (decl) == PARM_DECL - || TREE_CODE (decl) == CONST_DECL - || TREE_CODE (decl) == RESULT_DECL) - && !mark_used (decl)) - return error_mark_node; - - /* Only certain kinds of names are allowed in constant - expression. Template parameters have already - been handled above. */ - if (! error_operand_p (decl) - && !dependent_p - && integral_constant_expression_p - && !decl_constant_var_p (decl) - && TREE_CODE (decl) != CONST_DECL - && !builtin_valid_in_constant_expr_p (decl) - && !concept_check_p (decl)) - { - if (!allow_non_integral_constant_expression_p) - { - error ("%qD cannot appear in a constant-expression", decl); - return error_mark_node; - } - *non_integral_constant_expression_p = true; - } - - if (tree wrap = maybe_get_tls_wrapper_call (decl)) - /* Replace an evaluated use of the thread_local variable with - a call to its wrapper. */ - decl = wrap; - else if (TREE_CODE (decl) == TEMPLATE_ID_EXPR - && !dependent_p - && variable_template_p (TREE_OPERAND (decl, 0)) - && !concept_check_p (decl)) - { - decl = finish_template_variable (decl); - mark_used (decl); - decl = convert_from_reference (decl); - } - else if (concept_check_p (decl)) - { - /* Nothing more to do. All of the analysis for concept checks - is done by build_conept_id, called from the parser. */ - } - else if (scope) - { - if (TREE_CODE (decl) == SCOPE_REF) - { - gcc_assert (same_type_p (scope, TREE_OPERAND (decl, 0))); - decl = TREE_OPERAND (decl, 1); - } - - decl = (adjust_result_of_qualified_name_lookup - (decl, scope, current_nonlambda_class_type())); - - if (TREE_CODE (decl) == FUNCTION_DECL) - mark_used (decl); - - cp_warn_deprecated_use_scopes (scope); - - if (TYPE_P (scope)) - decl = finish_qualified_id_expr (scope, - decl, - done, - address_p, - template_p, - template_arg_p, - tf_warning_or_error); - else - decl = convert_from_reference (decl); - } - else if (TREE_CODE (decl) == FIELD_DECL) - { - /* Since SCOPE is NULL here, this is an unqualified name. - Access checking has been performed during name lookup - already. Turn off checking to avoid duplicate errors. */ - push_deferring_access_checks (dk_no_check); - decl = finish_non_static_data_member (decl, NULL_TREE, - /*qualifying_scope=*/NULL_TREE); - pop_deferring_access_checks (); - } - else if (is_overloaded_fn (decl)) - { - /* We only need to look at the first function, - because all the fns share the attribute we're - concerned with (all member fns or all non-members). */ - tree first_fn = get_first_fn (decl); - first_fn = STRIP_TEMPLATE (first_fn); - - /* [basic.def.odr]: "A function whose name appears as a - potentially-evaluated expression is odr-used if it is the unique - lookup result". - - But only mark it if it's a complete postfix-expression; in a call, - ADL might select a different function, and we'll call mark_used in - build_over_call. */ - if (done - && !really_overloaded_fn (decl) - && !mark_used (first_fn)) - return error_mark_node; - - if (!template_arg_p - && (TREE_CODE (first_fn) == USING_DECL - || (TREE_CODE (first_fn) == FUNCTION_DECL - && DECL_FUNCTION_MEMBER_P (first_fn) - && !shared_member_p (decl)))) - { - /* A set of member functions. */ - decl = maybe_dummy_object (DECL_CONTEXT (first_fn), 0); - return finish_class_member_access_expr (decl, id_expression, - /*template_p=*/false, - tf_warning_or_error); - } - - decl = baselink_for_fns (decl); - } - else - { - if (DECL_P (decl) && DECL_NONLOCAL (decl) - && DECL_CLASS_SCOPE_P (decl)) - { - tree context = context_for_name_lookup (decl); - if (context != current_class_type) - { - tree path = currently_open_derived_class (context); - if (!path) - /* PATH can be null for using an enum of an unrelated - class; we checked its access in lookup_using_decl. - - ??? Should this case make a clone instead, like - handle_using_decl? */ - gcc_assert (TREE_CODE (decl) == CONST_DECL); - else - perform_or_defer_access_check (TYPE_BINFO (path), - decl, decl, - tf_warning_or_error); - } - } - - decl = convert_from_reference (decl); - } - } - - return cp_expr (decl, location); -} - -/* As per finish_id_expression_1, but adding a wrapper node - around the result if needed to express LOCATION. */ - -cp_expr -finish_id_expression (tree id_expression, - tree decl, - tree scope, - cp_id_kind *idk, - bool integral_constant_expression_p, - bool allow_non_integral_constant_expression_p, - bool *non_integral_constant_expression_p, - bool template_p, - bool done, - bool address_p, - bool template_arg_p, - const char **error_msg, - location_t location) -{ - cp_expr result - = finish_id_expression_1 (id_expression, decl, scope, idk, - integral_constant_expression_p, - allow_non_integral_constant_expression_p, - non_integral_constant_expression_p, - template_p, done, address_p, template_arg_p, - error_msg, location); - return result.maybe_add_location_wrapper (); -} - -/* Implement the __typeof keyword: Return the type of EXPR, suitable for - use as a type-specifier. */ - -tree -finish_typeof (tree expr) -{ - tree type; - - if (type_dependent_expression_p (expr)) - { - type = cxx_make_type (TYPEOF_TYPE); - TYPEOF_TYPE_EXPR (type) = expr; - SET_TYPE_STRUCTURAL_EQUALITY (type); - - return type; - } - - expr = mark_type_use (expr); - - type = unlowered_expr_type (expr); - - if (!type || type == unknown_type_node) - { - error ("type of %qE is unknown", expr); - return error_mark_node; - } - - return type; -} - -/* Implement the __underlying_type keyword: Return the underlying - type of TYPE, suitable for use as a type-specifier. */ - -tree -finish_underlying_type (tree type) -{ - tree underlying_type; - - if (processing_template_decl) - { - underlying_type = cxx_make_type (UNDERLYING_TYPE); - UNDERLYING_TYPE_TYPE (underlying_type) = type; - SET_TYPE_STRUCTURAL_EQUALITY (underlying_type); - - return underlying_type; - } - - if (!complete_type_or_else (type, NULL_TREE)) - return error_mark_node; - - if (TREE_CODE (type) != ENUMERAL_TYPE) - { - error ("%qT is not an enumeration type", type); - return error_mark_node; - } - - underlying_type = ENUM_UNDERLYING_TYPE (type); - - /* Fixup necessary in this case because ENUM_UNDERLYING_TYPE - includes TYPE_MIN_VALUE and TYPE_MAX_VALUE information. - See finish_enum_value_list for details. */ - if (!ENUM_FIXED_UNDERLYING_TYPE_P (type)) - underlying_type - = c_common_type_for_mode (TYPE_MODE (underlying_type), - TYPE_UNSIGNED (underlying_type)); - - return underlying_type; -} - -/* Implement the __direct_bases keyword: Return the direct base classes - of type. */ - -tree -calculate_direct_bases (tree type, tsubst_flags_t complain) -{ - if (!complete_type_or_maybe_complain (type, NULL_TREE, complain) - || !NON_UNION_CLASS_TYPE_P (type)) - return make_tree_vec (0); - - releasing_vec vector; - vec<tree, va_gc> *base_binfos = BINFO_BASE_BINFOS (TYPE_BINFO (type)); - tree binfo; - unsigned i; - - /* Virtual bases are initialized first */ - for (i = 0; base_binfos->iterate (i, &binfo); i++) - if (BINFO_VIRTUAL_P (binfo)) - vec_safe_push (vector, binfo); - - /* Now non-virtuals */ - for (i = 0; base_binfos->iterate (i, &binfo); i++) - if (!BINFO_VIRTUAL_P (binfo)) - vec_safe_push (vector, binfo); - - tree bases_vec = make_tree_vec (vector->length ()); - - for (i = 0; i < vector->length (); ++i) - TREE_VEC_ELT (bases_vec, i) = BINFO_TYPE ((*vector)[i]); - - return bases_vec; -} - -/* Implement the __bases keyword: Return the base classes - of type */ - -/* Find morally non-virtual base classes by walking binfo hierarchy */ -/* Virtual base classes are handled separately in finish_bases */ - -static tree -dfs_calculate_bases_pre (tree binfo, void * /*data_*/) -{ - /* Don't walk bases of virtual bases */ - return BINFO_VIRTUAL_P (binfo) ? dfs_skip_bases : NULL_TREE; -} - -static tree -dfs_calculate_bases_post (tree binfo, void *data_) -{ - vec<tree, va_gc> **data = ((vec<tree, va_gc> **) data_); - if (!BINFO_VIRTUAL_P (binfo)) - vec_safe_push (*data, BINFO_TYPE (binfo)); - return NULL_TREE; -} - -/* Calculates the morally non-virtual base classes of a class */ -static vec<tree, va_gc> * -calculate_bases_helper (tree type) -{ - vec<tree, va_gc> *vector = make_tree_vector (); - - /* Now add non-virtual base classes in order of construction */ - if (TYPE_BINFO (type)) - dfs_walk_all (TYPE_BINFO (type), - dfs_calculate_bases_pre, dfs_calculate_bases_post, &vector); - return vector; -} - -tree -calculate_bases (tree type, tsubst_flags_t complain) -{ - if (!complete_type_or_maybe_complain (type, NULL_TREE, complain) - || !NON_UNION_CLASS_TYPE_P (type)) - return make_tree_vec (0); - - releasing_vec vector; - tree bases_vec = NULL_TREE; - unsigned i; - vec<tree, va_gc> *vbases; - tree binfo; - - /* First go through virtual base classes */ - for (vbases = CLASSTYPE_VBASECLASSES (type), i = 0; - vec_safe_iterate (vbases, i, &binfo); i++) - { - releasing_vec vbase_bases - = calculate_bases_helper (BINFO_TYPE (binfo)); - vec_safe_splice (vector, vbase_bases); - } - - /* Now for the non-virtual bases */ - releasing_vec nonvbases = calculate_bases_helper (type); - vec_safe_splice (vector, nonvbases); - - /* Note that during error recovery vector->length can even be zero. */ - if (vector->length () > 1) - { - /* Last element is entire class, so don't copy */ - bases_vec = make_tree_vec (vector->length () - 1); - - for (i = 0; i < vector->length () - 1; ++i) - TREE_VEC_ELT (bases_vec, i) = (*vector)[i]; - } - else - bases_vec = make_tree_vec (0); - - return bases_vec; -} - -tree -finish_bases (tree type, bool direct) -{ - tree bases = NULL_TREE; - - if (!processing_template_decl) - { - /* Parameter packs can only be used in templates */ - error ("parameter pack %<__bases%> only valid in template declaration"); - return error_mark_node; - } - - bases = cxx_make_type (BASES); - BASES_TYPE (bases) = type; - BASES_DIRECT (bases) = direct; - SET_TYPE_STRUCTURAL_EQUALITY (bases); - - return bases; -} - -/* Perform C++-specific checks for __builtin_offsetof before calling - fold_offsetof. */ - -tree -finish_offsetof (tree object_ptr, tree expr, location_t loc) -{ - /* If we're processing a template, we can't finish the semantics yet. - Otherwise we can fold the entire expression now. */ - if (processing_template_decl) - { - expr = build2 (OFFSETOF_EXPR, size_type_node, expr, object_ptr); - SET_EXPR_LOCATION (expr, loc); - return expr; - } - - if (expr == error_mark_node) - return error_mark_node; - - if (TREE_CODE (expr) == PSEUDO_DTOR_EXPR) - { - error ("cannot apply %<offsetof%> to destructor %<~%T%>", - TREE_OPERAND (expr, 2)); - return error_mark_node; - } - if (FUNC_OR_METHOD_TYPE_P (TREE_TYPE (expr)) - || TREE_TYPE (expr) == unknown_type_node) - { - while (TREE_CODE (expr) == COMPONENT_REF - || TREE_CODE (expr) == COMPOUND_EXPR) - expr = TREE_OPERAND (expr, 1); - - if (DECL_P (expr)) - { - error ("cannot apply %<offsetof%> to member function %qD", expr); - inform (DECL_SOURCE_LOCATION (expr), "declared here"); - } - else - error ("cannot apply %<offsetof%> to member function"); - return error_mark_node; - } - if (TREE_CODE (expr) == CONST_DECL) - { - error ("cannot apply %<offsetof%> to an enumerator %qD", expr); - return error_mark_node; - } - if (REFERENCE_REF_P (expr)) - expr = TREE_OPERAND (expr, 0); - if (!complete_type_or_else (TREE_TYPE (TREE_TYPE (object_ptr)), object_ptr)) - return error_mark_node; - if (warn_invalid_offsetof - && CLASS_TYPE_P (TREE_TYPE (TREE_TYPE (object_ptr))) - && CLASSTYPE_NON_STD_LAYOUT (TREE_TYPE (TREE_TYPE (object_ptr))) - && cp_unevaluated_operand == 0) - warning_at (loc, OPT_Winvalid_offsetof, "%<offsetof%> within " - "non-standard-layout type %qT is conditionally-supported", - TREE_TYPE (TREE_TYPE (object_ptr))); - return fold_offsetof (expr); -} - -/* Replace the AGGR_INIT_EXPR at *TP with an equivalent CALL_EXPR. This - function is broken out from the above for the benefit of the tree-ssa - project. */ - -void -simplify_aggr_init_expr (tree *tp) -{ - tree aggr_init_expr = *tp; - - /* Form an appropriate CALL_EXPR. */ - tree fn = AGGR_INIT_EXPR_FN (aggr_init_expr); - tree slot = AGGR_INIT_EXPR_SLOT (aggr_init_expr); - tree type = TREE_TYPE (slot); - - tree call_expr; - enum style_t { ctor, arg, pcc } style; - - if (AGGR_INIT_VIA_CTOR_P (aggr_init_expr)) - style = ctor; -#ifdef PCC_STATIC_STRUCT_RETURN - else if (1) - style = pcc; -#endif - else - { - gcc_assert (TREE_ADDRESSABLE (type)); - style = arg; - } - - call_expr = build_call_array_loc (input_location, - TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), - fn, - aggr_init_expr_nargs (aggr_init_expr), - AGGR_INIT_EXPR_ARGP (aggr_init_expr)); - TREE_NOTHROW (call_expr) = TREE_NOTHROW (aggr_init_expr); - CALL_FROM_THUNK_P (call_expr) = AGGR_INIT_FROM_THUNK_P (aggr_init_expr); - CALL_EXPR_OPERATOR_SYNTAX (call_expr) - = CALL_EXPR_OPERATOR_SYNTAX (aggr_init_expr); - CALL_EXPR_ORDERED_ARGS (call_expr) = CALL_EXPR_ORDERED_ARGS (aggr_init_expr); - CALL_EXPR_REVERSE_ARGS (call_expr) = CALL_EXPR_REVERSE_ARGS (aggr_init_expr); - - if (style == ctor) - { - /* Replace the first argument to the ctor with the address of the - slot. */ - cxx_mark_addressable (slot); - CALL_EXPR_ARG (call_expr, 0) = - build1 (ADDR_EXPR, build_pointer_type (type), slot); - } - else if (style == arg) - { - /* Just mark it addressable here, and leave the rest to - expand_call{,_inline}. */ - cxx_mark_addressable (slot); - CALL_EXPR_RETURN_SLOT_OPT (call_expr) = true; - call_expr = build2 (INIT_EXPR, TREE_TYPE (call_expr), slot, call_expr); - } - else if (style == pcc) - { - /* If we're using the non-reentrant PCC calling convention, then we - need to copy the returned value out of the static buffer into the - SLOT. */ - push_deferring_access_checks (dk_no_check); - call_expr = build_aggr_init (slot, call_expr, - DIRECT_BIND | LOOKUP_ONLYCONVERTING, - tf_warning_or_error); - pop_deferring_access_checks (); - call_expr = build2 (COMPOUND_EXPR, TREE_TYPE (slot), call_expr, slot); - } - - if (AGGR_INIT_ZERO_FIRST (aggr_init_expr)) - { - tree init = build_zero_init (type, NULL_TREE, - /*static_storage_p=*/false); - init = build2 (INIT_EXPR, void_type_node, slot, init); - call_expr = build2 (COMPOUND_EXPR, TREE_TYPE (call_expr), - init, call_expr); - } - - *tp = call_expr; -} - -/* Emit all thunks to FN that should be emitted when FN is emitted. */ - -void -emit_associated_thunks (tree fn) -{ - /* When we use vcall offsets, we emit thunks with the virtual - functions to which they thunk. The whole point of vcall offsets - is so that you can know statically the entire set of thunks that - will ever be needed for a given virtual function, thereby - enabling you to output all the thunks with the function itself. */ - if (DECL_VIRTUAL_P (fn) - /* Do not emit thunks for extern template instantiations. */ - && ! DECL_REALLY_EXTERN (fn)) - { - tree thunk; - - for (thunk = DECL_THUNKS (fn); thunk; thunk = DECL_CHAIN (thunk)) - { - if (!THUNK_ALIAS (thunk)) - { - use_thunk (thunk, /*emit_p=*/1); - if (DECL_RESULT_THUNK_P (thunk)) - { - tree probe; - - for (probe = DECL_THUNKS (thunk); - probe; probe = DECL_CHAIN (probe)) - use_thunk (probe, /*emit_p=*/1); - } - } - else - gcc_assert (!DECL_THUNKS (thunk)); - } - } -} - -/* Generate RTL for FN. */ - -bool -expand_or_defer_fn_1 (tree fn) -{ - /* When the parser calls us after finishing the body of a template - function, we don't really want to expand the body. */ - if (processing_template_decl) - { - /* Normally, collection only occurs in rest_of_compilation. So, - if we don't collect here, we never collect junk generated - during the processing of templates until we hit a - non-template function. It's not safe to do this inside a - nested class, though, as the parser may have local state that - is not a GC root. */ - if (!function_depth) - ggc_collect (); - return false; - } - - gcc_assert (DECL_SAVED_TREE (fn)); - - /* We make a decision about linkage for these functions at the end - of the compilation. Until that point, we do not want the back - end to output them -- but we do want it to see the bodies of - these functions so that it can inline them as appropriate. */ - if (DECL_DECLARED_INLINE_P (fn) || DECL_IMPLICIT_INSTANTIATION (fn)) - { - if (DECL_INTERFACE_KNOWN (fn)) - /* We've already made a decision as to how this function will - be handled. */; - else if (!at_eof - || DECL_IMMEDIATE_FUNCTION_P (fn) - || DECL_OMP_DECLARE_REDUCTION_P (fn)) - tentative_decl_linkage (fn); - else - import_export_decl (fn); - - /* If the user wants us to keep all inline functions, then mark - this function as needed so that finish_file will make sure to - output it later. Similarly, all dllexport'd functions must - be emitted; there may be callers in other DLLs. */ - if (DECL_DECLARED_INLINE_P (fn) - && !DECL_REALLY_EXTERN (fn) - && !DECL_IMMEDIATE_FUNCTION_P (fn) - && !DECL_OMP_DECLARE_REDUCTION_P (fn) - && (flag_keep_inline_functions - || (flag_keep_inline_dllexport - && lookup_attribute ("dllexport", DECL_ATTRIBUTES (fn))))) - { - mark_needed (fn); - DECL_EXTERNAL (fn) = 0; - } - } - - /* If this is a constructor or destructor body, we have to clone - it. */ - if (maybe_clone_body (fn)) - { - /* We don't want to process FN again, so pretend we've written - it out, even though we haven't. */ - TREE_ASM_WRITTEN (fn) = 1; - /* If this is a constexpr function, keep DECL_SAVED_TREE. */ - if (!DECL_DECLARED_CONSTEXPR_P (fn) - && !(modules_p () && DECL_DECLARED_INLINE_P (fn))) - DECL_SAVED_TREE (fn) = NULL_TREE; - return false; - } - - /* There's no reason to do any of the work here if we're only doing - semantic analysis; this code just generates RTL. */ - if (flag_syntax_only) - { - /* Pretend that this function has been written out so that we don't try - to expand it again. */ - TREE_ASM_WRITTEN (fn) = 1; - return false; - } - - if (DECL_OMP_DECLARE_REDUCTION_P (fn)) - return false; - - return true; -} - -void -expand_or_defer_fn (tree fn) -{ - if (expand_or_defer_fn_1 (fn)) - { - function_depth++; - - /* Expand or defer, at the whim of the compilation unit manager. */ - cgraph_node::finalize_function (fn, function_depth > 1); - emit_associated_thunks (fn); - - function_depth--; - - if (DECL_IMMEDIATE_FUNCTION_P (fn)) - { - if (cgraph_node *node = cgraph_node::get (fn)) - { - node->body_removed = true; - node->analyzed = false; - node->definition = false; - node->force_output = false; - } - } - } -} - -class nrv_data -{ -public: - nrv_data () : visited (37) {} - - tree var; - tree result; - hash_table<nofree_ptr_hash <tree_node> > visited; -}; - -/* Helper function for walk_tree, used by finalize_nrv below. */ - -static tree -finalize_nrv_r (tree* tp, int* walk_subtrees, void* data) -{ - class nrv_data *dp = (class nrv_data *)data; - tree_node **slot; - - /* No need to walk into types. There wouldn't be any need to walk into - non-statements, except that we have to consider STMT_EXPRs. */ - if (TYPE_P (*tp)) - *walk_subtrees = 0; - /* Change all returns to just refer to the RESULT_DECL; this is a nop, - but differs from using NULL_TREE in that it indicates that we care - about the value of the RESULT_DECL. */ - else if (TREE_CODE (*tp) == RETURN_EXPR) - TREE_OPERAND (*tp, 0) = dp->result; - /* Change all cleanups for the NRV to only run when an exception is - thrown. */ - else if (TREE_CODE (*tp) == CLEANUP_STMT - && CLEANUP_DECL (*tp) == dp->var) - CLEANUP_EH_ONLY (*tp) = 1; - /* Replace the DECL_EXPR for the NRV with an initialization of the - RESULT_DECL, if needed. */ - else if (TREE_CODE (*tp) == DECL_EXPR - && DECL_EXPR_DECL (*tp) == dp->var) - { - tree init; - if (DECL_INITIAL (dp->var) - && DECL_INITIAL (dp->var) != error_mark_node) - init = build2 (INIT_EXPR, void_type_node, dp->result, - DECL_INITIAL (dp->var)); - else - init = build_empty_stmt (EXPR_LOCATION (*tp)); - DECL_INITIAL (dp->var) = NULL_TREE; - SET_EXPR_LOCATION (init, EXPR_LOCATION (*tp)); - *tp = init; - } - /* And replace all uses of the NRV with the RESULT_DECL. */ - else if (*tp == dp->var) - *tp = dp->result; - - /* Avoid walking into the same tree more than once. Unfortunately, we - can't just use walk_tree_without duplicates because it would only call - us for the first occurrence of dp->var in the function body. */ - slot = dp->visited.find_slot (*tp, INSERT); - if (*slot) - *walk_subtrees = 0; - else - *slot = *tp; - - /* Keep iterating. */ - return NULL_TREE; -} - -/* Called from finish_function to implement the named return value - optimization by overriding all the RETURN_EXPRs and pertinent - CLEANUP_STMTs and replacing all occurrences of VAR with RESULT, the - RESULT_DECL for the function. */ - -void -finalize_nrv (tree *tp, tree var, tree result) -{ - class nrv_data data; - - /* Copy name from VAR to RESULT. */ - DECL_NAME (result) = DECL_NAME (var); - /* Don't forget that we take its address. */ - TREE_ADDRESSABLE (result) = TREE_ADDRESSABLE (var); - /* Finally set DECL_VALUE_EXPR to avoid assigning - a stack slot at -O0 for the original var and debug info - uses RESULT location for VAR. */ - SET_DECL_VALUE_EXPR (var, result); - DECL_HAS_VALUE_EXPR_P (var) = 1; - - data.var = var; - data.result = result; - cp_walk_tree (tp, finalize_nrv_r, &data, 0); -} - -/* Create CP_OMP_CLAUSE_INFO for clause C. Returns true if it is invalid. */ - -bool -cxx_omp_create_clause_info (tree c, tree type, bool need_default_ctor, - bool need_copy_ctor, bool need_copy_assignment, - bool need_dtor) -{ - int save_errorcount = errorcount; - tree info, t; - - /* Always allocate 3 elements for simplicity. These are the - function decls for the ctor, dtor, and assignment op. - This layout is known to the three lang hooks, - cxx_omp_clause_default_init, cxx_omp_clause_copy_init, - and cxx_omp_clause_assign_op. */ - info = make_tree_vec (3); - CP_OMP_CLAUSE_INFO (c) = info; - - if (need_default_ctor || need_copy_ctor) - { - if (need_default_ctor) - t = get_default_ctor (type); - else - t = get_copy_ctor (type, tf_warning_or_error); - - if (t && !trivial_fn_p (t)) - TREE_VEC_ELT (info, 0) = t; - } - - if (need_dtor && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) - TREE_VEC_ELT (info, 1) = get_dtor (type, tf_warning_or_error); - - if (need_copy_assignment) - { - t = get_copy_assign (type); - - if (t && !trivial_fn_p (t)) - TREE_VEC_ELT (info, 2) = t; - } - - return errorcount != save_errorcount; -} - -/* If DECL is DECL_OMP_PRIVATIZED_MEMBER, return corresponding - FIELD_DECL, otherwise return DECL itself. */ - -static tree -omp_clause_decl_field (tree decl) -{ - if (VAR_P (decl) - && DECL_HAS_VALUE_EXPR_P (decl) - && DECL_ARTIFICIAL (decl) - && DECL_LANG_SPECIFIC (decl) - && DECL_OMP_PRIVATIZED_MEMBER (decl)) - { - tree f = DECL_VALUE_EXPR (decl); - if (INDIRECT_REF_P (f)) - f = TREE_OPERAND (f, 0); - if (TREE_CODE (f) == COMPONENT_REF) - { - f = TREE_OPERAND (f, 1); - gcc_assert (TREE_CODE (f) == FIELD_DECL); - return f; - } - } - return NULL_TREE; -} - -/* Adjust DECL if needed for printing using %qE. */ - -static tree -omp_clause_printable_decl (tree decl) -{ - tree t = omp_clause_decl_field (decl); - if (t) - return t; - return decl; -} - -/* For a FIELD_DECL F and corresponding DECL_OMP_PRIVATIZED_MEMBER - VAR_DECL T that doesn't need a DECL_EXPR added, record it for - privatization. */ - -static void -omp_note_field_privatization (tree f, tree t) -{ - if (!omp_private_member_map) - omp_private_member_map = new hash_map<tree, tree>; - tree &v = omp_private_member_map->get_or_insert (f); - if (v == NULL_TREE) - { - v = t; - omp_private_member_vec.safe_push (f); - /* Signal that we don't want to create DECL_EXPR for this dummy var. */ - omp_private_member_vec.safe_push (integer_zero_node); - } -} - -/* Privatize FIELD_DECL T, return corresponding DECL_OMP_PRIVATIZED_MEMBER - dummy VAR_DECL. */ - -tree -omp_privatize_field (tree t, bool shared) -{ - tree m = finish_non_static_data_member (t, NULL_TREE, NULL_TREE); - if (m == error_mark_node) - return error_mark_node; - if (!omp_private_member_map && !shared) - omp_private_member_map = new hash_map<tree, tree>; - if (TYPE_REF_P (TREE_TYPE (t))) - { - gcc_assert (INDIRECT_REF_P (m)); - m = TREE_OPERAND (m, 0); - } - tree vb = NULL_TREE; - tree &v = shared ? vb : omp_private_member_map->get_or_insert (t); - if (v == NULL_TREE) - { - v = create_temporary_var (TREE_TYPE (m)); - retrofit_lang_decl (v); - DECL_OMP_PRIVATIZED_MEMBER (v) = 1; - SET_DECL_VALUE_EXPR (v, m); - DECL_HAS_VALUE_EXPR_P (v) = 1; - if (!shared) - omp_private_member_vec.safe_push (t); - } - return v; -} - -/* Helper function for handle_omp_array_sections. Called recursively - to handle multiple array-section-subscripts. C is the clause, - T current expression (initially OMP_CLAUSE_DECL), which is either - a TREE_LIST for array-section-subscript (TREE_PURPOSE is low-bound - expression if specified, TREE_VALUE length expression if specified, - TREE_CHAIN is what it has been specified after, or some decl. - TYPES vector is populated with array section types, MAYBE_ZERO_LEN - set to true if any of the array-section-subscript could have length - of zero (explicit or implicit), FIRST_NON_ONE is the index of the - first array-section-subscript which is known not to have length - of one. Given say: - map(a[:b][2:1][:c][:2][:d][e:f][2:5]) - FIRST_NON_ONE will be 3, array-section-subscript [:b], [2:1] and [:c] - all are or may have length of 1, array-section-subscript [:2] is the - first one known not to have length 1. For array-section-subscript - <= FIRST_NON_ONE we diagnose non-contiguous arrays if low bound isn't - 0 or length isn't the array domain max + 1, for > FIRST_NON_ONE we - can if MAYBE_ZERO_LEN is false. MAYBE_ZERO_LEN will be true in the above - case though, as some lengths could be zero. */ - -static tree -handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types, - bool &maybe_zero_len, unsigned int &first_non_one, - enum c_omp_region_type ort) -{ - tree ret, low_bound, length, type; - if (TREE_CODE (t) != TREE_LIST) - { - if (error_operand_p (t)) - return error_mark_node; - if (REFERENCE_REF_P (t) - && TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF) - t = TREE_OPERAND (t, 0); - ret = t; - while (TREE_CODE (t) == INDIRECT_REF) - { - t = TREE_OPERAND (t, 0); - STRIP_NOPS (t); - if (TREE_CODE (t) == POINTER_PLUS_EXPR) - t = TREE_OPERAND (t, 0); - } - while (TREE_CODE (t) == COMPOUND_EXPR) - { - t = TREE_OPERAND (t, 1); - STRIP_NOPS (t); - } - if (TREE_CODE (t) == COMPONENT_REF - && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM) - && !type_dependent_expression_p (t)) - { - if (TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL - && DECL_BIT_FIELD (TREE_OPERAND (t, 1))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "bit-field %qE in %qs clause", - t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - return error_mark_node; - } - while (TREE_CODE (t) == COMPONENT_REF) - { - if (TREE_TYPE (TREE_OPERAND (t, 0)) - && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == UNION_TYPE) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qE is a member of a union", t); - return error_mark_node; - } - t = TREE_OPERAND (t, 0); - while (TREE_CODE (t) == MEM_REF - || TREE_CODE (t) == INDIRECT_REF - || TREE_CODE (t) == ARRAY_REF) - { - t = TREE_OPERAND (t, 0); - STRIP_NOPS (t); - if (TREE_CODE (t) == POINTER_PLUS_EXPR) - t = TREE_OPERAND (t, 0); - } - } - if (REFERENCE_REF_P (t)) - t = TREE_OPERAND (t, 0); - } - if (TREE_CODE (t) == FIELD_DECL) - ret = finish_non_static_data_member (t, NULL_TREE, NULL_TREE); - else if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) - { - if (processing_template_decl && TREE_CODE (t) != OVERLOAD) - return NULL_TREE; - if (DECL_P (t)) - error_at (OMP_CLAUSE_LOCATION (c), - "%qD is not a variable in %qs clause", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - else - error_at (OMP_CLAUSE_LOCATION (c), - "%qE is not a variable in %qs clause", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - return error_mark_node; - } - else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_AFFINITY - && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND - && VAR_P (t) && CP_DECL_THREAD_LOCAL_P (t)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qD is threadprivate variable in %qs clause", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - return error_mark_node; - } - if (type_dependent_expression_p (ret)) - return NULL_TREE; - ret = convert_from_reference (ret); - return ret; - } - - if ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP - && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION) - && TREE_CODE (TREE_CHAIN (t)) == FIELD_DECL) - TREE_CHAIN (t) = omp_privatize_field (TREE_CHAIN (t), false); - ret = handle_omp_array_sections_1 (c, TREE_CHAIN (t), types, - maybe_zero_len, first_non_one, ort); - if (ret == error_mark_node || ret == NULL_TREE) - return ret; - - type = TREE_TYPE (ret); - low_bound = TREE_PURPOSE (t); - length = TREE_VALUE (t); - if ((low_bound && type_dependent_expression_p (low_bound)) - || (length && type_dependent_expression_p (length))) - return NULL_TREE; - - if (low_bound == error_mark_node || length == error_mark_node) - return error_mark_node; - - if (low_bound && !INTEGRAL_TYPE_P (TREE_TYPE (low_bound))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "low bound %qE of array section does not have integral type", - low_bound); - return error_mark_node; - } - if (length && !INTEGRAL_TYPE_P (TREE_TYPE (length))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "length %qE of array section does not have integral type", - length); - return error_mark_node; - } - if (low_bound) - low_bound = mark_rvalue_use (low_bound); - if (length) - length = mark_rvalue_use (length); - /* We need to reduce to real constant-values for checks below. */ - if (length) - length = fold_simple (length); - if (low_bound) - low_bound = fold_simple (low_bound); - if (low_bound - && TREE_CODE (low_bound) == INTEGER_CST - && TYPE_PRECISION (TREE_TYPE (low_bound)) - > TYPE_PRECISION (sizetype)) - low_bound = fold_convert (sizetype, low_bound); - if (length - && TREE_CODE (length) == INTEGER_CST - && TYPE_PRECISION (TREE_TYPE (length)) - > TYPE_PRECISION (sizetype)) - length = fold_convert (sizetype, length); - if (low_bound == NULL_TREE) - low_bound = integer_zero_node; - - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP - && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH - || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)) - { - if (length != integer_one_node) - { - error_at (OMP_CLAUSE_LOCATION (c), - "expected single pointer in %qs clause", - c_omp_map_clause_name (c, ort == C_ORT_ACC)); - return error_mark_node; - } - } - if (length != NULL_TREE) - { - if (!integer_nonzerop (length)) - { - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION) - { - if (integer_zerop (length)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "zero length array section in %qs clause", - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - return error_mark_node; - } - } - else - maybe_zero_len = true; - } - if (first_non_one == types.length () - && (TREE_CODE (length) != INTEGER_CST || integer_onep (length))) - first_non_one++; - } - if (TREE_CODE (type) == ARRAY_TYPE) - { - if (length == NULL_TREE - && (TYPE_DOMAIN (type) == NULL_TREE - || TYPE_MAX_VALUE (TYPE_DOMAIN (type)) == NULL_TREE)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "for unknown bound array type length expression must " - "be specified"); - return error_mark_node; - } - if (TREE_CODE (low_bound) == INTEGER_CST - && tree_int_cst_sgn (low_bound) == -1) - { - error_at (OMP_CLAUSE_LOCATION (c), - "negative low bound in array section in %qs clause", - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - return error_mark_node; - } - if (length != NULL_TREE - && TREE_CODE (length) == INTEGER_CST - && tree_int_cst_sgn (length) == -1) - { - error_at (OMP_CLAUSE_LOCATION (c), - "negative length in array section in %qs clause", - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - return error_mark_node; - } - if (TYPE_DOMAIN (type) - && TYPE_MAX_VALUE (TYPE_DOMAIN (type)) - && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) - == INTEGER_CST) - { - tree size - = fold_convert (sizetype, TYPE_MAX_VALUE (TYPE_DOMAIN (type))); - size = size_binop (PLUS_EXPR, size, size_one_node); - if (TREE_CODE (low_bound) == INTEGER_CST) - { - if (tree_int_cst_lt (size, low_bound)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "low bound %qE above array section size " - "in %qs clause", low_bound, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - return error_mark_node; - } - if (tree_int_cst_equal (size, low_bound)) - { - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION) - { - error_at (OMP_CLAUSE_LOCATION (c), - "zero length array section in %qs clause", - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - return error_mark_node; - } - maybe_zero_len = true; - } - else if (length == NULL_TREE - && first_non_one == types.length () - && tree_int_cst_equal - (TYPE_MAX_VALUE (TYPE_DOMAIN (type)), - low_bound)) - first_non_one++; - } - else if (length == NULL_TREE) - { - if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_AFFINITY - && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND - && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION - && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IN_REDUCTION - && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_TASK_REDUCTION) - maybe_zero_len = true; - if (first_non_one == types.length ()) - first_non_one++; - } - if (length && TREE_CODE (length) == INTEGER_CST) - { - if (tree_int_cst_lt (size, length)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "length %qE above array section size " - "in %qs clause", length, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - return error_mark_node; - } - if (TREE_CODE (low_bound) == INTEGER_CST) - { - tree lbpluslen - = size_binop (PLUS_EXPR, - fold_convert (sizetype, low_bound), - fold_convert (sizetype, length)); - if (TREE_CODE (lbpluslen) == INTEGER_CST - && tree_int_cst_lt (size, lbpluslen)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "high bound %qE above array section size " - "in %qs clause", lbpluslen, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - return error_mark_node; - } - } - } - } - else if (length == NULL_TREE) - { - if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_AFFINITY - && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND - && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_REDUCTION - && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_IN_REDUCTION - && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_TASK_REDUCTION) - maybe_zero_len = true; - if (first_non_one == types.length ()) - first_non_one++; - } - - /* For [lb:] we will need to evaluate lb more than once. */ - if (length == NULL_TREE && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND) - { - tree lb = cp_save_expr (low_bound); - if (lb != low_bound) - { - TREE_PURPOSE (t) = lb; - low_bound = lb; - } - } - } - else if (TYPE_PTR_P (type)) - { - if (length == NULL_TREE) - { - if (TREE_CODE (ret) == PARM_DECL && DECL_ARRAY_PARAMETER_P (ret)) - error_at (OMP_CLAUSE_LOCATION (c), - "for array function parameter length expression " - "must be specified"); - else - error_at (OMP_CLAUSE_LOCATION (c), - "for pointer type length expression must be specified"); - return error_mark_node; - } - if (length != NULL_TREE - && TREE_CODE (length) == INTEGER_CST - && tree_int_cst_sgn (length) == -1) - { - error_at (OMP_CLAUSE_LOCATION (c), - "negative length in array section in %qs clause", - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - return error_mark_node; - } - /* If there is a pointer type anywhere but in the very first - array-section-subscript, the array section could be non-contiguous. */ - if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_AFFINITY - && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND - && TREE_CODE (TREE_CHAIN (t)) == TREE_LIST) - { - /* If any prior dimension has a non-one length, then deem this - array section as non-contiguous. */ - for (tree d = TREE_CHAIN (t); TREE_CODE (d) == TREE_LIST; - d = TREE_CHAIN (d)) - { - tree d_length = TREE_VALUE (d); - if (d_length == NULL_TREE || !integer_onep (d_length)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "array section is not contiguous in %qs clause", - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - return error_mark_node; - } - } - } - } - else - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qE does not have pointer or array type", ret); - return error_mark_node; - } - if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND) - types.safe_push (TREE_TYPE (ret)); - /* We will need to evaluate lb more than once. */ - tree lb = cp_save_expr (low_bound); - if (lb != low_bound) - { - TREE_PURPOSE (t) = lb; - low_bound = lb; - } - /* Temporarily disable -fstrong-eval-order for array reductions. - The SAVE_EXPR and COMPOUND_EXPR added if low_bound has side-effects - is something the middle-end can't cope with and more importantly, - it needs to be the actual base variable that is privatized, not some - temporary assigned previous value of it. That, together with OpenMP - saying how many times the side-effects are evaluated is unspecified, - makes int *a, *b; ... reduction(+:a[a = b, 3:10]) really unspecified. */ - warning_sentinel s (flag_strong_eval_order, - OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION); - ret = grok_array_decl (OMP_CLAUSE_LOCATION (c), ret, low_bound, NULL, - tf_warning_or_error); - return ret; -} - -/* Handle array sections for clause C. */ - -static bool -handle_omp_array_sections (tree c, enum c_omp_region_type ort) -{ - bool maybe_zero_len = false; - unsigned int first_non_one = 0; - auto_vec<tree, 10> types; - tree *tp = &OMP_CLAUSE_DECL (c); - if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY) - && TREE_CODE (*tp) == TREE_LIST - && TREE_PURPOSE (*tp) - && TREE_CODE (TREE_PURPOSE (*tp)) == TREE_VEC) - tp = &TREE_VALUE (*tp); - tree first = handle_omp_array_sections_1 (c, *tp, types, - maybe_zero_len, first_non_one, - ort); - if (first == error_mark_node) - return true; - if (first == NULL_TREE) - return false; - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_AFFINITY) - { - tree t = *tp; - tree tem = NULL_TREE; - if (processing_template_decl) - return false; - /* Need to evaluate side effects in the length expressions - if any. */ - while (TREE_CODE (t) == TREE_LIST) - { - if (TREE_VALUE (t) && TREE_SIDE_EFFECTS (TREE_VALUE (t))) - { - if (tem == NULL_TREE) - tem = TREE_VALUE (t); - else - tem = build2 (COMPOUND_EXPR, TREE_TYPE (tem), - TREE_VALUE (t), tem); - } - t = TREE_CHAIN (t); - } - if (tem) - first = build2 (COMPOUND_EXPR, TREE_TYPE (first), tem, first); - *tp = first; - } - else - { - unsigned int num = types.length (), i; - tree t, side_effects = NULL_TREE, size = NULL_TREE; - tree condition = NULL_TREE; - - if (int_size_in_bytes (TREE_TYPE (first)) <= 0) - maybe_zero_len = true; - if (processing_template_decl && maybe_zero_len) - return false; - - for (i = num, t = OMP_CLAUSE_DECL (c); i > 0; - t = TREE_CHAIN (t)) - { - tree low_bound = TREE_PURPOSE (t); - tree length = TREE_VALUE (t); - - i--; - if (low_bound - && TREE_CODE (low_bound) == INTEGER_CST - && TYPE_PRECISION (TREE_TYPE (low_bound)) - > TYPE_PRECISION (sizetype)) - low_bound = fold_convert (sizetype, low_bound); - if (length - && TREE_CODE (length) == INTEGER_CST - && TYPE_PRECISION (TREE_TYPE (length)) - > TYPE_PRECISION (sizetype)) - length = fold_convert (sizetype, length); - if (low_bound == NULL_TREE) - low_bound = integer_zero_node; - if (!maybe_zero_len && i > first_non_one) - { - if (integer_nonzerop (low_bound)) - goto do_warn_noncontiguous; - if (length != NULL_TREE - && TREE_CODE (length) == INTEGER_CST - && TYPE_DOMAIN (types[i]) - && TYPE_MAX_VALUE (TYPE_DOMAIN (types[i])) - && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (types[i]))) - == INTEGER_CST) - { - tree size; - size = size_binop (PLUS_EXPR, - TYPE_MAX_VALUE (TYPE_DOMAIN (types[i])), - size_one_node); - if (!tree_int_cst_equal (length, size)) - { - do_warn_noncontiguous: - error_at (OMP_CLAUSE_LOCATION (c), - "array section is not contiguous in %qs " - "clause", - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - return true; - } - } - if (!processing_template_decl - && length != NULL_TREE - && TREE_SIDE_EFFECTS (length)) - { - if (side_effects == NULL_TREE) - side_effects = length; - else - side_effects = build2 (COMPOUND_EXPR, - TREE_TYPE (side_effects), - length, side_effects); - } - } - else if (processing_template_decl) - continue; - else - { - tree l; - - if (i > first_non_one - && ((length && integer_nonzerop (length)) - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION)) - continue; - if (length) - l = fold_convert (sizetype, length); - else - { - l = size_binop (PLUS_EXPR, - TYPE_MAX_VALUE (TYPE_DOMAIN (types[i])), - size_one_node); - l = size_binop (MINUS_EXPR, l, - fold_convert (sizetype, low_bound)); - } - if (i > first_non_one) - { - l = fold_build2 (NE_EXPR, boolean_type_node, l, - size_zero_node); - if (condition == NULL_TREE) - condition = l; - else - condition = fold_build2 (BIT_AND_EXPR, boolean_type_node, - l, condition); - } - else if (size == NULL_TREE) - { - size = size_in_bytes (TREE_TYPE (types[i])); - tree eltype = TREE_TYPE (types[num - 1]); - while (TREE_CODE (eltype) == ARRAY_TYPE) - eltype = TREE_TYPE (eltype); - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION) - size = size_binop (EXACT_DIV_EXPR, size, - size_in_bytes (eltype)); - size = size_binop (MULT_EXPR, size, l); - if (condition) - size = fold_build3 (COND_EXPR, sizetype, condition, - size, size_zero_node); - } - else - size = size_binop (MULT_EXPR, size, l); - } - } - if (!processing_template_decl) - { - if (side_effects) - size = build2 (COMPOUND_EXPR, sizetype, side_effects, size); - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION) - { - size = size_binop (MINUS_EXPR, size, size_one_node); - size = save_expr (size); - tree index_type = build_index_type (size); - tree eltype = TREE_TYPE (first); - while (TREE_CODE (eltype) == ARRAY_TYPE) - eltype = TREE_TYPE (eltype); - tree type = build_array_type (eltype, index_type); - tree ptype = build_pointer_type (eltype); - if (TYPE_REF_P (TREE_TYPE (t)) - && INDIRECT_TYPE_P (TREE_TYPE (TREE_TYPE (t)))) - t = convert_from_reference (t); - else if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE) - t = build_fold_addr_expr (t); - tree t2 = build_fold_addr_expr (first); - t2 = fold_convert_loc (OMP_CLAUSE_LOCATION (c), - ptrdiff_type_node, t2); - t2 = fold_build2_loc (OMP_CLAUSE_LOCATION (c), MINUS_EXPR, - ptrdiff_type_node, t2, - fold_convert_loc (OMP_CLAUSE_LOCATION (c), - ptrdiff_type_node, t)); - if (tree_fits_shwi_p (t2)) - t = build2 (MEM_REF, type, t, - build_int_cst (ptype, tree_to_shwi (t2))); - else - { - t2 = fold_convert_loc (OMP_CLAUSE_LOCATION (c), - sizetype, t2); - t = build2_loc (OMP_CLAUSE_LOCATION (c), POINTER_PLUS_EXPR, - TREE_TYPE (t), t, t2); - t = build2 (MEM_REF, type, t, build_int_cst (ptype, 0)); - } - OMP_CLAUSE_DECL (c) = t; - return false; - } - OMP_CLAUSE_DECL (c) = first; - OMP_CLAUSE_SIZE (c) = size; - if (TREE_CODE (t) == FIELD_DECL) - t = finish_non_static_data_member (t, NULL_TREE, NULL_TREE); - if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP - || (TREE_CODE (t) == COMPONENT_REF - && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)) - return false; - switch (OMP_CLAUSE_MAP_KIND (c)) - { - case GOMP_MAP_ALLOC: - case GOMP_MAP_IF_PRESENT: - case GOMP_MAP_TO: - case GOMP_MAP_FROM: - case GOMP_MAP_TOFROM: - case GOMP_MAP_ALWAYS_TO: - case GOMP_MAP_ALWAYS_FROM: - case GOMP_MAP_ALWAYS_TOFROM: - case GOMP_MAP_RELEASE: - case GOMP_MAP_DELETE: - case GOMP_MAP_FORCE_TO: - case GOMP_MAP_FORCE_FROM: - case GOMP_MAP_FORCE_TOFROM: - case GOMP_MAP_FORCE_PRESENT: - OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c) = 1; - break; - default: - break; - } - bool reference_always_pointer = true; - tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c), - OMP_CLAUSE_MAP); - if (TREE_CODE (t) == COMPONENT_REF) - { - OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH); - - if ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP - && TYPE_REF_P (TREE_TYPE (t))) - { - if (TREE_CODE (TREE_TYPE (TREE_TYPE (t))) == ARRAY_TYPE) - OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALWAYS_POINTER); - else - t = convert_from_reference (t); - - reference_always_pointer = false; - } - } - else if (REFERENCE_REF_P (t) - && TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF) - { - gomp_map_kind k; - if ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP - && TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE) - k = GOMP_MAP_ATTACH_DETACH; - else - { - t = TREE_OPERAND (t, 0); - k = (ort == C_ORT_ACC - ? GOMP_MAP_ATTACH_DETACH : GOMP_MAP_ALWAYS_POINTER); - } - OMP_CLAUSE_SET_MAP_KIND (c2, k); - } - else - OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER); - OMP_CLAUSE_MAP_IMPLICIT (c2) = OMP_CLAUSE_MAP_IMPLICIT (c); - if (OMP_CLAUSE_MAP_KIND (c2) != GOMP_MAP_FIRSTPRIVATE_POINTER - && !cxx_mark_addressable (t)) - return false; - OMP_CLAUSE_DECL (c2) = t; - t = build_fold_addr_expr (first); - t = fold_convert_loc (OMP_CLAUSE_LOCATION (c), - ptrdiff_type_node, t); - tree ptr = OMP_CLAUSE_DECL (c2); - ptr = convert_from_reference (ptr); - if (!INDIRECT_TYPE_P (TREE_TYPE (ptr))) - ptr = build_fold_addr_expr (ptr); - t = fold_build2_loc (OMP_CLAUSE_LOCATION (c), MINUS_EXPR, - ptrdiff_type_node, t, - fold_convert_loc (OMP_CLAUSE_LOCATION (c), - ptrdiff_type_node, ptr)); - OMP_CLAUSE_SIZE (c2) = t; - OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c); - OMP_CLAUSE_CHAIN (c) = c2; - - ptr = OMP_CLAUSE_DECL (c2); - if (reference_always_pointer - && OMP_CLAUSE_MAP_KIND (c2) != GOMP_MAP_FIRSTPRIVATE_POINTER - && TYPE_REF_P (TREE_TYPE (ptr)) - && INDIRECT_TYPE_P (TREE_TYPE (TREE_TYPE (ptr)))) - { - tree c3 = build_omp_clause (OMP_CLAUSE_LOCATION (c), - OMP_CLAUSE_MAP); - OMP_CLAUSE_SET_MAP_KIND (c3, OMP_CLAUSE_MAP_KIND (c2)); - OMP_CLAUSE_MAP_IMPLICIT (c2) = OMP_CLAUSE_MAP_IMPLICIT (c); - OMP_CLAUSE_DECL (c3) = ptr; - if (OMP_CLAUSE_MAP_KIND (c2) == GOMP_MAP_ALWAYS_POINTER - || OMP_CLAUSE_MAP_KIND (c2) == GOMP_MAP_ATTACH_DETACH) - { - OMP_CLAUSE_DECL (c2) = build_simple_mem_ref (ptr); - OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALWAYS_POINTER); - } - else - OMP_CLAUSE_DECL (c2) = convert_from_reference (ptr); - OMP_CLAUSE_SIZE (c3) = size_zero_node; - OMP_CLAUSE_CHAIN (c3) = OMP_CLAUSE_CHAIN (c2); - OMP_CLAUSE_CHAIN (c2) = c3; - } - } - } - return false; -} - -/* Return identifier to look up for omp declare reduction. */ - -tree -omp_reduction_id (enum tree_code reduction_code, tree reduction_id, tree type) -{ - const char *p = NULL; - const char *m = NULL; - switch (reduction_code) - { - case PLUS_EXPR: - case MULT_EXPR: - case MINUS_EXPR: - case BIT_AND_EXPR: - case BIT_XOR_EXPR: - case BIT_IOR_EXPR: - case TRUTH_ANDIF_EXPR: - case TRUTH_ORIF_EXPR: - reduction_id = ovl_op_identifier (false, reduction_code); - break; - case MIN_EXPR: - p = "min"; - break; - case MAX_EXPR: - p = "max"; - break; - default: - break; - } - - if (p == NULL) - { - if (TREE_CODE (reduction_id) != IDENTIFIER_NODE) - return error_mark_node; - p = IDENTIFIER_POINTER (reduction_id); - } - - if (type != NULL_TREE) - m = mangle_type_string (TYPE_MAIN_VARIANT (type)); - - const char prefix[] = "omp declare reduction "; - size_t lenp = sizeof (prefix); - if (strncmp (p, prefix, lenp - 1) == 0) - lenp = 1; - size_t len = strlen (p); - size_t lenm = m ? strlen (m) + 1 : 0; - char *name = XALLOCAVEC (char, lenp + len + lenm); - if (lenp > 1) - memcpy (name, prefix, lenp - 1); - memcpy (name + lenp - 1, p, len + 1); - if (m) - { - name[lenp + len - 1] = '~'; - memcpy (name + lenp + len, m, lenm); - } - return get_identifier (name); -} - -/* Lookup OpenMP UDR ID for TYPE, return the corresponding artificial - FUNCTION_DECL or NULL_TREE if not found. */ - -static tree -omp_reduction_lookup (location_t loc, tree id, tree type, tree *baselinkp, - vec<tree> *ambiguousp) -{ - tree orig_id = id; - tree baselink = NULL_TREE; - if (identifier_p (id)) - { - cp_id_kind idk; - bool nonint_cst_expression_p; - const char *error_msg; - id = omp_reduction_id (ERROR_MARK, id, type); - tree decl = lookup_name (id); - if (decl == NULL_TREE) - decl = error_mark_node; - id = finish_id_expression (id, decl, NULL_TREE, &idk, false, true, - &nonint_cst_expression_p, false, true, false, - false, &error_msg, loc); - if (idk == CP_ID_KIND_UNQUALIFIED - && identifier_p (id)) - { - vec<tree, va_gc> *args = NULL; - vec_safe_push (args, build_reference_type (type)); - id = perform_koenig_lookup (id, args, tf_none); - } - } - else if (TREE_CODE (id) == SCOPE_REF) - id = lookup_qualified_name (TREE_OPERAND (id, 0), - omp_reduction_id (ERROR_MARK, - TREE_OPERAND (id, 1), - type), - LOOK_want::NORMAL, false); - tree fns = id; - id = NULL_TREE; - if (fns && is_overloaded_fn (fns)) - { - for (lkp_iterator iter (get_fns (fns)); iter; ++iter) - { - tree fndecl = *iter; - if (TREE_CODE (fndecl) == FUNCTION_DECL) - { - tree argtype = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl))); - if (same_type_p (TREE_TYPE (argtype), type)) - { - id = fndecl; - break; - } - } - } - - if (id && BASELINK_P (fns)) - { - if (baselinkp) - *baselinkp = fns; - else - baselink = fns; - } - } - - if (!id && CLASS_TYPE_P (type) && TYPE_BINFO (type)) - { - auto_vec<tree> ambiguous; - tree binfo = TYPE_BINFO (type), base_binfo, ret = NULL_TREE; - unsigned int ix; - if (ambiguousp == NULL) - ambiguousp = &ambiguous; - for (ix = 0; BINFO_BASE_ITERATE (binfo, ix, base_binfo); ix++) - { - id = omp_reduction_lookup (loc, orig_id, BINFO_TYPE (base_binfo), - baselinkp ? baselinkp : &baselink, - ambiguousp); - if (id == NULL_TREE) - continue; - if (!ambiguousp->is_empty ()) - ambiguousp->safe_push (id); - else if (ret != NULL_TREE) - { - ambiguousp->safe_push (ret); - ambiguousp->safe_push (id); - ret = NULL_TREE; - } - else - ret = id; - } - if (ambiguousp != &ambiguous) - return ret; - if (!ambiguous.is_empty ()) - { - const char *str = _("candidates are:"); - unsigned int idx; - tree udr; - error_at (loc, "user defined reduction lookup is ambiguous"); - FOR_EACH_VEC_ELT (ambiguous, idx, udr) - { - inform (DECL_SOURCE_LOCATION (udr), "%s %#qD", str, udr); - if (idx == 0) - str = get_spaces (str); - } - ret = error_mark_node; - baselink = NULL_TREE; - } - id = ret; - } - if (id && baselink) - perform_or_defer_access_check (BASELINK_BINFO (baselink), - id, id, tf_warning_or_error); - return id; -} - -/* Helper function for cp_parser_omp_declare_reduction_exprs - and tsubst_omp_udr. - Remove CLEANUP_STMT for data (omp_priv variable). - Also append INIT_EXPR for DECL_INITIAL of omp_priv after its - DECL_EXPR. */ - -tree -cp_remove_omp_priv_cleanup_stmt (tree *tp, int *walk_subtrees, void *data) -{ - if (TYPE_P (*tp)) - *walk_subtrees = 0; - else if (TREE_CODE (*tp) == CLEANUP_STMT && CLEANUP_DECL (*tp) == (tree) data) - *tp = CLEANUP_BODY (*tp); - else if (TREE_CODE (*tp) == DECL_EXPR) - { - tree decl = DECL_EXPR_DECL (*tp); - if (!processing_template_decl - && decl == (tree) data - && DECL_INITIAL (decl) - && DECL_INITIAL (decl) != error_mark_node) - { - tree list = NULL_TREE; - append_to_statement_list_force (*tp, &list); - tree init_expr = build2 (INIT_EXPR, void_type_node, - decl, DECL_INITIAL (decl)); - DECL_INITIAL (decl) = NULL_TREE; - append_to_statement_list_force (init_expr, &list); - *tp = list; - } - } - return NULL_TREE; -} - -/* Data passed from cp_check_omp_declare_reduction to - cp_check_omp_declare_reduction_r. */ - -struct cp_check_omp_declare_reduction_data -{ - location_t loc; - tree stmts[7]; - bool combiner_p; -}; - -/* Helper function for cp_check_omp_declare_reduction, called via - cp_walk_tree. */ - -static tree -cp_check_omp_declare_reduction_r (tree *tp, int *, void *data) -{ - struct cp_check_omp_declare_reduction_data *udr_data - = (struct cp_check_omp_declare_reduction_data *) data; - if (SSA_VAR_P (*tp) - && !DECL_ARTIFICIAL (*tp) - && *tp != DECL_EXPR_DECL (udr_data->stmts[udr_data->combiner_p ? 0 : 3]) - && *tp != DECL_EXPR_DECL (udr_data->stmts[udr_data->combiner_p ? 1 : 4])) - { - location_t loc = udr_data->loc; - if (udr_data->combiner_p) - error_at (loc, "%<#pragma omp declare reduction%> combiner refers to " - "variable %qD which is not %<omp_out%> nor %<omp_in%>", - *tp); - else - error_at (loc, "%<#pragma omp declare reduction%> initializer refers " - "to variable %qD which is not %<omp_priv%> nor " - "%<omp_orig%>", - *tp); - return *tp; - } - return NULL_TREE; -} - -/* Diagnose violation of OpenMP #pragma omp declare reduction restrictions. */ - -bool -cp_check_omp_declare_reduction (tree udr) -{ - tree type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (udr))); - gcc_assert (TYPE_REF_P (type)); - type = TREE_TYPE (type); - int i; - location_t loc = DECL_SOURCE_LOCATION (udr); - - if (type == error_mark_node) - return false; - if (ARITHMETIC_TYPE_P (type)) - { - static enum tree_code predef_codes[] - = { PLUS_EXPR, MULT_EXPR, MINUS_EXPR, BIT_AND_EXPR, BIT_XOR_EXPR, - BIT_IOR_EXPR, TRUTH_ANDIF_EXPR, TRUTH_ORIF_EXPR }; - for (i = 0; i < 8; i++) - { - tree id = omp_reduction_id (predef_codes[i], NULL_TREE, NULL_TREE); - const char *n1 = IDENTIFIER_POINTER (DECL_NAME (udr)); - const char *n2 = IDENTIFIER_POINTER (id); - if (strncmp (n1, n2, IDENTIFIER_LENGTH (id)) == 0 - && (n1[IDENTIFIER_LENGTH (id)] == '~' - || n1[IDENTIFIER_LENGTH (id)] == '\0')) - break; - } - - if (i == 8 - && TREE_CODE (type) != COMPLEX_EXPR) - { - const char prefix_minmax[] = "omp declare reduction m"; - size_t prefix_size = sizeof (prefix_minmax) - 1; - const char *n = IDENTIFIER_POINTER (DECL_NAME (udr)); - if (strncmp (IDENTIFIER_POINTER (DECL_NAME (udr)), - prefix_minmax, prefix_size) == 0 - && ((n[prefix_size] == 'i' && n[prefix_size + 1] == 'n') - || (n[prefix_size] == 'a' && n[prefix_size + 1] == 'x')) - && (n[prefix_size + 2] == '~' || n[prefix_size + 2] == '\0')) - i = 0; - } - if (i < 8) - { - error_at (loc, "predeclared arithmetic type %qT in " - "%<#pragma omp declare reduction%>", type); - return false; - } - } - else if (FUNC_OR_METHOD_TYPE_P (type) - || TREE_CODE (type) == ARRAY_TYPE) - { - error_at (loc, "function or array type %qT in " - "%<#pragma omp declare reduction%>", type); - return false; - } - else if (TYPE_REF_P (type)) - { - error_at (loc, "reference type %qT in %<#pragma omp declare reduction%>", - type); - return false; - } - else if (TYPE_QUALS_NO_ADDR_SPACE (type)) - { - error_at (loc, "%<const%>, %<volatile%> or %<__restrict%>-qualified " - "type %qT in %<#pragma omp declare reduction%>", type); - return false; - } - - tree body = DECL_SAVED_TREE (udr); - if (body == NULL_TREE || TREE_CODE (body) != STATEMENT_LIST) - return true; - - tree_stmt_iterator tsi; - struct cp_check_omp_declare_reduction_data data; - memset (data.stmts, 0, sizeof data.stmts); - for (i = 0, tsi = tsi_start (body); - i < 7 && !tsi_end_p (tsi); - i++, tsi_next (&tsi)) - data.stmts[i] = tsi_stmt (tsi); - data.loc = loc; - gcc_assert (tsi_end_p (tsi)); - if (i >= 3) - { - gcc_assert (TREE_CODE (data.stmts[0]) == DECL_EXPR - && TREE_CODE (data.stmts[1]) == DECL_EXPR); - if (warning_suppressed_p (DECL_EXPR_DECL (data.stmts[0]) /* What warning? */)) - return true; - data.combiner_p = true; - if (cp_walk_tree (&data.stmts[2], cp_check_omp_declare_reduction_r, - &data, NULL)) - suppress_warning (DECL_EXPR_DECL (data.stmts[0]) /* What warning? */); - } - if (i >= 6) - { - gcc_assert (TREE_CODE (data.stmts[3]) == DECL_EXPR - && TREE_CODE (data.stmts[4]) == DECL_EXPR); - data.combiner_p = false; - if (cp_walk_tree (&data.stmts[5], cp_check_omp_declare_reduction_r, - &data, NULL) - || cp_walk_tree (&DECL_INITIAL (DECL_EXPR_DECL (data.stmts[3])), - cp_check_omp_declare_reduction_r, &data, NULL)) - suppress_warning (DECL_EXPR_DECL (data.stmts[0]) /* Wat warning? */); - if (i == 7) - gcc_assert (TREE_CODE (data.stmts[6]) == DECL_EXPR); - } - return true; -} - -/* Helper function of finish_omp_clauses. Clone STMT as if we were making - an inline call. But, remap - the OMP_DECL1 VAR_DECL (omp_out resp. omp_orig) to PLACEHOLDER - and OMP_DECL2 VAR_DECL (omp_in resp. omp_priv) to DECL. */ - -static tree -clone_omp_udr (tree stmt, tree omp_decl1, tree omp_decl2, - tree decl, tree placeholder) -{ - copy_body_data id; - hash_map<tree, tree> decl_map; - - decl_map.put (omp_decl1, placeholder); - decl_map.put (omp_decl2, decl); - memset (&id, 0, sizeof (id)); - id.src_fn = DECL_CONTEXT (omp_decl1); - id.dst_fn = current_function_decl; - id.src_cfun = DECL_STRUCT_FUNCTION (id.src_fn); - id.decl_map = &decl_map; - - id.copy_decl = copy_decl_no_change; - id.transform_call_graph_edges = CB_CGE_DUPLICATE; - id.transform_new_cfg = true; - id.transform_return_to_modify = false; - id.eh_lp_nr = 0; - walk_tree (&stmt, copy_tree_body_r, &id, NULL); - return stmt; -} - -/* Helper function of finish_omp_clauses, called via cp_walk_tree. - Find OMP_CLAUSE_PLACEHOLDER (passed in DATA) in *TP. */ - -static tree -find_omp_placeholder_r (tree *tp, int *, void *data) -{ - if (*tp == (tree) data) - return *tp; - return NULL_TREE; -} - -/* Helper function of finish_omp_clauses. Handle OMP_CLAUSE_REDUCTION C. - Return true if there is some error and the clause should be removed. */ - -static bool -finish_omp_reduction_clause (tree c, bool *need_default_ctor, bool *need_dtor) -{ - tree t = OMP_CLAUSE_DECL (c); - bool predefined = false; - if (TREE_CODE (t) == TREE_LIST) - { - gcc_assert (processing_template_decl); - return false; - } - tree type = TREE_TYPE (t); - if (TREE_CODE (t) == MEM_REF) - type = TREE_TYPE (type); - if (TYPE_REF_P (type)) - type = TREE_TYPE (type); - if (TREE_CODE (type) == ARRAY_TYPE) - { - tree oatype = type; - gcc_assert (TREE_CODE (t) != MEM_REF); - while (TREE_CODE (type) == ARRAY_TYPE) - type = TREE_TYPE (type); - if (!processing_template_decl) - { - t = require_complete_type (t); - if (t == error_mark_node - || !complete_type_or_else (oatype, NULL_TREE)) - return true; - tree size = size_binop (EXACT_DIV_EXPR, TYPE_SIZE_UNIT (oatype), - TYPE_SIZE_UNIT (type)); - if (integer_zerop (size)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qE in %<reduction%> clause is a zero size array", - omp_clause_printable_decl (t)); - return true; - } - size = size_binop (MINUS_EXPR, size, size_one_node); - size = save_expr (size); - tree index_type = build_index_type (size); - tree atype = build_array_type (type, index_type); - tree ptype = build_pointer_type (type); - if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE) - t = build_fold_addr_expr (t); - t = build2 (MEM_REF, atype, t, build_int_cst (ptype, 0)); - OMP_CLAUSE_DECL (c) = t; - } - } - if (type == error_mark_node) - return true; - else if (ARITHMETIC_TYPE_P (type)) - switch (OMP_CLAUSE_REDUCTION_CODE (c)) - { - case PLUS_EXPR: - case MULT_EXPR: - case MINUS_EXPR: - case TRUTH_ANDIF_EXPR: - case TRUTH_ORIF_EXPR: - predefined = true; - break; - case MIN_EXPR: - case MAX_EXPR: - if (TREE_CODE (type) == COMPLEX_TYPE) - break; - predefined = true; - break; - case BIT_AND_EXPR: - case BIT_IOR_EXPR: - case BIT_XOR_EXPR: - if (FLOAT_TYPE_P (type) || TREE_CODE (type) == COMPLEX_TYPE) - break; - predefined = true; - break; - default: - break; - } - else if (TYPE_READONLY (type)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qE has const type for %<reduction%>", - omp_clause_printable_decl (t)); - return true; - } - else if (!processing_template_decl) - { - t = require_complete_type (t); - if (t == error_mark_node) - return true; - OMP_CLAUSE_DECL (c) = t; - } - - if (predefined) - { - OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL_TREE; - return false; - } - else if (processing_template_decl) - { - if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) == error_mark_node) - return true; - return false; - } - - tree id = OMP_CLAUSE_REDUCTION_PLACEHOLDER (c); - - type = TYPE_MAIN_VARIANT (type); - OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = NULL_TREE; - if (id == NULL_TREE) - id = omp_reduction_id (OMP_CLAUSE_REDUCTION_CODE (c), - NULL_TREE, NULL_TREE); - id = omp_reduction_lookup (OMP_CLAUSE_LOCATION (c), id, type, NULL, NULL); - if (id) - { - if (id == error_mark_node) - return true; - mark_used (id); - tree body = DECL_SAVED_TREE (id); - if (!body) - return true; - if (TREE_CODE (body) == STATEMENT_LIST) - { - tree_stmt_iterator tsi; - tree placeholder = NULL_TREE, decl_placeholder = NULL_TREE; - int i; - tree stmts[7]; - tree atype = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (id))); - atype = TREE_TYPE (atype); - bool need_static_cast = !same_type_p (type, atype); - memset (stmts, 0, sizeof stmts); - for (i = 0, tsi = tsi_start (body); - i < 7 && !tsi_end_p (tsi); - i++, tsi_next (&tsi)) - stmts[i] = tsi_stmt (tsi); - gcc_assert (tsi_end_p (tsi)); - - if (i >= 3) - { - gcc_assert (TREE_CODE (stmts[0]) == DECL_EXPR - && TREE_CODE (stmts[1]) == DECL_EXPR); - placeholder = build_lang_decl (VAR_DECL, NULL_TREE, type); - DECL_ARTIFICIAL (placeholder) = 1; - DECL_IGNORED_P (placeholder) = 1; - OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) = placeholder; - if (TREE_CODE (t) == MEM_REF) - { - decl_placeholder = build_lang_decl (VAR_DECL, NULL_TREE, - type); - DECL_ARTIFICIAL (decl_placeholder) = 1; - DECL_IGNORED_P (decl_placeholder) = 1; - OMP_CLAUSE_REDUCTION_DECL_PLACEHOLDER (c) = decl_placeholder; - } - if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[0]))) - cxx_mark_addressable (placeholder); - if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[1])) - && (decl_placeholder - || !TYPE_REF_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))) - cxx_mark_addressable (decl_placeholder ? decl_placeholder - : OMP_CLAUSE_DECL (c)); - tree omp_out = placeholder; - tree omp_in = decl_placeholder ? decl_placeholder - : convert_from_reference (OMP_CLAUSE_DECL (c)); - if (need_static_cast) - { - tree rtype = build_reference_type (atype); - omp_out = build_static_cast (input_location, - rtype, omp_out, - tf_warning_or_error); - omp_in = build_static_cast (input_location, - rtype, omp_in, - tf_warning_or_error); - if (omp_out == error_mark_node || omp_in == error_mark_node) - return true; - omp_out = convert_from_reference (omp_out); - omp_in = convert_from_reference (omp_in); - } - OMP_CLAUSE_REDUCTION_MERGE (c) - = clone_omp_udr (stmts[2], DECL_EXPR_DECL (stmts[0]), - DECL_EXPR_DECL (stmts[1]), omp_in, omp_out); - } - if (i >= 6) - { - gcc_assert (TREE_CODE (stmts[3]) == DECL_EXPR - && TREE_CODE (stmts[4]) == DECL_EXPR); - if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[3])) - && (decl_placeholder - || !TYPE_REF_P (TREE_TYPE (OMP_CLAUSE_DECL (c))))) - cxx_mark_addressable (decl_placeholder ? decl_placeholder - : OMP_CLAUSE_DECL (c)); - if (TREE_ADDRESSABLE (DECL_EXPR_DECL (stmts[4]))) - cxx_mark_addressable (placeholder); - tree omp_priv = decl_placeholder ? decl_placeholder - : convert_from_reference (OMP_CLAUSE_DECL (c)); - tree omp_orig = placeholder; - if (need_static_cast) - { - if (i == 7) - { - error_at (OMP_CLAUSE_LOCATION (c), - "user defined reduction with constructor " - "initializer for base class %qT", atype); - return true; - } - tree rtype = build_reference_type (atype); - omp_priv = build_static_cast (input_location, - rtype, omp_priv, - tf_warning_or_error); - omp_orig = build_static_cast (input_location, - rtype, omp_orig, - tf_warning_or_error); - if (omp_priv == error_mark_node - || omp_orig == error_mark_node) - return true; - omp_priv = convert_from_reference (omp_priv); - omp_orig = convert_from_reference (omp_orig); - } - if (i == 6) - *need_default_ctor = true; - OMP_CLAUSE_REDUCTION_INIT (c) - = clone_omp_udr (stmts[5], DECL_EXPR_DECL (stmts[4]), - DECL_EXPR_DECL (stmts[3]), - omp_priv, omp_orig); - if (cp_walk_tree (&OMP_CLAUSE_REDUCTION_INIT (c), - find_omp_placeholder_r, placeholder, NULL)) - OMP_CLAUSE_REDUCTION_OMP_ORIG_REF (c) = 1; - } - else if (i >= 3) - { - if (CLASS_TYPE_P (type) && !pod_type_p (type)) - *need_default_ctor = true; - else - { - tree init; - tree v = decl_placeholder ? decl_placeholder - : convert_from_reference (t); - if (AGGREGATE_TYPE_P (TREE_TYPE (v))) - init = build_constructor (TREE_TYPE (v), NULL); - else - init = fold_convert (TREE_TYPE (v), integer_zero_node); - OMP_CLAUSE_REDUCTION_INIT (c) - = build2 (INIT_EXPR, TREE_TYPE (v), v, init); - } - } - } - } - if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)) - *need_dtor = true; - else - { - error_at (OMP_CLAUSE_LOCATION (c), - "user defined reduction not found for %qE", - omp_clause_printable_decl (t)); - return true; - } - if (TREE_CODE (OMP_CLAUSE_DECL (c)) == MEM_REF) - gcc_assert (TYPE_SIZE_UNIT (type) - && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST); - return false; -} - -/* Called from finish_struct_1. linear(this) or linear(this:step) - clauses might not be finalized yet because the class has been incomplete - when parsing #pragma omp declare simd methods. Fix those up now. */ - -void -finish_omp_declare_simd_methods (tree t) -{ - if (processing_template_decl) - return; - - for (tree x = TYPE_FIELDS (t); x; x = DECL_CHAIN (x)) - { - if (TREE_CODE (x) == USING_DECL - || !DECL_NONSTATIC_MEMBER_FUNCTION_P (x)) - continue; - tree ods = lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (x)); - if (!ods || !TREE_VALUE (ods)) - continue; - for (tree c = TREE_VALUE (TREE_VALUE (ods)); c; c = OMP_CLAUSE_CHAIN (c)) - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINEAR - && integer_zerop (OMP_CLAUSE_DECL (c)) - && OMP_CLAUSE_LINEAR_STEP (c) - && TYPE_PTR_P (TREE_TYPE (OMP_CLAUSE_LINEAR_STEP (c)))) - { - tree s = OMP_CLAUSE_LINEAR_STEP (c); - s = fold_convert_loc (OMP_CLAUSE_LOCATION (c), sizetype, s); - s = fold_build2_loc (OMP_CLAUSE_LOCATION (c), MULT_EXPR, - sizetype, s, TYPE_SIZE_UNIT (t)); - OMP_CLAUSE_LINEAR_STEP (c) = s; - } - } -} - -/* Adjust sink depend clause to take into account pointer offsets. - - Return TRUE if there was a problem processing the offset, and the - whole clause should be removed. */ - -static bool -cp_finish_omp_clause_depend_sink (tree sink_clause) -{ - tree t = OMP_CLAUSE_DECL (sink_clause); - gcc_assert (TREE_CODE (t) == TREE_LIST); - - /* Make sure we don't adjust things twice for templates. */ - if (processing_template_decl) - return false; - - for (; t; t = TREE_CHAIN (t)) - { - tree decl = TREE_VALUE (t); - if (TYPE_PTR_P (TREE_TYPE (decl))) - { - tree offset = TREE_PURPOSE (t); - bool neg = wi::neg_p (wi::to_wide (offset)); - offset = fold_unary (ABS_EXPR, TREE_TYPE (offset), offset); - decl = mark_rvalue_use (decl); - decl = convert_from_reference (decl); - tree t2 = pointer_int_sum (OMP_CLAUSE_LOCATION (sink_clause), - neg ? MINUS_EXPR : PLUS_EXPR, - decl, offset); - t2 = fold_build2_loc (OMP_CLAUSE_LOCATION (sink_clause), - MINUS_EXPR, sizetype, - fold_convert (sizetype, t2), - fold_convert (sizetype, decl)); - if (t2 == error_mark_node) - return true; - TREE_PURPOSE (t) = t2; - } - } - return false; -} - -/* Finish OpenMP iterators ITER. Return true if they are errorneous - and clauses containing them should be removed. */ - -static bool -cp_omp_finish_iterators (tree iter) -{ - bool ret = false; - for (tree it = iter; it; it = TREE_CHAIN (it)) - { - tree var = TREE_VEC_ELT (it, 0); - tree begin = TREE_VEC_ELT (it, 1); - tree end = TREE_VEC_ELT (it, 2); - tree step = TREE_VEC_ELT (it, 3); - tree orig_step; - tree type = TREE_TYPE (var); - location_t loc = DECL_SOURCE_LOCATION (var); - if (type == error_mark_node) - { - ret = true; - continue; - } - if (type_dependent_expression_p (var)) - continue; - if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type)) - { - error_at (loc, "iterator %qD has neither integral nor pointer type", - var); - ret = true; - continue; - } - else if (TYPE_READONLY (type)) - { - error_at (loc, "iterator %qD has const qualified type", var); - ret = true; - continue; - } - if (type_dependent_expression_p (begin) - || type_dependent_expression_p (end) - || type_dependent_expression_p (step)) - continue; - else if (error_operand_p (step)) - { - ret = true; - continue; - } - else if (!INTEGRAL_TYPE_P (TREE_TYPE (step))) - { - error_at (EXPR_LOC_OR_LOC (step, loc), - "iterator step with non-integral type"); - ret = true; - continue; - } - - begin = mark_rvalue_use (begin); - end = mark_rvalue_use (end); - step = mark_rvalue_use (step); - begin = cp_build_c_cast (input_location, type, begin, - tf_warning_or_error); - end = cp_build_c_cast (input_location, type, end, - tf_warning_or_error); - orig_step = step; - if (!processing_template_decl) - step = orig_step = save_expr (step); - tree stype = POINTER_TYPE_P (type) ? sizetype : type; - step = cp_build_c_cast (input_location, stype, step, - tf_warning_or_error); - if (POINTER_TYPE_P (type) && !processing_template_decl) - { - begin = save_expr (begin); - step = pointer_int_sum (loc, PLUS_EXPR, begin, step); - step = fold_build2_loc (loc, MINUS_EXPR, sizetype, - fold_convert (sizetype, step), - fold_convert (sizetype, begin)); - step = fold_convert (ssizetype, step); - } - if (!processing_template_decl) - { - begin = maybe_constant_value (begin); - end = maybe_constant_value (end); - step = maybe_constant_value (step); - orig_step = maybe_constant_value (orig_step); - } - if (integer_zerop (step)) - { - error_at (loc, "iterator %qD has zero step", var); - ret = true; - continue; - } - - if (begin == error_mark_node - || end == error_mark_node - || step == error_mark_node - || orig_step == error_mark_node) - { - ret = true; - continue; - } - - if (!processing_template_decl) - { - begin = fold_build_cleanup_point_expr (TREE_TYPE (begin), begin); - end = fold_build_cleanup_point_expr (TREE_TYPE (end), end); - step = fold_build_cleanup_point_expr (TREE_TYPE (step), step); - orig_step = fold_build_cleanup_point_expr (TREE_TYPE (orig_step), - orig_step); - } - hash_set<tree> pset; - tree it2; - for (it2 = TREE_CHAIN (it); it2; it2 = TREE_CHAIN (it2)) - { - tree var2 = TREE_VEC_ELT (it2, 0); - tree begin2 = TREE_VEC_ELT (it2, 1); - tree end2 = TREE_VEC_ELT (it2, 2); - tree step2 = TREE_VEC_ELT (it2, 3); - location_t loc2 = DECL_SOURCE_LOCATION (var2); - if (cp_walk_tree (&begin2, find_omp_placeholder_r, var, &pset)) - { - error_at (EXPR_LOC_OR_LOC (begin2, loc2), - "begin expression refers to outer iterator %qD", var); - break; - } - else if (cp_walk_tree (&end2, find_omp_placeholder_r, var, &pset)) - { - error_at (EXPR_LOC_OR_LOC (end2, loc2), - "end expression refers to outer iterator %qD", var); - break; - } - else if (cp_walk_tree (&step2, find_omp_placeholder_r, var, &pset)) - { - error_at (EXPR_LOC_OR_LOC (step2, loc2), - "step expression refers to outer iterator %qD", var); - break; - } - } - if (it2) - { - ret = true; - continue; - } - TREE_VEC_ELT (it, 1) = begin; - TREE_VEC_ELT (it, 2) = end; - if (processing_template_decl) - TREE_VEC_ELT (it, 3) = orig_step; - else - { - TREE_VEC_ELT (it, 3) = step; - TREE_VEC_ELT (it, 4) = orig_step; - } - } - return ret; -} - -/* Ensure that pointers are used in OpenACC attach and detach clauses. - Return true if an error has been detected. */ - -static bool -cp_oacc_check_attachments (tree c) -{ - if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP) - return false; - - /* OpenACC attach / detach clauses must be pointers. */ - if (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH - || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH) - { - tree t = OMP_CLAUSE_DECL (c); - tree type; - - while (TREE_CODE (t) == TREE_LIST) - t = TREE_CHAIN (t); - - type = TREE_TYPE (t); - - if (TREE_CODE (type) == REFERENCE_TYPE) - type = TREE_TYPE (type); - - if (TREE_CODE (type) != POINTER_TYPE) - { - error_at (OMP_CLAUSE_LOCATION (c), "expected pointer in %qs clause", - c_omp_map_clause_name (c, true)); - return true; - } - } - - return false; -} - -/* For all elements of CLAUSES, validate them vs OpenMP constraints. - Remove any elements from the list that are invalid. */ - -tree -finish_omp_clauses (tree clauses, enum c_omp_region_type ort) -{ - bitmap_head generic_head, firstprivate_head, lastprivate_head; - bitmap_head aligned_head, map_head, map_field_head, map_firstprivate_head; - bitmap_head oacc_reduction_head; - tree c, t, *pc; - tree safelen = NULL_TREE; - bool branch_seen = false; - bool copyprivate_seen = false; - bool ordered_seen = false; - bool order_seen = false; - bool schedule_seen = false; - bool oacc_async = false; - bool indir_component_ref_p = false; - tree last_iterators = NULL_TREE; - bool last_iterators_remove = false; - /* 1 if normal/task reduction has been seen, -1 if inscan reduction - has been seen, -2 if mixed inscan/normal reduction diagnosed. */ - int reduction_seen = 0; - bool allocate_seen = false; - tree detach_seen = NULL_TREE; - bool mergeable_seen = false; - bool implicit_moved = false; - bool target_in_reduction_seen = false; - - bitmap_obstack_initialize (NULL); - bitmap_initialize (&generic_head, &bitmap_default_obstack); - bitmap_initialize (&firstprivate_head, &bitmap_default_obstack); - bitmap_initialize (&lastprivate_head, &bitmap_default_obstack); - bitmap_initialize (&aligned_head, &bitmap_default_obstack); - /* If ort == C_ORT_OMP_DECLARE_SIMD used as uniform_head instead. */ - bitmap_initialize (&map_head, &bitmap_default_obstack); - bitmap_initialize (&map_field_head, &bitmap_default_obstack); - bitmap_initialize (&map_firstprivate_head, &bitmap_default_obstack); - /* If ort == C_ORT_OMP used as nontemporal_head or use_device_xxx_head - instead and for ort == C_ORT_OMP_TARGET used as in_reduction_head. */ - bitmap_initialize (&oacc_reduction_head, &bitmap_default_obstack); - - if (ort & C_ORT_ACC) - for (c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ASYNC) - { - oacc_async = true; - break; - } - - for (pc = &clauses, c = clauses; c ; c = *pc) - { - bool remove = false; - bool field_ok = false; - - switch (OMP_CLAUSE_CODE (c)) - { - case OMP_CLAUSE_SHARED: - field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP); - goto check_dup_generic; - case OMP_CLAUSE_PRIVATE: - field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP); - goto check_dup_generic; - case OMP_CLAUSE_REDUCTION: - if (reduction_seen == 0) - reduction_seen = OMP_CLAUSE_REDUCTION_INSCAN (c) ? -1 : 1; - else if (reduction_seen != -2 - && reduction_seen != (OMP_CLAUSE_REDUCTION_INSCAN (c) - ? -1 : 1)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<inscan%> and non-%<inscan%> %<reduction%> clauses " - "on the same construct"); - reduction_seen = -2; - } - /* FALLTHRU */ - case OMP_CLAUSE_IN_REDUCTION: - case OMP_CLAUSE_TASK_REDUCTION: - field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP); - t = OMP_CLAUSE_DECL (c); - if (TREE_CODE (t) == TREE_LIST) - { - if (handle_omp_array_sections (c, ort)) - { - remove = true; - break; - } - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION - && OMP_CLAUSE_REDUCTION_INSCAN (c)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<inscan%> %<reduction%> clause with array " - "section"); - remove = true; - break; - } - if (TREE_CODE (t) == TREE_LIST) - { - while (TREE_CODE (t) == TREE_LIST) - t = TREE_CHAIN (t); - } - else - { - gcc_assert (TREE_CODE (t) == MEM_REF); - t = TREE_OPERAND (t, 0); - if (TREE_CODE (t) == POINTER_PLUS_EXPR) - t = TREE_OPERAND (t, 0); - if (TREE_CODE (t) == ADDR_EXPR - || INDIRECT_REF_P (t)) - t = TREE_OPERAND (t, 0); - } - tree n = omp_clause_decl_field (t); - if (n) - t = n; - goto check_dup_generic_t; - } - if (oacc_async) - cxx_mark_addressable (t); - goto check_dup_generic; - case OMP_CLAUSE_COPYPRIVATE: - copyprivate_seen = true; - field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP); - goto check_dup_generic; - case OMP_CLAUSE_COPYIN: - goto check_dup_generic; - case OMP_CLAUSE_LINEAR: - field_ok = ((ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP); - t = OMP_CLAUSE_DECL (c); - if (ort != C_ORT_OMP_DECLARE_SIMD - && OMP_CLAUSE_LINEAR_KIND (c) != OMP_CLAUSE_LINEAR_DEFAULT) - { - error_at (OMP_CLAUSE_LOCATION (c), - "modifier should not be specified in %<linear%> " - "clause on %<simd%> or %<for%> constructs"); - OMP_CLAUSE_LINEAR_KIND (c) = OMP_CLAUSE_LINEAR_DEFAULT; - } - if ((VAR_P (t) || TREE_CODE (t) == PARM_DECL) - && !type_dependent_expression_p (t)) - { - tree type = TREE_TYPE (t); - if ((OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_REF - || OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_UVAL) - && !TYPE_REF_P (type)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "linear clause with %qs modifier applied to " - "non-reference variable with %qT type", - OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_REF - ? "ref" : "uval", TREE_TYPE (t)); - remove = true; - break; - } - if (TYPE_REF_P (type)) - type = TREE_TYPE (type); - if (OMP_CLAUSE_LINEAR_KIND (c) != OMP_CLAUSE_LINEAR_REF) - { - if (!INTEGRAL_TYPE_P (type) - && !TYPE_PTR_P (type)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "linear clause applied to non-integral " - "non-pointer variable with %qT type", - TREE_TYPE (t)); - remove = true; - break; - } - } - } - t = OMP_CLAUSE_LINEAR_STEP (c); - if (t == NULL_TREE) - t = integer_one_node; - if (t == error_mark_node) - { - remove = true; - break; - } - else if (!type_dependent_expression_p (t) - && !INTEGRAL_TYPE_P (TREE_TYPE (t)) - && (ort != C_ORT_OMP_DECLARE_SIMD - || TREE_CODE (t) != PARM_DECL - || !TYPE_REF_P (TREE_TYPE (t)) - || !INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (t))))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "linear step expression must be integral"); - remove = true; - break; - } - else - { - t = mark_rvalue_use (t); - if (ort == C_ORT_OMP_DECLARE_SIMD && TREE_CODE (t) == PARM_DECL) - { - OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c) = 1; - goto check_dup_generic; - } - if (!processing_template_decl - && (VAR_P (OMP_CLAUSE_DECL (c)) - || TREE_CODE (OMP_CLAUSE_DECL (c)) == PARM_DECL)) - { - if (ort == C_ORT_OMP_DECLARE_SIMD) - { - t = maybe_constant_value (t); - if (TREE_CODE (t) != INTEGER_CST) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<linear%> clause step %qE is neither " - "constant nor a parameter", t); - remove = true; - break; - } - } - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - tree type = TREE_TYPE (OMP_CLAUSE_DECL (c)); - if (TYPE_REF_P (type)) - type = TREE_TYPE (type); - if (OMP_CLAUSE_LINEAR_KIND (c) == OMP_CLAUSE_LINEAR_REF) - { - type = build_pointer_type (type); - tree d = fold_convert (type, OMP_CLAUSE_DECL (c)); - t = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR, - d, t); - t = fold_build2_loc (OMP_CLAUSE_LOCATION (c), - MINUS_EXPR, sizetype, - fold_convert (sizetype, t), - fold_convert (sizetype, d)); - if (t == error_mark_node) - { - remove = true; - break; - } - } - else if (TYPE_PTR_P (type) - /* Can't multiply the step yet if *this - is still incomplete type. */ - && (ort != C_ORT_OMP_DECLARE_SIMD - || TREE_CODE (OMP_CLAUSE_DECL (c)) != PARM_DECL - || !DECL_ARTIFICIAL (OMP_CLAUSE_DECL (c)) - || DECL_NAME (OMP_CLAUSE_DECL (c)) - != this_identifier - || !TYPE_BEING_DEFINED (TREE_TYPE (type)))) - { - tree d = convert_from_reference (OMP_CLAUSE_DECL (c)); - t = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR, - d, t); - t = fold_build2_loc (OMP_CLAUSE_LOCATION (c), - MINUS_EXPR, sizetype, - fold_convert (sizetype, t), - fold_convert (sizetype, d)); - if (t == error_mark_node) - { - remove = true; - break; - } - } - else - t = fold_convert (type, t); - } - OMP_CLAUSE_LINEAR_STEP (c) = t; - } - goto check_dup_generic; - check_dup_generic: - t = omp_clause_decl_field (OMP_CLAUSE_DECL (c)); - if (t) - { - if (!remove && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SHARED) - omp_note_field_privatization (t, OMP_CLAUSE_DECL (c)); - } - else - t = OMP_CLAUSE_DECL (c); - check_dup_generic_t: - if (t == current_class_ptr - && ((ort != C_ORT_OMP_DECLARE_SIMD && ort != C_ORT_ACC) - || (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LINEAR - && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_UNIFORM))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<this%> allowed in OpenMP only in %<declare simd%>" - " clauses"); - remove = true; - break; - } - if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL - && (!field_ok || TREE_CODE (t) != FIELD_DECL)) - { - if (processing_template_decl && TREE_CODE (t) != OVERLOAD) - break; - if (DECL_P (t)) - error_at (OMP_CLAUSE_LOCATION (c), - "%qD is not a variable in clause %qs", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - else - error_at (OMP_CLAUSE_LOCATION (c), - "%qE is not a variable in clause %qs", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - remove = true; - } - else if ((ort == C_ORT_ACC - && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION) - || (ort == C_ORT_OMP - && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR - || (OMP_CLAUSE_CODE (c) - == OMP_CLAUSE_USE_DEVICE_ADDR))) - || (ort == C_ORT_OMP_TARGET - && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION)) - { - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION - && (bitmap_bit_p (&generic_head, DECL_UID (t)) - || bitmap_bit_p (&firstprivate_head, DECL_UID (t)))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qD appears more than once in data-sharing " - "clauses", t); - remove = true; - break; - } - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION) - target_in_reduction_seen = true; - if (bitmap_bit_p (&oacc_reduction_head, DECL_UID (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - ort == C_ORT_ACC - ? "%qD appears more than once in reduction clauses" - : "%qD appears more than once in data clauses", - t); - remove = true; - } - else - bitmap_set_bit (&oacc_reduction_head, DECL_UID (t)); - } - else if (bitmap_bit_p (&generic_head, DECL_UID (t)) - || bitmap_bit_p (&firstprivate_head, DECL_UID (t)) - || bitmap_bit_p (&lastprivate_head, DECL_UID (t)) - || bitmap_bit_p (&map_firstprivate_head, DECL_UID (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qD appears more than once in data clauses", t); - remove = true; - } - else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE - && bitmap_bit_p (&map_head, DECL_UID (t))) - { - if (ort == C_ORT_ACC) - error_at (OMP_CLAUSE_LOCATION (c), - "%qD appears more than once in data clauses", t); - else - error_at (OMP_CLAUSE_LOCATION (c), - "%qD appears both in data and map clauses", t); - remove = true; - } - else - bitmap_set_bit (&generic_head, DECL_UID (t)); - if (!field_ok) - break; - handle_field_decl: - if (!remove - && TREE_CODE (t) == FIELD_DECL - && t == OMP_CLAUSE_DECL (c)) - { - OMP_CLAUSE_DECL (c) - = omp_privatize_field (t, (OMP_CLAUSE_CODE (c) - == OMP_CLAUSE_SHARED)); - if (OMP_CLAUSE_DECL (c) == error_mark_node) - remove = true; - } - break; - - case OMP_CLAUSE_FIRSTPRIVATE: - if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c) && !implicit_moved) - { - move_implicit: - implicit_moved = true; - /* Move firstprivate and map clauses with - OMP_CLAUSE_{FIRSTPRIVATE,MAP}_IMPLICIT set to the end of - clauses chain. */ - tree cl1 = NULL_TREE, cl2 = NULL_TREE; - tree *pc1 = pc, *pc2 = &cl1, *pc3 = &cl2; - while (*pc1) - if (OMP_CLAUSE_CODE (*pc1) == OMP_CLAUSE_FIRSTPRIVATE - && OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (*pc1)) - { - *pc3 = *pc1; - pc3 = &OMP_CLAUSE_CHAIN (*pc3); - *pc1 = OMP_CLAUSE_CHAIN (*pc1); - } - else if (OMP_CLAUSE_CODE (*pc1) == OMP_CLAUSE_MAP - && OMP_CLAUSE_MAP_IMPLICIT (*pc1)) - { - *pc2 = *pc1; - pc2 = &OMP_CLAUSE_CHAIN (*pc2); - *pc1 = OMP_CLAUSE_CHAIN (*pc1); - } - else - pc1 = &OMP_CLAUSE_CHAIN (*pc1); - *pc3 = NULL; - *pc2 = cl2; - *pc1 = cl1; - continue; - } - t = omp_clause_decl_field (OMP_CLAUSE_DECL (c)); - if (t) - omp_note_field_privatization (t, OMP_CLAUSE_DECL (c)); - else - t = OMP_CLAUSE_DECL (c); - if (ort != C_ORT_ACC && t == current_class_ptr) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<this%> allowed in OpenMP only in %<declare simd%>" - " clauses"); - remove = true; - break; - } - if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL - && ((ort & C_ORT_OMP_DECLARE_SIMD) != C_ORT_OMP - || TREE_CODE (t) != FIELD_DECL)) - { - if (processing_template_decl && TREE_CODE (t) != OVERLOAD) - break; - if (DECL_P (t)) - error_at (OMP_CLAUSE_LOCATION (c), - "%qD is not a variable in clause %<firstprivate%>", - t); - else - error_at (OMP_CLAUSE_LOCATION (c), - "%qE is not a variable in clause %<firstprivate%>", - t); - remove = true; - } - else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c) - && !OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (c) - && bitmap_bit_p (&map_firstprivate_head, DECL_UID (t))) - remove = true; - else if (bitmap_bit_p (&generic_head, DECL_UID (t)) - || bitmap_bit_p (&firstprivate_head, DECL_UID (t)) - || bitmap_bit_p (&map_firstprivate_head, DECL_UID (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qD appears more than once in data clauses", t); - remove = true; - } - else if (bitmap_bit_p (&map_head, DECL_UID (t))) - { - if (ort == C_ORT_ACC) - error_at (OMP_CLAUSE_LOCATION (c), - "%qD appears more than once in data clauses", t); - else if (OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT (c) - && !OMP_CLAUSE_FIRSTPRIVATE_IMPLICIT_TARGET (c)) - /* Silently drop the clause. */; - else - error_at (OMP_CLAUSE_LOCATION (c), - "%qD appears both in data and map clauses", t); - remove = true; - } - else - bitmap_set_bit (&firstprivate_head, DECL_UID (t)); - goto handle_field_decl; - - case OMP_CLAUSE_LASTPRIVATE: - t = omp_clause_decl_field (OMP_CLAUSE_DECL (c)); - if (t) - omp_note_field_privatization (t, OMP_CLAUSE_DECL (c)); - else - t = OMP_CLAUSE_DECL (c); - if (ort != C_ORT_ACC && t == current_class_ptr) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<this%> allowed in OpenMP only in %<declare simd%>" - " clauses"); - remove = true; - break; - } - if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL - && ((ort & C_ORT_OMP_DECLARE_SIMD) != C_ORT_OMP - || TREE_CODE (t) != FIELD_DECL)) - { - if (processing_template_decl && TREE_CODE (t) != OVERLOAD) - break; - if (DECL_P (t)) - error_at (OMP_CLAUSE_LOCATION (c), - "%qD is not a variable in clause %<lastprivate%>", - t); - else - error_at (OMP_CLAUSE_LOCATION (c), - "%qE is not a variable in clause %<lastprivate%>", - t); - remove = true; - } - else if (bitmap_bit_p (&generic_head, DECL_UID (t)) - || bitmap_bit_p (&lastprivate_head, DECL_UID (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qD appears more than once in data clauses", t); - remove = true; - } - else - bitmap_set_bit (&lastprivate_head, DECL_UID (t)); - goto handle_field_decl; - - case OMP_CLAUSE_IF: - t = OMP_CLAUSE_IF_EXPR (c); - t = maybe_convert_cond (t); - if (t == error_mark_node) - remove = true; - else if (!processing_template_decl) - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - OMP_CLAUSE_IF_EXPR (c) = t; - break; - - case OMP_CLAUSE_FINAL: - t = OMP_CLAUSE_FINAL_EXPR (c); - t = maybe_convert_cond (t); - if (t == error_mark_node) - remove = true; - else if (!processing_template_decl) - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - OMP_CLAUSE_FINAL_EXPR (c) = t; - break; - - case OMP_CLAUSE_GANG: - /* Operand 1 is the gang static: argument. */ - t = OMP_CLAUSE_OPERAND (c, 1); - if (t != NULL_TREE) - { - if (t == error_mark_node) - remove = true; - else if (!type_dependent_expression_p (t) - && !INTEGRAL_TYPE_P (TREE_TYPE (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<gang%> static expression must be integral"); - remove = true; - } - else - { - t = mark_rvalue_use (t); - if (!processing_template_decl) - { - t = maybe_constant_value (t); - if (TREE_CODE (t) == INTEGER_CST - && tree_int_cst_sgn (t) != 1 - && t != integer_minus_one_node) - { - warning_at (OMP_CLAUSE_LOCATION (c), 0, - "%<gang%> static value must be " - "positive"); - t = integer_one_node; - } - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - } - } - OMP_CLAUSE_OPERAND (c, 1) = t; - } - /* Check operand 0, the num argument. */ - /* FALLTHRU */ - - case OMP_CLAUSE_WORKER: - case OMP_CLAUSE_VECTOR: - if (OMP_CLAUSE_OPERAND (c, 0) == NULL_TREE) - break; - /* FALLTHRU */ - - case OMP_CLAUSE_NUM_TASKS: - case OMP_CLAUSE_NUM_TEAMS: - case OMP_CLAUSE_NUM_THREADS: - case OMP_CLAUSE_NUM_GANGS: - case OMP_CLAUSE_NUM_WORKERS: - case OMP_CLAUSE_VECTOR_LENGTH: - t = OMP_CLAUSE_OPERAND (c, 0); - if (t == error_mark_node) - remove = true; - else if (!type_dependent_expression_p (t) - && !INTEGRAL_TYPE_P (TREE_TYPE (t))) - { - switch (OMP_CLAUSE_CODE (c)) - { - case OMP_CLAUSE_GANG: - error_at (OMP_CLAUSE_LOCATION (c), - "%<gang%> num expression must be integral"); break; - case OMP_CLAUSE_VECTOR: - error_at (OMP_CLAUSE_LOCATION (c), - "%<vector%> length expression must be integral"); - break; - case OMP_CLAUSE_WORKER: - error_at (OMP_CLAUSE_LOCATION (c), - "%<worker%> num expression must be integral"); - break; - default: - error_at (OMP_CLAUSE_LOCATION (c), - "%qs expression must be integral", - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - } - remove = true; - } - else - { - t = mark_rvalue_use (t); - if (!processing_template_decl) - { - t = maybe_constant_value (t); - if (TREE_CODE (t) == INTEGER_CST - && tree_int_cst_sgn (t) != 1) - { - switch (OMP_CLAUSE_CODE (c)) - { - case OMP_CLAUSE_GANG: - warning_at (OMP_CLAUSE_LOCATION (c), 0, - "%<gang%> num value must be positive"); - break; - case OMP_CLAUSE_VECTOR: - warning_at (OMP_CLAUSE_LOCATION (c), 0, - "%<vector%> length value must be " - "positive"); - break; - case OMP_CLAUSE_WORKER: - warning_at (OMP_CLAUSE_LOCATION (c), 0, - "%<worker%> num value must be " - "positive"); - break; - default: - warning_at (OMP_CLAUSE_LOCATION (c), 0, - "%qs value must be positive", - omp_clause_code_name - [OMP_CLAUSE_CODE (c)]); - } - t = integer_one_node; - } - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - } - OMP_CLAUSE_OPERAND (c, 0) = t; - } - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS - && OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) - && !remove) - { - t = OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c); - if (t == error_mark_node) - remove = true; - else if (!type_dependent_expression_p (t) - && !INTEGRAL_TYPE_P (TREE_TYPE (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qs expression must be integral", - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - remove = true; - } - else - { - t = mark_rvalue_use (t); - if (!processing_template_decl) - { - t = maybe_constant_value (t); - if (TREE_CODE (t) == INTEGER_CST - && tree_int_cst_sgn (t) != 1) - { - warning_at (OMP_CLAUSE_LOCATION (c), 0, - "%qs value must be positive", - omp_clause_code_name - [OMP_CLAUSE_CODE (c)]); - t = NULL_TREE; - } - else - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - tree upper = OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c); - if (t - && TREE_CODE (t) == INTEGER_CST - && TREE_CODE (upper) == INTEGER_CST - && tree_int_cst_lt (upper, t)) - { - warning_at (OMP_CLAUSE_LOCATION (c), 0, - "%<num_teams%> lower bound %qE bigger " - "than upper bound %qE", t, upper); - t = NULL_TREE; - } - } - OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = t; - } - } - break; - - case OMP_CLAUSE_SCHEDULE: - t = OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c); - if (t == NULL) - ; - else if (t == error_mark_node) - remove = true; - else if (!type_dependent_expression_p (t) - && !INTEGRAL_TYPE_P (TREE_TYPE (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "schedule chunk size expression must be integral"); - remove = true; - } - else - { - t = mark_rvalue_use (t); - if (!processing_template_decl) - { - t = maybe_constant_value (t); - if (TREE_CODE (t) == INTEGER_CST - && tree_int_cst_sgn (t) != 1) - { - warning_at (OMP_CLAUSE_LOCATION (c), 0, - "chunk size value must be positive"); - t = integer_one_node; - } - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - } - OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t; - } - if (!remove) - schedule_seen = true; - break; - - case OMP_CLAUSE_SIMDLEN: - case OMP_CLAUSE_SAFELEN: - t = OMP_CLAUSE_OPERAND (c, 0); - if (t == error_mark_node) - remove = true; - else if (!type_dependent_expression_p (t) - && !INTEGRAL_TYPE_P (TREE_TYPE (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qs length expression must be integral", - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - remove = true; - } - else - { - t = mark_rvalue_use (t); - if (!processing_template_decl) - { - t = maybe_constant_value (t); - if (TREE_CODE (t) != INTEGER_CST - || tree_int_cst_sgn (t) != 1) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qs length expression must be positive " - "constant integer expression", - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - remove = true; - } - } - OMP_CLAUSE_OPERAND (c, 0) = t; - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SAFELEN) - safelen = c; - } - break; - - case OMP_CLAUSE_ASYNC: - t = OMP_CLAUSE_ASYNC_EXPR (c); - if (t == error_mark_node) - remove = true; - else if (!type_dependent_expression_p (t) - && !INTEGRAL_TYPE_P (TREE_TYPE (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<async%> expression must be integral"); - remove = true; - } - else - { - t = mark_rvalue_use (t); - if (!processing_template_decl) - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - OMP_CLAUSE_ASYNC_EXPR (c) = t; - } - break; - - case OMP_CLAUSE_WAIT: - t = OMP_CLAUSE_WAIT_EXPR (c); - if (t == error_mark_node) - remove = true; - else if (!processing_template_decl) - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - OMP_CLAUSE_WAIT_EXPR (c) = t; - break; - - case OMP_CLAUSE_THREAD_LIMIT: - t = OMP_CLAUSE_THREAD_LIMIT_EXPR (c); - if (t == error_mark_node) - remove = true; - else if (!type_dependent_expression_p (t) - && !INTEGRAL_TYPE_P (TREE_TYPE (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<thread_limit%> expression must be integral"); - remove = true; - } - else - { - t = mark_rvalue_use (t); - if (!processing_template_decl) - { - t = maybe_constant_value (t); - if (TREE_CODE (t) == INTEGER_CST - && tree_int_cst_sgn (t) != 1) - { - warning_at (OMP_CLAUSE_LOCATION (c), 0, - "%<thread_limit%> value must be positive"); - t = integer_one_node; - } - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - } - OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = t; - } - break; - - case OMP_CLAUSE_DEVICE: - t = OMP_CLAUSE_DEVICE_ID (c); - if (t == error_mark_node) - remove = true; - else if (!type_dependent_expression_p (t) - && !INTEGRAL_TYPE_P (TREE_TYPE (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<device%> id must be integral"); - remove = true; - } - else if (OMP_CLAUSE_DEVICE_ANCESTOR (c) - && TREE_CODE (t) == INTEGER_CST - && !integer_onep (t)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "the %<device%> clause expression must evaluate to " - "%<1%>"); - remove = true; - } - else - { - t = mark_rvalue_use (t); - if (!processing_template_decl) - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - OMP_CLAUSE_DEVICE_ID (c) = t; - } - break; - - case OMP_CLAUSE_DIST_SCHEDULE: - t = OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c); - if (t == NULL) - ; - else if (t == error_mark_node) - remove = true; - else if (!type_dependent_expression_p (t) - && !INTEGRAL_TYPE_P (TREE_TYPE (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<dist_schedule%> chunk size expression must be " - "integral"); - remove = true; - } - else - { - t = mark_rvalue_use (t); - if (!processing_template_decl) - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t; - } - break; - - case OMP_CLAUSE_ALIGNED: - t = OMP_CLAUSE_DECL (c); - if (t == current_class_ptr && ort != C_ORT_OMP_DECLARE_SIMD) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<this%> allowed in OpenMP only in %<declare simd%>" - " clauses"); - remove = true; - break; - } - if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) - { - if (processing_template_decl && TREE_CODE (t) != OVERLOAD) - break; - if (DECL_P (t)) - error_at (OMP_CLAUSE_LOCATION (c), - "%qD is not a variable in %<aligned%> clause", t); - else - error_at (OMP_CLAUSE_LOCATION (c), - "%qE is not a variable in %<aligned%> clause", t); - remove = true; - } - else if (!type_dependent_expression_p (t) - && !TYPE_PTR_P (TREE_TYPE (t)) - && TREE_CODE (TREE_TYPE (t)) != ARRAY_TYPE - && (!TYPE_REF_P (TREE_TYPE (t)) - || (!INDIRECT_TYPE_P (TREE_TYPE (TREE_TYPE (t))) - && (TREE_CODE (TREE_TYPE (TREE_TYPE (t))) - != ARRAY_TYPE)))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qE in %<aligned%> clause is neither a pointer nor " - "an array nor a reference to pointer or array", t); - remove = true; - } - else if (bitmap_bit_p (&aligned_head, DECL_UID (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qD appears more than once in %<aligned%> clauses", - t); - remove = true; - } - else - bitmap_set_bit (&aligned_head, DECL_UID (t)); - t = OMP_CLAUSE_ALIGNED_ALIGNMENT (c); - if (t == error_mark_node) - remove = true; - else if (t == NULL_TREE) - break; - else if (!type_dependent_expression_p (t) - && !INTEGRAL_TYPE_P (TREE_TYPE (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<aligned%> clause alignment expression must " - "be integral"); - remove = true; - } - else - { - t = mark_rvalue_use (t); - if (!processing_template_decl) - { - t = maybe_constant_value (t); - if (TREE_CODE (t) != INTEGER_CST - || tree_int_cst_sgn (t) != 1) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<aligned%> clause alignment expression must " - "be positive constant integer expression"); - remove = true; - } - else - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - } - OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = t; - } - break; - - case OMP_CLAUSE_NONTEMPORAL: - t = OMP_CLAUSE_DECL (c); - if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) - { - if (processing_template_decl && TREE_CODE (t) != OVERLOAD) - break; - if (DECL_P (t)) - error_at (OMP_CLAUSE_LOCATION (c), - "%qD is not a variable in %<nontemporal%> clause", - t); - else - error_at (OMP_CLAUSE_LOCATION (c), - "%qE is not a variable in %<nontemporal%> clause", - t); - remove = true; - } - else if (bitmap_bit_p (&oacc_reduction_head, DECL_UID (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qD appears more than once in %<nontemporal%> " - "clauses", t); - remove = true; - } - else - bitmap_set_bit (&oacc_reduction_head, DECL_UID (t)); - break; - - case OMP_CLAUSE_ALLOCATE: - t = omp_clause_decl_field (OMP_CLAUSE_DECL (c)); - if (t) - omp_note_field_privatization (t, OMP_CLAUSE_DECL (c)); - else - t = OMP_CLAUSE_DECL (c); - if (t == current_class_ptr) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<this%> not allowed in %<allocate%> clause"); - remove = true; - break; - } - if (!VAR_P (t) - && TREE_CODE (t) != PARM_DECL - && TREE_CODE (t) != FIELD_DECL) - { - if (processing_template_decl && TREE_CODE (t) != OVERLOAD) - break; - if (DECL_P (t)) - error_at (OMP_CLAUSE_LOCATION (c), - "%qD is not a variable in %<allocate%> clause", t); - else - error_at (OMP_CLAUSE_LOCATION (c), - "%qE is not a variable in %<allocate%> clause", t); - remove = true; - } - else if (bitmap_bit_p (&aligned_head, DECL_UID (t))) - { - warning_at (OMP_CLAUSE_LOCATION (c), 0, - "%qD appears more than once in %<allocate%> clauses", - t); - remove = true; - } - else - { - bitmap_set_bit (&aligned_head, DECL_UID (t)); - allocate_seen = true; - } - tree allocator, align; - align = OMP_CLAUSE_ALLOCATE_ALIGN (c); - if (error_operand_p (align)) - { - remove = true; - break; - } - if (align) - { - if (!type_dependent_expression_p (align) - && !INTEGRAL_TYPE_P (TREE_TYPE (align))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<allocate%> clause %<align%> modifier " - "argument needs to be positive constant " - "power of two integer expression"); - remove = true; - } - else - { - align = mark_rvalue_use (align); - if (!processing_template_decl) - { - align = maybe_constant_value (align); - if (TREE_CODE (align) != INTEGER_CST - || !tree_fits_uhwi_p (align) - || !integer_pow2p (align)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<allocate%> clause %<align%> modifier " - "argument needs to be positive constant " - "power of two integer expression"); - remove = true; - } - } - } - OMP_CLAUSE_ALLOCATE_ALIGN (c) = align; - } - allocator = OMP_CLAUSE_ALLOCATE_ALLOCATOR (c); - if (error_operand_p (allocator)) - { - remove = true; - break; - } - if (allocator == NULL_TREE) - goto handle_field_decl; - tree allocatort; - allocatort = TYPE_MAIN_VARIANT (TREE_TYPE (allocator)); - if (!type_dependent_expression_p (allocator) - && (TREE_CODE (allocatort) != ENUMERAL_TYPE - || TYPE_NAME (allocatort) == NULL_TREE - || TREE_CODE (TYPE_NAME (allocatort)) != TYPE_DECL - || (DECL_NAME (TYPE_NAME (allocatort)) - != get_identifier ("omp_allocator_handle_t")) - || (TYPE_CONTEXT (allocatort) - != DECL_CONTEXT (global_namespace)))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<allocate%> clause allocator expression has " - "type %qT rather than %<omp_allocator_handle_t%>", - TREE_TYPE (allocator)); - remove = true; - break; - } - else - { - allocator = mark_rvalue_use (allocator); - if (!processing_template_decl) - allocator = maybe_constant_value (allocator); - OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator; - } - goto handle_field_decl; - - case OMP_CLAUSE_DEPEND: - t = OMP_CLAUSE_DECL (c); - if (t == NULL_TREE) - { - gcc_assert (OMP_CLAUSE_DEPEND_KIND (c) - == OMP_CLAUSE_DEPEND_SOURCE); - break; - } - if (OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_SINK) - { - if (cp_finish_omp_clause_depend_sink (c)) - remove = true; - break; - } - /* FALLTHRU */ - case OMP_CLAUSE_AFFINITY: - t = OMP_CLAUSE_DECL (c); - if (TREE_CODE (t) == TREE_LIST - && TREE_PURPOSE (t) - && TREE_CODE (TREE_PURPOSE (t)) == TREE_VEC) - { - if (TREE_PURPOSE (t) != last_iterators) - last_iterators_remove - = cp_omp_finish_iterators (TREE_PURPOSE (t)); - last_iterators = TREE_PURPOSE (t); - t = TREE_VALUE (t); - if (last_iterators_remove) - t = error_mark_node; - } - else - last_iterators = NULL_TREE; - - if (TREE_CODE (t) == TREE_LIST) - { - if (handle_omp_array_sections (c, ort)) - remove = true; - else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND - && (OMP_CLAUSE_DEPEND_KIND (c) - == OMP_CLAUSE_DEPEND_DEPOBJ)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<depend%> clause with %<depobj%> dependence " - "type on array section"); - remove = true; - } - break; - } - if (t == error_mark_node) - remove = true; - else if (processing_template_decl && TREE_CODE (t) != OVERLOAD) - break; - else if (!lvalue_p (t)) - { - if (DECL_P (t)) - error_at (OMP_CLAUSE_LOCATION (c), - "%qD is not lvalue expression nor array section " - "in %qs clause", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - else - error_at (OMP_CLAUSE_LOCATION (c), - "%qE is not lvalue expression nor array section " - "in %qs clause", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - remove = true; - } - else if (TREE_CODE (t) == COMPONENT_REF - && TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL - && DECL_BIT_FIELD (TREE_OPERAND (t, 1))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "bit-field %qE in %qs clause", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - remove = true; - } - else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND - && OMP_CLAUSE_DEPEND_KIND (c) == OMP_CLAUSE_DEPEND_DEPOBJ) - { - if (!c_omp_depend_t_p (TYPE_REF_P (TREE_TYPE (t)) - ? TREE_TYPE (TREE_TYPE (t)) - : TREE_TYPE (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qE does not have %<omp_depend_t%> type in " - "%<depend%> clause with %<depobj%> dependence " - "type", t); - remove = true; - } - } - else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND - && c_omp_depend_t_p (TYPE_REF_P (TREE_TYPE (t)) - ? TREE_TYPE (TREE_TYPE (t)) - : TREE_TYPE (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qE should not have %<omp_depend_t%> type in " - "%<depend%> clause with dependence type other than " - "%<depobj%>", t); - remove = true; - } - if (!remove) - { - tree addr = cp_build_addr_expr (t, tf_warning_or_error); - if (addr == error_mark_node) - remove = true; - else - { - t = cp_build_indirect_ref (OMP_CLAUSE_LOCATION (c), - addr, RO_UNARY_STAR, - tf_warning_or_error); - if (t == error_mark_node) - remove = true; - else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == TREE_LIST - && TREE_PURPOSE (OMP_CLAUSE_DECL (c)) - && (TREE_CODE (TREE_PURPOSE (OMP_CLAUSE_DECL (c))) - == TREE_VEC)) - TREE_VALUE (OMP_CLAUSE_DECL (c)) = t; - else - OMP_CLAUSE_DECL (c) = t; - } - } - break; - case OMP_CLAUSE_DETACH: - t = OMP_CLAUSE_DECL (c); - if (detach_seen) - { - error_at (OMP_CLAUSE_LOCATION (c), - "too many %qs clauses on a task construct", - "detach"); - remove = true; - break; - } - else if (error_operand_p (t)) - { - remove = true; - break; - } - else - { - tree type = TYPE_MAIN_VARIANT (TREE_TYPE (t)); - if (!type_dependent_expression_p (t) - && (!INTEGRAL_TYPE_P (type) - || TREE_CODE (type) != ENUMERAL_TYPE - || TYPE_NAME (type) == NULL_TREE - || (DECL_NAME (TYPE_NAME (type)) - != get_identifier ("omp_event_handle_t")))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<detach%> clause event handle " - "has type %qT rather than " - "%<omp_event_handle_t%>", - type); - remove = true; - } - detach_seen = c; - cxx_mark_addressable (t); - } - break; - - case OMP_CLAUSE_MAP: - if (OMP_CLAUSE_MAP_IMPLICIT (c) && !implicit_moved) - goto move_implicit; - /* FALLTHRU */ - case OMP_CLAUSE_TO: - case OMP_CLAUSE_FROM: - case OMP_CLAUSE__CACHE_: - t = OMP_CLAUSE_DECL (c); - if (TREE_CODE (t) == TREE_LIST) - { - if (handle_omp_array_sections (c, ort)) - remove = true; - else - { - t = OMP_CLAUSE_DECL (c); - if (TREE_CODE (t) != TREE_LIST - && !type_dependent_expression_p (t) - && !cp_omp_mappable_type (TREE_TYPE (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "array section does not have mappable type " - "in %qs clause", - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - cp_omp_emit_unmappable_type_notes (TREE_TYPE (t)); - remove = true; - } - while (TREE_CODE (t) == ARRAY_REF) - t = TREE_OPERAND (t, 0); - if (TREE_CODE (t) == COMPONENT_REF - && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE) - { - do - { - t = TREE_OPERAND (t, 0); - if (REFERENCE_REF_P (t)) - t = TREE_OPERAND (t, 0); - if (TREE_CODE (t) == MEM_REF - || TREE_CODE (t) == INDIRECT_REF) - { - t = TREE_OPERAND (t, 0); - STRIP_NOPS (t); - if (TREE_CODE (t) == POINTER_PLUS_EXPR) - t = TREE_OPERAND (t, 0); - } - } - while (TREE_CODE (t) == COMPONENT_REF - || TREE_CODE (t) == ARRAY_REF); - - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP - && OMP_CLAUSE_MAP_IMPLICIT (c) - && (bitmap_bit_p (&map_head, DECL_UID (t)) - || bitmap_bit_p (&map_field_head, DECL_UID (t)) - || bitmap_bit_p (&map_firstprivate_head, - DECL_UID (t)))) - { - remove = true; - break; - } - if (bitmap_bit_p (&map_field_head, DECL_UID (t))) - break; - if (bitmap_bit_p (&map_head, DECL_UID (t))) - { - if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP) - error_at (OMP_CLAUSE_LOCATION (c), - "%qD appears more than once in motion" - " clauses", t); - else if (ort == C_ORT_ACC) - error_at (OMP_CLAUSE_LOCATION (c), - "%qD appears more than once in data" - " clauses", t); - else - error_at (OMP_CLAUSE_LOCATION (c), - "%qD appears more than once in map" - " clauses", t); - remove = true; - } - else - { - bitmap_set_bit (&map_head, DECL_UID (t)); - bitmap_set_bit (&map_field_head, DECL_UID (t)); - } - } - } - if (cp_oacc_check_attachments (c)) - remove = true; - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP - && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH - || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)) - /* In this case, we have a single array element which is a - pointer, and we already set OMP_CLAUSE_SIZE in - handle_omp_array_sections above. For attach/detach clauses, - reset the OMP_CLAUSE_SIZE (representing a bias) to zero - here. */ - OMP_CLAUSE_SIZE (c) = size_zero_node; - break; - } - if (t == error_mark_node) - { - remove = true; - break; - } - /* OpenACC attach / detach clauses must be pointers. */ - if (cp_oacc_check_attachments (c)) - { - remove = true; - break; - } - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP - && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH - || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_DETACH)) - /* For attach/detach clauses, set OMP_CLAUSE_SIZE (representing a - bias) to zero here, so it is not set erroneously to the pointer - size later on in gimplify.c. */ - OMP_CLAUSE_SIZE (c) = size_zero_node; - if (REFERENCE_REF_P (t) - && TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF) - { - t = TREE_OPERAND (t, 0); - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP - && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH_DETACH) - OMP_CLAUSE_DECL (c) = t; - } - while (TREE_CODE (t) == INDIRECT_REF - || TREE_CODE (t) == ARRAY_REF) - { - t = TREE_OPERAND (t, 0); - STRIP_NOPS (t); - if (TREE_CODE (t) == POINTER_PLUS_EXPR) - t = TREE_OPERAND (t, 0); - } - while (TREE_CODE (t) == COMPOUND_EXPR) - { - t = TREE_OPERAND (t, 1); - STRIP_NOPS (t); - } - indir_component_ref_p = false; - if (TREE_CODE (t) == COMPONENT_REF - && (TREE_CODE (TREE_OPERAND (t, 0)) == INDIRECT_REF - || TREE_CODE (TREE_OPERAND (t, 0)) == ARRAY_REF)) - { - t = TREE_OPERAND (TREE_OPERAND (t, 0), 0); - indir_component_ref_p = true; - STRIP_NOPS (t); - if (TREE_CODE (t) == POINTER_PLUS_EXPR) - t = TREE_OPERAND (t, 0); - } - if (TREE_CODE (t) == COMPONENT_REF - && OMP_CLAUSE_CODE (c) != OMP_CLAUSE__CACHE_) - { - if (type_dependent_expression_p (t)) - break; - if (TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL - && DECL_BIT_FIELD (TREE_OPERAND (t, 1))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "bit-field %qE in %qs clause", - t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - remove = true; - } - else if (!cp_omp_mappable_type (TREE_TYPE (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qE does not have a mappable type in %qs clause", - t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - cp_omp_emit_unmappable_type_notes (TREE_TYPE (t)); - remove = true; - } - while (TREE_CODE (t) == COMPONENT_REF) - { - if (TREE_TYPE (TREE_OPERAND (t, 0)) - && (TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) - == UNION_TYPE)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qE is a member of a union", t); - remove = true; - break; - } - t = TREE_OPERAND (t, 0); - if (TREE_CODE (t) == MEM_REF) - { - if (maybe_ne (mem_ref_offset (t), 0)) - error_at (OMP_CLAUSE_LOCATION (c), - "cannot dereference %qE in %qs clause", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - else - t = TREE_OPERAND (t, 0); - } - while (TREE_CODE (t) == MEM_REF - || TREE_CODE (t) == INDIRECT_REF - || TREE_CODE (t) == ARRAY_REF) - { - t = TREE_OPERAND (t, 0); - STRIP_NOPS (t); - if (TREE_CODE (t) == POINTER_PLUS_EXPR) - t = TREE_OPERAND (t, 0); - } - } - if (remove) - break; - if (REFERENCE_REF_P (t)) - t = TREE_OPERAND (t, 0); - if (VAR_P (t) || TREE_CODE (t) == PARM_DECL) - { - if (bitmap_bit_p (&map_field_head, DECL_UID (t)) - || (ort != C_ORT_ACC - && bitmap_bit_p (&map_head, DECL_UID (t)))) - goto handle_map_references; - } - } - if (!processing_template_decl - && TREE_CODE (t) == FIELD_DECL) - { - OMP_CLAUSE_DECL (c) = finish_non_static_data_member (t, NULL_TREE, - NULL_TREE); - break; - } - if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) - { - if (processing_template_decl && TREE_CODE (t) != OVERLOAD) - break; - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP - && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER - || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER - || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)) - break; - if (DECL_P (t)) - error_at (OMP_CLAUSE_LOCATION (c), - "%qD is not a variable in %qs clause", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - else - error_at (OMP_CLAUSE_LOCATION (c), - "%qE is not a variable in %qs clause", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - remove = true; - } - else if (VAR_P (t) && CP_DECL_THREAD_LOCAL_P (t)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qD is threadprivate variable in %qs clause", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - remove = true; - } - else if (!processing_template_decl - && !TYPE_REF_P (TREE_TYPE (t)) - && (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP - || (OMP_CLAUSE_MAP_KIND (c) - != GOMP_MAP_FIRSTPRIVATE_POINTER)) - && !indir_component_ref_p - && !cxx_mark_addressable (t)) - remove = true; - else if (!(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP - && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER - || (OMP_CLAUSE_MAP_KIND (c) - == GOMP_MAP_FIRSTPRIVATE_POINTER))) - && t == OMP_CLAUSE_DECL (c) - && !type_dependent_expression_p (t) - && !cp_omp_mappable_type (TYPE_REF_P (TREE_TYPE (t)) - ? TREE_TYPE (TREE_TYPE (t)) - : TREE_TYPE (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qD does not have a mappable type in %qs clause", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - cp_omp_emit_unmappable_type_notes (TREE_TYPE (t)); - remove = true; - } - else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP - && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FORCE_DEVICEPTR - && !type_dependent_expression_p (t) - && !INDIRECT_TYPE_P (TREE_TYPE (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qD is not a pointer variable", t); - remove = true; - } - else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP - && OMP_CLAUSE_MAP_IMPLICIT (c) - && (bitmap_bit_p (&map_head, DECL_UID (t)) - || bitmap_bit_p (&map_field_head, DECL_UID (t)) - || bitmap_bit_p (&map_firstprivate_head, - DECL_UID (t)))) - remove = true; - else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP - && OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_FIRSTPRIVATE_POINTER) - { - if (bitmap_bit_p (&generic_head, DECL_UID (t)) - || bitmap_bit_p (&firstprivate_head, DECL_UID (t)) - || bitmap_bit_p (&map_firstprivate_head, DECL_UID (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qD appears more than once in data clauses", t); - remove = true; - } - else if (bitmap_bit_p (&map_head, DECL_UID (t)) - && !bitmap_bit_p (&map_field_head, DECL_UID (t))) - { - if (ort == C_ORT_ACC) - error_at (OMP_CLAUSE_LOCATION (c), - "%qD appears more than once in data clauses", t); - else - error_at (OMP_CLAUSE_LOCATION (c), - "%qD appears both in data and map clauses", t); - remove = true; - } - else - bitmap_set_bit (&map_firstprivate_head, DECL_UID (t)); - } - else if (bitmap_bit_p (&map_head, DECL_UID (t)) - && !bitmap_bit_p (&map_field_head, DECL_UID (t))) - { - if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP) - error_at (OMP_CLAUSE_LOCATION (c), - "%qD appears more than once in motion clauses", t); - else if (ort == C_ORT_ACC) - error_at (OMP_CLAUSE_LOCATION (c), - "%qD appears more than once in data clauses", t); - else - error_at (OMP_CLAUSE_LOCATION (c), - "%qD appears more than once in map clauses", t); - remove = true; - } - else if (ort == C_ORT_ACC - && bitmap_bit_p (&generic_head, DECL_UID (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qD appears more than once in data clauses", t); - remove = true; - } - else if (bitmap_bit_p (&firstprivate_head, DECL_UID (t))) - { - if (ort == C_ORT_ACC) - error_at (OMP_CLAUSE_LOCATION (c), - "%qD appears more than once in data clauses", t); - else - error_at (OMP_CLAUSE_LOCATION (c), - "%qD appears both in data and map clauses", t); - remove = true; - } - else - { - bitmap_set_bit (&map_head, DECL_UID (t)); - - tree decl = OMP_CLAUSE_DECL (c); - if (t != decl - && (TREE_CODE (decl) == COMPONENT_REF - || (INDIRECT_REF_P (decl) - && TREE_CODE (TREE_OPERAND (decl, 0)) == COMPONENT_REF - && TYPE_REF_P (TREE_TYPE (TREE_OPERAND (decl, 0)))))) - bitmap_set_bit (&map_field_head, DECL_UID (t)); - } - handle_map_references: - if (!remove - && !processing_template_decl - && ort != C_ORT_DECLARE_SIMD - && TYPE_REF_P (TREE_TYPE (OMP_CLAUSE_DECL (c)))) - { - t = OMP_CLAUSE_DECL (c); - if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_MAP) - { - OMP_CLAUSE_DECL (c) = build_simple_mem_ref (t); - if (OMP_CLAUSE_SIZE (c) == NULL_TREE) - OMP_CLAUSE_SIZE (c) - = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (t))); - } - else if (OMP_CLAUSE_MAP_KIND (c) - != GOMP_MAP_FIRSTPRIVATE_POINTER - && (OMP_CLAUSE_MAP_KIND (c) - != GOMP_MAP_FIRSTPRIVATE_REFERENCE) - && (OMP_CLAUSE_MAP_KIND (c) - != GOMP_MAP_ALWAYS_POINTER) - && (OMP_CLAUSE_MAP_KIND (c) - != GOMP_MAP_ATTACH_DETACH)) - { - tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c), - OMP_CLAUSE_MAP); - if (TREE_CODE (t) == COMPONENT_REF) - OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ALWAYS_POINTER); - else - OMP_CLAUSE_SET_MAP_KIND (c2, - GOMP_MAP_FIRSTPRIVATE_REFERENCE); - OMP_CLAUSE_DECL (c2) = t; - OMP_CLAUSE_SIZE (c2) = size_zero_node; - OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (c); - OMP_CLAUSE_CHAIN (c) = c2; - OMP_CLAUSE_DECL (c) = build_simple_mem_ref (t); - if (OMP_CLAUSE_SIZE (c) == NULL_TREE) - OMP_CLAUSE_SIZE (c) - = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (t))); - c = c2; - } - } - break; - - case OMP_CLAUSE_TO_DECLARE: - case OMP_CLAUSE_LINK: - t = OMP_CLAUSE_DECL (c); - if (TREE_CODE (t) == FUNCTION_DECL - && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO_DECLARE) - ; - else if (!VAR_P (t)) - { - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO_DECLARE) - { - if (TREE_CODE (t) == TEMPLATE_ID_EXPR) - error_at (OMP_CLAUSE_LOCATION (c), - "template %qE in clause %qs", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - else if (really_overloaded_fn (t)) - error_at (OMP_CLAUSE_LOCATION (c), - "overloaded function name %qE in clause %qs", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - else - error_at (OMP_CLAUSE_LOCATION (c), - "%qE is neither a variable nor a function name " - "in clause %qs", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - } - else - error_at (OMP_CLAUSE_LOCATION (c), - "%qE is not a variable in clause %qs", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - remove = true; - } - else if (DECL_THREAD_LOCAL_P (t)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qD is threadprivate variable in %qs clause", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - remove = true; - } - else if (!cp_omp_mappable_type (TREE_TYPE (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qD does not have a mappable type in %qs clause", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - cp_omp_emit_unmappable_type_notes (TREE_TYPE (t)); - remove = true; - } - if (remove) - break; - if (bitmap_bit_p (&generic_head, DECL_UID (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qE appears more than once on the same " - "%<declare target%> directive", t); - remove = true; - } - else - bitmap_set_bit (&generic_head, DECL_UID (t)); - break; - - case OMP_CLAUSE_UNIFORM: - t = OMP_CLAUSE_DECL (c); - if (TREE_CODE (t) != PARM_DECL) - { - if (processing_template_decl) - break; - if (DECL_P (t)) - error_at (OMP_CLAUSE_LOCATION (c), - "%qD is not an argument in %<uniform%> clause", t); - else - error_at (OMP_CLAUSE_LOCATION (c), - "%qE is not an argument in %<uniform%> clause", t); - remove = true; - break; - } - /* map_head bitmap is used as uniform_head if declare_simd. */ - bitmap_set_bit (&map_head, DECL_UID (t)); - goto check_dup_generic; - - case OMP_CLAUSE_GRAINSIZE: - t = OMP_CLAUSE_GRAINSIZE_EXPR (c); - if (t == error_mark_node) - remove = true; - else if (!type_dependent_expression_p (t) - && !INTEGRAL_TYPE_P (TREE_TYPE (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<grainsize%> expression must be integral"); - remove = true; - } - else - { - t = mark_rvalue_use (t); - if (!processing_template_decl) - { - t = maybe_constant_value (t); - if (TREE_CODE (t) == INTEGER_CST - && tree_int_cst_sgn (t) != 1) - { - warning_at (OMP_CLAUSE_LOCATION (c), 0, - "%<grainsize%> value must be positive"); - t = integer_one_node; - } - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - } - OMP_CLAUSE_GRAINSIZE_EXPR (c) = t; - } - break; - - case OMP_CLAUSE_PRIORITY: - t = OMP_CLAUSE_PRIORITY_EXPR (c); - if (t == error_mark_node) - remove = true; - else if (!type_dependent_expression_p (t) - && !INTEGRAL_TYPE_P (TREE_TYPE (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<priority%> expression must be integral"); - remove = true; - } - else - { - t = mark_rvalue_use (t); - if (!processing_template_decl) - { - t = maybe_constant_value (t); - if (TREE_CODE (t) == INTEGER_CST - && tree_int_cst_sgn (t) == -1) - { - warning_at (OMP_CLAUSE_LOCATION (c), 0, - "%<priority%> value must be non-negative"); - t = integer_one_node; - } - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - } - OMP_CLAUSE_PRIORITY_EXPR (c) = t; - } - break; - - case OMP_CLAUSE_HINT: - t = OMP_CLAUSE_HINT_EXPR (c); - if (t == error_mark_node) - remove = true; - else if (!type_dependent_expression_p (t) - && !INTEGRAL_TYPE_P (TREE_TYPE (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<hint%> expression must be integral"); - remove = true; - } - else - { - t = mark_rvalue_use (t); - if (!processing_template_decl) - { - t = maybe_constant_value (t); - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - if (TREE_CODE (t) != INTEGER_CST) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<hint%> expression must be constant integer " - "expression"); - remove = true; - } - } - OMP_CLAUSE_HINT_EXPR (c) = t; - } - break; - - case OMP_CLAUSE_FILTER: - t = OMP_CLAUSE_FILTER_EXPR (c); - if (t == error_mark_node) - remove = true; - else if (!type_dependent_expression_p (t) - && !INTEGRAL_TYPE_P (TREE_TYPE (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<filter%> expression must be integral"); - remove = true; - } - else - { - t = mark_rvalue_use (t); - if (!processing_template_decl) - { - t = maybe_constant_value (t); - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - } - OMP_CLAUSE_FILTER_EXPR (c) = t; - } - break; - - case OMP_CLAUSE_IS_DEVICE_PTR: - case OMP_CLAUSE_USE_DEVICE_PTR: - field_ok = (ort & C_ORT_OMP_DECLARE_SIMD) == C_ORT_OMP; - t = OMP_CLAUSE_DECL (c); - if (!type_dependent_expression_p (t)) - { - tree type = TREE_TYPE (t); - if (!TYPE_PTR_P (type) - && (!TYPE_REF_P (type) || !TYPE_PTR_P (TREE_TYPE (type)))) - { - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_USE_DEVICE_PTR - && ort == C_ORT_OMP) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qs variable is neither a pointer " - "nor reference to pointer", - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - remove = true; - } - else if (TREE_CODE (type) != ARRAY_TYPE - && (!TYPE_REF_P (type) - || TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qs variable is neither a pointer, nor an " - "array nor reference to pointer or array", - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - remove = true; - } - } - } - goto check_dup_generic; - - case OMP_CLAUSE_USE_DEVICE_ADDR: - field_ok = true; - t = OMP_CLAUSE_DECL (c); - if (!processing_template_decl - && (VAR_P (t) || TREE_CODE (t) == PARM_DECL) - && !TYPE_REF_P (TREE_TYPE (t)) - && !cxx_mark_addressable (t)) - remove = true; - goto check_dup_generic; - - case OMP_CLAUSE_NOWAIT: - case OMP_CLAUSE_DEFAULT: - case OMP_CLAUSE_UNTIED: - case OMP_CLAUSE_COLLAPSE: - case OMP_CLAUSE_PARALLEL: - case OMP_CLAUSE_FOR: - case OMP_CLAUSE_SECTIONS: - case OMP_CLAUSE_TASKGROUP: - case OMP_CLAUSE_PROC_BIND: - case OMP_CLAUSE_DEVICE_TYPE: - case OMP_CLAUSE_NOGROUP: - case OMP_CLAUSE_THREADS: - case OMP_CLAUSE_SIMD: - case OMP_CLAUSE_DEFAULTMAP: - case OMP_CLAUSE_BIND: - case OMP_CLAUSE_AUTO: - case OMP_CLAUSE_INDEPENDENT: - case OMP_CLAUSE_SEQ: - case OMP_CLAUSE_IF_PRESENT: - case OMP_CLAUSE_FINALIZE: - case OMP_CLAUSE_NOHOST: - break; - - case OMP_CLAUSE_MERGEABLE: - mergeable_seen = true; - break; - - case OMP_CLAUSE_TILE: - for (tree list = OMP_CLAUSE_TILE_LIST (c); !remove && list; - list = TREE_CHAIN (list)) - { - t = TREE_VALUE (list); - - if (t == error_mark_node) - remove = true; - else if (!type_dependent_expression_p (t) - && !INTEGRAL_TYPE_P (TREE_TYPE (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<tile%> argument needs integral type"); - remove = true; - } - else - { - t = mark_rvalue_use (t); - if (!processing_template_decl) - { - /* Zero is used to indicate '*', we permit you - to get there via an ICE of value zero. */ - t = maybe_constant_value (t); - if (!tree_fits_shwi_p (t) - || tree_to_shwi (t) < 0) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<tile%> argument needs positive " - "integral constant"); - remove = true; - } - t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - } - } - - /* Update list item. */ - TREE_VALUE (list) = t; - } - break; - - case OMP_CLAUSE_ORDERED: - ordered_seen = true; - break; - - case OMP_CLAUSE_ORDER: - if (order_seen) - remove = true; - else - order_seen = true; - break; - - case OMP_CLAUSE_INBRANCH: - case OMP_CLAUSE_NOTINBRANCH: - if (branch_seen) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<inbranch%> clause is incompatible with " - "%<notinbranch%>"); - remove = true; - } - branch_seen = true; - break; - - case OMP_CLAUSE_INCLUSIVE: - case OMP_CLAUSE_EXCLUSIVE: - t = omp_clause_decl_field (OMP_CLAUSE_DECL (c)); - if (!t) - t = OMP_CLAUSE_DECL (c); - if (t == current_class_ptr) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<this%> allowed in OpenMP only in %<declare simd%>" - " clauses"); - remove = true; - break; - } - if (!VAR_P (t) - && TREE_CODE (t) != PARM_DECL - && TREE_CODE (t) != FIELD_DECL) - { - if (processing_template_decl && TREE_CODE (t) != OVERLOAD) - break; - if (DECL_P (t)) - error_at (OMP_CLAUSE_LOCATION (c), - "%qD is not a variable in clause %qs", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - else - error_at (OMP_CLAUSE_LOCATION (c), - "%qE is not a variable in clause %qs", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - remove = true; - } - break; - - default: - gcc_unreachable (); - } - - if (remove) - *pc = OMP_CLAUSE_CHAIN (c); - else - pc = &OMP_CLAUSE_CHAIN (c); - } - - if (reduction_seen < 0 && (ordered_seen || schedule_seen)) - reduction_seen = -2; - - for (pc = &clauses, c = clauses; c ; c = *pc) - { - enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c); - bool remove = false; - bool need_complete_type = false; - bool need_default_ctor = false; - bool need_copy_ctor = false; - bool need_copy_assignment = false; - bool need_implicitly_determined = false; - bool need_dtor = false; - tree type, inner_type; - - switch (c_kind) - { - case OMP_CLAUSE_SHARED: - need_implicitly_determined = true; - break; - case OMP_CLAUSE_PRIVATE: - need_complete_type = true; - need_default_ctor = true; - need_dtor = true; - need_implicitly_determined = true; - break; - case OMP_CLAUSE_FIRSTPRIVATE: - need_complete_type = true; - need_copy_ctor = true; - need_dtor = true; - need_implicitly_determined = true; - break; - case OMP_CLAUSE_LASTPRIVATE: - need_complete_type = true; - need_copy_assignment = true; - need_implicitly_determined = true; - break; - case OMP_CLAUSE_REDUCTION: - if (reduction_seen == -2) - OMP_CLAUSE_REDUCTION_INSCAN (c) = 0; - if (OMP_CLAUSE_REDUCTION_INSCAN (c)) - need_copy_assignment = true; - need_implicitly_determined = true; - break; - case OMP_CLAUSE_IN_REDUCTION: - case OMP_CLAUSE_TASK_REDUCTION: - case OMP_CLAUSE_INCLUSIVE: - case OMP_CLAUSE_EXCLUSIVE: - need_implicitly_determined = true; - break; - case OMP_CLAUSE_LINEAR: - if (ort != C_ORT_OMP_DECLARE_SIMD) - need_implicitly_determined = true; - else if (OMP_CLAUSE_LINEAR_VARIABLE_STRIDE (c) - && !bitmap_bit_p (&map_head, - DECL_UID (OMP_CLAUSE_LINEAR_STEP (c)))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<linear%> clause step is a parameter %qD not " - "specified in %<uniform%> clause", - OMP_CLAUSE_LINEAR_STEP (c)); - *pc = OMP_CLAUSE_CHAIN (c); - continue; - } - break; - case OMP_CLAUSE_COPYPRIVATE: - need_copy_assignment = true; - break; - case OMP_CLAUSE_COPYIN: - need_copy_assignment = true; - break; - case OMP_CLAUSE_SIMDLEN: - if (safelen - && !processing_template_decl - && tree_int_cst_lt (OMP_CLAUSE_SAFELEN_EXPR (safelen), - OMP_CLAUSE_SIMDLEN_EXPR (c))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<simdlen%> clause value is bigger than " - "%<safelen%> clause value"); - OMP_CLAUSE_SIMDLEN_EXPR (c) - = OMP_CLAUSE_SAFELEN_EXPR (safelen); - } - pc = &OMP_CLAUSE_CHAIN (c); - continue; - case OMP_CLAUSE_SCHEDULE: - if (ordered_seen - && (OMP_CLAUSE_SCHEDULE_KIND (c) - & OMP_CLAUSE_SCHEDULE_NONMONOTONIC)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<nonmonotonic%> schedule modifier specified " - "together with %<ordered%> clause"); - OMP_CLAUSE_SCHEDULE_KIND (c) - = (enum omp_clause_schedule_kind) - (OMP_CLAUSE_SCHEDULE_KIND (c) - & ~OMP_CLAUSE_SCHEDULE_NONMONOTONIC); - } - if (reduction_seen == -2) - error_at (OMP_CLAUSE_LOCATION (c), - "%qs clause specified together with %<inscan%> " - "%<reduction%> clause", "schedule"); - pc = &OMP_CLAUSE_CHAIN (c); - continue; - case OMP_CLAUSE_NOGROUP: - if (reduction_seen) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<nogroup%> clause must not be used together with " - "%<reduction%> clause"); - *pc = OMP_CLAUSE_CHAIN (c); - continue; - } - pc = &OMP_CLAUSE_CHAIN (c); - continue; - case OMP_CLAUSE_ORDERED: - if (reduction_seen == -2) - error_at (OMP_CLAUSE_LOCATION (c), - "%qs clause specified together with %<inscan%> " - "%<reduction%> clause", "ordered"); - pc = &OMP_CLAUSE_CHAIN (c); - continue; - case OMP_CLAUSE_ORDER: - if (ordered_seen) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<order%> clause must not be used together " - "with %<ordered%>"); - *pc = OMP_CLAUSE_CHAIN (c); - continue; - } - pc = &OMP_CLAUSE_CHAIN (c); - continue; - case OMP_CLAUSE_DETACH: - if (mergeable_seen) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<detach%> clause must not be used together with " - "%<mergeable%> clause"); - *pc = OMP_CLAUSE_CHAIN (c); - continue; - } - pc = &OMP_CLAUSE_CHAIN (c); - continue; - case OMP_CLAUSE_MAP: - if (target_in_reduction_seen && !processing_template_decl) - { - t = OMP_CLAUSE_DECL (c); - while (handled_component_p (t) - || TREE_CODE (t) == INDIRECT_REF - || TREE_CODE (t) == ADDR_EXPR - || TREE_CODE (t) == MEM_REF - || TREE_CODE (t) == NON_LVALUE_EXPR) - t = TREE_OPERAND (t, 0); - if (DECL_P (t) - && bitmap_bit_p (&oacc_reduction_head, DECL_UID (t))) - OMP_CLAUSE_MAP_IN_REDUCTION (c) = 1; - } - pc = &OMP_CLAUSE_CHAIN (c); - continue; - case OMP_CLAUSE_NOWAIT: - if (copyprivate_seen) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<nowait%> clause must not be used together " - "with %<copyprivate%>"); - *pc = OMP_CLAUSE_CHAIN (c); - continue; - } - /* FALLTHRU */ - default: - pc = &OMP_CLAUSE_CHAIN (c); - continue; - } - - t = OMP_CLAUSE_DECL (c); - switch (c_kind) - { - case OMP_CLAUSE_LASTPRIVATE: - if (DECL_P (t) - && !bitmap_bit_p (&firstprivate_head, DECL_UID (t))) - { - need_default_ctor = true; - need_dtor = true; - } - break; - - case OMP_CLAUSE_REDUCTION: - case OMP_CLAUSE_IN_REDUCTION: - case OMP_CLAUSE_TASK_REDUCTION: - if (allocate_seen) - { - if (TREE_CODE (t) == MEM_REF) - { - t = TREE_OPERAND (t, 0); - if (TREE_CODE (t) == POINTER_PLUS_EXPR) - t = TREE_OPERAND (t, 0); - if (TREE_CODE (t) == ADDR_EXPR - || TREE_CODE (t) == INDIRECT_REF) - t = TREE_OPERAND (t, 0); - if (DECL_P (t)) - bitmap_clear_bit (&aligned_head, DECL_UID (t)); - } - else if (TREE_CODE (t) == TREE_LIST) - { - while (TREE_CODE (t) == TREE_LIST) - t = TREE_CHAIN (t); - if (DECL_P (t)) - bitmap_clear_bit (&aligned_head, DECL_UID (t)); - t = OMP_CLAUSE_DECL (c); - } - else if (DECL_P (t)) - bitmap_clear_bit (&aligned_head, DECL_UID (t)); - t = OMP_CLAUSE_DECL (c); - } - if (processing_template_decl - && !VAR_P (t) && TREE_CODE (t) != PARM_DECL) - break; - if (finish_omp_reduction_clause (c, &need_default_ctor, - &need_dtor)) - remove = true; - else - t = OMP_CLAUSE_DECL (c); - break; - - case OMP_CLAUSE_COPYIN: - if (processing_template_decl - && !VAR_P (t) && TREE_CODE (t) != PARM_DECL) - break; - if (!VAR_P (t) || !CP_DECL_THREAD_LOCAL_P (t)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qE must be %<threadprivate%> for %<copyin%>", t); - remove = true; - } - break; - - default: - break; - } - - if (processing_template_decl - && !VAR_P (t) && TREE_CODE (t) != PARM_DECL) - { - pc = &OMP_CLAUSE_CHAIN (c); - continue; - } - - if (need_complete_type || need_copy_assignment) - { - t = require_complete_type (t); - if (t == error_mark_node) - remove = true; - else if (!processing_template_decl - && TYPE_REF_P (TREE_TYPE (t)) - && !complete_type_or_else (TREE_TYPE (TREE_TYPE (t)), t)) - remove = true; - } - if (need_implicitly_determined) - { - const char *share_name = NULL; - - if (allocate_seen - && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SHARED - && DECL_P (t)) - bitmap_clear_bit (&aligned_head, DECL_UID (t)); - - if (VAR_P (t) && CP_DECL_THREAD_LOCAL_P (t)) - share_name = "threadprivate"; - else switch (cxx_omp_predetermined_sharing_1 (t)) - { - case OMP_CLAUSE_DEFAULT_UNSPECIFIED: - break; - case OMP_CLAUSE_DEFAULT_SHARED: - if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE) - && c_omp_predefined_variable (t)) - /* The __func__ variable and similar function-local predefined - variables may be listed in a shared or firstprivate - clause. */ - break; - if (VAR_P (t) - && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE - && TREE_STATIC (t) - && cxx_omp_const_qual_no_mutable (t)) - { - tree ctx = CP_DECL_CONTEXT (t); - /* const qualified static data members without mutable - member may be specified in firstprivate clause. */ - if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx)) - break; - } - share_name = "shared"; - break; - case OMP_CLAUSE_DEFAULT_PRIVATE: - share_name = "private"; - break; - default: - gcc_unreachable (); - } - if (share_name) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qE is predetermined %qs for %qs", - omp_clause_printable_decl (t), share_name, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - remove = true; - } - else if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SHARED - && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE - && cxx_omp_const_qual_no_mutable (t)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<const%> qualified %qE without %<mutable%> member " - "may appear only in %<shared%> or %<firstprivate%> " - "clauses", omp_clause_printable_decl (t)); - remove = true; - } - } - - if (detach_seen - && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE) - && OMP_CLAUSE_DECL (c) == OMP_CLAUSE_DECL (detach_seen)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "the event handle of a %<detach%> clause " - "should not be in a data-sharing clause"); - remove = true; - } - - /* We're interested in the base element, not arrays. */ - inner_type = type = TREE_TYPE (t); - if ((need_complete_type - || need_copy_assignment - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TASK_REDUCTION) - && TYPE_REF_P (inner_type)) - inner_type = TREE_TYPE (inner_type); - while (TREE_CODE (inner_type) == ARRAY_TYPE) - inner_type = TREE_TYPE (inner_type); - - /* Check for special function availability by building a call to one. - Save the results, because later we won't be in the right context - for making these queries. */ - if (CLASS_TYPE_P (inner_type) - && COMPLETE_TYPE_P (inner_type) - && (need_default_ctor || need_copy_ctor - || need_copy_assignment || need_dtor) - && !type_dependent_expression_p (t) - && cxx_omp_create_clause_info (c, inner_type, need_default_ctor, - need_copy_ctor, need_copy_assignment, - need_dtor)) - remove = true; - - if (!remove - && c_kind == OMP_CLAUSE_SHARED - && processing_template_decl) - { - t = omp_clause_decl_field (OMP_CLAUSE_DECL (c)); - if (t) - OMP_CLAUSE_DECL (c) = t; - } - - if (remove) - *pc = OMP_CLAUSE_CHAIN (c); - else - pc = &OMP_CLAUSE_CHAIN (c); - } - - if (allocate_seen) - for (pc = &clauses, c = clauses; c ; c = *pc) - { - bool remove = false; - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_ALLOCATE - && !OMP_CLAUSE_ALLOCATE_COMBINED (c) - && DECL_P (OMP_CLAUSE_DECL (c)) - && bitmap_bit_p (&aligned_head, DECL_UID (OMP_CLAUSE_DECL (c)))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qD specified in %<allocate%> clause but not in " - "an explicit privatization clause", OMP_CLAUSE_DECL (c)); - remove = true; - } - if (remove) - *pc = OMP_CLAUSE_CHAIN (c); - else - pc = &OMP_CLAUSE_CHAIN (c); - } - - bitmap_obstack_release (NULL); - return clauses; -} - -/* Start processing OpenMP clauses that can include any - privatization clauses for non-static data members. */ - -tree -push_omp_privatization_clauses (bool ignore_next) -{ - if (omp_private_member_ignore_next) - { - omp_private_member_ignore_next = ignore_next; - return NULL_TREE; - } - omp_private_member_ignore_next = ignore_next; - if (omp_private_member_map) - omp_private_member_vec.safe_push (error_mark_node); - return push_stmt_list (); -} - -/* Revert remapping of any non-static data members since - the last push_omp_privatization_clauses () call. */ - -void -pop_omp_privatization_clauses (tree stmt) -{ - if (stmt == NULL_TREE) - return; - stmt = pop_stmt_list (stmt); - if (omp_private_member_map) - { - while (!omp_private_member_vec.is_empty ()) - { - tree t = omp_private_member_vec.pop (); - if (t == error_mark_node) - { - add_stmt (stmt); - return; - } - bool no_decl_expr = t == integer_zero_node; - if (no_decl_expr) - t = omp_private_member_vec.pop (); - tree *v = omp_private_member_map->get (t); - gcc_assert (v); - if (!no_decl_expr) - add_decl_expr (*v); - omp_private_member_map->remove (t); - } - delete omp_private_member_map; - omp_private_member_map = NULL; - } - add_stmt (stmt); -} - -/* Remember OpenMP privatization clauses mapping and clear it. - Used for lambdas. */ - -void -save_omp_privatization_clauses (vec<tree> &save) -{ - save = vNULL; - if (omp_private_member_ignore_next) - save.safe_push (integer_one_node); - omp_private_member_ignore_next = false; - if (!omp_private_member_map) - return; - - while (!omp_private_member_vec.is_empty ()) - { - tree t = omp_private_member_vec.pop (); - if (t == error_mark_node) - { - save.safe_push (t); - continue; - } - tree n = t; - if (t == integer_zero_node) - t = omp_private_member_vec.pop (); - tree *v = omp_private_member_map->get (t); - gcc_assert (v); - save.safe_push (*v); - save.safe_push (t); - if (n != t) - save.safe_push (n); - } - delete omp_private_member_map; - omp_private_member_map = NULL; -} - -/* Restore OpenMP privatization clauses mapping saved by the - above function. */ - -void -restore_omp_privatization_clauses (vec<tree> &save) -{ - gcc_assert (omp_private_member_vec.is_empty ()); - omp_private_member_ignore_next = false; - if (save.is_empty ()) - return; - if (save.length () == 1 && save[0] == integer_one_node) - { - omp_private_member_ignore_next = true; - save.release (); - return; - } - - omp_private_member_map = new hash_map <tree, tree>; - while (!save.is_empty ()) - { - tree t = save.pop (); - tree n = t; - if (t != error_mark_node) - { - if (t == integer_one_node) - { - omp_private_member_ignore_next = true; - gcc_assert (save.is_empty ()); - break; - } - if (t == integer_zero_node) - t = save.pop (); - tree &v = omp_private_member_map->get_or_insert (t); - v = save.pop (); - } - omp_private_member_vec.safe_push (t); - if (n != t) - omp_private_member_vec.safe_push (n); - } - save.release (); -} - -/* For all variables in the tree_list VARS, mark them as thread local. */ - -void -finish_omp_threadprivate (tree vars) -{ - tree t; - - /* Mark every variable in VARS to be assigned thread local storage. */ - for (t = vars; t; t = TREE_CHAIN (t)) - { - tree v = TREE_PURPOSE (t); - - if (error_operand_p (v)) - ; - else if (!VAR_P (v)) - error ("%<threadprivate%> %qD is not file, namespace " - "or block scope variable", v); - /* If V had already been marked threadprivate, it doesn't matter - whether it had been used prior to this point. */ - else if (TREE_USED (v) - && (DECL_LANG_SPECIFIC (v) == NULL - || !CP_DECL_THREADPRIVATE_P (v))) - error ("%qE declared %<threadprivate%> after first use", v); - else if (! TREE_STATIC (v) && ! DECL_EXTERNAL (v)) - error ("automatic variable %qE cannot be %<threadprivate%>", v); - else if (! COMPLETE_TYPE_P (complete_type (TREE_TYPE (v)))) - error ("%<threadprivate%> %qE has incomplete type", v); - else if (TREE_STATIC (v) && TYPE_P (CP_DECL_CONTEXT (v)) - && CP_DECL_CONTEXT (v) != current_class_type) - error ("%<threadprivate%> %qE directive not " - "in %qT definition", v, CP_DECL_CONTEXT (v)); - else - { - /* Allocate a LANG_SPECIFIC structure for V, if needed. */ - if (DECL_LANG_SPECIFIC (v) == NULL) - retrofit_lang_decl (v); - - if (! CP_DECL_THREAD_LOCAL_P (v)) - { - CP_DECL_THREAD_LOCAL_P (v) = true; - set_decl_tls_model (v, decl_default_tls_model (v)); - /* If rtl has been already set for this var, call - make_decl_rtl once again, so that encode_section_info - has a chance to look at the new decl flags. */ - if (DECL_RTL_SET_P (v)) - make_decl_rtl (v); - } - CP_DECL_THREADPRIVATE_P (v) = 1; - } - } -} - -/* Build an OpenMP structured block. */ - -tree -begin_omp_structured_block (void) -{ - return do_pushlevel (sk_omp); -} - -tree -finish_omp_structured_block (tree block) -{ - return do_poplevel (block); -} - -/* Similarly, except force the retention of the BLOCK. */ - -tree -begin_omp_parallel (void) -{ - keep_next_level (true); - return begin_omp_structured_block (); -} - -/* Generate OACC_DATA, with CLAUSES and BLOCK as its compound - statement. */ - -tree -finish_oacc_data (tree clauses, tree block) -{ - tree stmt; - - block = finish_omp_structured_block (block); - - stmt = make_node (OACC_DATA); - TREE_TYPE (stmt) = void_type_node; - OACC_DATA_CLAUSES (stmt) = clauses; - OACC_DATA_BODY (stmt) = block; - - return add_stmt (stmt); -} - -/* Generate OACC_HOST_DATA, with CLAUSES and BLOCK as its compound - statement. */ - -tree -finish_oacc_host_data (tree clauses, tree block) -{ - tree stmt; - - block = finish_omp_structured_block (block); - - stmt = make_node (OACC_HOST_DATA); - TREE_TYPE (stmt) = void_type_node; - OACC_HOST_DATA_CLAUSES (stmt) = clauses; - OACC_HOST_DATA_BODY (stmt) = block; - - return add_stmt (stmt); -} - -/* Generate OMP construct CODE, with BODY and CLAUSES as its compound - statement. */ - -tree -finish_omp_construct (enum tree_code code, tree body, tree clauses) -{ - body = finish_omp_structured_block (body); - - tree stmt = make_node (code); - TREE_TYPE (stmt) = void_type_node; - OMP_BODY (stmt) = body; - OMP_CLAUSES (stmt) = clauses; - - return add_stmt (stmt); -} - -/* Used to walk OpenMP target directive body. */ - -struct omp_target_walk_data -{ - /* Holds the 'this' expression found in current function. */ - tree current_object; - - /* True if the 'this' expression was accessed in the target body. */ - bool this_expr_accessed; - - /* For non-static functions, record which pointer-typed members were - accessed, and the whole expression. */ - hash_map<tree, tree> ptr_members_accessed; - - /* Record which lambda objects were accessed in target body. */ - hash_set<tree> lambda_objects_accessed; - - /* For lambda functions, the __closure object expression of the current - function, and the set of captured variables accessed in target body. */ - tree current_closure; - hash_set<tree> closure_vars_accessed; - - /* Local variables declared inside a BIND_EXPR, used to filter out such - variables when recording lambda_objects_accessed. */ - hash_set<tree> local_decls; -}; - -/* Helper function of finish_omp_target_clauses, called via - cp_walk_tree_without_duplicates. Traverse body of OpenMP target - directive *TP, and fill out omp_target_walk_data passed in *PTR. */ - -static tree -finish_omp_target_clauses_r (tree *tp, int *walk_subtrees, void *ptr) -{ - tree t = *tp; - struct omp_target_walk_data *data = (struct omp_target_walk_data *) ptr; - tree current_object = data->current_object; - tree current_closure = data->current_closure; - - /* References inside of these expression codes shouldn't incur any - form of mapping, so return early. */ - if (TREE_CODE (t) == SIZEOF_EXPR - || TREE_CODE (t) == ALIGNOF_EXPR) - { - *walk_subtrees = 0; - return NULL_TREE; - } - - if (TREE_CODE (t) == OMP_CLAUSE) - return NULL_TREE; - - if (current_object) - { - tree this_expr = TREE_OPERAND (current_object, 0); - - if (operand_equal_p (t, this_expr)) - { - data->this_expr_accessed = true; - *walk_subtrees = 0; - return NULL_TREE; - } - - if (TREE_CODE (t) == COMPONENT_REF - && POINTER_TYPE_P (TREE_TYPE (t)) - && operand_equal_p (TREE_OPERAND (t, 0), current_object) - && TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL) - { - data->this_expr_accessed = true; - tree fld = TREE_OPERAND (t, 1); - if (data->ptr_members_accessed.get (fld) == NULL) - { - if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE) - t = convert_from_reference (t); - data->ptr_members_accessed.put (fld, t); - } - *walk_subtrees = 0; - return NULL_TREE; - } - } - - /* When the current_function_decl is a lambda function, the closure object - argument's type seems to not yet have fields layed out, so a recording - of DECL_VALUE_EXPRs during the target body walk seems the only way to - find them. */ - if (current_closure - && (TREE_CODE (t) == VAR_DECL - || TREE_CODE (t) == PARM_DECL - || TREE_CODE (t) == RESULT_DECL) - && DECL_HAS_VALUE_EXPR_P (t) - && TREE_CODE (DECL_VALUE_EXPR (t)) == COMPONENT_REF - && operand_equal_p (current_closure, - TREE_OPERAND (DECL_VALUE_EXPR (t), 0))) - { - if (!data->closure_vars_accessed.contains (t)) - data->closure_vars_accessed.add (t); - *walk_subtrees = 0; - return NULL_TREE; - } - - if (TREE_CODE (t) == BIND_EXPR) - { - tree block = BIND_EXPR_BLOCK (t); - for (tree var = BLOCK_VARS (block); var; var = DECL_CHAIN (var)) - if (!data->local_decls.contains (var)) - data->local_decls.add (var); - return NULL_TREE; - } - - if (TREE_TYPE (t) && LAMBDA_TYPE_P (TREE_TYPE (t))) - { - tree lt = TREE_TYPE (t); - gcc_assert (CLASS_TYPE_P (lt)); - - if (!data->lambda_objects_accessed.contains (t) - /* Do not prepare to create target maps for locally declared - lambdas or anonymous ones. */ - && !data->local_decls.contains (t) - && TREE_CODE (t) != TARGET_EXPR) - data->lambda_objects_accessed.add (t); - *walk_subtrees = 0; - return NULL_TREE; - } - - return NULL_TREE; -} - -/* Helper function for finish_omp_target, and also from tsubst_expr. - Create additional clauses for mapping of non-static members, lambda objects, - etc. */ - -void -finish_omp_target_clauses (location_t loc, tree body, tree *clauses_ptr) -{ - omp_target_walk_data data; - data.this_expr_accessed = false; - - tree ct = current_nonlambda_class_type (); - if (ct) - { - tree object = maybe_dummy_object (ct, NULL); - object = maybe_resolve_dummy (object, true); - data.current_object = object; - } - else - data.current_object = NULL_TREE; - - if (DECL_LAMBDA_FUNCTION_P (current_function_decl)) - { - tree closure = DECL_ARGUMENTS (current_function_decl); - data.current_closure = build_indirect_ref (loc, closure, RO_UNARY_STAR); - } - else - data.current_closure = NULL_TREE; - - cp_walk_tree_without_duplicates (&body, finish_omp_target_clauses_r, &data); - - auto_vec<tree, 16> new_clauses; - - tree omp_target_this_expr = NULL_TREE; - tree *explicit_this_deref_map = NULL; - if (data.this_expr_accessed) - { - omp_target_this_expr = TREE_OPERAND (data.current_object, 0); - - /* See if explicit user-specified map(this[:]) clause already exists. - If not, we create an implicit map(tofrom:this[:1]) clause. */ - for (tree *cp = clauses_ptr; *cp; cp = &OMP_CLAUSE_CHAIN (*cp)) - if (OMP_CLAUSE_CODE (*cp) == OMP_CLAUSE_MAP - && (TREE_CODE (OMP_CLAUSE_DECL (*cp)) == INDIRECT_REF - || TREE_CODE (OMP_CLAUSE_DECL (*cp)) == MEM_REF) - && operand_equal_p (TREE_OPERAND (OMP_CLAUSE_DECL (*cp), 0), - omp_target_this_expr)) - { - explicit_this_deref_map = cp; - break; - } - } - - if (DECL_LAMBDA_FUNCTION_P (current_function_decl) - && (data.this_expr_accessed - || !data.closure_vars_accessed.is_empty ())) - { - /* For lambda functions, we need to first create a copy of the - __closure object. */ - tree closure = DECL_ARGUMENTS (current_function_decl); - tree c = build_omp_clause (loc, OMP_CLAUSE_MAP); - OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TO); - OMP_CLAUSE_DECL (c) - = build_indirect_ref (loc, closure, RO_UNARY_STAR); - OMP_CLAUSE_SIZE (c) - = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (closure))); - new_clauses.safe_push (c); - - tree closure_obj = OMP_CLAUSE_DECL (c); - tree closure_type = TREE_TYPE (closure_obj); - - gcc_assert (LAMBDA_TYPE_P (closure_type) - && CLASS_TYPE_P (closure_type)); - - tree c2 = build_omp_clause (loc, OMP_CLAUSE_MAP); - OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER); - OMP_CLAUSE_DECL (c2) = closure; - OMP_CLAUSE_SIZE (c2) = size_zero_node; - new_clauses.safe_push (c2); - } - - if (data.this_expr_accessed) - { - /* If the this-expr was accessed, create a map(*this) clause. */ - enum gomp_map_kind kind = GOMP_MAP_TOFROM; - if (explicit_this_deref_map) - { - tree this_map = *explicit_this_deref_map; - tree nc = OMP_CLAUSE_CHAIN (this_map); - gcc_assert (nc != NULL_TREE - && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP - && (OMP_CLAUSE_MAP_KIND (nc) - == GOMP_MAP_FIRSTPRIVATE_POINTER)); - kind = OMP_CLAUSE_MAP_KIND (this_map); - /* Remove the original 'map(*this) map(firstprivate_ptr:this)' - two-map sequence away from the chain. */ - *explicit_this_deref_map = OMP_CLAUSE_CHAIN (nc); - } - tree c = build_omp_clause (loc, OMP_CLAUSE_MAP); - OMP_CLAUSE_SET_MAP_KIND (c, kind); - OMP_CLAUSE_DECL (c) - = build_indirect_ref (loc, omp_target_this_expr, RO_UNARY_STAR); - OMP_CLAUSE_SIZE (c) - = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (omp_target_this_expr))); - new_clauses.safe_push (c); - - /* If we're in a lambda function, the this-pointer will actually be - '__closure->this', a mapped member of __closure, hence always_pointer. - Otherwise it's a firstprivate pointer. */ - enum gomp_map_kind ptr_kind - = (DECL_LAMBDA_FUNCTION_P (current_function_decl) - ? GOMP_MAP_ALWAYS_POINTER - : GOMP_MAP_FIRSTPRIVATE_POINTER); - c = build_omp_clause (loc, OMP_CLAUSE_MAP); - OMP_CLAUSE_SET_MAP_KIND (c, ptr_kind); - OMP_CLAUSE_DECL (c) = omp_target_this_expr; - OMP_CLAUSE_SIZE (c) = size_zero_node; - new_clauses.safe_push (c); - } - - if (DECL_LAMBDA_FUNCTION_P (current_function_decl)) - { - if (omp_target_this_expr) - { - STRIP_NOPS (omp_target_this_expr); - gcc_assert (DECL_HAS_VALUE_EXPR_P (omp_target_this_expr)); - omp_target_this_expr = DECL_VALUE_EXPR (omp_target_this_expr); - } - - for (hash_set<tree>::iterator i = data.closure_vars_accessed.begin (); - i != data.closure_vars_accessed.end (); ++i) - { - tree orig_decl = *i; - tree closure_expr = DECL_VALUE_EXPR (orig_decl); - - if (TREE_CODE (TREE_TYPE (orig_decl)) == POINTER_TYPE - || TREE_CODE (TREE_TYPE (orig_decl)) == REFERENCE_TYPE) - { - /* this-pointer is processed above, outside this loop. */ - if (omp_target_this_expr - && operand_equal_p (closure_expr, omp_target_this_expr)) - continue; - - bool ptr_p = TREE_CODE (TREE_TYPE (orig_decl)) == POINTER_TYPE; - enum gomp_map_kind kind, ptr_kind, nc_kind; - tree size; - - if (ptr_p) - { - /* For pointers, default mapped as zero-length array - section. */ - kind = GOMP_MAP_ALLOC; - nc_kind = GOMP_MAP_FIRSTPRIVATE_POINTER; - ptr_kind = GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION; - size = size_zero_node; - } - else - { - /* For references, default mapped as appearing on map - clause. */ - kind = GOMP_MAP_TOFROM; - nc_kind = GOMP_MAP_FIRSTPRIVATE_REFERENCE; - ptr_kind = GOMP_MAP_ALWAYS_POINTER; - size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (closure_expr))); - } - - for (tree *p = clauses_ptr; *p; p = &OMP_CLAUSE_CHAIN (*p)) - if (OMP_CLAUSE_CODE (*p) == OMP_CLAUSE_MAP - && (TREE_CODE (OMP_CLAUSE_DECL (*p)) == INDIRECT_REF - || TREE_CODE (OMP_CLAUSE_DECL (*p)) == MEM_REF) - && operand_equal_p (TREE_OPERAND (OMP_CLAUSE_DECL (*p), 0), - orig_decl)) - { - /* If this was already specified by user as a map, - save the user specified map kind, delete the - "map(*ptr/ref), map(firstprivate ptr/ref)" sequence, - and insert our own sequence: - "map(*__closure->ptr/ref), map(<ptr_kind>:__closure->ref" - */ - tree nc = OMP_CLAUSE_CHAIN (*p); - gcc_assert (nc != NULL_TREE - && OMP_CLAUSE_CODE (nc) == OMP_CLAUSE_MAP - && OMP_CLAUSE_MAP_KIND (nc) == nc_kind); - /* Update with user specified kind and size. */ - kind = OMP_CLAUSE_MAP_KIND (*p); - size = OMP_CLAUSE_SIZE (*p); - *p = OMP_CLAUSE_CHAIN (nc); - break; - } - - tree c = build_omp_clause (loc, OMP_CLAUSE_MAP); - OMP_CLAUSE_SET_MAP_KIND (c, kind); - OMP_CLAUSE_DECL (c) - = build_indirect_ref (loc, closure_expr, RO_UNARY_STAR); - OMP_CLAUSE_SIZE (c) = size; - if (ptr_p) - OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c) = 1; - new_clauses.safe_push (c); - - c = build_omp_clause (loc, OMP_CLAUSE_MAP); - OMP_CLAUSE_SET_MAP_KIND (c, ptr_kind); - OMP_CLAUSE_DECL (c) = closure_expr; - OMP_CLAUSE_SIZE (c) = size_zero_node; - new_clauses.safe_push (c); - } - } - } - - if (!data.ptr_members_accessed.is_empty ()) - for (hash_map<tree, tree>::iterator i = data.ptr_members_accessed.begin (); - i != data.ptr_members_accessed.end (); ++i) - { - /* For each referenced member that is of pointer or reference-to-pointer - type, create the equivalent of map(alloc:this->ptr[:0]). */ - tree field_decl = (*i).first; - tree ptr_member = (*i).second; - - for (tree c = *clauses_ptr; c; c = OMP_CLAUSE_CHAIN (c)) - { - /* If map(this->ptr[:N] already exists, avoid creating another - such map. */ - tree decl = OMP_CLAUSE_DECL (c); - if ((TREE_CODE (decl) == INDIRECT_REF - || TREE_CODE (decl) == MEM_REF) - && operand_equal_p (TREE_OPERAND (decl, 0), ptr_member)) - goto next_ptr_member; - } - - if (!cxx_mark_addressable (ptr_member)) - gcc_unreachable (); - - if (TREE_CODE (TREE_TYPE (field_decl)) == REFERENCE_TYPE) - { - /* For reference to pointers, we need to map the referenced - pointer first for things to be correct. */ - tree ptr_member_type = TREE_TYPE (ptr_member); - - /* Map pointer target as zero-length array section. */ - tree c = build_omp_clause (loc, OMP_CLAUSE_MAP); - OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALLOC); - OMP_CLAUSE_DECL (c) - = build1 (INDIRECT_REF, TREE_TYPE (ptr_member_type), ptr_member); - OMP_CLAUSE_SIZE (c) = size_zero_node; - OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c) = 1; - - /* Map pointer to zero-length array section. */ - tree c2 = build_omp_clause (loc, OMP_CLAUSE_MAP); - OMP_CLAUSE_SET_MAP_KIND - (c2, GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION); - OMP_CLAUSE_DECL (c2) = ptr_member; - OMP_CLAUSE_SIZE (c2) = size_zero_node; - - /* Attach reference-to-pointer field to pointer. */ - tree c3 = build_omp_clause (loc, OMP_CLAUSE_MAP); - OMP_CLAUSE_SET_MAP_KIND (c3, GOMP_MAP_ATTACH); - OMP_CLAUSE_DECL (c3) = TREE_OPERAND (ptr_member, 0); - OMP_CLAUSE_SIZE (c3) = size_zero_node; - - new_clauses.safe_push (c); - new_clauses.safe_push (c2); - new_clauses.safe_push (c3); - } - else if (TREE_CODE (TREE_TYPE (field_decl)) == POINTER_TYPE) - { - /* Map pointer target as zero-length array section. */ - tree c = build_omp_clause (loc, OMP_CLAUSE_MAP); - OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALLOC); - OMP_CLAUSE_DECL (c) = build_indirect_ref (loc, ptr_member, - RO_UNARY_STAR); - OMP_CLAUSE_SIZE (c) = size_zero_node; - OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c) = 1; - - /* Attach zero-length array section to pointer. */ - tree c2 = build_omp_clause (loc, OMP_CLAUSE_MAP); - OMP_CLAUSE_SET_MAP_KIND - (c2, GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION); - OMP_CLAUSE_DECL (c2) = ptr_member; - OMP_CLAUSE_SIZE (c2) = size_zero_node; - - new_clauses.safe_push (c); - new_clauses.safe_push (c2); - } - else - gcc_unreachable (); - - next_ptr_member: - ; - } - - for (hash_set<tree>::iterator i = data.lambda_objects_accessed.begin (); - i != data.lambda_objects_accessed.end (); ++i) - { - tree lobj = *i; - if (TREE_CODE (lobj) == TARGET_EXPR) - lobj = TREE_OPERAND (lobj, 0); - - tree lt = TREE_TYPE (lobj); - gcc_assert (LAMBDA_TYPE_P (lt) && CLASS_TYPE_P (lt)); - - tree lc = build_omp_clause (loc, OMP_CLAUSE_MAP); - OMP_CLAUSE_SET_MAP_KIND (lc, GOMP_MAP_TO); - OMP_CLAUSE_DECL (lc) = lobj; - OMP_CLAUSE_SIZE (lc) = TYPE_SIZE_UNIT (lt); - new_clauses.safe_push (lc); - - for (tree fld = TYPE_FIELDS (lt); fld; fld = DECL_CHAIN (fld)) - { - if (TREE_CODE (TREE_TYPE (fld)) == POINTER_TYPE) - { - tree exp = build3 (COMPONENT_REF, TREE_TYPE (fld), - lobj, fld, NULL_TREE); - tree c = build_omp_clause (loc, OMP_CLAUSE_MAP); - OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALLOC); - OMP_CLAUSE_DECL (c) - = build_indirect_ref (loc, exp, RO_UNARY_STAR); - OMP_CLAUSE_SIZE (c) = size_zero_node; - OMP_CLAUSE_MAP_MAYBE_ZERO_LENGTH_ARRAY_SECTION (c) = 1; - new_clauses.safe_push (c); - - c = build_omp_clause (loc, OMP_CLAUSE_MAP); - OMP_CLAUSE_SET_MAP_KIND - (c, GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION); - OMP_CLAUSE_DECL (c) = exp; - OMP_CLAUSE_SIZE (c) = size_zero_node; - new_clauses.safe_push (c); - } - else if (TREE_CODE (TREE_TYPE (fld)) == REFERENCE_TYPE) - { - tree exp = build3 (COMPONENT_REF, TREE_TYPE (fld), - lobj, fld, NULL_TREE); - tree c = build_omp_clause (loc, OMP_CLAUSE_MAP); - OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_TOFROM); - OMP_CLAUSE_DECL (c) - = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (exp)), exp); - OMP_CLAUSE_SIZE (c) - = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (exp))); - new_clauses.safe_push (c); - - c = build_omp_clause (loc, OMP_CLAUSE_MAP); - OMP_CLAUSE_SET_MAP_KIND (c, GOMP_MAP_ALWAYS_POINTER); - OMP_CLAUSE_DECL (c) = exp; - OMP_CLAUSE_SIZE (c) = size_zero_node; - new_clauses.safe_push (c); - } - } - } - - tree c = *clauses_ptr; - for (int i = new_clauses.length () - 1; i >= 0; i--) - { - OMP_CLAUSE_CHAIN (new_clauses[i]) = c; - c = new_clauses[i]; - } - *clauses_ptr = c; -} - -/* Called from cp_parser_omp_target. Create additional implicit clauses for - OpenMP target directives, and do sanity checks. */ - -tree -finish_omp_target (location_t loc, tree clauses, tree body, bool combined_p) -{ - if (!processing_template_decl) - finish_omp_target_clauses (loc, body, &clauses); - - tree stmt = make_node (OMP_TARGET); - TREE_TYPE (stmt) = void_type_node; - OMP_TARGET_CLAUSES (stmt) = clauses; - OMP_TARGET_BODY (stmt) = body; - OMP_TARGET_COMBINED (stmt) = combined_p; - SET_EXPR_LOCATION (stmt, loc); - - tree c = clauses; - while (c) - { - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP) - switch (OMP_CLAUSE_MAP_KIND (c)) - { - case GOMP_MAP_TO: - case GOMP_MAP_ALWAYS_TO: - case GOMP_MAP_FROM: - case GOMP_MAP_ALWAYS_FROM: - case GOMP_MAP_TOFROM: - case GOMP_MAP_ALWAYS_TOFROM: - case GOMP_MAP_ALLOC: - case GOMP_MAP_FIRSTPRIVATE_POINTER: - case GOMP_MAP_FIRSTPRIVATE_REFERENCE: - case GOMP_MAP_ALWAYS_POINTER: - case GOMP_MAP_ATTACH_DETACH: - case GOMP_MAP_ATTACH: - case GOMP_MAP_ATTACH_ZERO_LENGTH_ARRAY_SECTION: - case GOMP_MAP_POINTER_TO_ZERO_LENGTH_ARRAY_SECTION: - break; - default: - error_at (OMP_CLAUSE_LOCATION (c), - "%<#pragma omp target%> with map-type other " - "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> " - "on %<map%> clause"); - break; - } - c = OMP_CLAUSE_CHAIN (c); - } - return add_stmt (stmt); -} - -tree -finish_omp_parallel (tree clauses, tree body) -{ - tree stmt; - - body = finish_omp_structured_block (body); - - stmt = make_node (OMP_PARALLEL); - TREE_TYPE (stmt) = void_type_node; - OMP_PARALLEL_CLAUSES (stmt) = clauses; - OMP_PARALLEL_BODY (stmt) = body; - - return add_stmt (stmt); -} - -tree -begin_omp_task (void) -{ - keep_next_level (true); - return begin_omp_structured_block (); -} - -tree -finish_omp_task (tree clauses, tree body) -{ - tree stmt; - - body = finish_omp_structured_block (body); - - stmt = make_node (OMP_TASK); - TREE_TYPE (stmt) = void_type_node; - OMP_TASK_CLAUSES (stmt) = clauses; - OMP_TASK_BODY (stmt) = body; - - return add_stmt (stmt); -} - -/* Helper function for finish_omp_for. Convert Ith random access iterator - into integral iterator. Return FALSE if successful. */ - -static bool -handle_omp_for_class_iterator (int i, location_t locus, enum tree_code code, - tree declv, tree orig_declv, tree initv, - tree condv, tree incrv, tree *body, - tree *pre_body, tree &clauses, - int collapse, int ordered) -{ - tree diff, iter_init, iter_incr = NULL, last; - tree incr_var = NULL, orig_pre_body, orig_body, c; - tree decl = TREE_VEC_ELT (declv, i); - tree init = TREE_VEC_ELT (initv, i); - tree cond = TREE_VEC_ELT (condv, i); - tree incr = TREE_VEC_ELT (incrv, i); - tree iter = decl; - location_t elocus = locus; - - if (init && EXPR_HAS_LOCATION (init)) - elocus = EXPR_LOCATION (init); - - switch (TREE_CODE (cond)) - { - case GT_EXPR: - case GE_EXPR: - case LT_EXPR: - case LE_EXPR: - case NE_EXPR: - if (TREE_OPERAND (cond, 1) == iter) - cond = build2 (swap_tree_comparison (TREE_CODE (cond)), - TREE_TYPE (cond), iter, TREE_OPERAND (cond, 0)); - if (TREE_OPERAND (cond, 0) != iter) - cond = error_mark_node; - else - { - tree tem = build_x_binary_op (EXPR_LOCATION (cond), - TREE_CODE (cond), - iter, ERROR_MARK, - TREE_OPERAND (cond, 1), ERROR_MARK, - NULL_TREE, NULL, tf_warning_or_error); - if (error_operand_p (tem)) - return true; - } - break; - default: - cond = error_mark_node; - break; - } - if (cond == error_mark_node) - { - error_at (elocus, "invalid controlling predicate"); - return true; - } - diff = build_x_binary_op (elocus, MINUS_EXPR, - TREE_OPERAND (cond, 1), ERROR_MARK, - iter, ERROR_MARK, - NULL_TREE, NULL, tf_warning_or_error); - diff = cp_fully_fold (diff); - if (error_operand_p (diff)) - return true; - if (TREE_CODE (TREE_TYPE (diff)) != INTEGER_TYPE) - { - error_at (elocus, "difference between %qE and %qD does not have integer type", - TREE_OPERAND (cond, 1), iter); - return true; - } - if (!c_omp_check_loop_iv_exprs (locus, code, orig_declv, i, - TREE_VEC_ELT (declv, i), NULL_TREE, - cond, cp_walk_subtrees)) - return true; - - switch (TREE_CODE (incr)) - { - case PREINCREMENT_EXPR: - case PREDECREMENT_EXPR: - case POSTINCREMENT_EXPR: - case POSTDECREMENT_EXPR: - if (TREE_OPERAND (incr, 0) != iter) - { - incr = error_mark_node; - break; - } - iter_incr = build_x_unary_op (EXPR_LOCATION (incr), - TREE_CODE (incr), iter, - NULL_TREE, tf_warning_or_error); - if (error_operand_p (iter_incr)) - return true; - else if (TREE_CODE (incr) == PREINCREMENT_EXPR - || TREE_CODE (incr) == POSTINCREMENT_EXPR) - incr = integer_one_node; - else - incr = integer_minus_one_node; - break; - case MODIFY_EXPR: - if (TREE_OPERAND (incr, 0) != iter) - incr = error_mark_node; - else if (TREE_CODE (TREE_OPERAND (incr, 1)) == PLUS_EXPR - || TREE_CODE (TREE_OPERAND (incr, 1)) == MINUS_EXPR) - { - tree rhs = TREE_OPERAND (incr, 1); - if (TREE_OPERAND (rhs, 0) == iter) - { - if (TREE_CODE (TREE_TYPE (TREE_OPERAND (rhs, 1))) - != INTEGER_TYPE) - incr = error_mark_node; - else - { - iter_incr = build_x_modify_expr (EXPR_LOCATION (rhs), - iter, TREE_CODE (rhs), - TREE_OPERAND (rhs, 1), - NULL_TREE, - tf_warning_or_error); - if (error_operand_p (iter_incr)) - return true; - incr = TREE_OPERAND (rhs, 1); - incr = cp_convert (TREE_TYPE (diff), incr, - tf_warning_or_error); - if (TREE_CODE (rhs) == MINUS_EXPR) - { - incr = build1 (NEGATE_EXPR, TREE_TYPE (diff), incr); - incr = fold_simple (incr); - } - if (TREE_CODE (incr) != INTEGER_CST - && (TREE_CODE (incr) != NOP_EXPR - || (TREE_CODE (TREE_OPERAND (incr, 0)) - != INTEGER_CST))) - iter_incr = NULL; - } - } - else if (TREE_OPERAND (rhs, 1) == iter) - { - if (TREE_CODE (TREE_TYPE (TREE_OPERAND (rhs, 0))) != INTEGER_TYPE - || TREE_CODE (rhs) != PLUS_EXPR) - incr = error_mark_node; - else - { - iter_incr = build_x_binary_op (EXPR_LOCATION (rhs), - PLUS_EXPR, - TREE_OPERAND (rhs, 0), - ERROR_MARK, iter, - ERROR_MARK, NULL_TREE, NULL, - tf_warning_or_error); - if (error_operand_p (iter_incr)) - return true; - iter_incr = build_x_modify_expr (EXPR_LOCATION (rhs), - iter, NOP_EXPR, - iter_incr, NULL_TREE, - tf_warning_or_error); - if (error_operand_p (iter_incr)) - return true; - incr = TREE_OPERAND (rhs, 0); - iter_incr = NULL; - } - } - else - incr = error_mark_node; - } - else - incr = error_mark_node; - break; - default: - incr = error_mark_node; - break; - } - - if (incr == error_mark_node) - { - error_at (elocus, "invalid increment expression"); - return true; - } - - incr = cp_convert (TREE_TYPE (diff), incr, tf_warning_or_error); - incr = cp_fully_fold (incr); - tree loop_iv_seen = NULL_TREE; - for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c)) - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE - && OMP_CLAUSE_DECL (c) == iter) - { - if (code == OMP_TASKLOOP || code == OMP_LOOP) - { - loop_iv_seen = c; - OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c) = 1; - } - break; - } - else if ((code == OMP_TASKLOOP || code == OMP_LOOP) - && OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE - && OMP_CLAUSE_DECL (c) == iter) - { - loop_iv_seen = c; - if (code == OMP_TASKLOOP) - OMP_CLAUSE_PRIVATE_TASKLOOP_IV (c) = 1; - } - - decl = create_temporary_var (TREE_TYPE (diff)); - pushdecl (decl); - add_decl_expr (decl); - last = create_temporary_var (TREE_TYPE (diff)); - pushdecl (last); - add_decl_expr (last); - if (c && iter_incr == NULL && TREE_CODE (incr) != INTEGER_CST - && (!ordered || (i < collapse && collapse > 1))) - { - incr_var = create_temporary_var (TREE_TYPE (diff)); - pushdecl (incr_var); - add_decl_expr (incr_var); - } - gcc_assert (stmts_are_full_exprs_p ()); - tree diffvar = NULL_TREE; - if (code == OMP_TASKLOOP) - { - if (!loop_iv_seen) - { - tree ivc = build_omp_clause (locus, OMP_CLAUSE_FIRSTPRIVATE); - OMP_CLAUSE_DECL (ivc) = iter; - cxx_omp_finish_clause (ivc, NULL, false); - OMP_CLAUSE_CHAIN (ivc) = clauses; - clauses = ivc; - } - tree lvc = build_omp_clause (locus, OMP_CLAUSE_FIRSTPRIVATE); - OMP_CLAUSE_DECL (lvc) = last; - OMP_CLAUSE_CHAIN (lvc) = clauses; - clauses = lvc; - diffvar = create_temporary_var (TREE_TYPE (diff)); - pushdecl (diffvar); - add_decl_expr (diffvar); - } - else if (code == OMP_LOOP) - { - if (!loop_iv_seen) - { - /* While iterators on the loop construct are predetermined - lastprivate, if the decl is not declared inside of the - loop, OMP_CLAUSE_LASTPRIVATE should have been added - already. */ - loop_iv_seen = build_omp_clause (locus, OMP_CLAUSE_FIRSTPRIVATE); - OMP_CLAUSE_DECL (loop_iv_seen) = iter; - OMP_CLAUSE_CHAIN (loop_iv_seen) = clauses; - clauses = loop_iv_seen; - } - else if (OMP_CLAUSE_CODE (loop_iv_seen) == OMP_CLAUSE_PRIVATE) - { - OMP_CLAUSE_PRIVATE_DEBUG (loop_iv_seen) = 0; - OMP_CLAUSE_PRIVATE_OUTER_REF (loop_iv_seen) = 0; - OMP_CLAUSE_CODE (loop_iv_seen) = OMP_CLAUSE_FIRSTPRIVATE; - } - if (OMP_CLAUSE_CODE (loop_iv_seen) == OMP_CLAUSE_FIRSTPRIVATE) - cxx_omp_finish_clause (loop_iv_seen, NULL, false); - } - - orig_pre_body = *pre_body; - *pre_body = push_stmt_list (); - if (orig_pre_body) - add_stmt (orig_pre_body); - if (init != NULL) - finish_expr_stmt (build_x_modify_expr (elocus, - iter, NOP_EXPR, init, - NULL_TREE, tf_warning_or_error)); - init = build_int_cst (TREE_TYPE (diff), 0); - if (c && iter_incr == NULL - && (!ordered || (i < collapse && collapse > 1))) - { - if (incr_var) - { - finish_expr_stmt (build_x_modify_expr (elocus, - incr_var, NOP_EXPR, - incr, NULL_TREE, - tf_warning_or_error)); - incr = incr_var; - } - iter_incr = build_x_modify_expr (elocus, - iter, PLUS_EXPR, incr, - NULL_TREE, tf_warning_or_error); - } - if (c && ordered && i < collapse && collapse > 1) - iter_incr = incr; - finish_expr_stmt (build_x_modify_expr (elocus, - last, NOP_EXPR, init, - NULL_TREE, tf_warning_or_error)); - if (diffvar) - { - finish_expr_stmt (build_x_modify_expr (elocus, - diffvar, NOP_EXPR, - diff, NULL_TREE, tf_warning_or_error)); - diff = diffvar; - } - *pre_body = pop_stmt_list (*pre_body); - - cond = cp_build_binary_op (elocus, - TREE_CODE (cond), decl, diff, - tf_warning_or_error); - incr = build_modify_expr (elocus, decl, NULL_TREE, PLUS_EXPR, - elocus, incr, NULL_TREE); - - orig_body = *body; - *body = push_stmt_list (); - iter_init = build2 (MINUS_EXPR, TREE_TYPE (diff), decl, last); - iter_init = build_x_modify_expr (elocus, - iter, PLUS_EXPR, iter_init, - NULL_TREE, tf_warning_or_error); - if (iter_init != error_mark_node) - iter_init = build1 (NOP_EXPR, void_type_node, iter_init); - finish_expr_stmt (iter_init); - finish_expr_stmt (build_x_modify_expr (elocus, - last, NOP_EXPR, decl, - NULL_TREE, tf_warning_or_error)); - add_stmt (orig_body); - *body = pop_stmt_list (*body); - - if (c) - { - OMP_CLAUSE_LASTPRIVATE_STMT (c) = push_stmt_list (); - if (!ordered) - finish_expr_stmt (iter_incr); - else - { - iter_init = decl; - if (i < collapse && collapse > 1 && !error_operand_p (iter_incr)) - iter_init = build2 (PLUS_EXPR, TREE_TYPE (diff), - iter_init, iter_incr); - iter_init = build2 (MINUS_EXPR, TREE_TYPE (diff), iter_init, last); - iter_init = build_x_modify_expr (elocus, - iter, PLUS_EXPR, iter_init, - NULL_TREE, tf_warning_or_error); - if (iter_init != error_mark_node) - iter_init = build1 (NOP_EXPR, void_type_node, iter_init); - finish_expr_stmt (iter_init); - } - OMP_CLAUSE_LASTPRIVATE_STMT (c) - = pop_stmt_list (OMP_CLAUSE_LASTPRIVATE_STMT (c)); - } - - if (TREE_CODE (TREE_VEC_ELT (orig_declv, i)) == TREE_LIST) - { - tree t = TREE_VEC_ELT (orig_declv, i); - gcc_assert (TREE_PURPOSE (t) == NULL_TREE - && TREE_VALUE (t) == NULL_TREE - && TREE_CODE (TREE_CHAIN (t)) == TREE_VEC); - TREE_PURPOSE (t) = TREE_VEC_ELT (declv, i); - TREE_VALUE (t) = last; - } - else - TREE_VEC_ELT (orig_declv, i) - = tree_cons (TREE_VEC_ELT (declv, i), last, NULL_TREE); - TREE_VEC_ELT (declv, i) = decl; - TREE_VEC_ELT (initv, i) = init; - TREE_VEC_ELT (condv, i) = cond; - TREE_VEC_ELT (incrv, i) = incr; - - return false; -} - -/* Build and validate an OMP_FOR statement. CLAUSES, BODY, COND, INCR - are directly for their associated operands in the statement. DECL - and INIT are a combo; if DECL is NULL then INIT ought to be a - MODIFY_EXPR, and the DECL should be extracted. PRE_BODY are - optional statements that need to go before the loop into its - sk_omp scope. */ - -tree -finish_omp_for (location_t locus, enum tree_code code, tree declv, - tree orig_declv, tree initv, tree condv, tree incrv, - tree body, tree pre_body, vec<tree> *orig_inits, tree clauses) -{ - tree omp_for = NULL, orig_incr = NULL; - tree decl = NULL, init, cond, incr; - location_t elocus; - int i; - int collapse = 1; - int ordered = 0; - - gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (initv)); - gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (condv)); - gcc_assert (TREE_VEC_LENGTH (declv) == TREE_VEC_LENGTH (incrv)); - if (TREE_VEC_LENGTH (declv) > 1) - { - tree c; - - c = omp_find_clause (clauses, OMP_CLAUSE_TILE); - if (c) - collapse = list_length (OMP_CLAUSE_TILE_LIST (c)); - else - { - c = omp_find_clause (clauses, OMP_CLAUSE_COLLAPSE); - if (c) - collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (c)); - if (collapse != TREE_VEC_LENGTH (declv)) - ordered = TREE_VEC_LENGTH (declv); - } - } - for (i = 0; i < TREE_VEC_LENGTH (declv); i++) - { - decl = TREE_VEC_ELT (declv, i); - init = TREE_VEC_ELT (initv, i); - cond = TREE_VEC_ELT (condv, i); - incr = TREE_VEC_ELT (incrv, i); - elocus = locus; - - if (decl == NULL) - { - if (init != NULL) - switch (TREE_CODE (init)) - { - case MODIFY_EXPR: - decl = TREE_OPERAND (init, 0); - init = TREE_OPERAND (init, 1); - break; - case MODOP_EXPR: - if (TREE_CODE (TREE_OPERAND (init, 1)) == NOP_EXPR) - { - decl = TREE_OPERAND (init, 0); - init = TREE_OPERAND (init, 2); - } - break; - default: - break; - } - - if (decl == NULL) - { - error_at (locus, - "expected iteration declaration or initialization"); - return NULL; - } - } - - if (init && EXPR_HAS_LOCATION (init)) - elocus = EXPR_LOCATION (init); - - if (cond == global_namespace) - continue; - - if (cond == NULL) - { - error_at (elocus, "missing controlling predicate"); - return NULL; - } - - if (incr == NULL) - { - error_at (elocus, "missing increment expression"); - return NULL; - } - - TREE_VEC_ELT (declv, i) = decl; - TREE_VEC_ELT (initv, i) = init; - } - - if (orig_inits) - { - bool fail = false; - tree orig_init; - FOR_EACH_VEC_ELT (*orig_inits, i, orig_init) - if (orig_init - && !c_omp_check_loop_iv_exprs (locus, code, - orig_declv ? orig_declv : declv, i, - TREE_VEC_ELT (declv, i), orig_init, - NULL_TREE, cp_walk_subtrees)) - fail = true; - if (fail) - return NULL; - } - - if (dependent_omp_for_p (declv, initv, condv, incrv)) - { - tree stmt; - - stmt = make_node (code); - - for (i = 0; i < TREE_VEC_LENGTH (declv); i++) - { - /* This is really just a place-holder. We'll be decomposing this - again and going through the cp_build_modify_expr path below when - we instantiate the thing. */ - TREE_VEC_ELT (initv, i) - = build2 (MODIFY_EXPR, void_type_node, TREE_VEC_ELT (declv, i), - TREE_VEC_ELT (initv, i)); - } - - TREE_TYPE (stmt) = void_type_node; - OMP_FOR_INIT (stmt) = initv; - OMP_FOR_COND (stmt) = condv; - OMP_FOR_INCR (stmt) = incrv; - OMP_FOR_BODY (stmt) = body; - OMP_FOR_PRE_BODY (stmt) = pre_body; - OMP_FOR_CLAUSES (stmt) = clauses; - - SET_EXPR_LOCATION (stmt, locus); - return add_stmt (stmt); - } - - if (!orig_declv) - orig_declv = copy_node (declv); - - if (processing_template_decl) - orig_incr = make_tree_vec (TREE_VEC_LENGTH (incrv)); - - for (i = 0; i < TREE_VEC_LENGTH (declv); ) - { - decl = TREE_VEC_ELT (declv, i); - init = TREE_VEC_ELT (initv, i); - cond = TREE_VEC_ELT (condv, i); - incr = TREE_VEC_ELT (incrv, i); - if (orig_incr) - TREE_VEC_ELT (orig_incr, i) = incr; - elocus = locus; - - if (init && EXPR_HAS_LOCATION (init)) - elocus = EXPR_LOCATION (init); - - if (!DECL_P (decl)) - { - error_at (elocus, "expected iteration declaration or initialization"); - return NULL; - } - - if (incr && TREE_CODE (incr) == MODOP_EXPR) - { - if (orig_incr) - TREE_VEC_ELT (orig_incr, i) = incr; - incr = cp_build_modify_expr (elocus, TREE_OPERAND (incr, 0), - TREE_CODE (TREE_OPERAND (incr, 1)), - TREE_OPERAND (incr, 2), - tf_warning_or_error); - } - - if (CLASS_TYPE_P (TREE_TYPE (decl))) - { - if (code == OMP_SIMD) - { - error_at (elocus, "%<#pragma omp simd%> used with class " - "iteration variable %qE", decl); - return NULL; - } - if (handle_omp_for_class_iterator (i, locus, code, declv, orig_declv, - initv, condv, incrv, &body, - &pre_body, clauses, - collapse, ordered)) - return NULL; - continue; - } - - if (!INTEGRAL_TYPE_P (TREE_TYPE (decl)) - && !TYPE_PTR_P (TREE_TYPE (decl))) - { - error_at (elocus, "invalid type for iteration variable %qE", decl); - return NULL; - } - - if (!processing_template_decl && TREE_CODE (init) != TREE_VEC) - init = cp_build_modify_expr (elocus, decl, NOP_EXPR, init, - tf_warning_or_error); - else - init = build2 (MODIFY_EXPR, void_type_node, decl, init); - if (decl == error_mark_node || init == error_mark_node) - return NULL; - - TREE_VEC_ELT (declv, i) = decl; - TREE_VEC_ELT (initv, i) = init; - TREE_VEC_ELT (condv, i) = cond; - TREE_VEC_ELT (incrv, i) = incr; - i++; - } - - if (pre_body && IS_EMPTY_STMT (pre_body)) - pre_body = NULL; - - omp_for = c_finish_omp_for (locus, code, declv, orig_declv, initv, condv, - incrv, body, pre_body, - !processing_template_decl); - - /* Check for iterators appearing in lb, b or incr expressions. */ - if (omp_for && !c_omp_check_loop_iv (omp_for, orig_declv, cp_walk_subtrees)) - omp_for = NULL_TREE; - - if (omp_for == NULL) - return NULL; - - add_stmt (omp_for); - - for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INCR (omp_for)); i++) - { - init = TREE_VEC_ELT (OMP_FOR_INIT (omp_for), i); - decl = TREE_OPERAND (init, 0); - cond = TREE_VEC_ELT (OMP_FOR_COND (omp_for), i); - incr = TREE_VEC_ELT (OMP_FOR_INCR (omp_for), i); - - if (!processing_template_decl) - { - if (TREE_CODE (TREE_OPERAND (init, 1)) == TREE_VEC) - { - tree t = TREE_VEC_ELT (TREE_OPERAND (init, 1), 1); - TREE_VEC_ELT (TREE_OPERAND (init, 1), 1) - = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - t = TREE_VEC_ELT (TREE_OPERAND (init, 1), 2); - TREE_VEC_ELT (TREE_OPERAND (init, 1), 2) - = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - } - else - { - tree t = TREE_OPERAND (init, 1); - TREE_OPERAND (init, 1) - = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - } - if (TREE_CODE (TREE_OPERAND (cond, 1)) == TREE_VEC) - { - tree t = TREE_VEC_ELT (TREE_OPERAND (cond, 1), 1); - TREE_VEC_ELT (TREE_OPERAND (cond, 1), 1) - = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - t = TREE_VEC_ELT (TREE_OPERAND (cond, 1), 2); - TREE_VEC_ELT (TREE_OPERAND (cond, 1), 2) - = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - } - else - { - tree t = TREE_OPERAND (cond, 1); - TREE_OPERAND (cond, 1) - = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - } - } - - if (TREE_CODE (incr) != MODIFY_EXPR) - continue; - - if (TREE_SIDE_EFFECTS (TREE_OPERAND (incr, 1)) - && BINARY_CLASS_P (TREE_OPERAND (incr, 1)) - && !processing_template_decl) - { - tree t = TREE_OPERAND (TREE_OPERAND (incr, 1), 0); - if (TREE_SIDE_EFFECTS (t) - && t != decl - && (TREE_CODE (t) != NOP_EXPR - || TREE_OPERAND (t, 0) != decl)) - TREE_OPERAND (TREE_OPERAND (incr, 1), 0) - = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - - t = TREE_OPERAND (TREE_OPERAND (incr, 1), 1); - if (TREE_SIDE_EFFECTS (t) - && t != decl - && (TREE_CODE (t) != NOP_EXPR - || TREE_OPERAND (t, 0) != decl)) - TREE_OPERAND (TREE_OPERAND (incr, 1), 1) - = fold_build_cleanup_point_expr (TREE_TYPE (t), t); - } - - if (orig_incr) - TREE_VEC_ELT (OMP_FOR_INCR (omp_for), i) = TREE_VEC_ELT (orig_incr, i); - } - OMP_FOR_CLAUSES (omp_for) = clauses; - - /* For simd loops with non-static data member iterators, we could have added - OMP_CLAUSE_LINEAR clauses without OMP_CLAUSE_LINEAR_STEP. As we know the - step at this point, fill it in. */ - if (code == OMP_SIMD && !processing_template_decl - && TREE_VEC_LENGTH (OMP_FOR_INCR (omp_for)) == 1) - for (tree c = omp_find_clause (clauses, OMP_CLAUSE_LINEAR); c; - c = omp_find_clause (OMP_CLAUSE_CHAIN (c), OMP_CLAUSE_LINEAR)) - if (OMP_CLAUSE_LINEAR_STEP (c) == NULL_TREE) - { - decl = TREE_OPERAND (TREE_VEC_ELT (OMP_FOR_INIT (omp_for), 0), 0); - gcc_assert (decl == OMP_CLAUSE_DECL (c)); - incr = TREE_VEC_ELT (OMP_FOR_INCR (omp_for), 0); - tree step, stept; - switch (TREE_CODE (incr)) - { - case PREINCREMENT_EXPR: - case POSTINCREMENT_EXPR: - /* c_omp_for_incr_canonicalize_ptr() should have been - called to massage things appropriately. */ - gcc_assert (!INDIRECT_TYPE_P (TREE_TYPE (decl))); - OMP_CLAUSE_LINEAR_STEP (c) = build_int_cst (TREE_TYPE (decl), 1); - break; - case PREDECREMENT_EXPR: - case POSTDECREMENT_EXPR: - /* c_omp_for_incr_canonicalize_ptr() should have been - called to massage things appropriately. */ - gcc_assert (!INDIRECT_TYPE_P (TREE_TYPE (decl))); - OMP_CLAUSE_LINEAR_STEP (c) - = build_int_cst (TREE_TYPE (decl), -1); - break; - case MODIFY_EXPR: - gcc_assert (TREE_OPERAND (incr, 0) == decl); - incr = TREE_OPERAND (incr, 1); - switch (TREE_CODE (incr)) - { - case PLUS_EXPR: - if (TREE_OPERAND (incr, 1) == decl) - step = TREE_OPERAND (incr, 0); - else - step = TREE_OPERAND (incr, 1); - break; - case MINUS_EXPR: - case POINTER_PLUS_EXPR: - gcc_assert (TREE_OPERAND (incr, 0) == decl); - step = TREE_OPERAND (incr, 1); - break; - default: - gcc_unreachable (); - } - stept = TREE_TYPE (decl); - if (INDIRECT_TYPE_P (stept)) - stept = sizetype; - step = fold_convert (stept, step); - if (TREE_CODE (incr) == MINUS_EXPR) - step = fold_build1 (NEGATE_EXPR, stept, step); - OMP_CLAUSE_LINEAR_STEP (c) = step; - break; - default: - gcc_unreachable (); - } - } - /* Override saved methods on OMP_LOOP's OMP_CLAUSE_LASTPRIVATE_LOOP_IV - clauses, we need copy ctor for those rather than default ctor, - plus as for other lastprivates assignment op and dtor. */ - if (code == OMP_LOOP && !processing_template_decl) - for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c)) - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE - && OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c) - && cxx_omp_create_clause_info (c, TREE_TYPE (OMP_CLAUSE_DECL (c)), - false, true, true, true)) - CP_OMP_CLAUSE_INFO (c) = NULL_TREE; - - return omp_for; -} - -/* Fix up range for decls. Those decls were pushed into BIND's BIND_EXPR_VARS - and need to be moved into the BIND_EXPR inside of the OMP_FOR's body. */ - -tree -finish_omp_for_block (tree bind, tree omp_for) -{ - if (omp_for == NULL_TREE - || !OMP_FOR_ORIG_DECLS (omp_for) - || bind == NULL_TREE - || TREE_CODE (bind) != BIND_EXPR) - return bind; - tree b = NULL_TREE; - for (int i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (omp_for)); i++) - if (TREE_CODE (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (omp_for), i)) == TREE_LIST - && TREE_CHAIN (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (omp_for), i))) - { - tree v = TREE_CHAIN (TREE_VEC_ELT (OMP_FOR_ORIG_DECLS (omp_for), i)); - gcc_assert (BIND_EXPR_BLOCK (bind) - && (BIND_EXPR_VARS (bind) - == BLOCK_VARS (BIND_EXPR_BLOCK (bind)))); - for (int j = 2; j < TREE_VEC_LENGTH (v); j++) - for (tree *p = &BIND_EXPR_VARS (bind); *p; p = &DECL_CHAIN (*p)) - { - if (*p == TREE_VEC_ELT (v, j)) - { - tree var = *p; - *p = DECL_CHAIN (*p); - if (b == NULL_TREE) - { - b = make_node (BLOCK); - b = build3 (BIND_EXPR, void_type_node, NULL_TREE, - OMP_FOR_BODY (omp_for), b); - TREE_SIDE_EFFECTS (b) = 1; - OMP_FOR_BODY (omp_for) = b; - } - DECL_CHAIN (var) = BIND_EXPR_VARS (b); - BIND_EXPR_VARS (b) = var; - BLOCK_VARS (BIND_EXPR_BLOCK (b)) = var; - } - } - BLOCK_VARS (BIND_EXPR_BLOCK (bind)) = BIND_EXPR_VARS (bind); - } - return bind; -} - -void -finish_omp_atomic (location_t loc, enum tree_code code, enum tree_code opcode, - tree lhs, tree rhs, tree v, tree lhs1, tree rhs1, tree r, - tree clauses, enum omp_memory_order mo, bool weak) -{ - tree orig_lhs; - tree orig_rhs; - tree orig_v; - tree orig_lhs1; - tree orig_rhs1; - tree orig_r; - bool dependent_p; - tree stmt; - - orig_lhs = lhs; - orig_rhs = rhs; - orig_v = v; - orig_lhs1 = lhs1; - orig_rhs1 = rhs1; - orig_r = r; - dependent_p = false; - stmt = NULL_TREE; - - /* Even in a template, we can detect invalid uses of the atomic - pragma if neither LHS nor RHS is type-dependent. */ - if (processing_template_decl) - { - dependent_p = (type_dependent_expression_p (lhs) - || (rhs && type_dependent_expression_p (rhs)) - || (v && type_dependent_expression_p (v)) - || (lhs1 && type_dependent_expression_p (lhs1)) - || (rhs1 && type_dependent_expression_p (rhs1)) - || (r - && r != void_list_node - && type_dependent_expression_p (r))); - if (clauses) - { - gcc_assert (TREE_CODE (clauses) == OMP_CLAUSE - && OMP_CLAUSE_CODE (clauses) == OMP_CLAUSE_HINT - && OMP_CLAUSE_CHAIN (clauses) == NULL_TREE); - if (type_dependent_expression_p (OMP_CLAUSE_HINT_EXPR (clauses)) - || TREE_CODE (OMP_CLAUSE_HINT_EXPR (clauses)) != INTEGER_CST) - dependent_p = true; - } - if (!dependent_p) - { - lhs = build_non_dependent_expr (lhs); - if (rhs) - rhs = build_non_dependent_expr (rhs); - if (v) - v = build_non_dependent_expr (v); - if (lhs1) - lhs1 = build_non_dependent_expr (lhs1); - if (rhs1) - rhs1 = build_non_dependent_expr (rhs1); - if (r && r != void_list_node) - r = build_non_dependent_expr (r); - } - } - if (!dependent_p) - { - bool swapped = false; - if (rhs1 && opcode != COND_EXPR && cp_tree_equal (lhs, rhs)) - { - std::swap (rhs, rhs1); - swapped = !commutative_tree_code (opcode); - } - if (rhs1 && opcode != COND_EXPR && !cp_tree_equal (lhs, rhs1)) - { - if (code == OMP_ATOMIC) - error ("%<#pragma omp atomic update%> uses two different " - "expressions for memory"); - else - error ("%<#pragma omp atomic capture%> uses two different " - "expressions for memory"); - return; - } - if (lhs1 && !cp_tree_equal (lhs, lhs1)) - { - if (code == OMP_ATOMIC) - error ("%<#pragma omp atomic update%> uses two different " - "expressions for memory"); - else - error ("%<#pragma omp atomic capture%> uses two different " - "expressions for memory"); - return; - } - stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, - v, lhs1, rhs1, r, swapped, mo, weak, - processing_template_decl != 0); - if (stmt == error_mark_node) - return; - } - if (processing_template_decl) - { - if (code == OMP_ATOMIC_READ) - { - stmt = build_min_nt_loc (loc, OMP_ATOMIC_READ, orig_lhs); - OMP_ATOMIC_MEMORY_ORDER (stmt) = mo; - stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt); - } - else - { - if (opcode == NOP_EXPR) - stmt = build2 (MODIFY_EXPR, void_type_node, orig_lhs, orig_rhs); - else if (opcode == COND_EXPR) - { - stmt = build2 (EQ_EXPR, boolean_type_node, orig_lhs, orig_rhs); - if (orig_r) - stmt = build2 (MODIFY_EXPR, boolean_type_node, orig_r, - stmt); - stmt = build3 (COND_EXPR, void_type_node, stmt, orig_rhs1, - orig_lhs); - orig_rhs1 = NULL_TREE; - } - else - stmt = build2 (opcode, void_type_node, orig_lhs, orig_rhs); - if (orig_rhs1) - stmt = build_min_nt_loc (EXPR_LOCATION (orig_rhs1), - COMPOUND_EXPR, orig_rhs1, stmt); - if (code != OMP_ATOMIC) - { - stmt = build_min_nt_loc (loc, code, orig_lhs1, stmt); - OMP_ATOMIC_MEMORY_ORDER (stmt) = mo; - OMP_ATOMIC_WEAK (stmt) = weak; - stmt = build2 (MODIFY_EXPR, void_type_node, orig_v, stmt); - } - } - stmt = build2 (OMP_ATOMIC, void_type_node, - clauses ? clauses : integer_zero_node, stmt); - OMP_ATOMIC_MEMORY_ORDER (stmt) = mo; - OMP_ATOMIC_WEAK (stmt) = weak; - SET_EXPR_LOCATION (stmt, loc); - } - - /* Avoid -Wunused-value warnings here, the whole construct has side-effects - and even if it might be wrapped from fold-const.c or c-omp.c wrapped - in some tree that appears to be unused, the value is not unused. */ - warning_sentinel w (warn_unused_value); - finish_expr_stmt (stmt); -} - -void -finish_omp_barrier (void) -{ - tree fn = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER); - releasing_vec vec; - tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error); - finish_expr_stmt (stmt); -} - -void -finish_omp_depobj (location_t loc, tree depobj, - enum omp_clause_depend_kind kind, tree clause) -{ - if (!error_operand_p (depobj) && !type_dependent_expression_p (depobj)) - { - if (!lvalue_p (depobj)) - { - error_at (EXPR_LOC_OR_LOC (depobj, loc), - "%<depobj%> expression is not lvalue expression"); - depobj = error_mark_node; - } - } - - if (processing_template_decl) - { - if (clause == NULL_TREE) - clause = build_int_cst (integer_type_node, kind); - add_stmt (build_min_nt_loc (loc, OMP_DEPOBJ, depobj, clause)); - return; - } - - if (!error_operand_p (depobj)) - { - tree addr = cp_build_addr_expr (depobj, tf_warning_or_error); - if (addr == error_mark_node) - depobj = error_mark_node; - else - depobj = cp_build_indirect_ref (loc, addr, RO_UNARY_STAR, - tf_warning_or_error); - } - - c_finish_omp_depobj (loc, depobj, kind, clause); -} - -void -finish_omp_flush (int mo) -{ - tree fn = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE); - releasing_vec vec; - if (mo != MEMMODEL_LAST && mo != MEMMODEL_SEQ_CST) - { - fn = builtin_decl_explicit (BUILT_IN_ATOMIC_THREAD_FENCE); - vec->quick_push (build_int_cst (integer_type_node, mo)); - } - tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error); - finish_expr_stmt (stmt); -} - -void -finish_omp_taskwait (void) -{ - tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT); - releasing_vec vec; - tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error); - finish_expr_stmt (stmt); -} - -void -finish_omp_taskyield (void) -{ - tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD); - releasing_vec vec; - tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error); - finish_expr_stmt (stmt); -} - -void -finish_omp_cancel (tree clauses) -{ - tree fn = builtin_decl_explicit (BUILT_IN_GOMP_CANCEL); - int mask = 0; - if (omp_find_clause (clauses, OMP_CLAUSE_PARALLEL)) - mask = 1; - else if (omp_find_clause (clauses, OMP_CLAUSE_FOR)) - mask = 2; - else if (omp_find_clause (clauses, OMP_CLAUSE_SECTIONS)) - mask = 4; - else if (omp_find_clause (clauses, OMP_CLAUSE_TASKGROUP)) - mask = 8; - else - { - error ("%<#pragma omp cancel%> must specify one of " - "%<parallel%>, %<for%>, %<sections%> or %<taskgroup%> clauses"); - return; - } - releasing_vec vec; - tree ifc = omp_find_clause (clauses, OMP_CLAUSE_IF); - if (ifc != NULL_TREE) - { - if (OMP_CLAUSE_IF_MODIFIER (ifc) != ERROR_MARK - && OMP_CLAUSE_IF_MODIFIER (ifc) != VOID_CST) - error_at (OMP_CLAUSE_LOCATION (ifc), - "expected %<cancel%> %<if%> clause modifier"); - else - { - tree ifc2 = omp_find_clause (OMP_CLAUSE_CHAIN (ifc), OMP_CLAUSE_IF); - if (ifc2 != NULL_TREE) - { - gcc_assert (OMP_CLAUSE_IF_MODIFIER (ifc) == VOID_CST - && OMP_CLAUSE_IF_MODIFIER (ifc2) != ERROR_MARK - && OMP_CLAUSE_IF_MODIFIER (ifc2) != VOID_CST); - error_at (OMP_CLAUSE_LOCATION (ifc2), - "expected %<cancel%> %<if%> clause modifier"); - } - } - - if (!processing_template_decl) - ifc = maybe_convert_cond (OMP_CLAUSE_IF_EXPR (ifc)); - else - ifc = build_x_binary_op (OMP_CLAUSE_LOCATION (ifc), NE_EXPR, - OMP_CLAUSE_IF_EXPR (ifc), ERROR_MARK, - integer_zero_node, ERROR_MARK, - NULL_TREE, NULL, tf_warning_or_error); - } - else - ifc = boolean_true_node; - vec->quick_push (build_int_cst (integer_type_node, mask)); - vec->quick_push (ifc); - tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error); - finish_expr_stmt (stmt); -} - -void -finish_omp_cancellation_point (tree clauses) -{ - tree fn = builtin_decl_explicit (BUILT_IN_GOMP_CANCELLATION_POINT); - int mask = 0; - if (omp_find_clause (clauses, OMP_CLAUSE_PARALLEL)) - mask = 1; - else if (omp_find_clause (clauses, OMP_CLAUSE_FOR)) - mask = 2; - else if (omp_find_clause (clauses, OMP_CLAUSE_SECTIONS)) - mask = 4; - else if (omp_find_clause (clauses, OMP_CLAUSE_TASKGROUP)) - mask = 8; - else - { - error ("%<#pragma omp cancellation point%> must specify one of " - "%<parallel%>, %<for%>, %<sections%> or %<taskgroup%> clauses"); - return; - } - releasing_vec vec - = make_tree_vector_single (build_int_cst (integer_type_node, mask)); - tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error); - finish_expr_stmt (stmt); -} - -/* Begin a __transaction_atomic or __transaction_relaxed statement. - If PCOMPOUND is non-null, this is for a function-transaction-block, and we - should create an extra compound stmt. */ - -tree -begin_transaction_stmt (location_t loc, tree *pcompound, int flags) -{ - tree r; - - if (pcompound) - *pcompound = begin_compound_stmt (0); - - r = build_stmt (loc, TRANSACTION_EXPR, NULL_TREE); - - /* Only add the statement to the function if support enabled. */ - if (flag_tm) - add_stmt (r); - else - error_at (loc, ((flags & TM_STMT_ATTR_RELAXED) != 0 - ? G_("%<__transaction_relaxed%> without " - "transactional memory support enabled") - : G_("%<__transaction_atomic%> without " - "transactional memory support enabled"))); - - TRANSACTION_EXPR_BODY (r) = push_stmt_list (); - TREE_SIDE_EFFECTS (r) = 1; - return r; -} - -/* End a __transaction_atomic or __transaction_relaxed statement. - If COMPOUND_STMT is non-null, this is for a function-transaction-block, - and we should end the compound. If NOEX is non-NULL, we wrap the body in - a MUST_NOT_THROW_EXPR with NOEX as condition. */ - -void -finish_transaction_stmt (tree stmt, tree compound_stmt, int flags, tree noex) -{ - TRANSACTION_EXPR_BODY (stmt) = pop_stmt_list (TRANSACTION_EXPR_BODY (stmt)); - TRANSACTION_EXPR_OUTER (stmt) = (flags & TM_STMT_ATTR_OUTER) != 0; - TRANSACTION_EXPR_RELAXED (stmt) = (flags & TM_STMT_ATTR_RELAXED) != 0; - TRANSACTION_EXPR_IS_STMT (stmt) = 1; - - /* noexcept specifications are not allowed for function transactions. */ - gcc_assert (!(noex && compound_stmt)); - if (noex) - { - tree body = build_must_not_throw_expr (TRANSACTION_EXPR_BODY (stmt), - noex); - protected_set_expr_location - (body, EXPR_LOCATION (TRANSACTION_EXPR_BODY (stmt))); - TREE_SIDE_EFFECTS (body) = 1; - TRANSACTION_EXPR_BODY (stmt) = body; - } - - if (compound_stmt) - finish_compound_stmt (compound_stmt); -} - -/* Build a __transaction_atomic or __transaction_relaxed expression. If - NOEX is non-NULL, we wrap the body in a MUST_NOT_THROW_EXPR with NOEX as - condition. */ - -tree -build_transaction_expr (location_t loc, tree expr, int flags, tree noex) -{ - tree ret; - if (noex) - { - expr = build_must_not_throw_expr (expr, noex); - protected_set_expr_location (expr, loc); - TREE_SIDE_EFFECTS (expr) = 1; - } - ret = build1 (TRANSACTION_EXPR, TREE_TYPE (expr), expr); - if (flags & TM_STMT_ATTR_RELAXED) - TRANSACTION_EXPR_RELAXED (ret) = 1; - TREE_SIDE_EFFECTS (ret) = 1; - SET_EXPR_LOCATION (ret, loc); - return ret; -} - -void -init_cp_semantics (void) -{ -} - - -/* If we have a condition in conjunctive normal form (CNF), find the first - failing clause. In other words, given an expression like - - true && true && false && true && false - - return the first 'false'. EXPR is the expression. */ - -static tree -find_failing_clause_r (tree expr) -{ - if (TREE_CODE (expr) == TRUTH_ANDIF_EXPR) - { - /* First check the left side... */ - tree e = find_failing_clause_r (TREE_OPERAND (expr, 0)); - if (e == NULL_TREE) - /* ...if we didn't find a false clause, check the right side. */ - e = find_failing_clause_r (TREE_OPERAND (expr, 1)); - return e; - } - tree e = contextual_conv_bool (expr, tf_none); - e = fold_non_dependent_expr (e, tf_none, /*manifestly_const_eval=*/true); - if (integer_zerop (e)) - /* This is the failing clause. */ - return expr; - return NULL_TREE; -} - -/* Wrapper for find_failing_clause_r. */ - -static tree -find_failing_clause (tree expr) -{ - if (TREE_CODE (expr) != TRUTH_ANDIF_EXPR) - return NULL_TREE; - return find_failing_clause_r (expr); -} - -/* Build a STATIC_ASSERT for a static assertion with the condition - CONDITION and the message text MESSAGE. LOCATION is the location - of the static assertion in the source code. When MEMBER_P, this - static assertion is a member of a class. If SHOW_EXPR_P is true, - print the condition (because it was instantiation-dependent). */ - -void -finish_static_assert (tree condition, tree message, location_t location, - bool member_p, bool show_expr_p) -{ - tsubst_flags_t complain = tf_warning_or_error; - - if (message == NULL_TREE - || message == error_mark_node - || condition == NULL_TREE - || condition == error_mark_node) - return; - - if (check_for_bare_parameter_packs (condition)) - condition = error_mark_node; - - if (instantiation_dependent_expression_p (condition)) - { - /* We're in a template; build a STATIC_ASSERT and put it in - the right place. */ - tree assertion; - - assertion = make_node (STATIC_ASSERT); - STATIC_ASSERT_CONDITION (assertion) = condition; - STATIC_ASSERT_MESSAGE (assertion) = message; - STATIC_ASSERT_SOURCE_LOCATION (assertion) = location; - - if (member_p) - maybe_add_class_template_decl_list (current_class_type, - assertion, - /*friend_p=*/0); - else - add_stmt (assertion); - - return; - } - - /* Save the condition in case it was a concept check. */ - tree orig_condition = condition; - - /* Fold the expression and convert it to a boolean value. */ - condition = contextual_conv_bool (condition, complain); - condition = fold_non_dependent_expr (condition, complain, - /*manifestly_const_eval=*/true); - - if (TREE_CODE (condition) == INTEGER_CST && !integer_zerop (condition)) - /* Do nothing; the condition is satisfied. */ - ; - else - { - iloc_sentinel ils (location); - - if (integer_zerop (condition)) - { - int sz = TREE_INT_CST_LOW (TYPE_SIZE_UNIT - (TREE_TYPE (TREE_TYPE (message)))); - int len = TREE_STRING_LENGTH (message) / sz - 1; - - /* See if we can find which clause was failing (for logical AND). */ - tree bad = find_failing_clause (orig_condition); - /* If not, or its location is unusable, fall back to the previous - location. */ - location_t cloc = location; - if (cp_expr_location (bad) != UNKNOWN_LOCATION) - cloc = cp_expr_location (bad); - - /* Report the error. */ - if (len == 0) - error_at (cloc, "static assertion failed"); - else - error_at (cloc, "static assertion failed: %s", - TREE_STRING_POINTER (message)); - if (show_expr_p) - inform (cloc, "%qE evaluates to false", - /* Nobody wants to see the artificial (bool) cast. */ - (bad ? tree_strip_nop_conversions (bad) : orig_condition)); - - /* Actually explain the failure if this is a concept check or a - requires-expression. */ - if (concept_check_p (orig_condition) - || TREE_CODE (orig_condition) == REQUIRES_EXPR) - diagnose_constraints (location, orig_condition, NULL_TREE); - } - else if (condition && condition != error_mark_node) - { - error ("non-constant condition for static assertion"); - if (require_rvalue_constant_expression (condition)) - cxx_constant_value (condition); - } - } -} - -/* Implements the C++0x decltype keyword. Returns the type of EXPR, - suitable for use as a type-specifier. - - ID_EXPRESSION_OR_MEMBER_ACCESS_P is true when EXPR was parsed as an - id-expression or a class member access, FALSE when it was parsed as - a full expression. */ - -tree -finish_decltype_type (tree expr, bool id_expression_or_member_access_p, - tsubst_flags_t complain) -{ - tree type = NULL_TREE; - - if (!expr || error_operand_p (expr)) - return error_mark_node; - - if (TYPE_P (expr) - || TREE_CODE (expr) == TYPE_DECL - || (TREE_CODE (expr) == BIT_NOT_EXPR - && TYPE_P (TREE_OPERAND (expr, 0)))) - { - if (complain & tf_error) - error ("argument to %<decltype%> must be an expression"); - return error_mark_node; - } - - /* decltype is an unevaluated context. */ - cp_unevaluated u; - - /* Depending on the resolution of DR 1172, we may later need to distinguish - instantiation-dependent but not type-dependent expressions so that, say, - A<decltype(sizeof(T))>::U doesn't require 'typename'. */ - if (instantiation_dependent_uneval_expression_p (expr)) - { - type = cxx_make_type (DECLTYPE_TYPE); - DECLTYPE_TYPE_EXPR (type) = expr; - DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (type) - = id_expression_or_member_access_p; - SET_TYPE_STRUCTURAL_EQUALITY (type); - - return type; - } - else if (processing_template_decl) - { - expr = instantiate_non_dependent_expr_sfinae (expr, complain); - if (expr == error_mark_node) - return error_mark_node; - } - - /* The type denoted by decltype(e) is defined as follows: */ - - expr = resolve_nondeduced_context (expr, complain); - - if (invalid_nonstatic_memfn_p (input_location, expr, complain)) - return error_mark_node; - - if (type_unknown_p (expr)) - { - if (complain & tf_error) - error ("%<decltype%> cannot resolve address of overloaded function"); - return error_mark_node; - } - - /* To get the size of a static data member declared as an array of - unknown bound, we need to instantiate it. */ - if (VAR_P (expr) - && VAR_HAD_UNKNOWN_BOUND (expr) - && DECL_TEMPLATE_INSTANTIATION (expr)) - instantiate_decl (expr, /*defer_ok*/true, /*expl_inst_mem*/false); - - if (id_expression_or_member_access_p) - { - /* If e is an id-expression or a class member access (5.2.5 - [expr.ref]), decltype(e) is defined as the type of the entity - named by e. If there is no such entity, or e names a set of - overloaded functions, the program is ill-formed. */ - if (identifier_p (expr)) - expr = lookup_name (expr); - - if (INDIRECT_REF_P (expr) - || TREE_CODE (expr) == VIEW_CONVERT_EXPR) - /* This can happen when the expression is, e.g., "a.b". Just - look at the underlying operand. */ - expr = TREE_OPERAND (expr, 0); - - if (TREE_CODE (expr) == OFFSET_REF - || TREE_CODE (expr) == MEMBER_REF - || TREE_CODE (expr) == SCOPE_REF) - /* We're only interested in the field itself. If it is a - BASELINK, we will need to see through it in the next - step. */ - expr = TREE_OPERAND (expr, 1); - - if (BASELINK_P (expr)) - /* See through BASELINK nodes to the underlying function. */ - expr = BASELINK_FUNCTIONS (expr); - - /* decltype of a decomposition name drops references in the tuple case - (unlike decltype of a normal variable) and keeps cv-qualifiers from - the containing object in the other cases (unlike decltype of a member - access expression). */ - if (DECL_DECOMPOSITION_P (expr)) - { - if (DECL_HAS_VALUE_EXPR_P (expr)) - /* Expr is an array or struct subobject proxy, handle - bit-fields properly. */ - return unlowered_expr_type (expr); - else - /* Expr is a reference variable for the tuple case. */ - return lookup_decomp_type (expr); - } - - switch (TREE_CODE (expr)) - { - case FIELD_DECL: - if (DECL_BIT_FIELD_TYPE (expr)) - { - type = DECL_BIT_FIELD_TYPE (expr); - break; - } - /* Fall through for fields that aren't bitfields. */ - gcc_fallthrough (); - - case FUNCTION_DECL: - case VAR_DECL: - case CONST_DECL: - case PARM_DECL: - case RESULT_DECL: - case TEMPLATE_PARM_INDEX: - expr = mark_type_use (expr); - type = TREE_TYPE (expr); - break; - - case ERROR_MARK: - type = error_mark_node; - break; - - case COMPONENT_REF: - case COMPOUND_EXPR: - mark_type_use (expr); - type = is_bitfield_expr_with_lowered_type (expr); - if (!type) - type = TREE_TYPE (TREE_OPERAND (expr, 1)); - break; - - case BIT_FIELD_REF: - gcc_unreachable (); - - case INTEGER_CST: - case PTRMEM_CST: - /* We can get here when the id-expression refers to an - enumerator or non-type template parameter. */ - type = TREE_TYPE (expr); - break; - - default: - /* Handle instantiated template non-type arguments. */ - type = TREE_TYPE (expr); - break; - } - } - else - { - /* Within a lambda-expression: - - Every occurrence of decltype((x)) where x is a possibly - parenthesized id-expression that names an entity of - automatic storage duration is treated as if x were - transformed into an access to a corresponding data member - of the closure type that would have been declared if x - were a use of the denoted entity. */ - if (outer_automatic_var_p (expr) - && current_function_decl - && LAMBDA_FUNCTION_P (current_function_decl)) - type = capture_decltype (expr); - else if (error_operand_p (expr)) - type = error_mark_node; - else if (expr == current_class_ptr) - /* If the expression is just "this", we want the - cv-unqualified pointer for the "this" type. */ - type = TYPE_MAIN_VARIANT (TREE_TYPE (expr)); - else - { - /* Otherwise, where T is the type of e, if e is an lvalue, - decltype(e) is defined as T&; if an xvalue, T&&; otherwise, T. */ - cp_lvalue_kind clk = lvalue_kind (expr); - type = unlowered_expr_type (expr); - gcc_assert (!TYPE_REF_P (type)); - - /* For vector types, pick a non-opaque variant. */ - if (VECTOR_TYPE_P (type)) - type = strip_typedefs (type); - - if (clk != clk_none && !(clk & clk_class)) - type = cp_build_reference_type (type, (clk & clk_rvalueref)); - } - } - - return type; -} - -/* Called from trait_expr_value to evaluate either __has_nothrow_assign or - __has_nothrow_copy, depending on assign_p. Returns true iff all - the copy {ctor,assign} fns are nothrow. */ - -static bool -classtype_has_nothrow_assign_or_copy_p (tree type, bool assign_p) -{ - tree fns = NULL_TREE; - - if (assign_p || TYPE_HAS_COPY_CTOR (type)) - fns = get_class_binding (type, assign_p ? assign_op_identifier - : ctor_identifier); - - bool saw_copy = false; - for (ovl_iterator iter (fns); iter; ++iter) - { - tree fn = *iter; - - if (copy_fn_p (fn) > 0) - { - saw_copy = true; - if (!maybe_instantiate_noexcept (fn) - || !TYPE_NOTHROW_P (TREE_TYPE (fn))) - return false; - } - } - - return saw_copy; -} - -/* Return true if DERIVED is pointer interconvertible base of BASE. */ - -static bool -pointer_interconvertible_base_of_p (tree base, tree derived) -{ - if (base == error_mark_node || derived == error_mark_node) - return false; - base = TYPE_MAIN_VARIANT (base); - derived = TYPE_MAIN_VARIANT (derived); - if (!NON_UNION_CLASS_TYPE_P (base) - || !NON_UNION_CLASS_TYPE_P (derived)) - return false; - - if (same_type_p (base, derived)) - return true; - - if (!std_layout_type_p (derived)) - return false; - - return uniquely_derived_from_p (base, derived); -} - -/* Helper function for fold_builtin_is_pointer_inverconvertible_with_class, - return true if MEMBERTYPE is the type of the first non-static data member - of TYPE or for unions of any members. */ -static bool -first_nonstatic_data_member_p (tree type, tree membertype) -{ - for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) - { - if (TREE_CODE (field) != FIELD_DECL) - continue; - if (DECL_FIELD_IS_BASE (field) && is_empty_field (field)) - continue; - if (DECL_FIELD_IS_BASE (field)) - return first_nonstatic_data_member_p (TREE_TYPE (field), membertype); - if (ANON_AGGR_TYPE_P (TREE_TYPE (field))) - { - if ((TREE_CODE (TREE_TYPE (field)) == UNION_TYPE - || std_layout_type_p (TREE_TYPE (field))) - && first_nonstatic_data_member_p (TREE_TYPE (field), membertype)) - return true; - } - else if (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (field), - membertype)) - return true; - if (TREE_CODE (type) != UNION_TYPE) - return false; - } - return false; -} - -/* Fold __builtin_is_pointer_interconvertible_with_class call. */ - -tree -fold_builtin_is_pointer_inverconvertible_with_class (location_t loc, int nargs, - tree *args) -{ - /* Unless users call the builtin directly, the following 3 checks should be - ensured from std::is_pointer_interconvertible_with_class function - template. */ - if (nargs != 1) - { - error_at (loc, "%<__builtin_is_pointer_interconvertible_with_class%> " - "needs a single argument"); - return boolean_false_node; - } - tree arg = args[0]; - if (error_operand_p (arg)) - return boolean_false_node; - if (!TYPE_PTRMEM_P (TREE_TYPE (arg))) - { - error_at (loc, "%<__builtin_is_pointer_interconvertible_with_class%> " - "argument is not pointer to member"); - return boolean_false_node; - } - - if (!TYPE_PTRDATAMEM_P (TREE_TYPE (arg))) - return boolean_false_node; - - tree membertype = TREE_TYPE (TREE_TYPE (arg)); - tree basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (arg)); - if (!complete_type_or_else (basetype, NULL_TREE)) - return boolean_false_node; - - if (TREE_CODE (basetype) != UNION_TYPE - && !std_layout_type_p (basetype)) - return boolean_false_node; - - if (!first_nonstatic_data_member_p (basetype, membertype)) - return boolean_false_node; - - if (TREE_CODE (arg) == PTRMEM_CST) - arg = cplus_expand_constant (arg); - - if (integer_nonzerop (arg)) - return boolean_false_node; - if (integer_zerop (arg)) - return boolean_true_node; - - return fold_build2 (EQ_EXPR, boolean_type_node, arg, - build_zero_cst (TREE_TYPE (arg))); -} - -/* Helper function for is_corresponding_member_aggr. Return true if - MEMBERTYPE pointer-to-data-member ARG can be found in anonymous - union or structure BASETYPE. */ - -static bool -is_corresponding_member_union (tree basetype, tree membertype, tree arg) -{ - for (tree field = TYPE_FIELDS (basetype); field; field = DECL_CHAIN (field)) - if (TREE_CODE (field) != FIELD_DECL || DECL_BIT_FIELD_TYPE (field)) - continue; - else if (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (field), - membertype)) - { - if (TREE_CODE (arg) != INTEGER_CST - || tree_int_cst_equal (arg, byte_position (field))) - return true; - } - else if (ANON_AGGR_TYPE_P (TREE_TYPE (field))) - { - tree narg = arg; - if (TREE_CODE (basetype) != UNION_TYPE - && TREE_CODE (narg) == INTEGER_CST) - narg = size_binop (MINUS_EXPR, arg, byte_position (field)); - if (is_corresponding_member_union (TREE_TYPE (field), - membertype, narg)) - return true; - } - return false; -} - -/* Helper function for fold_builtin_is_corresponding_member call. - Return boolean_false_node if MEMBERTYPE1 BASETYPE1::*ARG1 and - MEMBERTYPE2 BASETYPE2::*ARG2 aren't corresponding members, - boolean_true_node if they are corresponding members, or for - non-constant ARG2 the highest member offset for corresponding - members. */ - -static tree -is_corresponding_member_aggr (location_t loc, tree basetype1, tree membertype1, - tree arg1, tree basetype2, tree membertype2, - tree arg2) -{ - tree field1 = TYPE_FIELDS (basetype1); - tree field2 = TYPE_FIELDS (basetype2); - tree ret = boolean_false_node; - while (1) - { - bool r = next_common_initial_seqence (field1, field2); - if (field1 == NULL_TREE || field2 == NULL_TREE) - break; - if (r - && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (field1), - membertype1) - && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (field2), - membertype2)) - { - tree pos = byte_position (field1); - if (TREE_CODE (arg1) == INTEGER_CST - && tree_int_cst_equal (arg1, pos)) - { - if (TREE_CODE (arg2) == INTEGER_CST) - return boolean_true_node; - return pos; - } - else if (TREE_CODE (arg1) != INTEGER_CST) - ret = pos; - } - else if (ANON_AGGR_TYPE_P (TREE_TYPE (field1)) - && ANON_AGGR_TYPE_P (TREE_TYPE (field2))) - { - if ((!lookup_attribute ("no_unique_address", - DECL_ATTRIBUTES (field1))) - != !lookup_attribute ("no_unique_address", - DECL_ATTRIBUTES (field2))) - break; - if (!tree_int_cst_equal (bit_position (field1), - bit_position (field2))) - break; - bool overlap = true; - tree pos = byte_position (field1); - if (TREE_CODE (arg1) == INTEGER_CST) - { - tree off1 = fold_convert (sizetype, arg1); - tree sz1 = TYPE_SIZE_UNIT (TREE_TYPE (field1)); - if (tree_int_cst_lt (off1, pos) - || tree_int_cst_le (size_binop (PLUS_EXPR, pos, sz1), off1)) - overlap = false; - } - if (TREE_CODE (arg2) == INTEGER_CST) - { - tree off2 = fold_convert (sizetype, arg2); - tree sz2 = TYPE_SIZE_UNIT (TREE_TYPE (field2)); - if (tree_int_cst_lt (off2, pos) - || tree_int_cst_le (size_binop (PLUS_EXPR, pos, sz2), off2)) - overlap = false; - } - if (overlap - && NON_UNION_CLASS_TYPE_P (TREE_TYPE (field1)) - && NON_UNION_CLASS_TYPE_P (TREE_TYPE (field2))) - { - tree narg1 = arg1; - if (TREE_CODE (arg1) == INTEGER_CST) - narg1 = size_binop (MINUS_EXPR, - fold_convert (sizetype, arg1), pos); - tree narg2 = arg2; - if (TREE_CODE (arg2) == INTEGER_CST) - narg2 = size_binop (MINUS_EXPR, - fold_convert (sizetype, arg2), pos); - tree t1 = TREE_TYPE (field1); - tree t2 = TREE_TYPE (field2); - tree nret = is_corresponding_member_aggr (loc, t1, membertype1, - narg1, t2, membertype2, - narg2); - if (nret != boolean_false_node) - { - if (nret == boolean_true_node) - return nret; - if (TREE_CODE (arg1) == INTEGER_CST) - return size_binop (PLUS_EXPR, nret, pos); - ret = size_binop (PLUS_EXPR, nret, pos); - } - } - else if (overlap - && TREE_CODE (TREE_TYPE (field1)) == UNION_TYPE - && TREE_CODE (TREE_TYPE (field2)) == UNION_TYPE) - { - tree narg1 = arg1; - if (TREE_CODE (arg1) == INTEGER_CST) - narg1 = size_binop (MINUS_EXPR, - fold_convert (sizetype, arg1), pos); - tree narg2 = arg2; - if (TREE_CODE (arg2) == INTEGER_CST) - narg2 = size_binop (MINUS_EXPR, - fold_convert (sizetype, arg2), pos); - if (is_corresponding_member_union (TREE_TYPE (field1), - membertype1, narg1) - && is_corresponding_member_union (TREE_TYPE (field2), - membertype2, narg2)) - { - sorry_at (loc, "%<__builtin_is_corresponding_member%> " - "not well defined for anonymous unions"); - return boolean_false_node; - } - } - } - if (!r) - break; - field1 = DECL_CHAIN (field1); - field2 = DECL_CHAIN (field2); - } - return ret; -} - -/* Fold __builtin_is_corresponding_member call. */ - -tree -fold_builtin_is_corresponding_member (location_t loc, int nargs, - tree *args) -{ - /* Unless users call the builtin directly, the following 3 checks should be - ensured from std::is_corresponding_member function template. */ - if (nargs != 2) - { - error_at (loc, "%<__builtin_is_corresponding_member%> " - "needs two arguments"); - return boolean_false_node; - } - tree arg1 = args[0]; - tree arg2 = args[1]; - if (error_operand_p (arg1) || error_operand_p (arg2)) - return boolean_false_node; - if (!TYPE_PTRMEM_P (TREE_TYPE (arg1)) - || !TYPE_PTRMEM_P (TREE_TYPE (arg2))) - { - error_at (loc, "%<__builtin_is_corresponding_member%> " - "argument is not pointer to member"); - return boolean_false_node; - } - - if (!TYPE_PTRDATAMEM_P (TREE_TYPE (arg1)) - || !TYPE_PTRDATAMEM_P (TREE_TYPE (arg2))) - return boolean_false_node; - - tree membertype1 = TREE_TYPE (TREE_TYPE (arg1)); - tree basetype1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (arg1)); - if (!complete_type_or_else (basetype1, NULL_TREE)) - return boolean_false_node; - - tree membertype2 = TREE_TYPE (TREE_TYPE (arg2)); - tree basetype2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (arg2)); - if (!complete_type_or_else (basetype2, NULL_TREE)) - return boolean_false_node; - - if (!NON_UNION_CLASS_TYPE_P (basetype1) - || !NON_UNION_CLASS_TYPE_P (basetype2) - || !std_layout_type_p (basetype1) - || !std_layout_type_p (basetype2)) - return boolean_false_node; - - /* If the member types aren't layout compatible, then they - can't be corresponding members. */ - if (!layout_compatible_type_p (membertype1, membertype2)) - return boolean_false_node; - - if (TREE_CODE (arg1) == PTRMEM_CST) - arg1 = cplus_expand_constant (arg1); - if (TREE_CODE (arg2) == PTRMEM_CST) - arg2 = cplus_expand_constant (arg2); - - if (null_member_pointer_value_p (arg1) - || null_member_pointer_value_p (arg2)) - return boolean_false_node; - - if (TREE_CODE (arg1) == INTEGER_CST - && TREE_CODE (arg2) == INTEGER_CST - && !tree_int_cst_equal (arg1, arg2)) - return boolean_false_node; - - if (TREE_CODE (arg2) == INTEGER_CST - && TREE_CODE (arg1) != INTEGER_CST) - { - std::swap (arg1, arg2); - std::swap (membertype1, membertype2); - std::swap (basetype1, basetype2); - } - - tree ret = is_corresponding_member_aggr (loc, basetype1, membertype1, arg1, - basetype2, membertype2, arg2); - if (TREE_TYPE (ret) == boolean_type_node) - return ret; - /* If both arg1 and arg2 are INTEGER_CSTs, is_corresponding_member_aggr - already returns boolean_{true,false}_node whether those particular - members are corresponding members or not. Otherwise, if only - one of them is INTEGER_CST (canonicalized to first being INTEGER_CST - above), it returns boolean_false_node if it is certainly not a - corresponding member and otherwise we need to do a runtime check that - those two OFFSET_TYPE offsets are equal. - If neither of the operands is INTEGER_CST, is_corresponding_member_aggr - returns the largest offset at which the members would be corresponding - members, so perform arg1 <= ret && arg1 == arg2 runtime check. */ - gcc_assert (TREE_CODE (arg2) != INTEGER_CST); - if (TREE_CODE (arg1) == INTEGER_CST) - return fold_build2 (EQ_EXPR, boolean_type_node, arg1, - fold_convert (TREE_TYPE (arg1), arg2)); - ret = fold_build2 (LE_EXPR, boolean_type_node, - fold_convert (pointer_sized_int_node, arg1), - fold_convert (pointer_sized_int_node, ret)); - return fold_build2 (TRUTH_AND_EXPR, boolean_type_node, ret, - fold_build2 (EQ_EXPR, boolean_type_node, arg1, - fold_convert (TREE_TYPE (arg1), arg2))); -} - -/* Actually evaluates the trait. */ - -static bool -trait_expr_value (cp_trait_kind kind, tree type1, tree type2) -{ - enum tree_code type_code1; - tree t; - - type_code1 = TREE_CODE (type1); - - switch (kind) - { - case CPTK_HAS_NOTHROW_ASSIGN: - type1 = strip_array_types (type1); - return (!CP_TYPE_CONST_P (type1) && type_code1 != REFERENCE_TYPE - && (trait_expr_value (CPTK_HAS_TRIVIAL_ASSIGN, type1, type2) - || (CLASS_TYPE_P (type1) - && classtype_has_nothrow_assign_or_copy_p (type1, - true)))); - - case CPTK_HAS_TRIVIAL_ASSIGN: - /* ??? The standard seems to be missing the "or array of such a class - type" wording for this trait. */ - type1 = strip_array_types (type1); - return (!CP_TYPE_CONST_P (type1) && type_code1 != REFERENCE_TYPE - && (trivial_type_p (type1) - || (CLASS_TYPE_P (type1) - && TYPE_HAS_TRIVIAL_COPY_ASSIGN (type1)))); - - case CPTK_HAS_NOTHROW_CONSTRUCTOR: - type1 = strip_array_types (type1); - return (trait_expr_value (CPTK_HAS_TRIVIAL_CONSTRUCTOR, type1, type2) - || (CLASS_TYPE_P (type1) - && (t = locate_ctor (type1)) - && maybe_instantiate_noexcept (t) - && TYPE_NOTHROW_P (TREE_TYPE (t)))); - - case CPTK_HAS_TRIVIAL_CONSTRUCTOR: - type1 = strip_array_types (type1); - return (trivial_type_p (type1) - || (CLASS_TYPE_P (type1) && TYPE_HAS_TRIVIAL_DFLT (type1))); - - case CPTK_HAS_NOTHROW_COPY: - type1 = strip_array_types (type1); - return (trait_expr_value (CPTK_HAS_TRIVIAL_COPY, type1, type2) - || (CLASS_TYPE_P (type1) - && classtype_has_nothrow_assign_or_copy_p (type1, false))); - - case CPTK_HAS_TRIVIAL_COPY: - /* ??? The standard seems to be missing the "or array of such a class - type" wording for this trait. */ - type1 = strip_array_types (type1); - return (trivial_type_p (type1) || type_code1 == REFERENCE_TYPE - || (CLASS_TYPE_P (type1) && TYPE_HAS_TRIVIAL_COPY_CTOR (type1))); - - case CPTK_HAS_TRIVIAL_DESTRUCTOR: - type1 = strip_array_types (type1); - return (trivial_type_p (type1) || type_code1 == REFERENCE_TYPE - || (CLASS_TYPE_P (type1) - && TYPE_HAS_TRIVIAL_DESTRUCTOR (type1))); - - case CPTK_HAS_VIRTUAL_DESTRUCTOR: - return type_has_virtual_destructor (type1); - - case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS: - return type_has_unique_obj_representations (type1); - - case CPTK_IS_ABSTRACT: - return ABSTRACT_CLASS_TYPE_P (type1); - - case CPTK_IS_AGGREGATE: - return CP_AGGREGATE_TYPE_P (type1); - - case CPTK_IS_BASE_OF: - return (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2) - && (same_type_ignoring_top_level_qualifiers_p (type1, type2) - || DERIVED_FROM_P (type1, type2))); - - case CPTK_IS_CLASS: - return NON_UNION_CLASS_TYPE_P (type1); - - case CPTK_IS_EMPTY: - return NON_UNION_CLASS_TYPE_P (type1) && CLASSTYPE_EMPTY_P (type1); - - case CPTK_IS_ENUM: - return type_code1 == ENUMERAL_TYPE; - - case CPTK_IS_FINAL: - return CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1); - - case CPTK_IS_LAYOUT_COMPATIBLE: - return layout_compatible_type_p (type1, type2); - - case CPTK_IS_LITERAL_TYPE: - return literal_type_p (type1); - - case CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF: - return pointer_interconvertible_base_of_p (type1, type2); - - case CPTK_IS_POD: - return pod_type_p (type1); - - case CPTK_IS_POLYMORPHIC: - return CLASS_TYPE_P (type1) && TYPE_POLYMORPHIC_P (type1); - - case CPTK_IS_SAME_AS: - return same_type_p (type1, type2); - - case CPTK_IS_STD_LAYOUT: - return std_layout_type_p (type1); - - case CPTK_IS_TRIVIAL: - return trivial_type_p (type1); - - case CPTK_IS_TRIVIALLY_ASSIGNABLE: - return is_trivially_xible (MODIFY_EXPR, type1, type2); - - case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE: - return is_trivially_xible (INIT_EXPR, type1, type2); - - case CPTK_IS_TRIVIALLY_COPYABLE: - return trivially_copyable_p (type1); - - case CPTK_IS_UNION: - return type_code1 == UNION_TYPE; - - case CPTK_IS_ASSIGNABLE: - return is_xible (MODIFY_EXPR, type1, type2); - - case CPTK_IS_CONSTRUCTIBLE: - return is_xible (INIT_EXPR, type1, type2); - - case CPTK_IS_NOTHROW_ASSIGNABLE: - return is_nothrow_xible (MODIFY_EXPR, type1, type2); - - case CPTK_IS_NOTHROW_CONSTRUCTIBLE: - return is_nothrow_xible (INIT_EXPR, type1, type2); - - default: - gcc_unreachable (); - return false; - } -} - -/* If TYPE is an array of unknown bound, or (possibly cv-qualified) - void, or a complete type, returns true, otherwise false. */ - -static bool -check_trait_type (tree type) -{ - if (type == NULL_TREE) - return true; - - if (TREE_CODE (type) == TREE_LIST) - return (check_trait_type (TREE_VALUE (type)) - && check_trait_type (TREE_CHAIN (type))); - - if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type) - && COMPLETE_TYPE_P (TREE_TYPE (type))) - return true; - - if (VOID_TYPE_P (type)) - return true; - - return !!complete_type_or_else (strip_array_types (type), NULL_TREE); -} - -/* Process a trait expression. */ - -tree -finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2) -{ - if (type1 == error_mark_node - || type2 == error_mark_node) - return error_mark_node; - - if (processing_template_decl) - { - tree trait_expr = make_node (TRAIT_EXPR); - TREE_TYPE (trait_expr) = boolean_type_node; - TRAIT_EXPR_TYPE1 (trait_expr) = type1; - TRAIT_EXPR_TYPE2 (trait_expr) = type2; - TRAIT_EXPR_KIND (trait_expr) = kind; - TRAIT_EXPR_LOCATION (trait_expr) = loc; - return trait_expr; - } - - switch (kind) - { - case CPTK_HAS_NOTHROW_ASSIGN: - case CPTK_HAS_TRIVIAL_ASSIGN: - case CPTK_HAS_NOTHROW_CONSTRUCTOR: - case CPTK_HAS_TRIVIAL_CONSTRUCTOR: - case CPTK_HAS_NOTHROW_COPY: - case CPTK_HAS_TRIVIAL_COPY: - case CPTK_HAS_TRIVIAL_DESTRUCTOR: - case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS: - case CPTK_HAS_VIRTUAL_DESTRUCTOR: - case CPTK_IS_ABSTRACT: - case CPTK_IS_AGGREGATE: - case CPTK_IS_EMPTY: - case CPTK_IS_FINAL: - case CPTK_IS_LITERAL_TYPE: - case CPTK_IS_POD: - case CPTK_IS_POLYMORPHIC: - case CPTK_IS_STD_LAYOUT: - case CPTK_IS_TRIVIAL: - case CPTK_IS_TRIVIALLY_COPYABLE: - if (!check_trait_type (type1)) - return error_mark_node; - break; - - case CPTK_IS_ASSIGNABLE: - case CPTK_IS_CONSTRUCTIBLE: - break; - - case CPTK_IS_TRIVIALLY_ASSIGNABLE: - case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE: - case CPTK_IS_NOTHROW_ASSIGNABLE: - case CPTK_IS_NOTHROW_CONSTRUCTIBLE: - if (!check_trait_type (type1) - || !check_trait_type (type2)) - return error_mark_node; - break; - - case CPTK_IS_BASE_OF: - case CPTK_IS_POINTER_INTERCONVERTIBLE_BASE_OF: - if (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2) - && !same_type_ignoring_top_level_qualifiers_p (type1, type2) - && !complete_type_or_else (type2, NULL_TREE)) - /* We already issued an error. */ - return error_mark_node; - break; - - case CPTK_IS_CLASS: - case CPTK_IS_ENUM: - case CPTK_IS_UNION: - case CPTK_IS_SAME_AS: - break; - - case CPTK_IS_LAYOUT_COMPATIBLE: - if (!array_of_unknown_bound_p (type1) - && TREE_CODE (type1) != VOID_TYPE - && !complete_type_or_else (type1, NULL_TREE)) - /* We already issued an error. */ - return error_mark_node; - if (!array_of_unknown_bound_p (type2) - && TREE_CODE (type2) != VOID_TYPE - && !complete_type_or_else (type2, NULL_TREE)) - /* We already issued an error. */ - return error_mark_node; - break; - - default: - gcc_unreachable (); - } - - tree val = (trait_expr_value (kind, type1, type2) - ? boolean_true_node : boolean_false_node); - return maybe_wrap_with_location (val, loc); -} - -/* Do-nothing variants of functions to handle pragma FLOAT_CONST_DECIMAL64, - which is ignored for C++. */ - -void -set_float_const_decimal64 (void) -{ -} - -void -clear_float_const_decimal64 (void) -{ -} - -bool -float_const_decimal64_p (void) -{ - return 0; -} - - -/* Return true if T designates the implied `this' parameter. */ - -bool -is_this_parameter (tree t) -{ - if (!DECL_P (t) || DECL_NAME (t) != this_identifier) - return false; - gcc_assert (TREE_CODE (t) == PARM_DECL - || (TREE_CODE (t) == VAR_DECL && DECL_HAS_VALUE_EXPR_P (t)) - || (cp_binding_oracle && TREE_CODE (t) == VAR_DECL)); - return true; -} - -/* Insert the deduced return type for an auto function. */ - -void -apply_deduced_return_type (tree fco, tree return_type) -{ - tree result; - - if (return_type == error_mark_node) - return; - - if (DECL_CONV_FN_P (fco)) - DECL_NAME (fco) = make_conv_op_name (return_type); - - TREE_TYPE (fco) = change_return_type (return_type, TREE_TYPE (fco)); - - result = DECL_RESULT (fco); - if (result == NULL_TREE) - return; - if (TREE_TYPE (result) == return_type) - return; - - if (!processing_template_decl && !VOID_TYPE_P (return_type) - && !complete_type_or_else (return_type, NULL_TREE)) - return; - - /* We already have a DECL_RESULT from start_preparsed_function. - Now we need to redo the work it and allocate_struct_function - did to reflect the new type. */ - gcc_assert (current_function_decl == fco); - result = build_decl (input_location, RESULT_DECL, NULL_TREE, - TYPE_MAIN_VARIANT (return_type)); - DECL_ARTIFICIAL (result) = 1; - DECL_IGNORED_P (result) = 1; - cp_apply_type_quals_to_decl (cp_type_quals (return_type), - result); - - DECL_RESULT (fco) = result; - - if (!processing_template_decl) - { - bool aggr = aggregate_value_p (result, fco); -#ifdef PCC_STATIC_STRUCT_RETURN - cfun->returns_pcc_struct = aggr; -#endif - cfun->returns_struct = aggr; - } -} - -/* DECL is a local variable or parameter from the surrounding scope of a - lambda-expression. Returns the decltype for a use of the capture field - for DECL even if it hasn't been captured yet. */ - -static tree -capture_decltype (tree decl) -{ - tree lam = CLASSTYPE_LAMBDA_EXPR (DECL_CONTEXT (current_function_decl)); - tree cap = lookup_name (DECL_NAME (decl), LOOK_where::BLOCK, - LOOK_want::HIDDEN_LAMBDA); - tree type; - - if (cap && is_capture_proxy (cap)) - type = TREE_TYPE (cap); - else - switch (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lam)) - { - case CPLD_NONE: - error ("%qD is not captured", decl); - return error_mark_node; - - case CPLD_COPY: - type = TREE_TYPE (decl); - if (TYPE_REF_P (type) - && TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE) - type = TREE_TYPE (type); - break; - - case CPLD_REFERENCE: - type = TREE_TYPE (decl); - if (!TYPE_REF_P (type)) - type = build_reference_type (TREE_TYPE (decl)); - break; - - default: - gcc_unreachable (); - } - - if (!TYPE_REF_P (type)) - { - if (!LAMBDA_EXPR_MUTABLE_P (lam)) - type = cp_build_qualified_type (type, (cp_type_quals (type) - |TYPE_QUAL_CONST)); - type = build_reference_type (type); - } - return type; -} - -/* Build a unary fold expression of EXPR over OP. If IS_RIGHT is true, - this is a right unary fold. Otherwise it is a left unary fold. */ - -static tree -finish_unary_fold_expr (tree expr, int op, tree_code dir) -{ - /* Build a pack expansion (assuming expr has pack type). */ - if (!uses_parameter_packs (expr)) - { - error_at (location_of (expr), "operand of fold expression has no " - "unexpanded parameter packs"); - return error_mark_node; - } - tree pack = make_pack_expansion (expr); - - /* Build the fold expression. */ - tree code = build_int_cstu (integer_type_node, abs (op)); - tree fold = build_min_nt_loc (UNKNOWN_LOCATION, dir, code, pack); - FOLD_EXPR_MODIFY_P (fold) = (op < 0); - TREE_TYPE (fold) = build_dependent_operator_type (NULL_TREE, - FOLD_EXPR_OP (fold), - FOLD_EXPR_MODIFY_P (fold)); - return fold; -} - -tree -finish_left_unary_fold_expr (tree expr, int op) -{ - return finish_unary_fold_expr (expr, op, UNARY_LEFT_FOLD_EXPR); -} - -tree -finish_right_unary_fold_expr (tree expr, int op) -{ - return finish_unary_fold_expr (expr, op, UNARY_RIGHT_FOLD_EXPR); -} - -/* Build a binary fold expression over EXPR1 and EXPR2. The - associativity of the fold is determined by EXPR1 and EXPR2 (whichever - has an unexpanded parameter pack). */ - -tree -finish_binary_fold_expr (tree pack, tree init, int op, tree_code dir) -{ - pack = make_pack_expansion (pack); - tree code = build_int_cstu (integer_type_node, abs (op)); - tree fold = build_min_nt_loc (UNKNOWN_LOCATION, dir, code, pack, init); - FOLD_EXPR_MODIFY_P (fold) = (op < 0); - TREE_TYPE (fold) = build_dependent_operator_type (NULL_TREE, - FOLD_EXPR_OP (fold), - FOLD_EXPR_MODIFY_P (fold)); - return fold; -} - -tree -finish_binary_fold_expr (tree expr1, tree expr2, int op) -{ - // Determine which expr has an unexpanded parameter pack and - // set the pack and initial term. - bool pack1 = uses_parameter_packs (expr1); - bool pack2 = uses_parameter_packs (expr2); - if (pack1 && !pack2) - return finish_binary_fold_expr (expr1, expr2, op, BINARY_RIGHT_FOLD_EXPR); - else if (pack2 && !pack1) - return finish_binary_fold_expr (expr2, expr1, op, BINARY_LEFT_FOLD_EXPR); - else - { - if (pack1) - error ("both arguments in binary fold have unexpanded parameter packs"); - else - error ("no unexpanded parameter packs in binary fold"); - } - return error_mark_node; -} - -/* Finish __builtin_launder (arg). */ - -tree -finish_builtin_launder (location_t loc, tree arg, tsubst_flags_t complain) -{ - tree orig_arg = arg; - if (!type_dependent_expression_p (arg)) - arg = decay_conversion (arg, complain); - if (error_operand_p (arg)) - return error_mark_node; - if (!type_dependent_expression_p (arg) - && !TYPE_PTR_P (TREE_TYPE (arg))) - { - error_at (loc, "non-pointer argument to %<__builtin_launder%>"); - return error_mark_node; - } - if (processing_template_decl) - arg = orig_arg; - return build_call_expr_internal_loc (loc, IFN_LAUNDER, - TREE_TYPE (arg), 1, arg); -} - -/* Finish __builtin_convertvector (arg, type). */ - -tree -cp_build_vec_convert (tree arg, location_t loc, tree type, - tsubst_flags_t complain) -{ - if (error_operand_p (type)) - return error_mark_node; - if (error_operand_p (arg)) - return error_mark_node; - - tree ret = NULL_TREE; - if (!type_dependent_expression_p (arg) && !dependent_type_p (type)) - ret = c_build_vec_convert (cp_expr_loc_or_input_loc (arg), - decay_conversion (arg, complain), - loc, type, (complain & tf_error) != 0); - - if (!processing_template_decl) - return ret; - - return build_call_expr_internal_loc (loc, IFN_VEC_CONVERT, type, 1, arg); -} - -/* Finish __builtin_bit_cast (type, arg). */ - -tree -cp_build_bit_cast (location_t loc, tree type, tree arg, - tsubst_flags_t complain) -{ - if (error_operand_p (type)) - return error_mark_node; - if (!dependent_type_p (type)) - { - if (!complete_type_or_maybe_complain (type, NULL_TREE, complain)) - return error_mark_node; - if (TREE_CODE (type) == ARRAY_TYPE) - { - /* std::bit_cast for destination ARRAY_TYPE is not possible, - as functions may not return an array, so don't bother trying - to support this (and then deal with VLAs etc.). */ - error_at (loc, "%<__builtin_bit_cast%> destination type %qT " - "is an array type", type); - return error_mark_node; - } - if (!trivially_copyable_p (type)) - { - error_at (loc, "%<__builtin_bit_cast%> destination type %qT " - "is not trivially copyable", type); - return error_mark_node; - } - } - - if (error_operand_p (arg)) - return error_mark_node; - - if (!type_dependent_expression_p (arg)) - { - if (TREE_CODE (TREE_TYPE (arg)) == ARRAY_TYPE) - { - /* Don't perform array-to-pointer conversion. */ - arg = mark_rvalue_use (arg, loc, true); - if (!complete_type_or_maybe_complain (TREE_TYPE (arg), arg, complain)) - return error_mark_node; - } - else - arg = decay_conversion (arg, complain); - - if (error_operand_p (arg)) - return error_mark_node; - - if (!trivially_copyable_p (TREE_TYPE (arg))) - { - error_at (cp_expr_loc_or_loc (arg, loc), - "%<__builtin_bit_cast%> source type %qT " - "is not trivially copyable", TREE_TYPE (arg)); - return error_mark_node; - } - if (!dependent_type_p (type) - && !cp_tree_equal (TYPE_SIZE_UNIT (type), - TYPE_SIZE_UNIT (TREE_TYPE (arg)))) - { - error_at (loc, "%<__builtin_bit_cast%> source size %qE " - "not equal to destination type size %qE", - TYPE_SIZE_UNIT (TREE_TYPE (arg)), - TYPE_SIZE_UNIT (type)); - return error_mark_node; - } - } - - tree ret = build_min (BIT_CAST_EXPR, type, arg); - SET_EXPR_LOCATION (ret, loc); - - if (!processing_template_decl && CLASS_TYPE_P (type)) - ret = get_target_expr_sfinae (ret, complain); - - return ret; -} - -#include "gt-cp-semantics.h" |