aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/semantics.c
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2022-01-14 16:56:44 +0100
committerMartin Liska <mliska@suse.cz>2022-01-17 22:12:04 +0100
commit5c69acb32329d49e58c26fa41ae74229a52b9106 (patch)
treeddb05f9d73afb6f998457d2ac4b720e3b3b60483 /gcc/cp/semantics.c
parent490e23032baaece71f2ec09fa1805064b150fbc2 (diff)
downloadgcc-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.c12340
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"