aboutsummaryrefslogtreecommitdiff
path: root/gcc/c/c-parser.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/c/c-parser.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/c/c-parser.c')
-rw-r--r--gcc/c/c-parser.c23404
1 files changed, 0 insertions, 23404 deletions
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
deleted file mode 100644
index 20774f7..0000000
--- a/gcc/c/c-parser.c
+++ /dev/null
@@ -1,23404 +0,0 @@
-/* Parser for C and Objective-C.
- Copyright (C) 1987-2022 Free Software Foundation, Inc.
-
- Parser actions based on the old Bison parser; structure somewhat
- influenced by and fragments based on the C++ parser.
-
-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/>. */
-
-/* TODO:
-
- Make sure all relevant comments, and all relevant code from all
- actions, brought over from old parser. Verify exact correspondence
- of syntax accepted.
-
- Add testcases covering every input symbol in every state in old and
- new parsers.
-
- Include full syntax for GNU C, including erroneous cases accepted
- with error messages, in syntax productions in comments.
-
- Make more diagnostics in the front end generally take an explicit
- location rather than implicitly using input_location. */
-
-#include "config.h"
-#define INCLUDE_MEMORY
-#include "system.h"
-#include "coretypes.h"
-#include "target.h"
-#include "function.h"
-#include "c-tree.h"
-#include "timevar.h"
-#include "stringpool.h"
-#include "cgraph.h"
-#include "attribs.h"
-#include "stor-layout.h"
-#include "varasm.h"
-#include "trans-mem.h"
-#include "c-family/c-pragma.h"
-#include "c-lang.h"
-#include "c-family/c-objc.h"
-#include "plugin.h"
-#include "omp-general.h"
-#include "omp-offload.h"
-#include "builtins.h"
-#include "gomp-constants.h"
-#include "c-family/c-indentation.h"
-#include "gimple-expr.h"
-#include "context.h"
-#include "gcc-rich-location.h"
-#include "c-parser.h"
-#include "gimple-parser.h"
-#include "read-rtl-function.h"
-#include "run-rtl-passes.h"
-#include "intl.h"
-#include "c-family/name-hint.h"
-#include "tree-iterator.h"
-#include "tree-pretty-print.h"
-#include "memmodel.h"
-#include "c-family/known-headers.h"
-
-/* We need to walk over decls with incomplete struct/union/enum types
- after parsing the whole translation unit.
- In finish_decl(), if the decl is static, has incomplete
- struct/union/enum type, it is appended to incomplete_record_decls.
- In c_parser_translation_unit(), we iterate over incomplete_record_decls
- and report error if any of the decls are still incomplete. */
-
-vec<tree> incomplete_record_decls;
-
-void
-set_c_expr_source_range (c_expr *expr,
- location_t start, location_t finish)
-{
- expr->src_range.m_start = start;
- expr->src_range.m_finish = finish;
- if (expr->value)
- set_source_range (expr->value, start, finish);
-}
-
-void
-set_c_expr_source_range (c_expr *expr,
- source_range src_range)
-{
- expr->src_range = src_range;
- if (expr->value)
- set_source_range (expr->value, src_range);
-}
-
-
-/* Initialization routine for this file. */
-
-void
-c_parse_init (void)
-{
- /* The only initialization required is of the reserved word
- identifiers. */
- unsigned int i;
- tree id;
- int mask = 0;
-
- /* Make sure RID_MAX hasn't grown past the 8 bits used to hold the keyword in
- the c_token structure. */
- gcc_assert (RID_MAX <= 255);
-
- mask |= D_CXXONLY;
- if (!flag_isoc99)
- mask |= D_C99;
- if (flag_no_asm)
- {
- mask |= D_ASM | D_EXT;
- if (!flag_isoc99)
- mask |= D_EXT89;
- }
- if (!c_dialect_objc ())
- mask |= D_OBJC | D_CXX_OBJC;
-
- ridpointers = ggc_cleared_vec_alloc<tree> ((int) RID_MAX);
- for (i = 0; i < num_c_common_reswords; i++)
- {
- /* If a keyword is disabled, do not enter it into the table
- and so create a canonical spelling that isn't a keyword. */
- if (c_common_reswords[i].disable & mask)
- {
- if (warn_cxx_compat
- && (c_common_reswords[i].disable & D_CXXWARN))
- {
- id = get_identifier (c_common_reswords[i].word);
- C_SET_RID_CODE (id, RID_CXX_COMPAT_WARN);
- C_IS_RESERVED_WORD (id) = 1;
- }
- continue;
- }
-
- id = get_identifier (c_common_reswords[i].word);
- C_SET_RID_CODE (id, c_common_reswords[i].rid);
- C_IS_RESERVED_WORD (id) = 1;
- ridpointers [(int) c_common_reswords[i].rid] = id;
- }
-
- for (i = 0; i < NUM_INT_N_ENTS; i++)
- {
- /* We always create the symbols but they aren't always supported. */
- char name[50];
- sprintf (name, "__int%d", int_n_data[i].bitsize);
- id = get_identifier (name);
- C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
- C_IS_RESERVED_WORD (id) = 1;
-
- sprintf (name, "__int%d__", int_n_data[i].bitsize);
- id = get_identifier (name);
- C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
- C_IS_RESERVED_WORD (id) = 1;
- }
-}
-
-/* A parser structure recording information about the state and
- context of parsing. Includes lexer information with up to two
- tokens of look-ahead; more are not needed for C. */
-struct GTY(()) c_parser {
- /* The look-ahead tokens. */
- c_token * GTY((skip)) tokens;
- /* Buffer for look-ahead tokens. */
- c_token tokens_buf[4];
- /* How many look-ahead tokens are available (0 - 4, or
- more if parsing from pre-lexed tokens). */
- unsigned int tokens_avail;
- /* Raw look-ahead tokens, used only for checking in Objective-C
- whether '[[' starts attributes. */
- vec<c_token, va_gc> *raw_tokens;
- /* The number of raw look-ahead tokens that have since been fully
- lexed. */
- unsigned int raw_tokens_used;
- /* True if a syntax error is being recovered from; false otherwise.
- c_parser_error sets this flag. It should clear this flag when
- enough tokens have been consumed to recover from the error. */
- BOOL_BITFIELD error : 1;
- /* True if we're processing a pragma, and shouldn't automatically
- consume CPP_PRAGMA_EOL. */
- BOOL_BITFIELD in_pragma : 1;
- /* True if we're parsing the outermost block of an if statement. */
- BOOL_BITFIELD in_if_block : 1;
- /* True if we want to lex a translated, joined string (for an
- initial #pragma pch_preprocess). Otherwise the parser is
- responsible for concatenating strings and translating to the
- execution character set as needed. */
- BOOL_BITFIELD lex_joined_string : 1;
- /* True if, when the parser is concatenating string literals, it
- should translate them to the execution character set (false
- inside attributes). */
- BOOL_BITFIELD translate_strings_p : 1;
-
- /* Objective-C specific parser/lexer information. */
-
- /* True if we are in a context where the Objective-C "PQ" keywords
- are considered keywords. */
- BOOL_BITFIELD objc_pq_context : 1;
- /* True if we are parsing a (potential) Objective-C foreach
- statement. This is set to true after we parsed 'for (' and while
- we wait for 'in' or ';' to decide if it's a standard C for loop or an
- Objective-C foreach loop. */
- BOOL_BITFIELD objc_could_be_foreach_context : 1;
- /* The following flag is needed to contextualize Objective-C lexical
- analysis. In some cases (e.g., 'int NSObject;'), it is
- undesirable to bind an identifier to an Objective-C class, even
- if a class with that name exists. */
- BOOL_BITFIELD objc_need_raw_identifier : 1;
- /* Nonzero if we're processing a __transaction statement. The value
- is 1 | TM_STMT_ATTR_*. */
- unsigned int in_transaction : 4;
- /* True if we are in a context where the Objective-C "Property attribute"
- keywords are valid. */
- BOOL_BITFIELD objc_property_attr_context : 1;
-
- /* Whether we have just seen/constructed a string-literal. Set when
- returning a string-literal from c_parser_string_literal. Reset
- in consume_token. Useful when we get a parse error and see an
- unknown token, which could have been a string-literal constant
- macro. */
- BOOL_BITFIELD seen_string_literal : 1;
-
- /* Location of the last consumed token. */
- location_t last_token_location;
-};
-
-/* Return a pointer to the Nth token in PARSERs tokens_buf. */
-
-c_token *
-c_parser_tokens_buf (c_parser *parser, unsigned n)
-{
- return &parser->tokens_buf[n];
-}
-
-/* Return the error state of PARSER. */
-
-bool
-c_parser_error (c_parser *parser)
-{
- return parser->error;
-}
-
-/* Set the error state of PARSER to ERR. */
-
-void
-c_parser_set_error (c_parser *parser, bool err)
-{
- parser->error = err;
-}
-
-
-/* The actual parser and external interface. ??? Does this need to be
- garbage-collected? */
-
-static GTY (()) c_parser *the_parser;
-
-/* Read in and lex a single token, storing it in *TOKEN. If RAW,
- context-sensitive postprocessing of the token is not done. */
-
-static void
-c_lex_one_token (c_parser *parser, c_token *token, bool raw = false)
-{
- timevar_push (TV_LEX);
-
- if (raw || vec_safe_length (parser->raw_tokens) == 0)
- {
- token->type = c_lex_with_flags (&token->value, &token->location,
- &token->flags,
- (parser->lex_joined_string
- ? 0 : C_LEX_STRING_NO_JOIN));
- token->id_kind = C_ID_NONE;
- token->keyword = RID_MAX;
- token->pragma_kind = PRAGMA_NONE;
- }
- else
- {
- /* Use a token previously lexed as a raw look-ahead token, and
- complete the processing on it. */
- *token = (*parser->raw_tokens)[parser->raw_tokens_used];
- ++parser->raw_tokens_used;
- if (parser->raw_tokens_used == vec_safe_length (parser->raw_tokens))
- {
- vec_free (parser->raw_tokens);
- parser->raw_tokens_used = 0;
- }
- }
-
- if (raw)
- goto out;
-
- switch (token->type)
- {
- case CPP_NAME:
- {
- tree decl;
-
- bool objc_force_identifier = parser->objc_need_raw_identifier;
- if (c_dialect_objc ())
- parser->objc_need_raw_identifier = false;
-
- if (C_IS_RESERVED_WORD (token->value))
- {
- enum rid rid_code = C_RID_CODE (token->value);
-
- if (rid_code == RID_CXX_COMPAT_WARN)
- {
- warning_at (token->location,
- OPT_Wc___compat,
- "identifier %qE conflicts with C++ keyword",
- token->value);
- }
- else if (rid_code >= RID_FIRST_ADDR_SPACE
- && rid_code <= RID_LAST_ADDR_SPACE)
- {
- addr_space_t as;
- as = (addr_space_t) (rid_code - RID_FIRST_ADDR_SPACE);
- targetm.addr_space.diagnose_usage (as, token->location);
- token->id_kind = C_ID_ADDRSPACE;
- token->keyword = rid_code;
- break;
- }
- else if (c_dialect_objc () && OBJC_IS_PQ_KEYWORD (rid_code))
- {
- /* We found an Objective-C "pq" keyword (in, out,
- inout, bycopy, byref, oneway). They need special
- care because the interpretation depends on the
- context. */
- if (parser->objc_pq_context)
- {
- token->type = CPP_KEYWORD;
- token->keyword = rid_code;
- break;
- }
- else if (parser->objc_could_be_foreach_context
- && rid_code == RID_IN)
- {
- /* We are in Objective-C, inside a (potential)
- foreach context (which means after having
- parsed 'for (', but before having parsed ';'),
- and we found 'in'. We consider it the keyword
- which terminates the declaration at the
- beginning of a foreach-statement. Note that
- this means you can't use 'in' for anything else
- in that context; in particular, in Objective-C
- you can't use 'in' as the name of the running
- variable in a C for loop. We could potentially
- try to add code here to disambiguate, but it
- seems a reasonable limitation. */
- token->type = CPP_KEYWORD;
- token->keyword = rid_code;
- break;
- }
- /* Else, "pq" keywords outside of the "pq" context are
- not keywords, and we fall through to the code for
- normal tokens. */
- }
- else if (c_dialect_objc () && OBJC_IS_PATTR_KEYWORD (rid_code))
- {
- /* We found an Objective-C "property attribute"
- keyword (getter, setter, readonly, etc). These are
- only valid in the property context. */
- if (parser->objc_property_attr_context)
- {
- token->type = CPP_KEYWORD;
- token->keyword = rid_code;
- break;
- }
- /* Else they are not special keywords.
- */
- }
- else if (c_dialect_objc ()
- && (OBJC_IS_AT_KEYWORD (rid_code)
- || OBJC_IS_CXX_KEYWORD (rid_code)))
- {
- /* We found one of the Objective-C "@" keywords (defs,
- selector, synchronized, etc) or one of the
- Objective-C "cxx" keywords (class, private,
- protected, public, try, catch, throw) without a
- preceding '@' sign. Do nothing and fall through to
- the code for normal tokens (in C++ we would still
- consider the CXX ones keywords, but not in C). */
- ;
- }
- else
- {
- token->type = CPP_KEYWORD;
- token->keyword = rid_code;
- break;
- }
- }
-
- decl = lookup_name (token->value);
- if (decl)
- {
- if (TREE_CODE (decl) == TYPE_DECL)
- {
- token->id_kind = C_ID_TYPENAME;
- break;
- }
- }
- else if (c_dialect_objc ())
- {
- tree objc_interface_decl = objc_is_class_name (token->value);
- /* Objective-C class names are in the same namespace as
- variables and typedefs, and hence are shadowed by local
- declarations. */
- if (objc_interface_decl
- && (!objc_force_identifier || global_bindings_p ()))
- {
- token->value = objc_interface_decl;
- token->id_kind = C_ID_CLASSNAME;
- break;
- }
- }
- token->id_kind = C_ID_ID;
- }
- break;
- case CPP_AT_NAME:
- /* This only happens in Objective-C; it must be a keyword. */
- token->type = CPP_KEYWORD;
- switch (C_RID_CODE (token->value))
- {
- /* Replace 'class' with '@class', 'private' with '@private',
- etc. This prevents confusion with the C++ keyword
- 'class', and makes the tokens consistent with other
- Objective-C 'AT' keywords. For example '@class' is
- reported as RID_AT_CLASS which is consistent with
- '@synchronized', which is reported as
- RID_AT_SYNCHRONIZED.
- */
- case RID_CLASS: token->keyword = RID_AT_CLASS; break;
- case RID_PRIVATE: token->keyword = RID_AT_PRIVATE; break;
- case RID_PROTECTED: token->keyword = RID_AT_PROTECTED; break;
- case RID_PUBLIC: token->keyword = RID_AT_PUBLIC; break;
- case RID_THROW: token->keyword = RID_AT_THROW; break;
- case RID_TRY: token->keyword = RID_AT_TRY; break;
- case RID_CATCH: token->keyword = RID_AT_CATCH; break;
- case RID_SYNCHRONIZED: token->keyword = RID_AT_SYNCHRONIZED; break;
- default: token->keyword = C_RID_CODE (token->value);
- }
- break;
- case CPP_COLON:
- case CPP_COMMA:
- case CPP_CLOSE_PAREN:
- case CPP_SEMICOLON:
- /* These tokens may affect the interpretation of any identifiers
- following, if doing Objective-C. */
- if (c_dialect_objc ())
- parser->objc_need_raw_identifier = false;
- break;
- case CPP_PRAGMA:
- /* We smuggled the cpp_token->u.pragma value in an INTEGER_CST. */
- token->pragma_kind = (enum pragma_kind) TREE_INT_CST_LOW (token->value);
- token->value = NULL;
- break;
- default:
- break;
- }
- out:
- timevar_pop (TV_LEX);
-}
-
-/* Return a pointer to the next token from PARSER, reading it in if
- necessary. */
-
-c_token *
-c_parser_peek_token (c_parser *parser)
-{
- if (parser->tokens_avail == 0)
- {
- c_lex_one_token (parser, &parser->tokens[0]);
- parser->tokens_avail = 1;
- }
- return &parser->tokens[0];
-}
-
-/* Return a pointer to the next-but-one token from PARSER, reading it
- in if necessary. The next token is already read in. */
-
-c_token *
-c_parser_peek_2nd_token (c_parser *parser)
-{
- if (parser->tokens_avail >= 2)
- return &parser->tokens[1];
- gcc_assert (parser->tokens_avail == 1);
- gcc_assert (parser->tokens[0].type != CPP_EOF);
- gcc_assert (parser->tokens[0].type != CPP_PRAGMA_EOL);
- c_lex_one_token (parser, &parser->tokens[1]);
- parser->tokens_avail = 2;
- return &parser->tokens[1];
-}
-
-/* Return a pointer to the Nth token from PARSER, reading it
- in if necessary. The N-1th token is already read in. */
-
-c_token *
-c_parser_peek_nth_token (c_parser *parser, unsigned int n)
-{
- /* N is 1-based, not zero-based. */
- gcc_assert (n > 0);
-
- if (parser->tokens_avail >= n)
- return &parser->tokens[n - 1];
- gcc_assert (parser->tokens_avail == n - 1);
- c_lex_one_token (parser, &parser->tokens[n - 1]);
- parser->tokens_avail = n;
- return &parser->tokens[n - 1];
-}
-
-/* Return a pointer to the Nth token from PARSER, reading it in as a
- raw look-ahead token if necessary. The N-1th token is already read
- in. Raw look-ahead tokens remain available for when the non-raw
- functions above are called. */
-
-c_token *
-c_parser_peek_nth_token_raw (c_parser *parser, unsigned int n)
-{
- /* N is 1-based, not zero-based. */
- gcc_assert (n > 0);
-
- if (parser->tokens_avail >= n)
- return &parser->tokens[n - 1];
- unsigned int raw_len = vec_safe_length (parser->raw_tokens);
- unsigned int raw_avail
- = parser->tokens_avail + raw_len - parser->raw_tokens_used;
- gcc_assert (raw_avail >= n - 1);
- if (raw_avail >= n)
- return &(*parser->raw_tokens)[parser->raw_tokens_used
- + n - 1 - parser->tokens_avail];
- vec_safe_reserve (parser->raw_tokens, 1);
- parser->raw_tokens->quick_grow (raw_len + 1);
- c_lex_one_token (parser, &(*parser->raw_tokens)[raw_len], true);
- return &(*parser->raw_tokens)[raw_len];
-}
-
-bool
-c_keyword_starts_typename (enum rid keyword)
-{
- switch (keyword)
- {
- case RID_UNSIGNED:
- case RID_LONG:
- case RID_SHORT:
- case RID_SIGNED:
- case RID_COMPLEX:
- case RID_INT:
- case RID_CHAR:
- case RID_FLOAT:
- case RID_DOUBLE:
- case RID_VOID:
- case RID_DFLOAT32:
- case RID_DFLOAT64:
- case RID_DFLOAT128:
- CASE_RID_FLOATN_NX:
- case RID_BOOL:
- case RID_ENUM:
- case RID_STRUCT:
- case RID_UNION:
- case RID_TYPEOF:
- case RID_CONST:
- case RID_ATOMIC:
- case RID_VOLATILE:
- case RID_RESTRICT:
- case RID_ATTRIBUTE:
- case RID_FRACT:
- case RID_ACCUM:
- case RID_SAT:
- case RID_AUTO_TYPE:
- case RID_ALIGNAS:
- return true;
- default:
- if (keyword >= RID_FIRST_INT_N
- && keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
- && int_n_enabled_p[keyword - RID_FIRST_INT_N])
- return true;
- return false;
- }
-}
-
-/* Return true if TOKEN can start a type name,
- false otherwise. */
-bool
-c_token_starts_typename (c_token *token)
-{
- switch (token->type)
- {
- case CPP_NAME:
- switch (token->id_kind)
- {
- case C_ID_ID:
- return false;
- case C_ID_ADDRSPACE:
- return true;
- case C_ID_TYPENAME:
- return true;
- case C_ID_CLASSNAME:
- gcc_assert (c_dialect_objc ());
- return true;
- default:
- gcc_unreachable ();
- }
- case CPP_KEYWORD:
- return c_keyword_starts_typename (token->keyword);
- case CPP_LESS:
- if (c_dialect_objc ())
- return true;
- return false;
- default:
- return false;
- }
-}
-
-/* Return true if the next token from PARSER can start a type name,
- false otherwise. LA specifies how to do lookahead in order to
- detect unknown type names. If unsure, pick CLA_PREFER_ID. */
-
-static inline bool
-c_parser_next_tokens_start_typename (c_parser *parser, enum c_lookahead_kind la)
-{
- c_token *token = c_parser_peek_token (parser);
- if (c_token_starts_typename (token))
- return true;
-
- /* Try a bit harder to detect an unknown typename. */
- if (la != cla_prefer_id
- && token->type == CPP_NAME
- && token->id_kind == C_ID_ID
-
- /* Do not try too hard when we could have "object in array". */
- && !parser->objc_could_be_foreach_context
-
- && (la == cla_prefer_type
- || c_parser_peek_2nd_token (parser)->type == CPP_NAME
- || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
-
- /* Only unknown identifiers. */
- && !lookup_name (token->value))
- return true;
-
- return false;
-}
-
-/* Return true if TOKEN is a type qualifier, false otherwise. */
-static bool
-c_token_is_qualifier (c_token *token)
-{
- switch (token->type)
- {
- case CPP_NAME:
- switch (token->id_kind)
- {
- case C_ID_ADDRSPACE:
- return true;
- default:
- return false;
- }
- case CPP_KEYWORD:
- switch (token->keyword)
- {
- case RID_CONST:
- case RID_VOLATILE:
- case RID_RESTRICT:
- case RID_ATTRIBUTE:
- case RID_ATOMIC:
- return true;
- default:
- return false;
- }
- case CPP_LESS:
- return false;
- default:
- gcc_unreachable ();
- }
-}
-
-/* Return true if the next token from PARSER is a type qualifier,
- false otherwise. */
-static inline bool
-c_parser_next_token_is_qualifier (c_parser *parser)
-{
- c_token *token = c_parser_peek_token (parser);
- return c_token_is_qualifier (token);
-}
-
-/* Return true if TOKEN can start declaration specifiers (not
- including standard attributes), false otherwise. */
-static bool
-c_token_starts_declspecs (c_token *token)
-{
- switch (token->type)
- {
- case CPP_NAME:
- switch (token->id_kind)
- {
- case C_ID_ID:
- return false;
- case C_ID_ADDRSPACE:
- return true;
- case C_ID_TYPENAME:
- return true;
- case C_ID_CLASSNAME:
- gcc_assert (c_dialect_objc ());
- return true;
- default:
- gcc_unreachable ();
- }
- case CPP_KEYWORD:
- switch (token->keyword)
- {
- case RID_STATIC:
- case RID_EXTERN:
- case RID_REGISTER:
- case RID_TYPEDEF:
- case RID_INLINE:
- case RID_NORETURN:
- case RID_AUTO:
- case RID_THREAD:
- case RID_UNSIGNED:
- case RID_LONG:
- case RID_SHORT:
- case RID_SIGNED:
- case RID_COMPLEX:
- case RID_INT:
- case RID_CHAR:
- case RID_FLOAT:
- case RID_DOUBLE:
- case RID_VOID:
- case RID_DFLOAT32:
- case RID_DFLOAT64:
- case RID_DFLOAT128:
- CASE_RID_FLOATN_NX:
- case RID_BOOL:
- case RID_ENUM:
- case RID_STRUCT:
- case RID_UNION:
- case RID_TYPEOF:
- case RID_CONST:
- case RID_VOLATILE:
- case RID_RESTRICT:
- case RID_ATTRIBUTE:
- case RID_FRACT:
- case RID_ACCUM:
- case RID_SAT:
- case RID_ALIGNAS:
- case RID_ATOMIC:
- case RID_AUTO_TYPE:
- return true;
- default:
- if (token->keyword >= RID_FIRST_INT_N
- && token->keyword < RID_FIRST_INT_N + NUM_INT_N_ENTS
- && int_n_enabled_p[token->keyword - RID_FIRST_INT_N])
- return true;
- return false;
- }
- case CPP_LESS:
- if (c_dialect_objc ())
- return true;
- return false;
- default:
- return false;
- }
-}
-
-
-/* Return true if TOKEN can start declaration specifiers (not
- including standard attributes) or a static assertion, false
- otherwise. */
-static bool
-c_token_starts_declaration (c_token *token)
-{
- if (c_token_starts_declspecs (token)
- || token->keyword == RID_STATIC_ASSERT)
- return true;
- else
- return false;
-}
-
-/* Return true if the next token from PARSER can start declaration
- specifiers (not including standard attributes), false
- otherwise. */
-bool
-c_parser_next_token_starts_declspecs (c_parser *parser)
-{
- c_token *token = c_parser_peek_token (parser);
-
- /* In Objective-C, a classname normally starts a declspecs unless it
- is immediately followed by a dot. In that case, it is the
- Objective-C 2.0 "dot-syntax" for class objects, ie, calls the
- setter/getter on the class. c_token_starts_declspecs() can't
- differentiate between the two cases because it only checks the
- current token, so we have a special check here. */
- if (c_dialect_objc ()
- && token->type == CPP_NAME
- && token->id_kind == C_ID_CLASSNAME
- && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
- return false;
-
- return c_token_starts_declspecs (token);
-}
-
-/* Return true if the next tokens from PARSER can start declaration
- specifiers (not including standard attributes) or a static
- assertion, false otherwise. */
-bool
-c_parser_next_tokens_start_declaration (c_parser *parser)
-{
- c_token *token = c_parser_peek_token (parser);
-
- /* Same as above. */
- if (c_dialect_objc ()
- && token->type == CPP_NAME
- && token->id_kind == C_ID_CLASSNAME
- && c_parser_peek_2nd_token (parser)->type == CPP_DOT)
- return false;
-
- /* Labels do not start declarations. */
- if (token->type == CPP_NAME
- && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
- return false;
-
- if (c_token_starts_declaration (token))
- return true;
-
- if (c_parser_next_tokens_start_typename (parser, cla_nonabstract_decl))
- return true;
-
- return false;
-}
-
-/* Consume the next token from PARSER. */
-
-void
-c_parser_consume_token (c_parser *parser)
-{
- gcc_assert (parser->tokens_avail >= 1);
- gcc_assert (parser->tokens[0].type != CPP_EOF);
- gcc_assert (!parser->in_pragma || parser->tokens[0].type != CPP_PRAGMA_EOL);
- gcc_assert (parser->error || parser->tokens[0].type != CPP_PRAGMA);
- parser->last_token_location = parser->tokens[0].location;
- if (parser->tokens != &parser->tokens_buf[0])
- parser->tokens++;
- else if (parser->tokens_avail >= 2)
- {
- parser->tokens[0] = parser->tokens[1];
- if (parser->tokens_avail >= 3)
- {
- parser->tokens[1] = parser->tokens[2];
- if (parser->tokens_avail >= 4)
- parser->tokens[2] = parser->tokens[3];
- }
- }
- parser->tokens_avail--;
- parser->seen_string_literal = false;
-}
-
-/* Expect the current token to be a #pragma. Consume it and remember
- that we've begun parsing a pragma. */
-
-static void
-c_parser_consume_pragma (c_parser *parser)
-{
- gcc_assert (!parser->in_pragma);
- gcc_assert (parser->tokens_avail >= 1);
- gcc_assert (parser->tokens[0].type == CPP_PRAGMA);
- if (parser->tokens != &parser->tokens_buf[0])
- parser->tokens++;
- else if (parser->tokens_avail >= 2)
- {
- parser->tokens[0] = parser->tokens[1];
- if (parser->tokens_avail >= 3)
- parser->tokens[1] = parser->tokens[2];
- }
- parser->tokens_avail--;
- parser->in_pragma = true;
-}
-
-/* Update the global input_location from TOKEN. */
-static inline void
-c_parser_set_source_position_from_token (c_token *token)
-{
- if (token->type != CPP_EOF)
- {
- input_location = token->location;
- }
-}
-
-/* Helper function for c_parser_error.
- Having peeked a token of kind TOK1_KIND that might signify
- a conflict marker, peek successor tokens to determine
- if we actually do have a conflict marker.
- Specifically, we consider a run of 7 '<', '=' or '>' characters
- at the start of a line as a conflict marker.
- These come through the lexer as three pairs and a single,
- e.g. three CPP_LSHIFT ("<<") and a CPP_LESS ('<').
- If it returns true, *OUT_LOC is written to with the location/range
- of the marker. */
-
-static bool
-c_parser_peek_conflict_marker (c_parser *parser, enum cpp_ttype tok1_kind,
- location_t *out_loc)
-{
- c_token *token2 = c_parser_peek_2nd_token (parser);
- if (token2->type != tok1_kind)
- return false;
- c_token *token3 = c_parser_peek_nth_token (parser, 3);
- if (token3->type != tok1_kind)
- return false;
- c_token *token4 = c_parser_peek_nth_token (parser, 4);
- if (token4->type != conflict_marker_get_final_tok_kind (tok1_kind))
- return false;
-
- /* It must be at the start of the line. */
- location_t start_loc = c_parser_peek_token (parser)->location;
- if (LOCATION_COLUMN (start_loc) != 1)
- return false;
-
- /* We have a conflict marker. Construct a location of the form:
- <<<<<<<
- ^~~~~~~
- with start == caret, finishing at the end of the marker. */
- location_t finish_loc = get_finish (token4->location);
- *out_loc = make_location (start_loc, start_loc, finish_loc);
-
- return true;
-}
-
-/* Issue a diagnostic of the form
- FILE:LINE: MESSAGE before TOKEN
- where TOKEN is the next token in the input stream of PARSER.
- MESSAGE (specified by the caller) is usually of the form "expected
- OTHER-TOKEN".
-
- Use RICHLOC as the location of the diagnostic.
-
- Do not issue a diagnostic if still recovering from an error.
-
- Return true iff an error was actually emitted.
-
- ??? This is taken from the C++ parser, but building up messages in
- this way is not i18n-friendly and some other approach should be
- used. */
-
-static bool
-c_parser_error_richloc (c_parser *parser, const char *gmsgid,
- rich_location *richloc)
-{
- c_token *token = c_parser_peek_token (parser);
- if (parser->error)
- return false;
- parser->error = true;
- if (!gmsgid)
- return false;
-
- /* If this is actually a conflict marker, report it as such. */
- if (token->type == CPP_LSHIFT
- || token->type == CPP_RSHIFT
- || token->type == CPP_EQ_EQ)
- {
- location_t loc;
- if (c_parser_peek_conflict_marker (parser, token->type, &loc))
- {
- error_at (loc, "version control conflict marker in file");
- return true;
- }
- }
-
- /* If we were parsing a string-literal and there is an unknown name
- token right after, then check to see if that could also have been
- a literal string by checking the name against a list of known
- standard string literal constants defined in header files. If
- there is one, then add that as an hint to the error message. */
- auto_diagnostic_group d;
- name_hint h;
- if (parser->seen_string_literal && token->type == CPP_NAME)
- {
- tree name = token->value;
- const char *token_name = IDENTIFIER_POINTER (name);
- const char *header_hint
- = get_c_stdlib_header_for_string_macro_name (token_name);
- if (header_hint != NULL)
- h = name_hint (NULL, new suggest_missing_header (token->location,
- token_name,
- header_hint));
- }
-
- c_parse_error (gmsgid,
- /* Because c_parse_error does not understand
- CPP_KEYWORD, keywords are treated like
- identifiers. */
- (token->type == CPP_KEYWORD ? CPP_NAME : token->type),
- /* ??? The C parser does not save the cpp flags of a
- token, we need to pass 0 here and we will not get
- the source spelling of some tokens but rather the
- canonical spelling. */
- token->value, /*flags=*/0, richloc);
- return true;
-}
-
-/* As c_parser_error_richloc, but issue the message at the
- location of PARSER's next token, or at input_location
- if the next token is EOF. */
-
-bool
-c_parser_error (c_parser *parser, const char *gmsgid)
-{
- c_token *token = c_parser_peek_token (parser);
- c_parser_set_source_position_from_token (token);
- rich_location richloc (line_table, input_location);
- return c_parser_error_richloc (parser, gmsgid, &richloc);
-}
-
-/* Some tokens naturally come in pairs e.g.'(' and ')'.
- This class is for tracking such a matching pair of symbols.
- In particular, it tracks the location of the first token,
- so that if the second token is missing, we can highlight the
- location of the first token when notifying the user about the
- problem. */
-
-template <typename traits_t>
-class token_pair
-{
- public:
- /* token_pair's ctor. */
- token_pair () : m_open_loc (UNKNOWN_LOCATION) {}
-
- /* If the next token is the opening symbol for this pair, consume it and
- return true.
- Otherwise, issue an error and return false.
- In either case, record the location of the opening token. */
-
- bool require_open (c_parser *parser)
- {
- c_token *token = c_parser_peek_token (parser);
- if (token)
- m_open_loc = token->location;
-
- return c_parser_require (parser, traits_t::open_token_type,
- traits_t::open_gmsgid);
- }
-
- /* Consume the next token from PARSER, recording its location as
- that of the opening token within the pair. */
-
- void consume_open (c_parser *parser)
- {
- c_token *token = c_parser_peek_token (parser);
- gcc_assert (token->type == traits_t::open_token_type);
- m_open_loc = token->location;
- c_parser_consume_token (parser);
- }
-
- /* If the next token is the closing symbol for this pair, consume it
- and return true.
- Otherwise, issue an error, highlighting the location of the
- corresponding opening token, and return false. */
-
- bool require_close (c_parser *parser) const
- {
- return c_parser_require (parser, traits_t::close_token_type,
- traits_t::close_gmsgid, m_open_loc);
- }
-
- /* Like token_pair::require_close, except that tokens will be skipped
- until the desired token is found. An error message is still produced
- if the next token is not as expected. */
-
- void skip_until_found_close (c_parser *parser) const
- {
- c_parser_skip_until_found (parser, traits_t::close_token_type,
- traits_t::close_gmsgid, m_open_loc);
- }
-
- private:
- location_t m_open_loc;
-};
-
-/* Traits for token_pair<T> for tracking matching pairs of parentheses. */
-
-struct matching_paren_traits
-{
- static const enum cpp_ttype open_token_type = CPP_OPEN_PAREN;
- static const char * const open_gmsgid;
- static const enum cpp_ttype close_token_type = CPP_CLOSE_PAREN;
- static const char * const close_gmsgid;
-};
-
-const char * const matching_paren_traits::open_gmsgid = "expected %<(%>";
-const char * const matching_paren_traits::close_gmsgid = "expected %<)%>";
-
-/* "matching_parens" is a token_pair<T> class for tracking matching
- pairs of parentheses. */
-
-typedef token_pair<matching_paren_traits> matching_parens;
-
-/* Traits for token_pair<T> for tracking matching pairs of braces. */
-
-struct matching_brace_traits
-{
- static const enum cpp_ttype open_token_type = CPP_OPEN_BRACE;
- static const char * const open_gmsgid;
- static const enum cpp_ttype close_token_type = CPP_CLOSE_BRACE;
- static const char * const close_gmsgid;
-};
-
-const char * const matching_brace_traits::open_gmsgid = "expected %<{%>";
-const char * const matching_brace_traits::close_gmsgid = "expected %<}%>";
-
-/* "matching_braces" is a token_pair<T> class for tracking matching
- pairs of braces. */
-
-typedef token_pair<matching_brace_traits> matching_braces;
-
-/* Get a description of the matching symbol to TYPE e.g. "(" for
- CPP_CLOSE_PAREN. */
-
-static const char *
-get_matching_symbol (enum cpp_ttype type)
-{
- switch (type)
- {
- default:
- gcc_unreachable ();
- case CPP_CLOSE_PAREN:
- return "(";
- case CPP_CLOSE_BRACE:
- return "{";
- }
-}
-
-/* If the next token is of the indicated TYPE, consume it. Otherwise,
- issue the error MSGID. If MSGID is NULL then a message has already
- been produced and no message will be produced this time. Returns
- true if found, false otherwise.
-
- If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it
- within any error as the location of an "opening" token matching
- the close token TYPE (e.g. the location of the '(' when TYPE is
- CPP_CLOSE_PAREN).
-
- If TYPE_IS_UNIQUE is true (the default) then msgid describes exactly
- one type (e.g. "expected %<)%>") and thus it may be reasonable to
- attempt to generate a fix-it hint for the problem.
- Otherwise msgid describes multiple token types (e.g.
- "expected %<;%>, %<,%> or %<)%>"), and thus we shouldn't attempt to
- generate a fix-it hint. */
-
-bool
-c_parser_require (c_parser *parser,
- enum cpp_ttype type,
- const char *msgid,
- location_t matching_location,
- bool type_is_unique)
-{
- if (c_parser_next_token_is (parser, type))
- {
- c_parser_consume_token (parser);
- return true;
- }
- else
- {
- location_t next_token_loc = c_parser_peek_token (parser)->location;
- gcc_rich_location richloc (next_token_loc);
-
- /* Potentially supply a fix-it hint, suggesting to add the
- missing token immediately after the *previous* token.
- This may move the primary location within richloc. */
- if (!parser->error && type_is_unique)
- maybe_suggest_missing_token_insertion (&richloc, type,
- parser->last_token_location);
-
- /* If matching_location != UNKNOWN_LOCATION, highlight it.
- Attempt to consolidate diagnostics by printing it as a
- secondary range within the main diagnostic. */
- bool added_matching_location = false;
- if (matching_location != UNKNOWN_LOCATION)
- added_matching_location
- = richloc.add_location_if_nearby (matching_location);
-
- if (c_parser_error_richloc (parser, msgid, &richloc))
- /* If we weren't able to consolidate matching_location, then
- print it as a secondary diagnostic. */
- if (matching_location != UNKNOWN_LOCATION && !added_matching_location)
- inform (matching_location, "to match this %qs",
- get_matching_symbol (type));
-
- return false;
- }
-}
-
-/* If the next token is the indicated keyword, consume it. Otherwise,
- issue the error MSGID. Returns true if found, false otherwise. */
-
-static bool
-c_parser_require_keyword (c_parser *parser,
- enum rid keyword,
- const char *msgid)
-{
- if (c_parser_next_token_is_keyword (parser, keyword))
- {
- c_parser_consume_token (parser);
- return true;
- }
- else
- {
- c_parser_error (parser, msgid);
- return false;
- }
-}
-
-/* Like c_parser_require, except that tokens will be skipped until the
- desired token is found. An error message is still produced if the
- next token is not as expected. If MSGID is NULL then a message has
- already been produced and no message will be produced this
- time.
-
- If MATCHING_LOCATION is not UNKNOWN_LOCATION, then highlight it
- within any error as the location of an "opening" token matching
- the close token TYPE (e.g. the location of the '(' when TYPE is
- CPP_CLOSE_PAREN). */
-
-void
-c_parser_skip_until_found (c_parser *parser,
- enum cpp_ttype type,
- const char *msgid,
- location_t matching_location)
-{
- unsigned nesting_depth = 0;
-
- if (c_parser_require (parser, type, msgid, matching_location))
- return;
-
- /* Skip tokens until the desired token is found. */
- while (true)
- {
- /* Peek at the next token. */
- c_token *token = c_parser_peek_token (parser);
- /* If we've reached the token we want, consume it and stop. */
- if (token->type == type && !nesting_depth)
- {
- c_parser_consume_token (parser);
- break;
- }
-
- /* If we've run out of tokens, stop. */
- if (token->type == CPP_EOF)
- return;
- if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
- return;
- if (token->type == CPP_OPEN_BRACE
- || token->type == CPP_OPEN_PAREN
- || token->type == CPP_OPEN_SQUARE)
- ++nesting_depth;
- else if (token->type == CPP_CLOSE_BRACE
- || token->type == CPP_CLOSE_PAREN
- || token->type == CPP_CLOSE_SQUARE)
- {
- if (nesting_depth-- == 0)
- break;
- }
- /* Consume this token. */
- c_parser_consume_token (parser);
- }
- parser->error = false;
-}
-
-/* Skip tokens until the end of a parameter is found, but do not
- consume the comma, semicolon or closing delimiter. */
-
-static void
-c_parser_skip_to_end_of_parameter (c_parser *parser)
-{
- unsigned nesting_depth = 0;
-
- while (true)
- {
- c_token *token = c_parser_peek_token (parser);
- if ((token->type == CPP_COMMA || token->type == CPP_SEMICOLON)
- && !nesting_depth)
- break;
- /* If we've run out of tokens, stop. */
- if (token->type == CPP_EOF)
- return;
- if (token->type == CPP_PRAGMA_EOL && parser->in_pragma)
- return;
- if (token->type == CPP_OPEN_BRACE
- || token->type == CPP_OPEN_PAREN
- || token->type == CPP_OPEN_SQUARE)
- ++nesting_depth;
- else if (token->type == CPP_CLOSE_BRACE
- || token->type == CPP_CLOSE_PAREN
- || token->type == CPP_CLOSE_SQUARE)
- {
- if (nesting_depth-- == 0)
- break;
- }
- /* Consume this token. */
- c_parser_consume_token (parser);
- }
- parser->error = false;
-}
-
-/* Expect to be at the end of the pragma directive and consume an
- end of line marker. */
-
-static void
-c_parser_skip_to_pragma_eol (c_parser *parser, bool error_if_not_eol = true)
-{
- gcc_assert (parser->in_pragma);
- parser->in_pragma = false;
-
- if (error_if_not_eol && c_parser_peek_token (parser)->type != CPP_PRAGMA_EOL)
- c_parser_error (parser, "expected end of line");
-
- cpp_ttype token_type;
- do
- {
- c_token *token = c_parser_peek_token (parser);
- token_type = token->type;
- if (token_type == CPP_EOF)
- break;
- c_parser_consume_token (parser);
- }
- while (token_type != CPP_PRAGMA_EOL);
-
- parser->error = false;
-}
-
-/* Skip tokens until we have consumed an entire block, or until we
- have consumed a non-nested ';'. */
-
-static void
-c_parser_skip_to_end_of_block_or_statement (c_parser *parser)
-{
- unsigned nesting_depth = 0;
- bool save_error = parser->error;
-
- while (true)
- {
- c_token *token;
-
- /* Peek at the next token. */
- token = c_parser_peek_token (parser);
-
- switch (token->type)
- {
- case CPP_EOF:
- return;
-
- case CPP_PRAGMA_EOL:
- if (parser->in_pragma)
- return;
- break;
-
- case CPP_SEMICOLON:
- /* If the next token is a ';', we have reached the
- end of the statement. */
- if (!nesting_depth)
- {
- /* Consume the ';'. */
- c_parser_consume_token (parser);
- goto finished;
- }
- break;
-
- case CPP_CLOSE_BRACE:
- /* If the next token is a non-nested '}', then we have
- reached the end of the current block. */
- if (nesting_depth == 0 || --nesting_depth == 0)
- {
- c_parser_consume_token (parser);
- goto finished;
- }
- break;
-
- case CPP_OPEN_BRACE:
- /* If it the next token is a '{', then we are entering a new
- block. Consume the entire block. */
- ++nesting_depth;
- break;
-
- case CPP_PRAGMA:
- /* If we see a pragma, consume the whole thing at once. We
- have some safeguards against consuming pragmas willy-nilly.
- Normally, we'd expect to be here with parser->error set,
- which disables these safeguards. But it's possible to get
- here for secondary error recovery, after parser->error has
- been cleared. */
- c_parser_consume_pragma (parser);
- c_parser_skip_to_pragma_eol (parser);
- parser->error = save_error;
- continue;
-
- default:
- break;
- }
-
- c_parser_consume_token (parser);
- }
-
- finished:
- parser->error = false;
-}
-
-/* CPP's options (initialized by c-opts.c). */
-extern cpp_options *cpp_opts;
-
-/* Save the warning flags which are controlled by __extension__. */
-
-static inline int
-disable_extension_diagnostics (void)
-{
- int ret = (pedantic
- | (warn_pointer_arith << 1)
- | (warn_traditional << 2)
- | (flag_iso << 3)
- | (warn_long_long << 4)
- | (warn_cxx_compat << 5)
- | (warn_overlength_strings << 6)
- /* warn_c90_c99_compat has three states: -1/0/1, so we must
- play tricks to properly restore it. */
- | ((warn_c90_c99_compat == 1) << 7)
- | ((warn_c90_c99_compat == -1) << 8)
- /* Similarly for warn_c99_c11_compat. */
- | ((warn_c99_c11_compat == 1) << 9)
- | ((warn_c99_c11_compat == -1) << 10)
- /* Similarly for warn_c11_c2x_compat. */
- | ((warn_c11_c2x_compat == 1) << 11)
- | ((warn_c11_c2x_compat == -1) << 12)
- );
- cpp_opts->cpp_pedantic = pedantic = 0;
- warn_pointer_arith = 0;
- cpp_opts->cpp_warn_traditional = warn_traditional = 0;
- flag_iso = 0;
- cpp_opts->cpp_warn_long_long = warn_long_long = 0;
- warn_cxx_compat = 0;
- warn_overlength_strings = 0;
- warn_c90_c99_compat = 0;
- warn_c99_c11_compat = 0;
- warn_c11_c2x_compat = 0;
- return ret;
-}
-
-/* Restore the warning flags which are controlled by __extension__.
- FLAGS is the return value from disable_extension_diagnostics. */
-
-static inline void
-restore_extension_diagnostics (int flags)
-{
- cpp_opts->cpp_pedantic = pedantic = flags & 1;
- warn_pointer_arith = (flags >> 1) & 1;
- cpp_opts->cpp_warn_traditional = warn_traditional = (flags >> 2) & 1;
- flag_iso = (flags >> 3) & 1;
- cpp_opts->cpp_warn_long_long = warn_long_long = (flags >> 4) & 1;
- warn_cxx_compat = (flags >> 5) & 1;
- warn_overlength_strings = (flags >> 6) & 1;
- /* See above for why is this needed. */
- warn_c90_c99_compat = (flags >> 7) & 1 ? 1 : ((flags >> 8) & 1 ? -1 : 0);
- warn_c99_c11_compat = (flags >> 9) & 1 ? 1 : ((flags >> 10) & 1 ? -1 : 0);
- warn_c11_c2x_compat = (flags >> 11) & 1 ? 1 : ((flags >> 12) & 1 ? -1 : 0);
-}
-
-/* Helper data structure for parsing #pragma acc routine. */
-struct oacc_routine_data {
- bool error_seen; /* Set if error has been reported. */
- bool fndecl_seen; /* Set if one fn decl/definition has been seen already. */
- tree clauses;
- location_t loc;
-};
-
-/* Used for parsing objc foreach statements. */
-static tree objc_foreach_break_label, objc_foreach_continue_label;
-
-static bool c_parser_nth_token_starts_std_attributes (c_parser *,
- unsigned int);
-static tree c_parser_std_attribute_specifier_sequence (c_parser *);
-static void c_parser_external_declaration (c_parser *);
-static void c_parser_asm_definition (c_parser *);
-static void c_parser_declaration_or_fndef (c_parser *, bool, bool, bool,
- bool, bool, tree * = NULL,
- vec<c_token> * = NULL,
- bool have_attrs = false,
- tree attrs = NULL,
- struct oacc_routine_data * = NULL,
- bool * = NULL);
-static void c_parser_static_assert_declaration_no_semi (c_parser *);
-static void c_parser_static_assert_declaration (c_parser *);
-static struct c_typespec c_parser_enum_specifier (c_parser *);
-static struct c_typespec c_parser_struct_or_union_specifier (c_parser *);
-static tree c_parser_struct_declaration (c_parser *);
-static struct c_typespec c_parser_typeof_specifier (c_parser *);
-static tree c_parser_alignas_specifier (c_parser *);
-static struct c_declarator *c_parser_direct_declarator (c_parser *, bool,
- c_dtr_syn, bool *);
-static struct c_declarator *c_parser_direct_declarator_inner (c_parser *,
- bool,
- struct c_declarator *);
-static struct c_arg_info *c_parser_parms_declarator (c_parser *, bool, tree,
- bool);
-static struct c_arg_info *c_parser_parms_list_declarator (c_parser *, tree,
- tree, bool);
-static struct c_parm *c_parser_parameter_declaration (c_parser *, tree, bool);
-static tree c_parser_simple_asm_expr (c_parser *);
-static tree c_parser_gnu_attributes (c_parser *);
-static struct c_expr c_parser_initializer (c_parser *);
-static struct c_expr c_parser_braced_init (c_parser *, tree, bool,
- struct obstack *);
-static void c_parser_initelt (c_parser *, struct obstack *);
-static void c_parser_initval (c_parser *, struct c_expr *,
- struct obstack *);
-static tree c_parser_compound_statement (c_parser *, location_t * = NULL);
-static location_t c_parser_compound_statement_nostart (c_parser *);
-static void c_parser_label (c_parser *, tree);
-static void c_parser_statement (c_parser *, bool *, location_t * = NULL);
-static void c_parser_statement_after_labels (c_parser *, bool *,
- vec<tree> * = NULL);
-static tree c_parser_c99_block_statement (c_parser *, bool *,
- location_t * = NULL);
-static void c_parser_if_statement (c_parser *, bool *, vec<tree> *);
-static void c_parser_switch_statement (c_parser *, bool *);
-static void c_parser_while_statement (c_parser *, bool, unsigned short, bool *);
-static void c_parser_do_statement (c_parser *, bool, unsigned short);
-static void c_parser_for_statement (c_parser *, bool, unsigned short, bool *);
-static tree c_parser_asm_statement (c_parser *);
-static tree c_parser_asm_operands (c_parser *);
-static tree c_parser_asm_goto_operands (c_parser *);
-static tree c_parser_asm_clobbers (c_parser *);
-static struct c_expr c_parser_expr_no_commas (c_parser *, struct c_expr *,
- tree = NULL_TREE);
-static struct c_expr c_parser_conditional_expression (c_parser *,
- struct c_expr *, tree);
-static struct c_expr c_parser_binary_expression (c_parser *, struct c_expr *,
- tree);
-static struct c_expr c_parser_cast_expression (c_parser *, struct c_expr *);
-static struct c_expr c_parser_unary_expression (c_parser *);
-static struct c_expr c_parser_sizeof_expression (c_parser *);
-static struct c_expr c_parser_alignof_expression (c_parser *);
-static struct c_expr c_parser_postfix_expression (c_parser *);
-static struct c_expr c_parser_postfix_expression_after_paren_type (c_parser *,
- struct c_type_name *,
- location_t);
-static struct c_expr c_parser_postfix_expression_after_primary (c_parser *,
- location_t loc,
- struct c_expr);
-static tree c_parser_transaction (c_parser *, enum rid);
-static struct c_expr c_parser_transaction_expression (c_parser *, enum rid);
-static tree c_parser_transaction_cancel (c_parser *);
-static struct c_expr c_parser_expression (c_parser *);
-static struct c_expr c_parser_expression_conv (c_parser *);
-static vec<tree, va_gc> *c_parser_expr_list (c_parser *, bool, bool,
- vec<tree, va_gc> **, location_t *,
- tree *, vec<location_t> *,
- unsigned int * = NULL);
-static struct c_expr c_parser_has_attribute_expression (c_parser *);
-
-static void c_parser_oacc_declare (c_parser *);
-static void c_parser_oacc_enter_exit_data (c_parser *, bool);
-static void c_parser_oacc_update (c_parser *);
-static void c_parser_omp_construct (c_parser *, bool *);
-static void c_parser_omp_threadprivate (c_parser *);
-static void c_parser_omp_barrier (c_parser *);
-static void c_parser_omp_depobj (c_parser *);
-static void c_parser_omp_flush (c_parser *);
-static tree c_parser_omp_for_loop (location_t, c_parser *, enum tree_code,
- tree, tree *, bool *);
-static void c_parser_omp_taskwait (c_parser *);
-static void c_parser_omp_taskyield (c_parser *);
-static void c_parser_omp_cancel (c_parser *);
-static void c_parser_omp_nothing (c_parser *);
-
-enum pragma_context { pragma_external, pragma_struct, pragma_param,
- pragma_stmt, pragma_compound };
-static bool c_parser_pragma (c_parser *, enum pragma_context, bool *);
-static bool c_parser_omp_cancellation_point (c_parser *, enum pragma_context);
-static bool c_parser_omp_target (c_parser *, enum pragma_context, bool *);
-static void c_parser_omp_end_declare_target (c_parser *);
-static bool c_parser_omp_declare (c_parser *, enum pragma_context);
-static void c_parser_omp_requires (c_parser *);
-static bool c_parser_omp_error (c_parser *, enum pragma_context);
-static bool c_parser_omp_ordered (c_parser *, enum pragma_context, bool *);
-static void c_parser_oacc_routine (c_parser *, enum pragma_context);
-
-/* These Objective-C parser functions are only ever called when
- compiling Objective-C. */
-static void c_parser_objc_class_definition (c_parser *, tree);
-static void c_parser_objc_class_instance_variables (c_parser *);
-static void c_parser_objc_class_declaration (c_parser *);
-static void c_parser_objc_alias_declaration (c_parser *);
-static void c_parser_objc_protocol_definition (c_parser *, tree);
-static bool c_parser_objc_method_type (c_parser *);
-static void c_parser_objc_method_definition (c_parser *);
-static void c_parser_objc_methodprotolist (c_parser *);
-static void c_parser_objc_methodproto (c_parser *);
-static tree c_parser_objc_method_decl (c_parser *, bool, tree *, tree *);
-static tree c_parser_objc_type_name (c_parser *);
-static tree c_parser_objc_protocol_refs (c_parser *);
-static void c_parser_objc_try_catch_finally_statement (c_parser *);
-static void c_parser_objc_synchronized_statement (c_parser *);
-static tree c_parser_objc_selector (c_parser *);
-static tree c_parser_objc_selector_arg (c_parser *);
-static tree c_parser_objc_receiver (c_parser *);
-static tree c_parser_objc_message_args (c_parser *);
-static tree c_parser_objc_keywordexpr (c_parser *);
-static void c_parser_objc_at_property_declaration (c_parser *);
-static void c_parser_objc_at_synthesize_declaration (c_parser *);
-static void c_parser_objc_at_dynamic_declaration (c_parser *);
-static bool c_parser_objc_diagnose_bad_element_prefix
- (c_parser *, struct c_declspecs *);
-static location_t c_parser_parse_rtl_body (c_parser *, char *);
-
-/* Parse a translation unit (C90 6.7, C99 6.9, C11 6.9).
-
- translation-unit:
- external-declarations
-
- external-declarations:
- external-declaration
- external-declarations external-declaration
-
- GNU extensions:
-
- translation-unit:
- empty
-*/
-
-static void
-c_parser_translation_unit (c_parser *parser)
-{
- if (c_parser_next_token_is (parser, CPP_EOF))
- {
- pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
- "ISO C forbids an empty translation unit");
- }
- else
- {
- void *obstack_position = obstack_alloc (&parser_obstack, 0);
- mark_valid_location_for_stdc_pragma (false);
- do
- {
- ggc_collect ();
- c_parser_external_declaration (parser);
- obstack_free (&parser_obstack, obstack_position);
- }
- while (c_parser_next_token_is_not (parser, CPP_EOF));
- }
-
- unsigned int i;
- tree decl;
- FOR_EACH_VEC_ELT (incomplete_record_decls, i, decl)
- if (DECL_SIZE (decl) == NULL_TREE && TREE_TYPE (decl) != error_mark_node)
- error ("storage size of %q+D isn%'t known", decl);
-
- if (current_omp_declare_target_attribute)
- {
- if (!errorcount)
- error ("%<#pragma omp declare target%> without corresponding "
- "%<#pragma omp end declare target%>");
- current_omp_declare_target_attribute = 0;
- }
-}
-
-/* Parse an external declaration (C90 6.7, C99 6.9, C11 6.9).
-
- external-declaration:
- function-definition
- declaration
-
- GNU extensions:
-
- external-declaration:
- asm-definition
- ;
- __extension__ external-declaration
-
- Objective-C:
-
- external-declaration:
- objc-class-definition
- objc-class-declaration
- objc-alias-declaration
- objc-protocol-definition
- objc-method-definition
- @end
-*/
-
-static void
-c_parser_external_declaration (c_parser *parser)
-{
- int ext;
- switch (c_parser_peek_token (parser)->type)
- {
- case CPP_KEYWORD:
- switch (c_parser_peek_token (parser)->keyword)
- {
- case RID_EXTENSION:
- ext = disable_extension_diagnostics ();
- c_parser_consume_token (parser);
- c_parser_external_declaration (parser);
- restore_extension_diagnostics (ext);
- break;
- case RID_ASM:
- c_parser_asm_definition (parser);
- break;
- case RID_AT_INTERFACE:
- case RID_AT_IMPLEMENTATION:
- gcc_assert (c_dialect_objc ());
- c_parser_objc_class_definition (parser, NULL_TREE);
- break;
- case RID_AT_CLASS:
- gcc_assert (c_dialect_objc ());
- c_parser_objc_class_declaration (parser);
- break;
- case RID_AT_ALIAS:
- gcc_assert (c_dialect_objc ());
- c_parser_objc_alias_declaration (parser);
- break;
- case RID_AT_PROTOCOL:
- gcc_assert (c_dialect_objc ());
- c_parser_objc_protocol_definition (parser, NULL_TREE);
- break;
- case RID_AT_PROPERTY:
- gcc_assert (c_dialect_objc ());
- c_parser_objc_at_property_declaration (parser);
- break;
- case RID_AT_SYNTHESIZE:
- gcc_assert (c_dialect_objc ());
- c_parser_objc_at_synthesize_declaration (parser);
- break;
- case RID_AT_DYNAMIC:
- gcc_assert (c_dialect_objc ());
- c_parser_objc_at_dynamic_declaration (parser);
- break;
- case RID_AT_END:
- gcc_assert (c_dialect_objc ());
- c_parser_consume_token (parser);
- objc_finish_implementation ();
- break;
- default:
- goto decl_or_fndef;
- }
- break;
- case CPP_SEMICOLON:
- pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
- "ISO C does not allow extra %<;%> outside of a function");
- c_parser_consume_token (parser);
- break;
- case CPP_PRAGMA:
- mark_valid_location_for_stdc_pragma (true);
- c_parser_pragma (parser, pragma_external, NULL);
- mark_valid_location_for_stdc_pragma (false);
- break;
- case CPP_PLUS:
- case CPP_MINUS:
- if (c_dialect_objc ())
- {
- c_parser_objc_method_definition (parser);
- break;
- }
- /* Else fall through, and yield a syntax error trying to parse
- as a declaration or function definition. */
- /* FALLTHRU */
- default:
- decl_or_fndef:
- /* A declaration or a function definition (or, in Objective-C,
- an @interface or @protocol with prefix attributes). We can
- only tell which after parsing the declaration specifiers, if
- any, and the first declarator. */
- c_parser_declaration_or_fndef (parser, true, true, true, false, true);
- break;
- }
-}
-
-static void c_finish_omp_declare_simd (c_parser *, tree, tree, vec<c_token> *);
-static void c_finish_oacc_routine (struct oacc_routine_data *, tree, bool);
-
-/* Build and add a DEBUG_BEGIN_STMT statement with location LOC. */
-
-static void
-add_debug_begin_stmt (location_t loc)
-{
- /* Don't add DEBUG_BEGIN_STMTs outside of functions, see PR84721. */
- if (!MAY_HAVE_DEBUG_MARKER_STMTS || !building_stmt_list_p ())
- return;
-
- tree stmt = build0 (DEBUG_BEGIN_STMT, void_type_node);
- SET_EXPR_LOCATION (stmt, loc);
- add_stmt (stmt);
-}
-
-/* Parse a declaration or function definition (C90 6.5, 6.7.1, C99
- 6.7, 6.9.1, C11 6.7, 6.9.1). If FNDEF_OK is true, a function definition
- is accepted; otherwise (old-style parameter declarations) only other
- declarations are accepted. If STATIC_ASSERT_OK is true, a static
- assertion is accepted; otherwise (old-style parameter declarations)
- it is not. If NESTED is true, we are inside a function or parsing
- old-style parameter declarations; any functions encountered are
- nested functions and declaration specifiers are required; otherwise
- we are at top level and functions are normal functions and
- declaration specifiers may be optional. If EMPTY_OK is true, empty
- declarations are OK (subject to all other constraints); otherwise
- (old-style parameter declarations) they are diagnosed. If
- START_ATTR_OK is true, the declaration specifiers may start with
- attributes (GNU or standard); otherwise they may not.
- OBJC_FOREACH_OBJECT_DECLARATION can be used to get back the parsed
- declaration when parsing an Objective-C foreach statement.
- FALLTHRU_ATTR_P is used to signal whether this function parsed
- "__attribute__((fallthrough));". ATTRS are any standard attributes
- parsed in the caller (in contexts where such attributes had to be
- parsed to determine whether what follows is a declaration or a
- statement); HAVE_ATTRS says whether there were any such attributes
- (even empty).
-
- declaration:
- declaration-specifiers init-declarator-list[opt] ;
- static_assert-declaration
-
- function-definition:
- declaration-specifiers[opt] declarator declaration-list[opt]
- compound-statement
-
- declaration-list:
- declaration
- declaration-list declaration
-
- init-declarator-list:
- init-declarator
- init-declarator-list , init-declarator
-
- init-declarator:
- declarator simple-asm-expr[opt] gnu-attributes[opt]
- declarator simple-asm-expr[opt] gnu-attributes[opt] = initializer
-
- GNU extensions:
-
- nested-function-definition:
- declaration-specifiers declarator declaration-list[opt]
- compound-statement
-
- attribute ;
-
- Objective-C:
- gnu-attributes objc-class-definition
- gnu-attributes objc-category-definition
- gnu-attributes objc-protocol-definition
-
- The simple-asm-expr and gnu-attributes are GNU extensions.
-
- This function does not handle __extension__; that is handled in its
- callers. ??? Following the old parser, __extension__ may start
- external declarations, declarations in functions and declarations
- at the start of "for" loops, but not old-style parameter
- declarations.
-
- C99 requires declaration specifiers in a function definition; the
- absence is diagnosed through the diagnosis of implicit int. In GNU
- C we also allow but diagnose declarations without declaration
- specifiers, but only at top level (elsewhere they conflict with
- other syntax).
-
- In Objective-C, declarations of the looping variable in a foreach
- statement are exceptionally terminated by 'in' (for example, 'for
- (NSObject *object in array) { ... }').
-
- OpenMP:
-
- declaration:
- threadprivate-directive
-
- GIMPLE:
-
- gimple-function-definition:
- declaration-specifiers[opt] __GIMPLE (gimple-or-rtl-pass-list) declarator
- declaration-list[opt] compound-statement
-
- rtl-function-definition:
- declaration-specifiers[opt] __RTL (gimple-or-rtl-pass-list) declarator
- declaration-list[opt] compound-statement */
-
-static void
-c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
- bool static_assert_ok, bool empty_ok,
- bool nested, bool start_attr_ok,
- tree *objc_foreach_object_declaration
- /* = NULL */,
- vec<c_token> *omp_declare_simd_clauses
- /* = NULL */,
- bool have_attrs /* = false */,
- tree attrs /* = NULL_TREE */,
- struct oacc_routine_data *oacc_routine_data
- /* = NULL */,
- bool *fallthru_attr_p /* = NULL */)
-{
- struct c_declspecs *specs;
- tree prefix_attrs;
- tree all_prefix_attrs;
- bool diagnosed_no_specs = false;
- location_t here = c_parser_peek_token (parser)->location;
-
- add_debug_begin_stmt (c_parser_peek_token (parser)->location);
-
- if (static_assert_ok
- && c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
- {
- c_parser_static_assert_declaration (parser);
- return;
- }
- specs = build_null_declspecs ();
-
- /* Handle any standard attributes parsed in the caller. */
- if (have_attrs)
- {
- declspecs_add_attrs (here, specs, attrs);
- specs->non_std_attrs_seen_p = false;
- }
-
- /* Try to detect an unknown type name when we have "A B" or "A *B". */
- if (c_parser_peek_token (parser)->type == CPP_NAME
- && c_parser_peek_token (parser)->id_kind == C_ID_ID
- && (c_parser_peek_2nd_token (parser)->type == CPP_NAME
- || c_parser_peek_2nd_token (parser)->type == CPP_MULT)
- && (!nested || !lookup_name (c_parser_peek_token (parser)->value)))
- {
- tree name = c_parser_peek_token (parser)->value;
-
- /* Issue a warning about NAME being an unknown type name, perhaps
- with some kind of hint.
- If the user forgot a "struct" etc, suggest inserting
- it. Otherwise, attempt to look for misspellings. */
- gcc_rich_location richloc (here);
- if (tag_exists_p (RECORD_TYPE, name))
- {
- /* This is not C++ with its implicit typedef. */
- richloc.add_fixit_insert_before ("struct ");
- error_at (&richloc,
- "unknown type name %qE;"
- " use %<struct%> keyword to refer to the type",
- name);
- }
- else if (tag_exists_p (UNION_TYPE, name))
- {
- richloc.add_fixit_insert_before ("union ");
- error_at (&richloc,
- "unknown type name %qE;"
- " use %<union%> keyword to refer to the type",
- name);
- }
- else if (tag_exists_p (ENUMERAL_TYPE, name))
- {
- richloc.add_fixit_insert_before ("enum ");
- error_at (&richloc,
- "unknown type name %qE;"
- " use %<enum%> keyword to refer to the type",
- name);
- }
- else
- {
- auto_diagnostic_group d;
- name_hint hint = lookup_name_fuzzy (name, FUZZY_LOOKUP_TYPENAME,
- here);
- if (const char *suggestion = hint.suggestion ())
- {
- richloc.add_fixit_replace (suggestion);
- error_at (&richloc,
- "unknown type name %qE; did you mean %qs?",
- name, suggestion);
- }
- else
- error_at (here, "unknown type name %qE", name);
- }
-
- /* Parse declspecs normally to get a correct pointer type, but avoid
- a further "fails to be a type name" error. Refuse nested functions
- since it is not how the user likely wants us to recover. */
- c_parser_peek_token (parser)->type = CPP_KEYWORD;
- c_parser_peek_token (parser)->keyword = RID_VOID;
- c_parser_peek_token (parser)->value = error_mark_node;
- fndef_ok = !nested;
- }
-
- /* When there are standard attributes at the start of the
- declaration (to apply to the entity being declared), an
- init-declarator-list or function definition must be present. */
- if (c_parser_nth_token_starts_std_attributes (parser, 1))
- have_attrs = true;
-
- c_parser_declspecs (parser, specs, true, true, start_attr_ok,
- true, true, start_attr_ok, true, cla_nonabstract_decl);
- if (parser->error)
- {
- c_parser_skip_to_end_of_block_or_statement (parser);
- return;
- }
- if (nested && !specs->declspecs_seen_p)
- {
- c_parser_error (parser, "expected declaration specifiers");
- c_parser_skip_to_end_of_block_or_statement (parser);
- return;
- }
-
- finish_declspecs (specs);
- bool auto_type_p = specs->typespec_word == cts_auto_type;
- if (c_parser_next_token_is (parser, CPP_SEMICOLON))
- {
- if (auto_type_p)
- error_at (here, "%<__auto_type%> in empty declaration");
- else if (specs->typespec_kind == ctsk_none
- && attribute_fallthrough_p (specs->attrs))
- {
- if (fallthru_attr_p != NULL)
- *fallthru_attr_p = true;
- if (nested)
- {
- tree fn = build_call_expr_internal_loc (here, IFN_FALLTHROUGH,
- void_type_node, 0);
- add_stmt (fn);
- }
- else
- pedwarn (here, OPT_Wattributes,
- "%<fallthrough%> attribute at top level");
- }
- else if (empty_ok && !(have_attrs
- && specs->non_std_attrs_seen_p))
- shadow_tag (specs);
- else
- {
- shadow_tag_warned (specs, 1);
- pedwarn (here, 0, "empty declaration");
- }
- c_parser_consume_token (parser);
- if (oacc_routine_data)
- c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false);
- return;
- }
-
- /* Provide better error recovery. Note that a type name here is usually
- better diagnosed as a redeclaration. */
- if (empty_ok
- && specs->typespec_kind == ctsk_tagdef
- && c_parser_next_token_starts_declspecs (parser)
- && !c_parser_next_token_is (parser, CPP_NAME))
- {
- c_parser_error (parser, "expected %<;%>, identifier or %<(%>");
- parser->error = false;
- shadow_tag_warned (specs, 1);
- return;
- }
- else if (c_dialect_objc () && !auto_type_p)
- {
- /* Prefix attributes are an error on method decls. */
- switch (c_parser_peek_token (parser)->type)
- {
- case CPP_PLUS:
- case CPP_MINUS:
- if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
- return;
- if (specs->attrs)
- {
- warning_at (c_parser_peek_token (parser)->location,
- OPT_Wattributes,
- "prefix attributes are ignored for methods");
- specs->attrs = NULL_TREE;
- }
- if (fndef_ok)
- c_parser_objc_method_definition (parser);
- else
- c_parser_objc_methodproto (parser);
- return;
- break;
- default:
- break;
- }
- /* This is where we parse 'attributes @interface ...',
- 'attributes @implementation ...', 'attributes @protocol ...'
- (where attributes could be, for example, __attribute__
- ((deprecated)).
- */
- switch (c_parser_peek_token (parser)->keyword)
- {
- case RID_AT_INTERFACE:
- {
- if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
- return;
- c_parser_objc_class_definition (parser, specs->attrs);
- return;
- }
- break;
- case RID_AT_IMPLEMENTATION:
- {
- if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
- return;
- if (specs->attrs)
- {
- warning_at (c_parser_peek_token (parser)->location,
- OPT_Wattributes,
- "prefix attributes are ignored for implementations");
- specs->attrs = NULL_TREE;
- }
- c_parser_objc_class_definition (parser, NULL_TREE);
- return;
- }
- break;
- case RID_AT_PROTOCOL:
- {
- if (c_parser_objc_diagnose_bad_element_prefix (parser, specs))
- return;
- c_parser_objc_protocol_definition (parser, specs->attrs);
- return;
- }
- break;
- case RID_AT_ALIAS:
- case RID_AT_CLASS:
- case RID_AT_END:
- case RID_AT_PROPERTY:
- if (specs->attrs)
- {
- c_parser_error (parser, "unexpected attribute");
- specs->attrs = NULL;
- }
- break;
- default:
- break;
- }
- }
- else if (attribute_fallthrough_p (specs->attrs))
- warning_at (here, OPT_Wattributes,
- "%<fallthrough%> attribute not followed by %<;%>");
-
- pending_xref_error ();
- prefix_attrs = specs->attrs;
- all_prefix_attrs = prefix_attrs;
- specs->attrs = NULL_TREE;
- while (true)
- {
- struct c_declarator *declarator;
- bool dummy = false;
- timevar_id_t tv;
- tree fnbody = NULL_TREE;
- /* Declaring either one or more declarators (in which case we
- should diagnose if there were no declaration specifiers) or a
- function definition (in which case the diagnostic for
- implicit int suffices). */
- declarator = c_parser_declarator (parser,
- specs->typespec_kind != ctsk_none,
- C_DTR_NORMAL, &dummy);
- if (declarator == NULL)
- {
- if (omp_declare_simd_clauses)
- c_finish_omp_declare_simd (parser, NULL_TREE, NULL_TREE,
- omp_declare_simd_clauses);
- if (oacc_routine_data)
- c_finish_oacc_routine (oacc_routine_data, NULL_TREE, false);
- c_parser_skip_to_end_of_block_or_statement (parser);
- return;
- }
- if (auto_type_p && declarator->kind != cdk_id)
- {
- error_at (here,
- "%<__auto_type%> requires a plain identifier"
- " as declarator");
- c_parser_skip_to_end_of_block_or_statement (parser);
- return;
- }
- if (c_parser_next_token_is (parser, CPP_EQ)
- || c_parser_next_token_is (parser, CPP_COMMA)
- || c_parser_next_token_is (parser, CPP_SEMICOLON)
- || c_parser_next_token_is_keyword (parser, RID_ASM)
- || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE)
- || c_parser_next_token_is_keyword (parser, RID_IN))
- {
- tree asm_name = NULL_TREE;
- tree postfix_attrs = NULL_TREE;
- if (!diagnosed_no_specs && !specs->declspecs_seen_p)
- {
- diagnosed_no_specs = true;
- pedwarn (here, 0, "data definition has no type or storage class");
- }
- /* Having seen a data definition, there cannot now be a
- function definition. */
- fndef_ok = false;
- if (c_parser_next_token_is_keyword (parser, RID_ASM))
- asm_name = c_parser_simple_asm_expr (parser);
- if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
- {
- postfix_attrs = c_parser_gnu_attributes (parser);
- if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
- {
- /* This means there is an attribute specifier after
- the declarator in a function definition. Provide
- some more information for the user. */
- error_at (here, "attributes should be specified before the "
- "declarator in a function definition");
- c_parser_skip_to_end_of_block_or_statement (parser);
- return;
- }
- }
- if (c_parser_next_token_is (parser, CPP_EQ))
- {
- tree d;
- struct c_expr init;
- location_t init_loc;
- c_parser_consume_token (parser);
- if (auto_type_p)
- {
- init_loc = c_parser_peek_token (parser)->location;
- rich_location richloc (line_table, init_loc);
- start_init (NULL_TREE, asm_name, global_bindings_p (), &richloc);
- /* A parameter is initialized, which is invalid. Don't
- attempt to instrument the initializer. */
- int flag_sanitize_save = flag_sanitize;
- if (nested && !empty_ok)
- flag_sanitize = 0;
- init = c_parser_expr_no_commas (parser, NULL);
- flag_sanitize = flag_sanitize_save;
- if (TREE_CODE (init.value) == COMPONENT_REF
- && DECL_C_BIT_FIELD (TREE_OPERAND (init.value, 1)))
- error_at (here,
- "%<__auto_type%> used with a bit-field"
- " initializer");
- init = convert_lvalue_to_rvalue (init_loc, init, true, true);
- tree init_type = TREE_TYPE (init.value);
- bool vm_type = variably_modified_type_p (init_type,
- NULL_TREE);
- if (vm_type)
- init.value = save_expr (init.value);
- finish_init ();
- specs->typespec_kind = ctsk_typeof;
- specs->locations[cdw_typedef] = init_loc;
- specs->typedef_p = true;
- specs->type = init_type;
- if (vm_type)
- {
- bool maybe_const = true;
- tree type_expr = c_fully_fold (init.value, false,
- &maybe_const);
- specs->expr_const_operands &= maybe_const;
- if (specs->expr)
- specs->expr = build2 (COMPOUND_EXPR,
- TREE_TYPE (type_expr),
- specs->expr, type_expr);
- else
- specs->expr = type_expr;
- }
- d = start_decl (declarator, specs, true,
- chainon (postfix_attrs, all_prefix_attrs));
- if (!d)
- d = error_mark_node;
- if (omp_declare_simd_clauses)
- c_finish_omp_declare_simd (parser, d, NULL_TREE,
- omp_declare_simd_clauses);
- }
- else
- {
- /* The declaration of the variable is in effect while
- its initializer is parsed. */
- d = start_decl (declarator, specs, true,
- chainon (postfix_attrs, all_prefix_attrs));
- if (!d)
- d = error_mark_node;
- if (omp_declare_simd_clauses)
- c_finish_omp_declare_simd (parser, d, NULL_TREE,
- omp_declare_simd_clauses);
- init_loc = c_parser_peek_token (parser)->location;
- rich_location richloc (line_table, init_loc);
- start_init (d, asm_name, global_bindings_p (), &richloc);
- /* A parameter is initialized, which is invalid. Don't
- attempt to instrument the initializer. */
- int flag_sanitize_save = flag_sanitize;
- if (TREE_CODE (d) == PARM_DECL)
- flag_sanitize = 0;
- init = c_parser_initializer (parser);
- flag_sanitize = flag_sanitize_save;
- finish_init ();
- }
- if (oacc_routine_data)
- c_finish_oacc_routine (oacc_routine_data, d, false);
- if (d != error_mark_node)
- {
- maybe_warn_string_init (init_loc, TREE_TYPE (d), init);
- finish_decl (d, init_loc, init.value,
- init.original_type, asm_name);
- }
- }
- else
- {
- if (auto_type_p)
- {
- error_at (here,
- "%<__auto_type%> requires an initialized "
- "data declaration");
- c_parser_skip_to_end_of_block_or_statement (parser);
- return;
- }
-
- location_t lastloc = UNKNOWN_LOCATION;
- tree attrs = chainon (postfix_attrs, all_prefix_attrs);
- tree d = start_decl (declarator, specs, false, attrs, &lastloc);
- if (d && TREE_CODE (d) == FUNCTION_DECL)
- {
- /* Find the innermost declarator that is neither cdk_id
- nor cdk_attrs. */
- const struct c_declarator *decl = declarator;
- const struct c_declarator *last_non_id_attrs = NULL;
-
- while (decl)
- switch (decl->kind)
- {
- case cdk_array:
- case cdk_function:
- case cdk_pointer:
- last_non_id_attrs = decl;
- decl = decl->declarator;
- break;
-
- case cdk_attrs:
- decl = decl->declarator;
- break;
-
- case cdk_id:
- decl = 0;
- break;
-
- default:
- gcc_unreachable ();
- }
-
- /* If it exists and is cdk_function declaration whose
- arguments have not been set yet, use its arguments. */
- if (last_non_id_attrs
- && last_non_id_attrs->kind == cdk_function)
- {
- tree parms = last_non_id_attrs->u.arg_info->parms;
- if (DECL_ARGUMENTS (d) == NULL_TREE
- && DECL_INITIAL (d) == NULL_TREE)
- DECL_ARGUMENTS (d) = parms;
-
- warn_parm_array_mismatch (lastloc, d, parms);
- }
- }
- if (omp_declare_simd_clauses)
- {
- tree parms = NULL_TREE;
- if (d && TREE_CODE (d) == FUNCTION_DECL)
- {
- struct c_declarator *ce = declarator;
- while (ce != NULL)
- if (ce->kind == cdk_function)
- {
- parms = ce->u.arg_info->parms;
- break;
- }
- else
- ce = ce->declarator;
- }
- if (parms)
- temp_store_parm_decls (d, parms);
- c_finish_omp_declare_simd (parser, d, parms,
- omp_declare_simd_clauses);
- if (parms)
- temp_pop_parm_decls ();
- }
- if (oacc_routine_data)
- c_finish_oacc_routine (oacc_routine_data, d, false);
- if (d)
- finish_decl (d, UNKNOWN_LOCATION, NULL_TREE,
- NULL_TREE, asm_name);
-
- if (c_parser_next_token_is_keyword (parser, RID_IN))
- {
- if (d)
- *objc_foreach_object_declaration = d;
- else
- *objc_foreach_object_declaration = error_mark_node;
- }
- }
- if (c_parser_next_token_is (parser, CPP_COMMA))
- {
- if (auto_type_p)
- {
- error_at (here,
- "%<__auto_type%> may only be used with"
- " a single declarator");
- c_parser_skip_to_end_of_block_or_statement (parser);
- return;
- }
- c_parser_consume_token (parser);
- if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
- all_prefix_attrs = chainon (c_parser_gnu_attributes (parser),
- prefix_attrs);
- else
- all_prefix_attrs = prefix_attrs;
- continue;
- }
- else if (c_parser_next_token_is (parser, CPP_SEMICOLON))
- {
- c_parser_consume_token (parser);
- return;
- }
- else if (c_parser_next_token_is_keyword (parser, RID_IN))
- {
- /* This can only happen in Objective-C: we found the
- 'in' that terminates the declaration inside an
- Objective-C foreach statement. Do not consume the
- token, so that the caller can use it to determine
- that this indeed is a foreach context. */
- return;
- }
- else
- {
- c_parser_error (parser, "expected %<,%> or %<;%>");
- c_parser_skip_to_end_of_block_or_statement (parser);
- return;
- }
- }
- else if (auto_type_p)
- {
- error_at (here,
- "%<__auto_type%> requires an initialized data declaration");
- c_parser_skip_to_end_of_block_or_statement (parser);
- return;
- }
- else if (!fndef_ok)
- {
- c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, "
- "%<asm%> or %<__attribute__%>");
- c_parser_skip_to_end_of_block_or_statement (parser);
- return;
- }
- /* Function definition (nested or otherwise). */
- if (nested)
- {
- pedwarn (here, OPT_Wpedantic, "ISO C forbids nested functions");
- c_push_function_context ();
- }
- if (!start_function (specs, declarator, all_prefix_attrs))
- {
- /* At this point we've consumed:
- declaration-specifiers declarator
- and the next token isn't CPP_EQ, CPP_COMMA, CPP_SEMICOLON,
- RID_ASM, RID_ATTRIBUTE, or RID_IN,
- but the
- declaration-specifiers declarator
- aren't grokkable as a function definition, so we have
- an error. */
- gcc_assert (!c_parser_next_token_is (parser, CPP_SEMICOLON));
- if (c_parser_next_token_starts_declspecs (parser))
- {
- /* If we have
- declaration-specifiers declarator decl-specs
- then assume we have a missing semicolon, which would
- give us:
- declaration-specifiers declarator decl-specs
- ^
- ;
- <~~~~~~~~~ declaration ~~~~~~~~~~>
- Use c_parser_require to get an error with a fix-it hint. */
- c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>");
- parser->error = false;
- }
- else
- {
- /* This can appear in many cases looking nothing like a
- function definition, so we don't give a more specific
- error suggesting there was one. */
- c_parser_error (parser, "expected %<=%>, %<,%>, %<;%>, %<asm%> "
- "or %<__attribute__%>");
- }
- if (nested)
- c_pop_function_context ();
- break;
- }
-
- if (DECL_DECLARED_INLINE_P (current_function_decl))
- tv = TV_PARSE_INLINE;
- else
- tv = TV_PARSE_FUNC;
- auto_timevar at (g_timer, tv);
-
- /* Parse old-style parameter declarations. ??? Attributes are
- not allowed to start declaration specifiers here because of a
- syntax conflict between a function declaration with attribute
- suffix and a function definition with an attribute prefix on
- first old-style parameter declaration. Following the old
- parser, they are not accepted on subsequent old-style
- parameter declarations either. However, there is no
- ambiguity after the first declaration, nor indeed on the
- first as long as we don't allow postfix attributes after a
- declarator with a nonempty identifier list in a definition;
- and postfix attributes have never been accepted here in
- function definitions either. */
- while (c_parser_next_token_is_not (parser, CPP_EOF)
- && c_parser_next_token_is_not (parser, CPP_OPEN_BRACE))
- c_parser_declaration_or_fndef (parser, false, false, false,
- true, false);
- store_parm_decls ();
- if (omp_declare_simd_clauses)
- c_finish_omp_declare_simd (parser, current_function_decl, NULL_TREE,
- omp_declare_simd_clauses);
- if (oacc_routine_data)
- c_finish_oacc_routine (oacc_routine_data, current_function_decl, true);
- location_t startloc = c_parser_peek_token (parser)->location;
- DECL_STRUCT_FUNCTION (current_function_decl)->function_start_locus
- = startloc;
- location_t endloc = startloc;
-
- /* If the definition was marked with __RTL, use the RTL parser now,
- consuming the function body. */
- if (specs->declspec_il == cdil_rtl)
- {
- endloc = c_parser_parse_rtl_body (parser, specs->gimple_or_rtl_pass);
-
- /* Normally, store_parm_decls sets next_is_function_body,
- anticipating a function body. We need a push_scope/pop_scope
- pair to flush out this state, or subsequent function parsing
- will go wrong. */
- push_scope ();
- pop_scope ();
-
- finish_function (endloc);
- return;
- }
- /* If the definition was marked with __GIMPLE then parse the
- function body as GIMPLE. */
- else if (specs->declspec_il != cdil_none)
- {
- bool saved = in_late_binary_op;
- in_late_binary_op = true;
- c_parser_parse_gimple_body (parser, specs->gimple_or_rtl_pass,
- specs->declspec_il,
- specs->entry_bb_count);
- in_late_binary_op = saved;
- }
- else
- fnbody = c_parser_compound_statement (parser, &endloc);
- tree fndecl = current_function_decl;
- if (nested)
- {
- tree decl = current_function_decl;
- /* Mark nested functions as needing static-chain initially.
- lower_nested_functions will recompute it but the
- DECL_STATIC_CHAIN flag is also used before that happens,
- by initializer_constant_valid_p. See gcc.dg/nested-fn-2.c. */
- DECL_STATIC_CHAIN (decl) = 1;
- add_stmt (fnbody);
- finish_function (endloc);
- c_pop_function_context ();
- add_stmt (build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl));
- }
- else
- {
- if (fnbody)
- add_stmt (fnbody);
- finish_function (endloc);
- }
- /* Get rid of the empty stmt list for GIMPLE/RTL. */
- if (specs->declspec_il != cdil_none)
- DECL_SAVED_TREE (fndecl) = NULL_TREE;
-
- break;
- }
-}
-
-/* Parse an asm-definition (asm() outside a function body). This is a
- GNU extension.
-
- asm-definition:
- simple-asm-expr ;
-*/
-
-static void
-c_parser_asm_definition (c_parser *parser)
-{
- tree asm_str = c_parser_simple_asm_expr (parser);
- if (asm_str)
- symtab->finalize_toplevel_asm (asm_str);
- c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-}
-
-/* Parse a static assertion (C11 6.7.10).
-
- static_assert-declaration:
- static_assert-declaration-no-semi ;
-*/
-
-static void
-c_parser_static_assert_declaration (c_parser *parser)
-{
- c_parser_static_assert_declaration_no_semi (parser);
- if (parser->error
- || !c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
- c_parser_skip_to_end_of_block_or_statement (parser);
-}
-
-/* Parse a static assertion (C11 6.7.10), without the trailing
- semicolon.
-
- static_assert-declaration-no-semi:
- _Static_assert ( constant-expression , string-literal )
-
- C2X:
- static_assert-declaration-no-semi:
- _Static_assert ( constant-expression )
-*/
-
-static void
-c_parser_static_assert_declaration_no_semi (c_parser *parser)
-{
- location_t assert_loc, value_loc;
- tree value;
- tree string = NULL_TREE;
-
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT));
- assert_loc = c_parser_peek_token (parser)->location;
- if (flag_isoc99)
- pedwarn_c99 (assert_loc, OPT_Wpedantic,
- "ISO C99 does not support %<_Static_assert%>");
- else
- pedwarn_c99 (assert_loc, OPT_Wpedantic,
- "ISO C90 does not support %<_Static_assert%>");
- c_parser_consume_token (parser);
- matching_parens parens;
- if (!parens.require_open (parser))
- return;
- location_t value_tok_loc = c_parser_peek_token (parser)->location;
- value = c_parser_expr_no_commas (parser, NULL).value;
- value_loc = EXPR_LOC_OR_LOC (value, value_tok_loc);
- if (c_parser_next_token_is (parser, CPP_COMMA))
- {
- c_parser_consume_token (parser);
- switch (c_parser_peek_token (parser)->type)
- {
- case CPP_STRING:
- case CPP_STRING16:
- case CPP_STRING32:
- case CPP_WSTRING:
- case CPP_UTF8STRING:
- string = c_parser_string_literal (parser, false, true).value;
- break;
- default:
- c_parser_error (parser, "expected string literal");
- return;
- }
- }
- else if (flag_isoc11)
- /* If pedantic for pre-C11, the use of _Static_assert itself will
- have been diagnosed, so do not also diagnose the use of this
- new C2X feature of _Static_assert. */
- pedwarn_c11 (assert_loc, OPT_Wpedantic,
- "ISO C11 does not support omitting the string in "
- "%<_Static_assert%>");
- parens.require_close (parser);
-
- if (!INTEGRAL_TYPE_P (TREE_TYPE (value)))
- {
- error_at (value_loc, "expression in static assertion is not an integer");
- return;
- }
- if (TREE_CODE (value) != INTEGER_CST)
- {
- value = c_fully_fold (value, false, NULL);
- /* Strip no-op conversions. */
- STRIP_TYPE_NOPS (value);
- if (TREE_CODE (value) == INTEGER_CST)
- pedwarn (value_loc, OPT_Wpedantic, "expression in static assertion "
- "is not an integer constant expression");
- }
- if (TREE_CODE (value) != INTEGER_CST)
- {
- error_at (value_loc, "expression in static assertion is not constant");
- return;
- }
- constant_expression_warning (value);
- if (integer_zerop (value))
- {
- if (string)
- error_at (assert_loc, "static assertion failed: %E", string);
- else
- error_at (assert_loc, "static assertion failed");
- }
-}
-
-/* Parse some declaration specifiers (possibly none) (C90 6.5, C99
- 6.7, C11 6.7), adding them to SPECS (which may already include some).
- Storage class specifiers are accepted iff SCSPEC_OK; type
- specifiers are accepted iff TYPESPEC_OK; alignment specifiers are
- accepted iff ALIGNSPEC_OK; gnu-attributes are accepted at the start
- iff START_ATTR_OK; __auto_type is accepted iff AUTO_TYPE_OK. In
- addition to the syntax shown, standard attributes are accepted at
- the start iff START_STD_ATTR_OK and at the end iff END_STD_ATTR_OK;
- unlike gnu-attributes, they are not accepted in the middle of the
- list. (This combines various different syntax productions in the C
- standard, and in some cases gnu-attributes and standard attributes
- at the start may already have been parsed before this function is
- called.)
-
- declaration-specifiers:
- storage-class-specifier declaration-specifiers[opt]
- type-specifier declaration-specifiers[opt]
- type-qualifier declaration-specifiers[opt]
- function-specifier declaration-specifiers[opt]
- alignment-specifier declaration-specifiers[opt]
-
- Function specifiers (inline) are from C99, and are currently
- handled as storage class specifiers, as is __thread. Alignment
- specifiers are from C11.
-
- C90 6.5.1, C99 6.7.1, C11 6.7.1:
- storage-class-specifier:
- typedef
- extern
- static
- auto
- register
- _Thread_local
-
- (_Thread_local is new in C11.)
-
- C99 6.7.4, C11 6.7.4:
- function-specifier:
- inline
- _Noreturn
-
- (_Noreturn is new in C11.)
-
- C90 6.5.2, C99 6.7.2, C11 6.7.2:
- type-specifier:
- void
- char
- short
- int
- long
- float
- double
- signed
- unsigned
- _Bool
- _Complex
- [_Imaginary removed in C99 TC2]
- struct-or-union-specifier
- enum-specifier
- typedef-name
- atomic-type-specifier
-
- (_Bool and _Complex are new in C99.)
- (atomic-type-specifier is new in C11.)
-
- C90 6.5.3, C99 6.7.3, C11 6.7.3:
-
- type-qualifier:
- const
- restrict
- volatile
- address-space-qualifier
- _Atomic
-
- (restrict is new in C99.)
- (_Atomic is new in C11.)
-
- GNU extensions:
-
- declaration-specifiers:
- gnu-attributes declaration-specifiers[opt]
-
- type-qualifier:
- address-space
-
- address-space:
- identifier recognized by the target
-
- storage-class-specifier:
- __thread
-
- type-specifier:
- typeof-specifier
- __auto_type
- __intN
- _Decimal32
- _Decimal64
- _Decimal128
- _Fract
- _Accum
- _Sat
-
- (_Fract, _Accum, and _Sat are new from ISO/IEC DTR 18037:
- http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1169.pdf)
-
- atomic-type-specifier
- _Atomic ( type-name )
-
- Objective-C:
-
- type-specifier:
- class-name objc-protocol-refs[opt]
- typedef-name objc-protocol-refs
- objc-protocol-refs
-*/
-
-void
-c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
- bool scspec_ok, bool typespec_ok, bool start_attr_ok,
- bool alignspec_ok, bool auto_type_ok,
- bool start_std_attr_ok, bool end_std_attr_ok,
- enum c_lookahead_kind la)
-{
- bool attrs_ok = start_attr_ok;
- bool seen_type = specs->typespec_kind != ctsk_none;
-
- if (!typespec_ok)
- gcc_assert (la == cla_prefer_id);
-
- if (start_std_attr_ok
- && c_parser_nth_token_starts_std_attributes (parser, 1))
- {
- gcc_assert (!specs->non_std_attrs_seen_p);
- location_t loc = c_parser_peek_token (parser)->location;
- tree attrs = c_parser_std_attribute_specifier_sequence (parser);
- declspecs_add_attrs (loc, specs, attrs);
- specs->non_std_attrs_seen_p = false;
- }
-
- while (c_parser_next_token_is (parser, CPP_NAME)
- || c_parser_next_token_is (parser, CPP_KEYWORD)
- || (c_dialect_objc () && c_parser_next_token_is (parser, CPP_LESS)))
- {
- struct c_typespec t;
- tree attrs;
- tree align;
- location_t loc = c_parser_peek_token (parser)->location;
-
- /* If we cannot accept a type, exit if the next token must start
- one. Also, if we already have seen a tagged definition,
- a typename would be an error anyway and likely the user
- has simply forgotten a semicolon, so we exit. */
- if ((!typespec_ok || specs->typespec_kind == ctsk_tagdef)
- && c_parser_next_tokens_start_typename (parser, la)
- && !c_parser_next_token_is_qualifier (parser)
- && !c_parser_next_token_is_keyword (parser, RID_ALIGNAS))
- break;
-
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- c_token *name_token = c_parser_peek_token (parser);
- tree value = name_token->value;
- c_id_kind kind = name_token->id_kind;
-
- if (kind == C_ID_ADDRSPACE)
- {
- addr_space_t as
- = name_token->keyword - RID_FIRST_ADDR_SPACE;
- declspecs_add_addrspace (name_token->location, specs, as);
- c_parser_consume_token (parser);
- attrs_ok = true;
- continue;
- }
-
- gcc_assert (!c_parser_next_token_is_qualifier (parser));
-
- /* If we cannot accept a type, and the next token must start one,
- exit. Do the same if we already have seen a tagged definition,
- since it would be an error anyway and likely the user has simply
- forgotten a semicolon. */
- if (seen_type || !c_parser_next_tokens_start_typename (parser, la))
- break;
-
- /* Now at an unknown typename (C_ID_ID), a C_ID_TYPENAME or
- a C_ID_CLASSNAME. */
- c_parser_consume_token (parser);
- seen_type = true;
- attrs_ok = true;
- if (kind == C_ID_ID)
- {
- error_at (loc, "unknown type name %qE", value);
- t.kind = ctsk_typedef;
- t.spec = error_mark_node;
- }
- else if (kind == C_ID_TYPENAME
- && (!c_dialect_objc ()
- || c_parser_next_token_is_not (parser, CPP_LESS)))
- {
- t.kind = ctsk_typedef;
- /* For a typedef name, record the meaning, not the name.
- In case of 'foo foo, bar;'. */
- t.spec = lookup_name (value);
- }
- else
- {
- tree proto = NULL_TREE;
- gcc_assert (c_dialect_objc ());
- t.kind = ctsk_objc;
- if (c_parser_next_token_is (parser, CPP_LESS))
- proto = c_parser_objc_protocol_refs (parser);
- t.spec = objc_get_protocol_qualified_type (value, proto);
- }
- t.expr = NULL_TREE;
- t.expr_const_operands = true;
- declspecs_add_type (name_token->location, specs, t);
- continue;
- }
- if (c_parser_next_token_is (parser, CPP_LESS))
- {
- /* Make "<SomeProtocol>" equivalent to "id <SomeProtocol>" -
- nisse@lysator.liu.se. */
- tree proto;
- gcc_assert (c_dialect_objc ());
- if (!typespec_ok || seen_type)
- break;
- proto = c_parser_objc_protocol_refs (parser);
- t.kind = ctsk_objc;
- t.spec = objc_get_protocol_qualified_type (NULL_TREE, proto);
- t.expr = NULL_TREE;
- t.expr_const_operands = true;
- declspecs_add_type (loc, specs, t);
- continue;
- }
- gcc_assert (c_parser_next_token_is (parser, CPP_KEYWORD));
- switch (c_parser_peek_token (parser)->keyword)
- {
- case RID_STATIC:
- case RID_EXTERN:
- case RID_REGISTER:
- case RID_TYPEDEF:
- case RID_INLINE:
- case RID_NORETURN:
- case RID_AUTO:
- case RID_THREAD:
- if (!scspec_ok)
- goto out;
- attrs_ok = true;
- /* TODO: Distinguish between function specifiers (inline, noreturn)
- and storage class specifiers, either here or in
- declspecs_add_scspec. */
- declspecs_add_scspec (loc, specs,
- c_parser_peek_token (parser)->value);
- c_parser_consume_token (parser);
- break;
- case RID_AUTO_TYPE:
- if (!auto_type_ok)
- goto out;
- /* Fall through. */
- case RID_UNSIGNED:
- case RID_LONG:
- case RID_SHORT:
- case RID_SIGNED:
- case RID_COMPLEX:
- case RID_INT:
- case RID_CHAR:
- case RID_FLOAT:
- case RID_DOUBLE:
- case RID_VOID:
- case RID_DFLOAT32:
- case RID_DFLOAT64:
- case RID_DFLOAT128:
- CASE_RID_FLOATN_NX:
- case RID_BOOL:
- case RID_FRACT:
- case RID_ACCUM:
- case RID_SAT:
- case RID_INT_N_0:
- case RID_INT_N_1:
- case RID_INT_N_2:
- case RID_INT_N_3:
- if (!typespec_ok)
- goto out;
- attrs_ok = true;
- seen_type = true;
- if (c_dialect_objc ())
- parser->objc_need_raw_identifier = true;
- t.kind = ctsk_resword;
- t.spec = c_parser_peek_token (parser)->value;
- t.expr = NULL_TREE;
- t.expr_const_operands = true;
- declspecs_add_type (loc, specs, t);
- c_parser_consume_token (parser);
- break;
- case RID_ENUM:
- if (!typespec_ok)
- goto out;
- attrs_ok = true;
- seen_type = true;
- t = c_parser_enum_specifier (parser);
- invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
- declspecs_add_type (loc, specs, t);
- break;
- case RID_STRUCT:
- case RID_UNION:
- if (!typespec_ok)
- goto out;
- attrs_ok = true;
- seen_type = true;
- t = c_parser_struct_or_union_specifier (parser);
- invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, t.spec);
- declspecs_add_type (loc, specs, t);
- break;
- case RID_TYPEOF:
- /* ??? The old parser rejected typeof after other type
- specifiers, but is a syntax error the best way of
- handling this? */
- if (!typespec_ok || seen_type)
- goto out;
- attrs_ok = true;
- seen_type = true;
- t = c_parser_typeof_specifier (parser);
- declspecs_add_type (loc, specs, t);
- break;
- case RID_ATOMIC:
- /* C parser handling of Objective-C constructs needs
- checking for correct lvalue-to-rvalue conversions, and
- the code in build_modify_expr handling various
- Objective-C cases, and that in build_unary_op handling
- Objective-C cases for increment / decrement, also needs
- updating; uses of TYPE_MAIN_VARIANT in objc_compare_types
- and objc_types_are_equivalent may also need updates. */
- if (c_dialect_objc ())
- sorry ("%<_Atomic%> in Objective-C");
- if (flag_isoc99)
- pedwarn_c99 (loc, OPT_Wpedantic,
- "ISO C99 does not support the %<_Atomic%> qualifier");
- else
- pedwarn_c99 (loc, OPT_Wpedantic,
- "ISO C90 does not support the %<_Atomic%> qualifier");
- attrs_ok = true;
- tree value;
- value = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- if (typespec_ok && c_parser_next_token_is (parser, CPP_OPEN_PAREN))
- {
- /* _Atomic ( type-name ). */
- seen_type = true;
- c_parser_consume_token (parser);
- struct c_type_name *type = c_parser_type_name (parser);
- t.kind = ctsk_typeof;
- t.spec = error_mark_node;
- t.expr = NULL_TREE;
- t.expr_const_operands = true;
- if (type != NULL)
- t.spec = groktypename (type, &t.expr,
- &t.expr_const_operands);
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>");
- if (t.spec != error_mark_node)
- {
- if (TREE_CODE (t.spec) == ARRAY_TYPE)
- error_at (loc, "%<_Atomic%>-qualified array type");
- else if (TREE_CODE (t.spec) == FUNCTION_TYPE)
- error_at (loc, "%<_Atomic%>-qualified function type");
- else if (TYPE_QUALS (t.spec) != TYPE_UNQUALIFIED)
- error_at (loc, "%<_Atomic%> applied to a qualified type");
- else
- t.spec = c_build_qualified_type (t.spec, TYPE_QUAL_ATOMIC);
- }
- declspecs_add_type (loc, specs, t);
- }
- else
- declspecs_add_qual (loc, specs, value);
- break;
- case RID_CONST:
- case RID_VOLATILE:
- case RID_RESTRICT:
- attrs_ok = true;
- declspecs_add_qual (loc, specs, c_parser_peek_token (parser)->value);
- c_parser_consume_token (parser);
- break;
- case RID_ATTRIBUTE:
- if (!attrs_ok)
- goto out;
- attrs = c_parser_gnu_attributes (parser);
- declspecs_add_attrs (loc, specs, attrs);
- break;
- case RID_ALIGNAS:
- if (!alignspec_ok)
- goto out;
- align = c_parser_alignas_specifier (parser);
- declspecs_add_alignas (loc, specs, align);
- break;
- case RID_GIMPLE:
- if (! flag_gimple)
- error_at (loc, "%<__GIMPLE%> only valid with %<-fgimple%>");
- c_parser_consume_token (parser);
- specs->declspec_il = cdil_gimple;
- specs->locations[cdw_gimple] = loc;
- c_parser_gimple_or_rtl_pass_list (parser, specs);
- break;
- case RID_RTL:
- c_parser_consume_token (parser);
- specs->declspec_il = cdil_rtl;
- specs->locations[cdw_rtl] = loc;
- c_parser_gimple_or_rtl_pass_list (parser, specs);
- break;
- default:
- goto out;
- }
- }
- out:
- if (end_std_attr_ok
- && c_parser_nth_token_starts_std_attributes (parser, 1))
- specs->postfix_attrs = c_parser_std_attribute_specifier_sequence (parser);
-}
-
-/* Parse an enum specifier (C90 6.5.2.2, C99 6.7.2.2, C11 6.7.2.2).
-
- enum-specifier:
- enum gnu-attributes[opt] identifier[opt] { enumerator-list }
- gnu-attributes[opt]
- enum gnu-attributes[opt] identifier[opt] { enumerator-list , }
- gnu-attributes[opt]
- enum gnu-attributes[opt] identifier
-
- The form with trailing comma is new in C99. The forms with
- gnu-attributes are GNU extensions. In GNU C, we accept any expression
- without commas in the syntax (assignment expressions, not just
- conditional expressions); assignment expressions will be diagnosed
- as non-constant.
-
- enumerator-list:
- enumerator
- enumerator-list , enumerator
-
- enumerator:
- enumeration-constant attribute-specifier-sequence[opt]
- enumeration-constant attribute-specifier-sequence[opt]
- = constant-expression
-
- GNU Extensions:
-
- enumerator:
- enumeration-constant attribute-specifier-sequence[opt] gnu-attributes[opt]
- enumeration-constant attribute-specifier-sequence[opt] gnu-attributes[opt]
- = constant-expression
-
-*/
-
-static struct c_typespec
-c_parser_enum_specifier (c_parser *parser)
-{
- struct c_typespec ret;
- bool have_std_attrs;
- tree std_attrs = NULL_TREE;
- tree attrs;
- tree ident = NULL_TREE;
- location_t enum_loc;
- location_t ident_loc = UNKNOWN_LOCATION; /* Quiet warning. */
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_ENUM));
- c_parser_consume_token (parser);
- have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1);
- if (have_std_attrs)
- std_attrs = c_parser_std_attribute_specifier_sequence (parser);
- attrs = c_parser_gnu_attributes (parser);
- enum_loc = c_parser_peek_token (parser)->location;
- /* Set the location in case we create a decl now. */
- c_parser_set_source_position_from_token (c_parser_peek_token (parser));
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- ident = c_parser_peek_token (parser)->value;
- ident_loc = c_parser_peek_token (parser)->location;
- enum_loc = ident_loc;
- c_parser_consume_token (parser);
- }
- if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
- {
- /* Parse an enum definition. */
- struct c_enum_contents the_enum;
- tree type;
- tree postfix_attrs;
- /* We chain the enumerators in reverse order, then put them in
- forward order at the end. */
- tree values;
- timevar_push (TV_PARSE_ENUM);
- type = start_enum (enum_loc, &the_enum, ident);
- values = NULL_TREE;
- c_parser_consume_token (parser);
- while (true)
- {
- tree enum_id;
- tree enum_value;
- tree enum_decl;
- bool seen_comma;
- c_token *token;
- location_t comma_loc = UNKNOWN_LOCATION; /* Quiet warning. */
- location_t decl_loc, value_loc;
- if (c_parser_next_token_is_not (parser, CPP_NAME))
- {
- /* Give a nicer error for "enum {}". */
- if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE)
- && !parser->error)
- {
- error_at (c_parser_peek_token (parser)->location,
- "empty enum is invalid");
- parser->error = true;
- }
- else
- c_parser_error (parser, "expected identifier");
- c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
- values = error_mark_node;
- break;
- }
- token = c_parser_peek_token (parser);
- enum_id = token->value;
- /* Set the location in case we create a decl now. */
- c_parser_set_source_position_from_token (token);
- decl_loc = value_loc = token->location;
- c_parser_consume_token (parser);
- /* Parse any specified attributes. */
- tree std_attrs = NULL_TREE;
- if (c_parser_nth_token_starts_std_attributes (parser, 1))
- std_attrs = c_parser_std_attribute_specifier_sequence (parser);
- tree enum_attrs = chainon (std_attrs,
- c_parser_gnu_attributes (parser));
- if (c_parser_next_token_is (parser, CPP_EQ))
- {
- c_parser_consume_token (parser);
- value_loc = c_parser_peek_token (parser)->location;
- enum_value = c_parser_expr_no_commas (parser, NULL).value;
- }
- else
- enum_value = NULL_TREE;
- enum_decl = build_enumerator (decl_loc, value_loc,
- &the_enum, enum_id, enum_value);
- if (enum_attrs)
- decl_attributes (&TREE_PURPOSE (enum_decl), enum_attrs, 0);
- TREE_CHAIN (enum_decl) = values;
- values = enum_decl;
- seen_comma = false;
- if (c_parser_next_token_is (parser, CPP_COMMA))
- {
- comma_loc = c_parser_peek_token (parser)->location;
- seen_comma = true;
- c_parser_consume_token (parser);
- }
- if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
- {
- if (seen_comma)
- pedwarn_c90 (comma_loc, OPT_Wpedantic,
- "comma at end of enumerator list");
- c_parser_consume_token (parser);
- break;
- }
- if (!seen_comma)
- {
- c_parser_error (parser, "expected %<,%> or %<}%>");
- c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
- values = error_mark_node;
- break;
- }
- }
- postfix_attrs = c_parser_gnu_attributes (parser);
- ret.spec = finish_enum (type, nreverse (values),
- chainon (std_attrs,
- chainon (attrs, postfix_attrs)));
- ret.kind = ctsk_tagdef;
- ret.expr = NULL_TREE;
- ret.expr_const_operands = true;
- timevar_pop (TV_PARSE_ENUM);
- return ret;
- }
- else if (!ident)
- {
- c_parser_error (parser, "expected %<{%>");
- ret.spec = error_mark_node;
- ret.kind = ctsk_tagref;
- ret.expr = NULL_TREE;
- ret.expr_const_operands = true;
- return ret;
- }
- /* Attributes may only appear when the members are defined or in
- certain forward declarations (treat enum forward declarations in
- GNU C analogously to struct and union forward declarations in
- standard C). */
- if (have_std_attrs && c_parser_next_token_is_not (parser, CPP_SEMICOLON))
- c_parser_error (parser, "expected %<;%>");
- ret = parser_xref_tag (ident_loc, ENUMERAL_TYPE, ident, have_std_attrs,
- std_attrs);
- /* In ISO C, enumerated types can be referred to only if already
- defined. */
- if (pedantic && !COMPLETE_TYPE_P (ret.spec))
- {
- gcc_assert (ident);
- pedwarn (enum_loc, OPT_Wpedantic,
- "ISO C forbids forward references to %<enum%> types");
- }
- return ret;
-}
-
-/* Parse a struct or union specifier (C90 6.5.2.1, C99 6.7.2.1, C11 6.7.2.1).
-
- struct-or-union-specifier:
- struct-or-union attribute-specifier-sequence[opt] gnu-attributes[opt]
- identifier[opt] { struct-contents } gnu-attributes[opt]
- struct-or-union attribute-specifier-sequence[opt] gnu-attributes[opt]
- identifier
-
- struct-contents:
- struct-declaration-list
-
- struct-declaration-list:
- struct-declaration ;
- struct-declaration-list struct-declaration ;
-
- GNU extensions:
-
- struct-contents:
- empty
- struct-declaration
- struct-declaration-list struct-declaration
-
- struct-declaration-list:
- struct-declaration-list ;
- ;
-
- (Note that in the syntax here, unlike that in ISO C, the semicolons
- are included here rather than in struct-declaration, in order to
- describe the syntax with extra semicolons and missing semicolon at
- end.)
-
- Objective-C:
-
- struct-declaration-list:
- @defs ( class-name )
-
- (Note this does not include a trailing semicolon, but can be
- followed by further declarations, and gets a pedwarn-if-pedantic
- when followed by a semicolon.) */
-
-static struct c_typespec
-c_parser_struct_or_union_specifier (c_parser *parser)
-{
- struct c_typespec ret;
- bool have_std_attrs;
- tree std_attrs = NULL_TREE;
- tree attrs;
- tree ident = NULL_TREE;
- location_t struct_loc;
- location_t ident_loc = UNKNOWN_LOCATION;
- enum tree_code code;
- switch (c_parser_peek_token (parser)->keyword)
- {
- case RID_STRUCT:
- code = RECORD_TYPE;
- break;
- case RID_UNION:
- code = UNION_TYPE;
- break;
- default:
- gcc_unreachable ();
- }
- struct_loc = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
- have_std_attrs = c_parser_nth_token_starts_std_attributes (parser, 1);
- if (have_std_attrs)
- std_attrs = c_parser_std_attribute_specifier_sequence (parser);
- attrs = c_parser_gnu_attributes (parser);
-
- /* Set the location in case we create a decl now. */
- c_parser_set_source_position_from_token (c_parser_peek_token (parser));
-
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- ident = c_parser_peek_token (parser)->value;
- ident_loc = c_parser_peek_token (parser)->location;
- struct_loc = ident_loc;
- c_parser_consume_token (parser);
- }
- if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
- {
- /* Parse a struct or union definition. Start the scope of the
- tag before parsing components. */
- class c_struct_parse_info *struct_info;
- tree type = start_struct (struct_loc, code, ident, &struct_info);
- tree postfix_attrs;
- /* We chain the components in reverse order, then put them in
- forward order at the end. Each struct-declaration may
- declare multiple components (comma-separated), so we must use
- chainon to join them, although when parsing each
- struct-declaration we can use TREE_CHAIN directly.
-
- The theory behind all this is that there will be more
- semicolon separated fields than comma separated fields, and
- so we'll be minimizing the number of node traversals required
- by chainon. */
- tree contents;
- timevar_push (TV_PARSE_STRUCT);
- contents = NULL_TREE;
- c_parser_consume_token (parser);
- /* Handle the Objective-C @defs construct,
- e.g. foo(sizeof(struct{ @defs(ClassName) }));. */
- if (c_parser_next_token_is_keyword (parser, RID_AT_DEFS))
- {
- tree name;
- gcc_assert (c_dialect_objc ());
- c_parser_consume_token (parser);
- matching_parens parens;
- if (!parens.require_open (parser))
- goto end_at_defs;
- if (c_parser_next_token_is (parser, CPP_NAME)
- && c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME)
- {
- name = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- }
- else
- {
- c_parser_error (parser, "expected class name");
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- goto end_at_defs;
- }
- parens.skip_until_found_close (parser);
- contents = nreverse (objc_get_class_ivars (name));
- }
- end_at_defs:
- /* Parse the struct-declarations and semicolons. Problems with
- semicolons are diagnosed here; empty structures are diagnosed
- elsewhere. */
- while (true)
- {
- tree decls;
- /* Parse any stray semicolon. */
- if (c_parser_next_token_is (parser, CPP_SEMICOLON))
- {
- location_t semicolon_loc
- = c_parser_peek_token (parser)->location;
- gcc_rich_location richloc (semicolon_loc);
- richloc.add_fixit_remove ();
- pedwarn (&richloc, OPT_Wpedantic,
- "extra semicolon in struct or union specified");
- c_parser_consume_token (parser);
- continue;
- }
- /* Stop if at the end of the struct or union contents. */
- if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
- {
- c_parser_consume_token (parser);
- break;
- }
- /* Accept #pragmas at struct scope. */
- if (c_parser_next_token_is (parser, CPP_PRAGMA))
- {
- c_parser_pragma (parser, pragma_struct, NULL);
- continue;
- }
- /* Parse some comma-separated declarations, but not the
- trailing semicolon if any. */
- decls = c_parser_struct_declaration (parser);
- contents = chainon (decls, contents);
- /* If no semicolon follows, either we have a parse error or
- are at the end of the struct or union and should
- pedwarn. */
- if (c_parser_next_token_is (parser, CPP_SEMICOLON))
- c_parser_consume_token (parser);
- else
- {
- if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
- pedwarn (c_parser_peek_token (parser)->location, 0,
- "no semicolon at end of struct or union");
- else if (parser->error
- || !c_parser_next_token_starts_declspecs (parser))
- {
- c_parser_error (parser, "expected %<;%>");
- c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
- break;
- }
-
- /* If we come here, we have already emitted an error
- for an expected `;', identifier or `(', and we also
- recovered already. Go on with the next field. */
- }
- }
- postfix_attrs = c_parser_gnu_attributes (parser);
- ret.spec = finish_struct (struct_loc, type, nreverse (contents),
- chainon (std_attrs,
- chainon (attrs, postfix_attrs)),
- struct_info);
- ret.kind = ctsk_tagdef;
- ret.expr = NULL_TREE;
- ret.expr_const_operands = true;
- timevar_pop (TV_PARSE_STRUCT);
- return ret;
- }
- else if (!ident)
- {
- c_parser_error (parser, "expected %<{%>");
- ret.spec = error_mark_node;
- ret.kind = ctsk_tagref;
- ret.expr = NULL_TREE;
- ret.expr_const_operands = true;
- return ret;
- }
- /* Attributes may only appear when the members are defined or in
- certain forward declarations. */
- if (have_std_attrs && c_parser_next_token_is_not (parser, CPP_SEMICOLON))
- c_parser_error (parser, "expected %<;%>");
- /* ??? Existing practice is that GNU attributes are ignored after
- the struct or union keyword when not defining the members. */
- ret = parser_xref_tag (ident_loc, code, ident, have_std_attrs, std_attrs);
- return ret;
-}
-
-/* Parse a struct-declaration (C90 6.5.2.1, C99 6.7.2.1, C11 6.7.2.1),
- *without* the trailing semicolon.
-
- struct-declaration:
- attribute-specifier-sequence[opt] specifier-qualifier-list
- attribute-specifier-sequence[opt] struct-declarator-list
- static_assert-declaration-no-semi
-
- specifier-qualifier-list:
- type-specifier specifier-qualifier-list[opt]
- type-qualifier specifier-qualifier-list[opt]
- alignment-specifier specifier-qualifier-list[opt]
- gnu-attributes specifier-qualifier-list[opt]
-
- struct-declarator-list:
- struct-declarator
- struct-declarator-list , gnu-attributes[opt] struct-declarator
-
- struct-declarator:
- declarator gnu-attributes[opt]
- declarator[opt] : constant-expression gnu-attributes[opt]
-
- GNU extensions:
-
- struct-declaration:
- __extension__ struct-declaration
- specifier-qualifier-list
-
- Unlike the ISO C syntax, semicolons are handled elsewhere. The use
- of gnu-attributes where shown is a GNU extension. In GNU C, we accept
- any expression without commas in the syntax (assignment
- expressions, not just conditional expressions); assignment
- expressions will be diagnosed as non-constant. */
-
-static tree
-c_parser_struct_declaration (c_parser *parser)
-{
- struct c_declspecs *specs;
- tree prefix_attrs;
- tree all_prefix_attrs;
- tree decls;
- location_t decl_loc;
- if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
- {
- int ext;
- tree decl;
- ext = disable_extension_diagnostics ();
- c_parser_consume_token (parser);
- decl = c_parser_struct_declaration (parser);
- restore_extension_diagnostics (ext);
- return decl;
- }
- if (c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
- {
- c_parser_static_assert_declaration_no_semi (parser);
- return NULL_TREE;
- }
- specs = build_null_declspecs ();
- decl_loc = c_parser_peek_token (parser)->location;
- /* Strictly by the standard, we shouldn't allow _Alignas here,
- but it appears to have been intended to allow it there, so
- we're keeping it as it is until WG14 reaches a conclusion
- of N1731.
- <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1731.pdf> */
- c_parser_declspecs (parser, specs, false, true, true,
- true, false, true, true, cla_nonabstract_decl);
- if (parser->error)
- return NULL_TREE;
- if (!specs->declspecs_seen_p)
- {
- c_parser_error (parser, "expected specifier-qualifier-list");
- return NULL_TREE;
- }
- finish_declspecs (specs);
- if (c_parser_next_token_is (parser, CPP_SEMICOLON)
- || c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
- {
- tree ret;
- if (specs->typespec_kind == ctsk_none)
- {
- pedwarn (decl_loc, OPT_Wpedantic,
- "ISO C forbids member declarations with no members");
- shadow_tag_warned (specs, pedantic);
- ret = NULL_TREE;
- }
- else
- {
- /* Support for unnamed structs or unions as members of
- structs or unions (which is [a] useful and [b] supports
- MS P-SDK). */
- tree attrs = NULL;
-
- ret = grokfield (c_parser_peek_token (parser)->location,
- build_id_declarator (NULL_TREE), specs,
- NULL_TREE, &attrs);
- if (ret)
- decl_attributes (&ret, attrs, 0);
- }
- return ret;
- }
-
- /* Provide better error recovery. Note that a type name here is valid,
- and will be treated as a field name. */
- if (specs->typespec_kind == ctsk_tagdef
- && TREE_CODE (specs->type) != ENUMERAL_TYPE
- && c_parser_next_token_starts_declspecs (parser)
- && !c_parser_next_token_is (parser, CPP_NAME))
- {
- c_parser_error (parser, "expected %<;%>, identifier or %<(%>");
- parser->error = false;
- return NULL_TREE;
- }
-
- pending_xref_error ();
- prefix_attrs = specs->attrs;
- all_prefix_attrs = prefix_attrs;
- specs->attrs = NULL_TREE;
- decls = NULL_TREE;
- while (true)
- {
- /* Declaring one or more declarators or un-named bit-fields. */
- struct c_declarator *declarator;
- bool dummy = false;
- if (c_parser_next_token_is (parser, CPP_COLON))
- declarator = build_id_declarator (NULL_TREE);
- else
- declarator = c_parser_declarator (parser,
- specs->typespec_kind != ctsk_none,
- C_DTR_NORMAL, &dummy);
- if (declarator == NULL)
- {
- c_parser_skip_to_end_of_block_or_statement (parser);
- break;
- }
- if (c_parser_next_token_is (parser, CPP_COLON)
- || c_parser_next_token_is (parser, CPP_COMMA)
- || c_parser_next_token_is (parser, CPP_SEMICOLON)
- || c_parser_next_token_is (parser, CPP_CLOSE_BRACE)
- || c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
- {
- tree postfix_attrs = NULL_TREE;
- tree width = NULL_TREE;
- tree d;
- if (c_parser_next_token_is (parser, CPP_COLON))
- {
- c_parser_consume_token (parser);
- width = c_parser_expr_no_commas (parser, NULL).value;
- }
- if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
- postfix_attrs = c_parser_gnu_attributes (parser);
- d = grokfield (c_parser_peek_token (parser)->location,
- declarator, specs, width, &all_prefix_attrs);
- decl_attributes (&d, chainon (postfix_attrs,
- all_prefix_attrs), 0);
- DECL_CHAIN (d) = decls;
- decls = d;
- if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
- all_prefix_attrs = chainon (c_parser_gnu_attributes (parser),
- prefix_attrs);
- else
- all_prefix_attrs = prefix_attrs;
- if (c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
- else if (c_parser_next_token_is (parser, CPP_SEMICOLON)
- || c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
- {
- /* Semicolon consumed in caller. */
- break;
- }
- else
- {
- c_parser_error (parser, "expected %<,%>, %<;%> or %<}%>");
- break;
- }
- }
- else
- {
- c_parser_error (parser,
- "expected %<:%>, %<,%>, %<;%>, %<}%> or "
- "%<__attribute__%>");
- break;
- }
- }
- return decls;
-}
-
-/* Parse a typeof specifier (a GNU extension).
-
- typeof-specifier:
- typeof ( expression )
- typeof ( type-name )
-*/
-
-static struct c_typespec
-c_parser_typeof_specifier (c_parser *parser)
-{
- struct c_typespec ret;
- ret.kind = ctsk_typeof;
- ret.spec = error_mark_node;
- ret.expr = NULL_TREE;
- ret.expr_const_operands = true;
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_TYPEOF));
- c_parser_consume_token (parser);
- c_inhibit_evaluation_warnings++;
- in_typeof++;
- matching_parens parens;
- if (!parens.require_open (parser))
- {
- c_inhibit_evaluation_warnings--;
- in_typeof--;
- return ret;
- }
- if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
- {
- struct c_type_name *type = c_parser_type_name (parser);
- c_inhibit_evaluation_warnings--;
- in_typeof--;
- if (type != NULL)
- {
- ret.spec = groktypename (type, &ret.expr, &ret.expr_const_operands);
- pop_maybe_used (variably_modified_type_p (ret.spec, NULL_TREE));
- }
- }
- else
- {
- bool was_vm;
- location_t here = c_parser_peek_token (parser)->location;
- struct c_expr expr = c_parser_expression (parser);
- c_inhibit_evaluation_warnings--;
- in_typeof--;
- if (TREE_CODE (expr.value) == COMPONENT_REF
- && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
- error_at (here, "%<typeof%> applied to a bit-field");
- mark_exp_read (expr.value);
- ret.spec = TREE_TYPE (expr.value);
- was_vm = variably_modified_type_p (ret.spec, NULL_TREE);
- /* This is returned with the type so that when the type is
- evaluated, this can be evaluated. */
- if (was_vm)
- ret.expr = c_fully_fold (expr.value, false, &ret.expr_const_operands);
- pop_maybe_used (was_vm);
- }
- parens.skip_until_found_close (parser);
- return ret;
-}
-
-/* Parse an alignment-specifier.
-
- C11 6.7.5:
-
- alignment-specifier:
- _Alignas ( type-name )
- _Alignas ( constant-expression )
-*/
-
-static tree
-c_parser_alignas_specifier (c_parser * parser)
-{
- tree ret = error_mark_node;
- location_t loc = c_parser_peek_token (parser)->location;
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNAS));
- c_parser_consume_token (parser);
- if (flag_isoc99)
- pedwarn_c99 (loc, OPT_Wpedantic,
- "ISO C99 does not support %<_Alignas%>");
- else
- pedwarn_c99 (loc, OPT_Wpedantic,
- "ISO C90 does not support %<_Alignas%>");
- matching_parens parens;
- if (!parens.require_open (parser))
- return ret;
- if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
- {
- struct c_type_name *type = c_parser_type_name (parser);
- if (type != NULL)
- ret = c_sizeof_or_alignof_type (loc, groktypename (type, NULL, NULL),
- false, true, 1);
- }
- else
- ret = c_parser_expr_no_commas (parser, NULL).value;
- parens.skip_until_found_close (parser);
- return ret;
-}
-
-/* Parse a declarator, possibly an abstract declarator (C90 6.5.4,
- 6.5.5, C99 6.7.5, 6.7.6, C11 6.7.6, 6.7.7). If TYPE_SEEN_P then
- a typedef name may be redeclared; otherwise it may not. KIND
- indicates which kind of declarator is wanted. Returns a valid
- declarator except in the case of a syntax error in which case NULL is
- returned. *SEEN_ID is set to true if an identifier being declared is
- seen; this is used to diagnose bad forms of abstract array declarators
- and to determine whether an identifier list is syntactically permitted.
-
- declarator:
- pointer[opt] direct-declarator
-
- direct-declarator:
- identifier
- ( gnu-attributes[opt] declarator )
- direct-declarator array-declarator
- direct-declarator ( parameter-type-list )
- direct-declarator ( identifier-list[opt] )
-
- pointer:
- * type-qualifier-list[opt]
- * type-qualifier-list[opt] pointer
-
- type-qualifier-list:
- type-qualifier
- gnu-attributes
- type-qualifier-list type-qualifier
- type-qualifier-list gnu-attributes
-
- array-declarator:
- [ type-qualifier-list[opt] assignment-expression[opt] ]
- [ static type-qualifier-list[opt] assignment-expression ]
- [ type-qualifier-list static assignment-expression ]
- [ type-qualifier-list[opt] * ]
-
- parameter-type-list:
- parameter-list
- parameter-list , ...
-
- parameter-list:
- parameter-declaration
- parameter-list , parameter-declaration
-
- parameter-declaration:
- declaration-specifiers declarator gnu-attributes[opt]
- declaration-specifiers abstract-declarator[opt] gnu-attributes[opt]
-
- identifier-list:
- identifier
- identifier-list , identifier
-
- abstract-declarator:
- pointer
- pointer[opt] direct-abstract-declarator
-
- direct-abstract-declarator:
- ( gnu-attributes[opt] abstract-declarator )
- direct-abstract-declarator[opt] array-declarator
- direct-abstract-declarator[opt] ( parameter-type-list[opt] )
-
- GNU extensions:
-
- direct-declarator:
- direct-declarator ( parameter-forward-declarations
- parameter-type-list[opt] )
-
- direct-abstract-declarator:
- direct-abstract-declarator[opt] ( parameter-forward-declarations
- parameter-type-list[opt] )
-
- parameter-forward-declarations:
- parameter-list ;
- parameter-forward-declarations parameter-list ;
-
- The uses of gnu-attributes shown above are GNU extensions.
-
- Some forms of array declarator are not included in C99 in the
- syntax for abstract declarators; these are disallowed elsewhere.
- This may be a defect (DR#289).
-
- This function also accepts an omitted abstract declarator as being
- an abstract declarator, although not part of the formal syntax. */
-
-struct c_declarator *
-c_parser_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
- bool *seen_id)
-{
- /* Parse any initial pointer part. */
- if (c_parser_next_token_is (parser, CPP_MULT))
- {
- struct c_declspecs *quals_attrs = build_null_declspecs ();
- struct c_declarator *inner;
- c_parser_consume_token (parser);
- c_parser_declspecs (parser, quals_attrs, false, false, true,
- false, false, true, false, cla_prefer_id);
- inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
- if (inner == NULL)
- return NULL;
- else
- return make_pointer_declarator (quals_attrs, inner);
- }
- /* Now we have a direct declarator, direct abstract declarator or
- nothing (which counts as a direct abstract declarator here). */
- return c_parser_direct_declarator (parser, type_seen_p, kind, seen_id);
-}
-
-/* Parse a direct declarator or direct abstract declarator; arguments
- as c_parser_declarator. */
-
-static struct c_declarator *
-c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
- bool *seen_id)
-{
- /* The direct declarator must start with an identifier (possibly
- omitted) or a parenthesized declarator (possibly abstract). In
- an ordinary declarator, initial parentheses must start a
- parenthesized declarator. In an abstract declarator or parameter
- declarator, they could start a parenthesized declarator or a
- parameter list. To tell which, the open parenthesis and any
- following gnu-attributes must be read. If a declaration
- specifier or standard attributes follow, then it is a parameter
- list; if the specifier is a typedef name, there might be an
- ambiguity about redeclaring it, which is resolved in the
- direction of treating it as a typedef name. If a close
- parenthesis follows, it is also an empty parameter list, as the
- syntax does not permit empty abstract declarators. Otherwise, it
- is a parenthesized declarator (in which case the analysis may be
- repeated inside it, recursively).
-
- ??? There is an ambiguity in a parameter declaration "int
- (__attribute__((foo)) x)", where x is not a typedef name: it
- could be an abstract declarator for a function, or declare x with
- parentheses. The proper resolution of this ambiguity needs
- documenting. At present we follow an accident of the old
- parser's implementation, whereby the first parameter must have
- some declaration specifiers other than just gnu-attributes. Thus as
- a parameter declaration it is treated as a parenthesized
- parameter named x, and as an abstract declarator it is
- rejected.
-
- ??? Also following the old parser, gnu-attributes inside an empty
- parameter list are ignored, making it a list not yielding a
- prototype, rather than giving an error or making it have one
- parameter with implicit type int.
-
- ??? Also following the old parser, typedef names may be
- redeclared in declarators, but not Objective-C class names. */
-
- if (kind != C_DTR_ABSTRACT
- && c_parser_next_token_is (parser, CPP_NAME)
- && ((type_seen_p
- && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
- || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
- || c_parser_peek_token (parser)->id_kind == C_ID_ID))
- {
- struct c_declarator *inner
- = build_id_declarator (c_parser_peek_token (parser)->value);
- *seen_id = true;
- inner->id_loc = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
- if (c_parser_nth_token_starts_std_attributes (parser, 1))
- inner->u.id.attrs = c_parser_std_attribute_specifier_sequence (parser);
- return c_parser_direct_declarator_inner (parser, *seen_id, inner);
- }
-
- if (kind != C_DTR_NORMAL
- && c_parser_next_token_is (parser, CPP_OPEN_SQUARE)
- && !c_parser_nth_token_starts_std_attributes (parser, 1))
- {
- struct c_declarator *inner = build_id_declarator (NULL_TREE);
- inner->id_loc = c_parser_peek_token (parser)->location;
- return c_parser_direct_declarator_inner (parser, *seen_id, inner);
- }
-
- /* Either we are at the end of an abstract declarator, or we have
- parentheses. */
-
- if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
- {
- tree attrs;
- struct c_declarator *inner;
- c_parser_consume_token (parser);
- bool have_gnu_attrs = c_parser_next_token_is_keyword (parser,
- RID_ATTRIBUTE);
- attrs = c_parser_gnu_attributes (parser);
- if (kind != C_DTR_NORMAL
- && (c_parser_next_token_starts_declspecs (parser)
- || (!have_gnu_attrs
- && c_parser_nth_token_starts_std_attributes (parser, 1))
- || c_parser_next_token_is (parser, CPP_CLOSE_PAREN)))
- {
- struct c_arg_info *args
- = c_parser_parms_declarator (parser, kind == C_DTR_NORMAL,
- attrs, have_gnu_attrs);
- if (args == NULL)
- return NULL;
- else
- {
- inner = build_id_declarator (NULL_TREE);
- if (!(args->types
- && args->types != error_mark_node
- && TREE_CODE (TREE_VALUE (args->types)) == IDENTIFIER_NODE)
- && c_parser_nth_token_starts_std_attributes (parser, 1))
- {
- tree std_attrs
- = c_parser_std_attribute_specifier_sequence (parser);
- if (std_attrs)
- inner = build_attrs_declarator (std_attrs, inner);
- }
- inner = build_function_declarator (args, inner);
- return c_parser_direct_declarator_inner (parser, *seen_id,
- inner);
- }
- }
- /* A parenthesized declarator. */
- inner = c_parser_declarator (parser, type_seen_p, kind, seen_id);
- if (inner != NULL && attrs != NULL)
- inner = build_attrs_declarator (attrs, inner);
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- {
- c_parser_consume_token (parser);
- if (inner == NULL)
- return NULL;
- else
- return c_parser_direct_declarator_inner (parser, *seen_id, inner);
- }
- else
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>");
- return NULL;
- }
- }
- else
- {
- if (kind == C_DTR_NORMAL)
- {
- c_parser_error (parser, "expected identifier or %<(%>");
- return NULL;
- }
- else
- return build_id_declarator (NULL_TREE);
- }
-}
-
-/* Parse part of a direct declarator or direct abstract declarator,
- given that some (in INNER) has already been parsed; ID_PRESENT is
- true if an identifier is present, false for an abstract
- declarator. */
-
-static struct c_declarator *
-c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
- struct c_declarator *inner)
-{
- /* Parse a sequence of array declarators and parameter lists. */
- if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE)
- && !c_parser_nth_token_starts_std_attributes (parser, 1))
- {
- location_t brace_loc = c_parser_peek_token (parser)->location;
- struct c_declarator *declarator;
- struct c_declspecs *quals_attrs = build_null_declspecs ();
- bool static_seen;
- bool star_seen;
- struct c_expr dimen;
- dimen.value = NULL_TREE;
- dimen.original_code = ERROR_MARK;
- dimen.original_type = NULL_TREE;
- c_parser_consume_token (parser);
- c_parser_declspecs (parser, quals_attrs, false, false, true,
- false, false, false, false, cla_prefer_id);
- static_seen = c_parser_next_token_is_keyword (parser, RID_STATIC);
- if (static_seen)
- c_parser_consume_token (parser);
- if (static_seen && !quals_attrs->declspecs_seen_p)
- c_parser_declspecs (parser, quals_attrs, false, false, true,
- false, false, false, false, cla_prefer_id);
- if (!quals_attrs->declspecs_seen_p)
- quals_attrs = NULL;
- /* If "static" is present, there must be an array dimension.
- Otherwise, there may be a dimension, "*", or no
- dimension. */
- if (static_seen)
- {
- star_seen = false;
- dimen = c_parser_expr_no_commas (parser, NULL);
- }
- else
- {
- if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
- {
- dimen.value = NULL_TREE;
- star_seen = false;
- }
- else if (c_parser_next_token_is (parser, CPP_MULT))
- {
- if (c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_SQUARE)
- {
- dimen.value = NULL_TREE;
- star_seen = true;
- c_parser_consume_token (parser);
- }
- else
- {
- star_seen = false;
- dimen = c_parser_expr_no_commas (parser, NULL);
- }
- }
- else
- {
- star_seen = false;
- dimen = c_parser_expr_no_commas (parser, NULL);
- }
- }
- if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
- c_parser_consume_token (parser);
- else
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
- "expected %<]%>");
- return NULL;
- }
- if (dimen.value)
- dimen = convert_lvalue_to_rvalue (brace_loc, dimen, true, true);
- declarator = build_array_declarator (brace_loc, dimen.value, quals_attrs,
- static_seen, star_seen);
- if (declarator == NULL)
- return NULL;
- if (c_parser_nth_token_starts_std_attributes (parser, 1))
- {
- tree std_attrs
- = c_parser_std_attribute_specifier_sequence (parser);
- if (std_attrs)
- inner = build_attrs_declarator (std_attrs, inner);
- }
- inner = set_array_declarator_inner (declarator, inner);
- return c_parser_direct_declarator_inner (parser, id_present, inner);
- }
- else if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
- {
- tree attrs;
- struct c_arg_info *args;
- c_parser_consume_token (parser);
- bool have_gnu_attrs = c_parser_next_token_is_keyword (parser,
- RID_ATTRIBUTE);
- attrs = c_parser_gnu_attributes (parser);
- args = c_parser_parms_declarator (parser, id_present, attrs,
- have_gnu_attrs);
- if (args == NULL)
- return NULL;
- else
- {
- if (!(args->types
- && args->types != error_mark_node
- && TREE_CODE (TREE_VALUE (args->types)) == IDENTIFIER_NODE)
- && c_parser_nth_token_starts_std_attributes (parser, 1))
- {
- tree std_attrs
- = c_parser_std_attribute_specifier_sequence (parser);
- if (std_attrs)
- inner = build_attrs_declarator (std_attrs, inner);
- }
- inner = build_function_declarator (args, inner);
- return c_parser_direct_declarator_inner (parser, id_present, inner);
- }
- }
- return inner;
-}
-
-/* Parse a parameter list or identifier list, including the closing
- parenthesis but not the opening one. ATTRS are the gnu-attributes
- at the start of the list. ID_LIST_OK is true if an identifier list
- is acceptable; such a list must not have attributes at the start.
- HAVE_GNU_ATTRS says whether any gnu-attributes (including empty
- attributes) were present (in which case standard attributes cannot
- occur). */
-
-static struct c_arg_info *
-c_parser_parms_declarator (c_parser *parser, bool id_list_ok, tree attrs,
- bool have_gnu_attrs)
-{
- push_scope ();
- declare_parm_level ();
- /* If the list starts with an identifier, it is an identifier list.
- Otherwise, it is either a prototype list or an empty list. */
- if (id_list_ok
- && !attrs
- && c_parser_next_token_is (parser, CPP_NAME)
- && c_parser_peek_token (parser)->id_kind == C_ID_ID
-
- /* Look ahead to detect typos in type names. */
- && c_parser_peek_2nd_token (parser)->type != CPP_NAME
- && c_parser_peek_2nd_token (parser)->type != CPP_MULT
- && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN
- && c_parser_peek_2nd_token (parser)->type != CPP_OPEN_SQUARE
- && c_parser_peek_2nd_token (parser)->type != CPP_KEYWORD)
- {
- tree list = NULL_TREE, *nextp = &list;
- while (c_parser_next_token_is (parser, CPP_NAME)
- && c_parser_peek_token (parser)->id_kind == C_ID_ID)
- {
- *nextp = build_tree_list (NULL_TREE,
- c_parser_peek_token (parser)->value);
- nextp = & TREE_CHAIN (*nextp);
- c_parser_consume_token (parser);
- if (c_parser_next_token_is_not (parser, CPP_COMMA))
- break;
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- {
- c_parser_error (parser, "expected identifier");
- break;
- }
- }
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- {
- struct c_arg_info *ret = build_arg_info ();
- ret->types = list;
- c_parser_consume_token (parser);
- pop_scope ();
- return ret;
- }
- else
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>");
- pop_scope ();
- return NULL;
- }
- }
- else
- {
- struct c_arg_info *ret
- = c_parser_parms_list_declarator (parser, attrs, NULL, have_gnu_attrs);
- pop_scope ();
- return ret;
- }
-}
-
-/* Parse a parameter list (possibly empty), including the closing
- parenthesis but not the opening one. ATTRS are the gnu-attributes
- at the start of the list; if HAVE_GNU_ATTRS, there were some such
- attributes (possibly empty, in which case ATTRS is NULL_TREE),
- which means standard attributes cannot start the list. EXPR is
- NULL or an expression that needs to be evaluated for the side
- effects of array size expressions in the parameters. */
-
-static struct c_arg_info *
-c_parser_parms_list_declarator (c_parser *parser, tree attrs, tree expr,
- bool have_gnu_attrs)
-{
- bool bad_parm = false;
-
- /* ??? Following the old parser, forward parameter declarations may
- use abstract declarators, and if no real parameter declarations
- follow the forward declarations then this is not diagnosed. Also
- note as above that gnu-attributes are ignored as the only contents of
- the parentheses, or as the only contents after forward
- declarations. */
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- {
- struct c_arg_info *ret = build_arg_info ();
- c_parser_consume_token (parser);
- return ret;
- }
- if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
- {
- struct c_arg_info *ret = build_arg_info ();
-
- if (flag_allow_parameterless_variadic_functions)
- {
- /* F (...) is allowed. */
- ret->types = NULL_TREE;
- }
- else
- {
- /* Suppress -Wold-style-definition for this case. */
- ret->types = error_mark_node;
- error_at (c_parser_peek_token (parser)->location,
- "ISO C requires a named argument before %<...%>");
- }
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- {
- c_parser_consume_token (parser);
- return ret;
- }
- else
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>");
- return NULL;
- }
- }
- /* Nonempty list of parameters, either terminated with semicolon
- (forward declarations; recurse) or with close parenthesis (normal
- function) or with ", ... )" (variadic function). */
- while (true)
- {
- /* Parse a parameter. */
- struct c_parm *parm = c_parser_parameter_declaration (parser, attrs,
- have_gnu_attrs);
- attrs = NULL_TREE;
- have_gnu_attrs = false;
- if (parm == NULL)
- bad_parm = true;
- else
- push_parm_decl (parm, &expr);
- if (c_parser_next_token_is (parser, CPP_SEMICOLON))
- {
- tree new_attrs;
- c_parser_consume_token (parser);
- mark_forward_parm_decls ();
- bool new_have_gnu_attrs
- = c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE);
- new_attrs = c_parser_gnu_attributes (parser);
- return c_parser_parms_list_declarator (parser, new_attrs, expr,
- new_have_gnu_attrs);
- }
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- {
- c_parser_consume_token (parser);
- if (bad_parm)
- return NULL;
- else
- return get_parm_info (false, expr);
- }
- if (!c_parser_require (parser, CPP_COMMA,
- "expected %<;%>, %<,%> or %<)%>",
- UNKNOWN_LOCATION, false))
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- return NULL;
- }
- if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
- {
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- {
- c_parser_consume_token (parser);
- if (bad_parm)
- return NULL;
- else
- return get_parm_info (true, expr);
- }
- else
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>");
- return NULL;
- }
- }
- }
-}
-
-/* Parse a parameter declaration. ATTRS are the gnu-attributes at the
- start of the declaration if it is the first parameter;
- HAVE_GNU_ATTRS is true if there were any gnu-attributes there (even
- empty) there. */
-
-static struct c_parm *
-c_parser_parameter_declaration (c_parser *parser, tree attrs,
- bool have_gnu_attrs)
-{
- struct c_declspecs *specs;
- struct c_declarator *declarator;
- tree prefix_attrs;
- tree postfix_attrs = NULL_TREE;
- bool dummy = false;
-
- /* Accept #pragmas between parameter declarations. */
- while (c_parser_next_token_is (parser, CPP_PRAGMA))
- c_parser_pragma (parser, pragma_param, NULL);
-
- if (!c_parser_next_token_starts_declspecs (parser)
- && !c_parser_nth_token_starts_std_attributes (parser, 1))
- {
- c_token *token = c_parser_peek_token (parser);
- if (parser->error)
- return NULL;
- c_parser_set_source_position_from_token (token);
- if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
- {
- auto_diagnostic_group d;
- name_hint hint = lookup_name_fuzzy (token->value,
- FUZZY_LOOKUP_TYPENAME,
- token->location);
- if (const char *suggestion = hint.suggestion ())
- {
- gcc_rich_location richloc (token->location);
- richloc.add_fixit_replace (suggestion);
- error_at (&richloc,
- "unknown type name %qE; did you mean %qs?",
- token->value, suggestion);
- }
- else
- error_at (token->location, "unknown type name %qE", token->value);
- parser->error = true;
- }
- /* ??? In some Objective-C cases '...' isn't applicable so there
- should be a different message. */
- else
- c_parser_error (parser,
- "expected declaration specifiers or %<...%>");
- c_parser_skip_to_end_of_parameter (parser);
- return NULL;
- }
-
- location_t start_loc = c_parser_peek_token (parser)->location;
-
- specs = build_null_declspecs ();
- if (attrs)
- {
- declspecs_add_attrs (input_location, specs, attrs);
- attrs = NULL_TREE;
- }
- c_parser_declspecs (parser, specs, true, true, true, true, false,
- !have_gnu_attrs, true, cla_nonabstract_decl);
- finish_declspecs (specs);
- pending_xref_error ();
- prefix_attrs = specs->attrs;
- specs->attrs = NULL_TREE;
- declarator = c_parser_declarator (parser,
- specs->typespec_kind != ctsk_none,
- C_DTR_PARM, &dummy);
- if (declarator == NULL)
- {
- c_parser_skip_until_found (parser, CPP_COMMA, NULL);
- return NULL;
- }
- if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
- postfix_attrs = c_parser_gnu_attributes (parser);
-
- /* Generate a location for the parameter, ranging from the start of the
- initial token to the end of the final token.
-
- If we have a identifier, then use it for the caret location, e.g.
-
- extern int callee (int one, int (*two)(int, int), float three);
- ~~~~~~^~~~~~~~~~~~~~
-
- otherwise, reuse the start location for the caret location e.g.:
-
- extern int callee (int one, int (*)(int, int), float three);
- ^~~~~~~~~~~~~~~~~
- */
- location_t end_loc = parser->last_token_location;
-
- /* Find any cdk_id declarator; determine if we have an identifier. */
- c_declarator *id_declarator = declarator;
- while (id_declarator && id_declarator->kind != cdk_id)
- id_declarator = id_declarator->declarator;
- location_t caret_loc = (id_declarator->u.id.id
- ? id_declarator->id_loc
- : start_loc);
- location_t param_loc = make_location (caret_loc, start_loc, end_loc);
-
- return build_c_parm (specs, chainon (postfix_attrs, prefix_attrs),
- declarator, param_loc);
-}
-
-/* Parse a string literal in an asm expression. It should not be
- translated, and wide string literals are an error although
- permitted by the syntax. This is a GNU extension.
-
- asm-string-literal:
- string-literal
-*/
-
-static tree
-c_parser_asm_string_literal (c_parser *parser)
-{
- tree str;
- int save_flag = warn_overlength_strings;
- warn_overlength_strings = 0;
- str = c_parser_string_literal (parser, false, false).value;
- warn_overlength_strings = save_flag;
- return str;
-}
-
-/* Parse a simple asm expression. This is used in restricted
- contexts, where a full expression with inputs and outputs does not
- make sense. This is a GNU extension.
-
- simple-asm-expr:
- asm ( asm-string-literal )
-*/
-
-static tree
-c_parser_simple_asm_expr (c_parser *parser)
-{
- tree str;
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
- c_parser_consume_token (parser);
- matching_parens parens;
- if (!parens.require_open (parser))
- return NULL_TREE;
- str = c_parser_asm_string_literal (parser);
- if (!parens.require_close (parser))
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- return NULL_TREE;
- }
- return str;
-}
-
-static tree
-c_parser_gnu_attribute_any_word (c_parser *parser)
-{
- tree attr_name = NULL_TREE;
-
- if (c_parser_next_token_is (parser, CPP_KEYWORD))
- {
- /* ??? See comment above about what keywords are accepted here. */
- bool ok;
- switch (c_parser_peek_token (parser)->keyword)
- {
- case RID_STATIC:
- case RID_UNSIGNED:
- case RID_LONG:
- case RID_CONST:
- case RID_EXTERN:
- case RID_REGISTER:
- case RID_TYPEDEF:
- case RID_SHORT:
- case RID_INLINE:
- case RID_NORETURN:
- case RID_VOLATILE:
- case RID_SIGNED:
- case RID_AUTO:
- case RID_RESTRICT:
- case RID_COMPLEX:
- case RID_THREAD:
- case RID_INT:
- case RID_CHAR:
- case RID_FLOAT:
- case RID_DOUBLE:
- case RID_VOID:
- case RID_DFLOAT32:
- case RID_DFLOAT64:
- case RID_DFLOAT128:
- CASE_RID_FLOATN_NX:
- case RID_BOOL:
- case RID_FRACT:
- case RID_ACCUM:
- case RID_SAT:
- case RID_TRANSACTION_ATOMIC:
- case RID_TRANSACTION_CANCEL:
- case RID_ATOMIC:
- case RID_AUTO_TYPE:
- case RID_INT_N_0:
- case RID_INT_N_1:
- case RID_INT_N_2:
- case RID_INT_N_3:
- ok = true;
- break;
- default:
- ok = false;
- break;
- }
- if (!ok)
- return NULL_TREE;
-
- /* Accept __attribute__((__const)) as __attribute__((const)) etc. */
- attr_name = ridpointers[(int) c_parser_peek_token (parser)->keyword];
- }
- else if (c_parser_next_token_is (parser, CPP_NAME))
- attr_name = c_parser_peek_token (parser)->value;
-
- return attr_name;
-}
-
-/* Parse attribute arguments. This is a common form of syntax
- covering all currently valid GNU and standard attributes.
-
- gnu-attribute-arguments:
- identifier
- identifier , nonempty-expr-list
- expr-list
-
- where the "identifier" must not be declared as a type. ??? Why not
- allow identifiers declared as types to start the arguments? */
-
-static tree
-c_parser_attribute_arguments (c_parser *parser, bool takes_identifier,
- bool require_string, bool allow_empty_args)
-{
- vec<tree, va_gc> *expr_list;
- tree attr_args;
- /* Parse the attribute contents. If they start with an
- identifier which is followed by a comma or close
- parenthesis, then the arguments start with that
- identifier; otherwise they are an expression list.
- In objective-c the identifier may be a classname. */
- if (c_parser_next_token_is (parser, CPP_NAME)
- && (c_parser_peek_token (parser)->id_kind == C_ID_ID
- || (c_dialect_objc ()
- && c_parser_peek_token (parser)->id_kind
- == C_ID_CLASSNAME))
- && ((c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
- || (c_parser_peek_2nd_token (parser)->type
- == CPP_CLOSE_PAREN))
- && (takes_identifier
- || (c_dialect_objc ()
- && c_parser_peek_token (parser)->id_kind
- == C_ID_CLASSNAME)))
- {
- tree arg1 = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- attr_args = build_tree_list (NULL_TREE, arg1);
- else
- {
- tree tree_list;
- c_parser_consume_token (parser);
- expr_list = c_parser_expr_list (parser, false, true,
- NULL, NULL, NULL, NULL);
- tree_list = build_tree_list_vec (expr_list);
- attr_args = tree_cons (NULL_TREE, arg1, tree_list);
- release_tree_vector (expr_list);
- }
- }
- else
- {
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- {
- if (!allow_empty_args)
- error_at (c_parser_peek_token (parser)->location,
- "parentheses must be omitted if "
- "attribute argument list is empty");
- attr_args = NULL_TREE;
- }
- else if (require_string)
- {
- /* The only valid argument for this attribute is a string
- literal. Handle this specially here to avoid accepting
- string literals with excess parentheses. */
- tree string = c_parser_string_literal (parser, false, true).value;
- attr_args = build_tree_list (NULL_TREE, string);
- }
- else
- {
- expr_list = c_parser_expr_list (parser, false, true,
- NULL, NULL, NULL, NULL);
- attr_args = build_tree_list_vec (expr_list);
- release_tree_vector (expr_list);
- }
- }
- return attr_args;
-}
-
-/* Parse (possibly empty) gnu-attributes. This is a GNU extension.
-
- gnu-attributes:
- empty
- gnu-attributes gnu-attribute
-
- gnu-attribute:
- __attribute__ ( ( gnu-attribute-list ) )
-
- gnu-attribute-list:
- gnu-attrib
- gnu-attribute_list , gnu-attrib
-
- gnu-attrib:
- empty
- any-word
- any-word ( gnu-attribute-arguments )
-
- where "any-word" may be any identifier (including one declared as a
- type), a reserved word storage class specifier, type specifier or
- type qualifier. ??? This still leaves out most reserved keywords
- (following the old parser), shouldn't we include them?
- When EXPECT_COMMA is true, expect the attribute to be preceded
- by a comma and fail if it isn't.
- When EMPTY_OK is true, allow and consume any number of consecutive
- commas with no attributes in between. */
-
-static tree
-c_parser_gnu_attribute (c_parser *parser, tree attrs,
- bool expect_comma = false, bool empty_ok = true)
-{
- bool comma_first = c_parser_next_token_is (parser, CPP_COMMA);
- if (!comma_first
- && !c_parser_next_token_is (parser, CPP_NAME)
- && !c_parser_next_token_is (parser, CPP_KEYWORD))
- return NULL_TREE;
-
- while (c_parser_next_token_is (parser, CPP_COMMA))
- {
- c_parser_consume_token (parser);
- if (!empty_ok)
- return attrs;
- }
-
- tree attr_name = c_parser_gnu_attribute_any_word (parser);
- if (attr_name == NULL_TREE)
- return NULL_TREE;
-
- attr_name = canonicalize_attr_name (attr_name);
- c_parser_consume_token (parser);
-
- tree attr;
- if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
- {
- if (expect_comma && !comma_first)
- {
- /* A comma is missing between the last attribute on the chain
- and this one. */
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>");
- return error_mark_node;
- }
- attr = build_tree_list (attr_name, NULL_TREE);
- /* Add this attribute to the list. */
- attrs = chainon (attrs, attr);
- return attrs;
- }
- c_parser_consume_token (parser);
-
- tree attr_args
- = c_parser_attribute_arguments (parser,
- attribute_takes_identifier_p (attr_name),
- false, true);
-
- attr = build_tree_list (attr_name, attr_args);
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- c_parser_consume_token (parser);
- else
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>");
- return error_mark_node;
- }
-
- if (expect_comma && !comma_first)
- {
- /* A comma is missing between the last attribute on the chain
- and this one. */
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>");
- return error_mark_node;
- }
-
- /* Add this attribute to the list. */
- attrs = chainon (attrs, attr);
- return attrs;
-}
-
-static tree
-c_parser_gnu_attributes (c_parser *parser)
-{
- tree attrs = NULL_TREE;
- while (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
- {
- bool save_translate_strings_p = parser->translate_strings_p;
- parser->translate_strings_p = false;
- /* Consume the `__attribute__' keyword. */
- c_parser_consume_token (parser);
- /* Look for the two `(' tokens. */
- if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
- {
- parser->translate_strings_p = save_translate_strings_p;
- return attrs;
- }
- if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
- {
- parser->translate_strings_p = save_translate_strings_p;
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- return attrs;
- }
- /* Parse the attribute list. Require a comma between successive
- (possibly empty) attributes. */
- for (bool expect_comma = false; ; expect_comma = true)
- {
- /* Parse a single attribute. */
- tree attr = c_parser_gnu_attribute (parser, attrs, expect_comma);
- if (attr == error_mark_node)
- return attrs;
- if (!attr)
- break;
- attrs = attr;
- }
-
- /* Look for the two `)' tokens. */
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- c_parser_consume_token (parser);
- else
- {
- parser->translate_strings_p = save_translate_strings_p;
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>");
- return attrs;
- }
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- c_parser_consume_token (parser);
- else
- {
- parser->translate_strings_p = save_translate_strings_p;
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>");
- return attrs;
- }
- parser->translate_strings_p = save_translate_strings_p;
- }
-
- return attrs;
-}
-
-/* Parse an optional balanced token sequence.
-
- balanced-token-sequence:
- balanced-token
- balanced-token-sequence balanced-token
-
- balanced-token:
- ( balanced-token-sequence[opt] )
- [ balanced-token-sequence[opt] ]
- { balanced-token-sequence[opt] }
- any token other than ()[]{}
-*/
-
-static void
-c_parser_balanced_token_sequence (c_parser *parser)
-{
- while (true)
- {
- c_token *token = c_parser_peek_token (parser);
- switch (token->type)
- {
- case CPP_OPEN_BRACE:
- {
- matching_braces braces;
- braces.consume_open (parser);
- c_parser_balanced_token_sequence (parser);
- braces.require_close (parser);
- break;
- }
-
- case CPP_OPEN_PAREN:
- {
- matching_parens parens;
- parens.consume_open (parser);
- c_parser_balanced_token_sequence (parser);
- parens.require_close (parser);
- break;
- }
-
- case CPP_OPEN_SQUARE:
- c_parser_consume_token (parser);
- c_parser_balanced_token_sequence (parser);
- c_parser_require (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
- break;
-
- case CPP_CLOSE_BRACE:
- case CPP_CLOSE_PAREN:
- case CPP_CLOSE_SQUARE:
- case CPP_EOF:
- return;
-
- case CPP_PRAGMA:
- c_parser_consume_pragma (parser);
- c_parser_skip_to_pragma_eol (parser, false);
- break;
-
- default:
- c_parser_consume_token (parser);
- break;
- }
- }
-}
-
-/* Parse standard (C2X) attributes (including GNU attributes in the
- gnu:: namespace).
-
- attribute-specifier-sequence:
- attribute-specifier-sequence[opt] attribute-specifier
-
- attribute-specifier:
- [ [ attribute-list ] ]
-
- attribute-list:
- attribute[opt]
- attribute-list, attribute[opt]
-
- attribute:
- attribute-token attribute-argument-clause[opt]
-
- attribute-token:
- standard-attribute
- attribute-prefixed-token
-
- standard-attribute:
- identifier
-
- attribute-prefixed-token:
- attribute-prefix :: identifier
-
- attribute-prefix:
- identifier
-
- attribute-argument-clause:
- ( balanced-token-sequence[opt] )
-
- Keywords are accepted as identifiers for this purpose.
-*/
-
-static tree
-c_parser_std_attribute (c_parser *parser, bool for_tm)
-{
- c_token *token = c_parser_peek_token (parser);
- tree ns, name, attribute;
-
- /* Parse the attribute-token. */
- if (token->type != CPP_NAME && token->type != CPP_KEYWORD)
- {
- c_parser_error (parser, "expected identifier");
- return error_mark_node;
- }
- name = canonicalize_attr_name (token->value);
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_SCOPE))
- {
- ns = name;
- c_parser_consume_token (parser);
- token = c_parser_peek_token (parser);
- if (token->type != CPP_NAME && token->type != CPP_KEYWORD)
- {
- c_parser_error (parser, "expected identifier");
- return error_mark_node;
- }
- name = canonicalize_attr_name (token->value);
- c_parser_consume_token (parser);
- }
- else
- ns = NULL_TREE;
- attribute = build_tree_list (build_tree_list (ns, name), NULL_TREE);
-
- /* Parse the arguments, if any. */
- const attribute_spec *as = lookup_attribute_spec (TREE_PURPOSE (attribute));
- if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
- goto out;
- {
- location_t open_loc = c_parser_peek_token (parser)->location;
- matching_parens parens;
- parens.consume_open (parser);
- if ((as && as->max_length == 0)
- /* Special-case the transactional-memory attribute "outer",
- which is specially handled but not registered as an
- attribute, to avoid allowing arbitrary balanced token
- sequences as arguments. */
- || is_attribute_p ("outer", name))
- {
- error_at (open_loc, "%qE attribute does not take any arguments", name);
- parens.skip_until_found_close (parser);
- return error_mark_node;
- }
- /* If this is a fake attribute created to handle -Wno-attributes,
- we must skip parsing the arguments. */
- if (as && !attribute_ignored_p (as))
- {
- bool takes_identifier
- = (ns != NULL_TREE
- && strcmp (IDENTIFIER_POINTER (ns), "gnu") == 0
- && attribute_takes_identifier_p (name));
- bool require_string
- = (ns == NULL_TREE
- && (strcmp (IDENTIFIER_POINTER (name), "deprecated") == 0
- || strcmp (IDENTIFIER_POINTER (name), "nodiscard") == 0));
- TREE_VALUE (attribute)
- = c_parser_attribute_arguments (parser, takes_identifier,
- require_string, false);
- }
- else
- c_parser_balanced_token_sequence (parser);
- parens.require_close (parser);
- }
- out:
- if (ns == NULL_TREE && !for_tm && !as)
- {
- /* An attribute with standard syntax and no namespace specified
- is a constraint violation if it is not one of the known
- standard attributes. Diagnose it here with a pedwarn and
- then discard it to prevent a duplicate warning later. */
- pedwarn (input_location, OPT_Wattributes, "%qE attribute ignored",
- name);
- return error_mark_node;
- }
- return attribute;
-}
-
-static tree
-c_parser_std_attribute_specifier (c_parser *parser, bool for_tm)
-{
- location_t loc = c_parser_peek_token (parser)->location;
- if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>"))
- return NULL_TREE;
- if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>"))
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
- return NULL_TREE;
- }
- if (!for_tm)
- pedwarn_c11 (loc, OPT_Wpedantic,
- "ISO C does not support %<[[]]%> attributes before C2X");
- tree attributes = NULL_TREE;
- while (true)
- {
- c_token *token = c_parser_peek_token (parser);
- if (token->type == CPP_CLOSE_SQUARE)
- break;
- if (token->type == CPP_COMMA)
- {
- c_parser_consume_token (parser);
- continue;
- }
- tree attribute = c_parser_std_attribute (parser, for_tm);
- if (attribute != error_mark_node)
- {
- TREE_CHAIN (attribute) = attributes;
- attributes = attribute;
- }
- if (c_parser_next_token_is_not (parser, CPP_COMMA))
- break;
- }
- c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
- c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>");
- return nreverse (attributes);
-}
-
-/* Look past an optional balanced token sequence of raw look-ahead
- tokens starting with the *Nth token. *N is updated to point to the
- following token. Return true if such a sequence was found, false
- if the tokens parsed were not balanced. */
-
-static bool
-c_parser_check_balanced_raw_token_sequence (c_parser *parser, unsigned int *n)
-{
- while (true)
- {
- c_token *token = c_parser_peek_nth_token_raw (parser, *n);
- switch (token->type)
- {
- case CPP_OPEN_BRACE:
- {
- ++*n;
- if (c_parser_check_balanced_raw_token_sequence (parser, n))
- {
- token = c_parser_peek_nth_token_raw (parser, *n);
- if (token->type == CPP_CLOSE_BRACE)
- ++*n;
- else
- return false;
- }
- else
- return false;
- break;
- }
-
- case CPP_OPEN_PAREN:
- {
- ++*n;
- if (c_parser_check_balanced_raw_token_sequence (parser, n))
- {
- token = c_parser_peek_nth_token_raw (parser, *n);
- if (token->type == CPP_CLOSE_PAREN)
- ++*n;
- else
- return false;
- }
- else
- return false;
- break;
- }
-
- case CPP_OPEN_SQUARE:
- {
- ++*n;
- if (c_parser_check_balanced_raw_token_sequence (parser, n))
- {
- token = c_parser_peek_nth_token_raw (parser, *n);
- if (token->type == CPP_CLOSE_SQUARE)
- ++*n;
- else
- return false;
- }
- else
- return false;
- break;
- }
-
- case CPP_CLOSE_BRACE:
- case CPP_CLOSE_PAREN:
- case CPP_CLOSE_SQUARE:
- case CPP_EOF:
- return true;
-
- default:
- ++*n;
- break;
- }
- }
-}
-
-/* Return whether standard attributes start with the Nth token. */
-
-static bool
-c_parser_nth_token_starts_std_attributes (c_parser *parser, unsigned int n)
-{
- if (!(c_parser_peek_nth_token (parser, n)->type == CPP_OPEN_SQUARE
- && c_parser_peek_nth_token (parser, n + 1)->type == CPP_OPEN_SQUARE))
- return false;
- /* In C, '[[' must start attributes. In Objective-C, we need to
- check whether '[[' is matched by ']]'. */
- if (!c_dialect_objc ())
- return true;
- n += 2;
- if (!c_parser_check_balanced_raw_token_sequence (parser, &n))
- return false;
- c_token *token = c_parser_peek_nth_token_raw (parser, n);
- if (token->type != CPP_CLOSE_SQUARE)
- return false;
- token = c_parser_peek_nth_token_raw (parser, n + 1);
- return token->type == CPP_CLOSE_SQUARE;
-}
-
-static tree
-c_parser_std_attribute_specifier_sequence (c_parser *parser)
-{
- tree attributes = NULL_TREE;
- do
- {
- tree attrs = c_parser_std_attribute_specifier (parser, false);
- attributes = chainon (attributes, attrs);
- }
- while (c_parser_nth_token_starts_std_attributes (parser, 1));
- return attributes;
-}
-
-/* Parse a type name (C90 6.5.5, C99 6.7.6, C11 6.7.7). ALIGNAS_OK
- says whether alignment specifiers are OK (only in cases that might
- be the type name of a compound literal).
-
- type-name:
- specifier-qualifier-list abstract-declarator[opt]
-*/
-
-struct c_type_name *
-c_parser_type_name (c_parser *parser, bool alignas_ok)
-{
- struct c_declspecs *specs = build_null_declspecs ();
- struct c_declarator *declarator;
- struct c_type_name *ret;
- bool dummy = false;
- c_parser_declspecs (parser, specs, false, true, true, alignas_ok, false,
- false, true, cla_prefer_type);
- if (!specs->declspecs_seen_p)
- {
- c_parser_error (parser, "expected specifier-qualifier-list");
- return NULL;
- }
- if (specs->type != error_mark_node)
- {
- pending_xref_error ();
- finish_declspecs (specs);
- }
- declarator = c_parser_declarator (parser,
- specs->typespec_kind != ctsk_none,
- C_DTR_ABSTRACT, &dummy);
- if (declarator == NULL)
- return NULL;
- ret = XOBNEW (&parser_obstack, struct c_type_name);
- ret->specs = specs;
- ret->declarator = declarator;
- return ret;
-}
-
-/* Parse an initializer (C90 6.5.7, C99 6.7.8, C11 6.7.9).
-
- initializer:
- assignment-expression
- { initializer-list }
- { initializer-list , }
-
- initializer-list:
- designation[opt] initializer
- initializer-list , designation[opt] initializer
-
- designation:
- designator-list =
-
- designator-list:
- designator
- designator-list designator
-
- designator:
- array-designator
- . identifier
-
- array-designator:
- [ constant-expression ]
-
- GNU extensions:
-
- initializer:
- { }
-
- designation:
- array-designator
- identifier :
-
- array-designator:
- [ constant-expression ... constant-expression ]
-
- Any expression without commas is accepted in the syntax for the
- constant-expressions, with non-constant expressions rejected later.
-
- This function is only used for top-level initializers; for nested
- ones, see c_parser_initval. */
-
-static struct c_expr
-c_parser_initializer (c_parser *parser)
-{
- if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
- return c_parser_braced_init (parser, NULL_TREE, false, NULL);
- else
- {
- struct c_expr ret;
- location_t loc = c_parser_peek_token (parser)->location;
- ret = c_parser_expr_no_commas (parser, NULL);
- if (TREE_CODE (ret.value) != STRING_CST
- && TREE_CODE (ret.value) != COMPOUND_LITERAL_EXPR)
- ret = convert_lvalue_to_rvalue (loc, ret, true, true);
- return ret;
- }
-}
-
-/* The location of the last comma within the current initializer list,
- or UNKNOWN_LOCATION if not within one. */
-
-location_t last_init_list_comma;
-
-/* Parse a braced initializer list. TYPE is the type specified for a
- compound literal, and NULL_TREE for other initializers and for
- nested braced lists. NESTED_P is true for nested braced lists,
- false for the list of a compound literal or the list that is the
- top-level initializer in a declaration. */
-
-static struct c_expr
-c_parser_braced_init (c_parser *parser, tree type, bool nested_p,
- struct obstack *outer_obstack)
-{
- struct c_expr ret;
- struct obstack braced_init_obstack;
- location_t brace_loc = c_parser_peek_token (parser)->location;
- gcc_obstack_init (&braced_init_obstack);
- gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
- matching_braces braces;
- braces.consume_open (parser);
- if (nested_p)
- {
- finish_implicit_inits (brace_loc, outer_obstack);
- push_init_level (brace_loc, 0, &braced_init_obstack);
- }
- else
- really_start_incremental_init (type);
- if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
- {
- pedwarn (brace_loc, OPT_Wpedantic, "ISO C forbids empty initializer braces");
- }
- else
- {
- /* Parse a non-empty initializer list, possibly with a trailing
- comma. */
- while (true)
- {
- c_parser_initelt (parser, &braced_init_obstack);
- if (parser->error)
- break;
- if (c_parser_next_token_is (parser, CPP_COMMA))
- {
- last_init_list_comma = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
- }
- else
- break;
- if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
- break;
- }
- }
- c_token *next_tok = c_parser_peek_token (parser);
- if (next_tok->type != CPP_CLOSE_BRACE)
- {
- ret.set_error ();
- ret.original_code = ERROR_MARK;
- ret.original_type = NULL;
- braces.skip_until_found_close (parser);
- pop_init_level (brace_loc, 0, &braced_init_obstack, last_init_list_comma);
- obstack_free (&braced_init_obstack, NULL);
- return ret;
- }
- location_t close_loc = next_tok->location;
- c_parser_consume_token (parser);
- ret = pop_init_level (brace_loc, 0, &braced_init_obstack, close_loc);
- obstack_free (&braced_init_obstack, NULL);
- set_c_expr_source_range (&ret, brace_loc, close_loc);
- return ret;
-}
-
-/* Parse a nested initializer, including designators. */
-
-static void
-c_parser_initelt (c_parser *parser, struct obstack * braced_init_obstack)
-{
- /* Parse any designator or designator list. A single array
- designator may have the subsequent "=" omitted in GNU C, but a
- longer list or a structure member designator may not. */
- if (c_parser_next_token_is (parser, CPP_NAME)
- && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
- {
- /* Old-style structure member designator. */
- set_init_label (c_parser_peek_token (parser)->location,
- c_parser_peek_token (parser)->value,
- c_parser_peek_token (parser)->location,
- braced_init_obstack);
- /* Use the colon as the error location. */
- pedwarn (c_parser_peek_2nd_token (parser)->location, OPT_Wpedantic,
- "obsolete use of designated initializer with %<:%>");
- c_parser_consume_token (parser);
- c_parser_consume_token (parser);
- }
- else
- {
- /* des_seen is 0 if there have been no designators, 1 if there
- has been a single array designator and 2 otherwise. */
- int des_seen = 0;
- /* Location of a designator. */
- location_t des_loc = UNKNOWN_LOCATION; /* Quiet warning. */
- while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE)
- || c_parser_next_token_is (parser, CPP_DOT))
- {
- int des_prev = des_seen;
- if (!des_seen)
- des_loc = c_parser_peek_token (parser)->location;
- if (des_seen < 2)
- des_seen++;
- if (c_parser_next_token_is (parser, CPP_DOT))
- {
- des_seen = 2;
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- set_init_label (des_loc, c_parser_peek_token (parser)->value,
- c_parser_peek_token (parser)->location,
- braced_init_obstack);
- c_parser_consume_token (parser);
- }
- else
- {
- struct c_expr init;
- init.set_error ();
- init.original_code = ERROR_MARK;
- init.original_type = NULL;
- c_parser_error (parser, "expected identifier");
- c_parser_skip_until_found (parser, CPP_COMMA, NULL);
- process_init_element (input_location, init, false,
- braced_init_obstack);
- return;
- }
- }
- else
- {
- tree first, second;
- location_t ellipsis_loc = UNKNOWN_LOCATION; /* Quiet warning. */
- location_t array_index_loc = UNKNOWN_LOCATION;
- /* ??? Following the old parser, [ objc-receiver
- objc-message-args ] is accepted as an initializer,
- being distinguished from a designator by what follows
- the first assignment expression inside the square
- brackets, but after a first array designator a
- subsequent square bracket is for Objective-C taken to
- start an expression, using the obsolete form of
- designated initializer without '=', rather than
- possibly being a second level of designation: in LALR
- terms, the '[' is shifted rather than reducing
- designator to designator-list. */
- if (des_prev == 1 && c_dialect_objc ())
- {
- des_seen = des_prev;
- break;
- }
- if (des_prev == 0 && c_dialect_objc ())
- {
- /* This might be an array designator or an
- Objective-C message expression. If the former,
- continue parsing here; if the latter, parse the
- remainder of the initializer given the starting
- primary-expression. ??? It might make sense to
- distinguish when des_prev == 1 as well; see
- previous comment. */
- tree rec, args;
- struct c_expr mexpr;
- c_parser_consume_token (parser);
- if (c_parser_peek_token (parser)->type == CPP_NAME
- && ((c_parser_peek_token (parser)->id_kind
- == C_ID_TYPENAME)
- || (c_parser_peek_token (parser)->id_kind
- == C_ID_CLASSNAME)))
- {
- /* Type name receiver. */
- tree id = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- rec = objc_get_class_reference (id);
- goto parse_message_args;
- }
- first = c_parser_expr_no_commas (parser, NULL).value;
- mark_exp_read (first);
- if (c_parser_next_token_is (parser, CPP_ELLIPSIS)
- || c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
- goto array_desig_after_first;
- /* Expression receiver. So far only one part
- without commas has been parsed; there might be
- more of the expression. */
- rec = first;
- while (c_parser_next_token_is (parser, CPP_COMMA))
- {
- struct c_expr next;
- location_t comma_loc, exp_loc;
- comma_loc = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
- exp_loc = c_parser_peek_token (parser)->location;
- next = c_parser_expr_no_commas (parser, NULL);
- next = convert_lvalue_to_rvalue (exp_loc, next,
- true, true);
- rec = build_compound_expr (comma_loc, rec, next.value);
- }
- parse_message_args:
- /* Now parse the objc-message-args. */
- args = c_parser_objc_message_args (parser);
- c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
- "expected %<]%>");
- mexpr.value
- = objc_build_message_expr (rec, args);
- mexpr.original_code = ERROR_MARK;
- mexpr.original_type = NULL;
- /* Now parse and process the remainder of the
- initializer, starting with this message
- expression as a primary-expression. */
- c_parser_initval (parser, &mexpr, braced_init_obstack);
- return;
- }
- c_parser_consume_token (parser);
- array_index_loc = c_parser_peek_token (parser)->location;
- first = c_parser_expr_no_commas (parser, NULL).value;
- mark_exp_read (first);
- array_desig_after_first:
- if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
- {
- ellipsis_loc = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
- second = c_parser_expr_no_commas (parser, NULL).value;
- mark_exp_read (second);
- }
- else
- second = NULL_TREE;
- if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
- {
- c_parser_consume_token (parser);
- set_init_index (array_index_loc, first, second,
- braced_init_obstack);
- if (second)
- pedwarn (ellipsis_loc, OPT_Wpedantic,
- "ISO C forbids specifying range of elements to initialize");
- }
- else
- c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
- "expected %<]%>");
- }
- }
- if (des_seen >= 1)
- {
- if (c_parser_next_token_is (parser, CPP_EQ))
- {
- pedwarn_c90 (des_loc, OPT_Wpedantic,
- "ISO C90 forbids specifying subobject "
- "to initialize");
- c_parser_consume_token (parser);
- }
- else
- {
- if (des_seen == 1)
- pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
- "obsolete use of designated initializer without %<=%>");
- else
- {
- struct c_expr init;
- init.set_error ();
- init.original_code = ERROR_MARK;
- init.original_type = NULL;
- c_parser_error (parser, "expected %<=%>");
- c_parser_skip_until_found (parser, CPP_COMMA, NULL);
- process_init_element (input_location, init, false,
- braced_init_obstack);
- return;
- }
- }
- }
- }
- c_parser_initval (parser, NULL, braced_init_obstack);
-}
-
-/* Parse a nested initializer; as c_parser_initializer but parses
- initializers within braced lists, after any designators have been
- applied. If AFTER is not NULL then it is an Objective-C message
- expression which is the primary-expression starting the
- initializer. */
-
-static void
-c_parser_initval (c_parser *parser, struct c_expr *after,
- struct obstack * braced_init_obstack)
-{
- struct c_expr init;
- gcc_assert (!after || c_dialect_objc ());
- location_t loc = c_parser_peek_token (parser)->location;
-
- if (c_parser_next_token_is (parser, CPP_OPEN_BRACE) && !after)
- init = c_parser_braced_init (parser, NULL_TREE, true,
- braced_init_obstack);
- else
- {
- init = c_parser_expr_no_commas (parser, after);
- if (init.value != NULL_TREE
- && TREE_CODE (init.value) != STRING_CST
- && TREE_CODE (init.value) != COMPOUND_LITERAL_EXPR)
- init = convert_lvalue_to_rvalue (loc, init, true, true);
- }
- process_init_element (loc, init, false, braced_init_obstack);
-}
-
-/* Parse a compound statement (possibly a function body) (C90 6.6.2,
- C99 6.8.2, C11 6.8.2, C2X 6.8.2).
-
- compound-statement:
- { block-item-list[opt] }
- { label-declarations block-item-list }
-
- block-item-list:
- block-item
- block-item-list block-item
-
- block-item:
- label
- nested-declaration
- statement
-
- nested-declaration:
- declaration
-
- GNU extensions:
-
- compound-statement:
- { label-declarations block-item-list }
-
- nested-declaration:
- __extension__ nested-declaration
- nested-function-definition
-
- label-declarations:
- label-declaration
- label-declarations label-declaration
-
- label-declaration:
- __label__ identifier-list ;
-
- Allowing the mixing of declarations and code is new in C99. The
- GNU syntax also permits (not shown above) labels at the end of
- compound statements, which yield an error. We don't allow labels
- on declarations; this might seem like a natural extension, but
- there would be a conflict between gnu-attributes on the label and
- prefix gnu-attributes on the declaration. ??? The syntax follows the
- old parser in requiring something after label declarations.
- Although they are erroneous if the labels declared aren't defined,
- is it useful for the syntax to be this way?
-
- OpenACC:
-
- block-item:
- openacc-directive
-
- openacc-directive:
- update-directive
-
- OpenMP:
-
- block-item:
- openmp-directive
-
- openmp-directive:
- barrier-directive
- flush-directive
- taskwait-directive
- taskyield-directive
- cancel-directive
- cancellation-point-directive */
-
-static tree
-c_parser_compound_statement (c_parser *parser, location_t *endlocp)
-{
- tree stmt;
- location_t brace_loc;
- brace_loc = c_parser_peek_token (parser)->location;
- if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
- {
- /* Ensure a scope is entered and left anyway to avoid confusion
- if we have just prepared to enter a function body. */
- stmt = c_begin_compound_stmt (true);
- c_end_compound_stmt (brace_loc, stmt, true);
- return error_mark_node;
- }
- stmt = c_begin_compound_stmt (true);
- location_t end_loc = c_parser_compound_statement_nostart (parser);
- if (endlocp)
- *endlocp = end_loc;
-
- return c_end_compound_stmt (brace_loc, stmt, true);
-}
-
-/* Parse a compound statement except for the opening brace. This is
- used for parsing both compound statements and statement expressions
- (which follow different paths to handling the opening). */
-
-static location_t
-c_parser_compound_statement_nostart (c_parser *parser)
-{
- bool last_stmt = false;
- bool last_label = false;
- bool save_valid_for_pragma = valid_location_for_stdc_pragma_p ();
- location_t label_loc = UNKNOWN_LOCATION; /* Quiet warning. */
- if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
- {
- location_t endloc = c_parser_peek_token (parser)->location;
- add_debug_begin_stmt (endloc);
- c_parser_consume_token (parser);
- return endloc;
- }
- mark_valid_location_for_stdc_pragma (true);
- if (c_parser_next_token_is_keyword (parser, RID_LABEL))
- {
- /* Read zero or more forward-declarations for labels that nested
- functions can jump to. */
- mark_valid_location_for_stdc_pragma (false);
- while (c_parser_next_token_is_keyword (parser, RID_LABEL))
- {
- label_loc = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
- /* Any identifiers, including those declared as type names,
- are OK here. */
- while (true)
- {
- tree label;
- if (c_parser_next_token_is_not (parser, CPP_NAME))
- {
- c_parser_error (parser, "expected identifier");
- break;
- }
- label
- = declare_label (c_parser_peek_token (parser)->value);
- C_DECLARED_LABEL_FLAG (label) = 1;
- add_stmt (build_stmt (label_loc, DECL_EXPR, label));
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
- else
- break;
- }
- c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
- }
- pedwarn (label_loc, OPT_Wpedantic, "ISO C forbids label declarations");
- }
- /* We must now have at least one statement, label or declaration. */
- if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
- {
- mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
- c_parser_error (parser, "expected declaration or statement");
- location_t endloc = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
- return endloc;
- }
- while (c_parser_next_token_is_not (parser, CPP_CLOSE_BRACE))
- {
- location_t loc = c_parser_peek_token (parser)->location;
- loc = expansion_point_location_if_in_system_header (loc);
- /* Standard attributes may start a label, statement or declaration. */
- bool have_std_attrs
- = c_parser_nth_token_starts_std_attributes (parser, 1);
- tree std_attrs = NULL_TREE;
- if (have_std_attrs)
- std_attrs = c_parser_std_attribute_specifier_sequence (parser);
- if (c_parser_next_token_is_keyword (parser, RID_CASE)
- || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
- || (c_parser_next_token_is (parser, CPP_NAME)
- && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
- {
- if (c_parser_next_token_is_keyword (parser, RID_CASE))
- label_loc = c_parser_peek_2nd_token (parser)->location;
- else
- label_loc = c_parser_peek_token (parser)->location;
- last_label = true;
- last_stmt = false;
- mark_valid_location_for_stdc_pragma (false);
- c_parser_label (parser, std_attrs);
- }
- else if (c_parser_next_tokens_start_declaration (parser)
- || (have_std_attrs
- && c_parser_next_token_is (parser, CPP_SEMICOLON)))
- {
- if (last_label)
- pedwarn_c11 (c_parser_peek_token (parser)->location, OPT_Wpedantic,
- "a label can only be part of a statement and "
- "a declaration is not a statement");
-
- mark_valid_location_for_stdc_pragma (false);
- bool fallthru_attr_p = false;
- c_parser_declaration_or_fndef (parser, true, !have_std_attrs,
- true, true, true, NULL,
- NULL, have_std_attrs, std_attrs,
- NULL, &fallthru_attr_p);
-
- if (last_stmt && !fallthru_attr_p)
- pedwarn_c90 (loc, OPT_Wdeclaration_after_statement,
- "ISO C90 forbids mixed declarations and code");
- last_stmt = fallthru_attr_p;
- last_label = false;
- }
- else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
- {
- /* __extension__ can start a declaration, but is also an
- unary operator that can start an expression. Consume all
- but the last of a possible series of __extension__ to
- determine which. If standard attributes have already
- been seen, it must start a statement, not a declaration,
- but standard attributes starting a declaration may appear
- after __extension__. */
- while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
- && (c_parser_peek_2nd_token (parser)->keyword
- == RID_EXTENSION))
- c_parser_consume_token (parser);
- if (!have_std_attrs
- && (c_token_starts_declaration (c_parser_peek_2nd_token (parser))
- || c_parser_nth_token_starts_std_attributes (parser, 2)))
- {
- int ext;
- ext = disable_extension_diagnostics ();
- c_parser_consume_token (parser);
- last_label = false;
- mark_valid_location_for_stdc_pragma (false);
- c_parser_declaration_or_fndef (parser, true, true, true, true,
- true);
- /* Following the old parser, __extension__ does not
- disable this diagnostic. */
- restore_extension_diagnostics (ext);
- if (last_stmt)
- pedwarn_c90 (loc, OPT_Wdeclaration_after_statement,
- "ISO C90 forbids mixed declarations and code");
- last_stmt = false;
- }
- else
- goto statement;
- }
- else if (c_parser_next_token_is (parser, CPP_PRAGMA))
- {
- if (have_std_attrs)
- c_parser_error (parser, "expected declaration or statement");
- /* External pragmas, and some omp pragmas, are not associated
- with regular c code, and so are not to be considered statements
- syntactically. This ensures that the user doesn't put them
- places that would turn into syntax errors if the directive
- were ignored. */
- if (c_parser_pragma (parser,
- last_label ? pragma_stmt : pragma_compound,
- NULL))
- last_label = false, last_stmt = true;
- }
- else if (c_parser_next_token_is (parser, CPP_EOF))
- {
- mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
- c_parser_error (parser, "expected declaration or statement");
- return c_parser_peek_token (parser)->location;
- }
- else if (c_parser_next_token_is_keyword (parser, RID_ELSE))
- {
- if (parser->in_if_block)
- {
- mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
- error_at (loc, "expected %<}%> before %<else%>");
- return c_parser_peek_token (parser)->location;
- }
- else
- {
- error_at (loc, "%<else%> without a previous %<if%>");
- c_parser_consume_token (parser);
- continue;
- }
- }
- else
- {
- statement:
- c_warn_unused_attributes (std_attrs);
- last_label = false;
- last_stmt = true;
- mark_valid_location_for_stdc_pragma (false);
- c_parser_statement_after_labels (parser, NULL);
- }
-
- parser->error = false;
- }
- if (last_label)
- pedwarn_c11 (label_loc, OPT_Wpedantic, "label at end of compound statement");
- location_t endloc = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
- /* Restore the value we started with. */
- mark_valid_location_for_stdc_pragma (save_valid_for_pragma);
- return endloc;
-}
-
-/* Parse all consecutive labels, possibly preceded by standard
- attributes. In this context, a statement is required, not a
- declaration, so attributes must be followed by a statement that is
- not just a semicolon. */
-
-static void
-c_parser_all_labels (c_parser *parser)
-{
- tree std_attrs = NULL;
- if (c_parser_nth_token_starts_std_attributes (parser, 1))
- {
- std_attrs = c_parser_std_attribute_specifier_sequence (parser);
- if (c_parser_next_token_is (parser, CPP_SEMICOLON))
- c_parser_error (parser, "expected statement");
- }
- while (c_parser_next_token_is_keyword (parser, RID_CASE)
- || c_parser_next_token_is_keyword (parser, RID_DEFAULT)
- || (c_parser_next_token_is (parser, CPP_NAME)
- && c_parser_peek_2nd_token (parser)->type == CPP_COLON))
- {
- c_parser_label (parser, std_attrs);
- std_attrs = NULL;
- if (c_parser_nth_token_starts_std_attributes (parser, 1))
- {
- std_attrs = c_parser_std_attribute_specifier_sequence (parser);
- if (c_parser_next_token_is (parser, CPP_SEMICOLON))
- c_parser_error (parser, "expected statement");
- }
- }
- if (std_attrs)
- c_warn_unused_attributes (std_attrs);
-}
-
-/* Parse a label (C90 6.6.1, C99 6.8.1, C11 6.8.1).
-
- label:
- identifier : gnu-attributes[opt]
- case constant-expression :
- default :
-
- GNU extensions:
-
- label:
- case constant-expression ... constant-expression :
-
- The use of gnu-attributes on labels is a GNU extension. The syntax in
- GNU C accepts any expressions without commas, non-constant
- expressions being rejected later. Any standard
- attribute-specifier-sequence before the first label has been parsed
- in the caller, to distinguish statements from declarations. Any
- attribute-specifier-sequence after the label is parsed in this
- function. */
-static void
-c_parser_label (c_parser *parser, tree std_attrs)
-{
- location_t loc1 = c_parser_peek_token (parser)->location;
- tree label = NULL_TREE;
-
- /* Remember whether this case or a user-defined label is allowed to fall
- through to. */
- bool fallthrough_p = c_parser_peek_token (parser)->flags & PREV_FALLTHROUGH;
-
- if (c_parser_next_token_is_keyword (parser, RID_CASE))
- {
- tree exp1, exp2;
- c_parser_consume_token (parser);
- exp1 = c_parser_expr_no_commas (parser, NULL).value;
- if (c_parser_next_token_is (parser, CPP_COLON))
- {
- c_parser_consume_token (parser);
- label = do_case (loc1, exp1, NULL_TREE);
- }
- else if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
- {
- c_parser_consume_token (parser);
- exp2 = c_parser_expr_no_commas (parser, NULL).value;
- if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
- label = do_case (loc1, exp1, exp2);
- }
- else
- c_parser_error (parser, "expected %<:%> or %<...%>");
- }
- else if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
- {
- c_parser_consume_token (parser);
- if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
- label = do_case (loc1, NULL_TREE, NULL_TREE);
- }
- else
- {
- tree name = c_parser_peek_token (parser)->value;
- tree tlab;
- tree attrs;
- location_t loc2 = c_parser_peek_token (parser)->location;
- gcc_assert (c_parser_next_token_is (parser, CPP_NAME));
- c_parser_consume_token (parser);
- gcc_assert (c_parser_next_token_is (parser, CPP_COLON));
- c_parser_consume_token (parser);
- attrs = c_parser_gnu_attributes (parser);
- tlab = define_label (loc2, name);
- if (tlab)
- {
- decl_attributes (&tlab, attrs, 0);
- decl_attributes (&tlab, std_attrs, 0);
- label = add_stmt (build_stmt (loc1, LABEL_EXPR, tlab));
- }
- if (attrs
- && c_parser_next_tokens_start_declaration (parser))
- warning_at (loc2, OPT_Wattributes, "GNU-style attribute between"
- " label and declaration appertains to the label");
- }
- if (label)
- {
- if (TREE_CODE (label) == LABEL_EXPR)
- FALLTHROUGH_LABEL_P (LABEL_EXPR_LABEL (label)) = fallthrough_p;
- else
- FALLTHROUGH_LABEL_P (CASE_LABEL (label)) = fallthrough_p;
- }
-}
-
-/* Parse a statement (C90 6.6, C99 6.8, C11 6.8).
-
- statement:
- labeled-statement
- attribute-specifier-sequence[opt] compound-statement
- expression-statement
- attribute-specifier-sequence[opt] selection-statement
- attribute-specifier-sequence[opt] iteration-statement
- attribute-specifier-sequence[opt] jump-statement
-
- labeled-statement:
- attribute-specifier-sequence[opt] label statement
-
- expression-statement:
- expression[opt] ;
- attribute-specifier-sequence expression ;
-
- selection-statement:
- if-statement
- switch-statement
-
- iteration-statement:
- while-statement
- do-statement
- for-statement
-
- jump-statement:
- goto identifier ;
- continue ;
- break ;
- return expression[opt] ;
-
- GNU extensions:
-
- statement:
- attribute-specifier-sequence[opt] asm-statement
-
- jump-statement:
- goto * expression ;
-
- expression-statement:
- gnu-attributes ;
-
- Objective-C:
-
- statement:
- attribute-specifier-sequence[opt] objc-throw-statement
- attribute-specifier-sequence[opt] objc-try-catch-statement
- attribute-specifier-sequence[opt] objc-synchronized-statement
-
- objc-throw-statement:
- @throw expression ;
- @throw ;
-
- OpenACC:
-
- statement:
- attribute-specifier-sequence[opt] openacc-construct
-
- openacc-construct:
- parallel-construct
- kernels-construct
- data-construct
- loop-construct
-
- parallel-construct:
- parallel-directive structured-block
-
- kernels-construct:
- kernels-directive structured-block
-
- data-construct:
- data-directive structured-block
-
- loop-construct:
- loop-directive structured-block
-
- OpenMP:
-
- statement:
- attribute-specifier-sequence[opt] openmp-construct
-
- openmp-construct:
- parallel-construct
- for-construct
- simd-construct
- for-simd-construct
- sections-construct
- single-construct
- parallel-for-construct
- parallel-for-simd-construct
- parallel-sections-construct
- master-construct
- critical-construct
- atomic-construct
- ordered-construct
-
- parallel-construct:
- parallel-directive structured-block
-
- for-construct:
- for-directive iteration-statement
-
- simd-construct:
- simd-directive iteration-statements
-
- for-simd-construct:
- for-simd-directive iteration-statements
-
- sections-construct:
- sections-directive section-scope
-
- single-construct:
- single-directive structured-block
-
- parallel-for-construct:
- parallel-for-directive iteration-statement
-
- parallel-for-simd-construct:
- parallel-for-simd-directive iteration-statement
-
- parallel-sections-construct:
- parallel-sections-directive section-scope
-
- master-construct:
- master-directive structured-block
-
- critical-construct:
- critical-directive structured-block
-
- atomic-construct:
- atomic-directive expression-statement
-
- ordered-construct:
- ordered-directive structured-block
-
- Transactional Memory:
-
- statement:
- attribute-specifier-sequence[opt] transaction-statement
- attribute-specifier-sequence[opt] transaction-cancel-statement
-
- IF_P is used to track whether there's a (possibly labeled) if statement
- which is not enclosed in braces and has an else clause. This is used to
- implement -Wparentheses. */
-
-static void
-c_parser_statement (c_parser *parser, bool *if_p, location_t *loc_after_labels)
-{
- c_parser_all_labels (parser);
- if (loc_after_labels)
- *loc_after_labels = c_parser_peek_token (parser)->location;
- c_parser_statement_after_labels (parser, if_p, NULL);
-}
-
-/* Parse a statement, other than a labeled statement. CHAIN is a vector
- of if-else-if conditions. All labels and standard attributes have
- been parsed in the caller.
-
- IF_P is used to track whether there's a (possibly labeled) if statement
- which is not enclosed in braces and has an else clause. This is used to
- implement -Wparentheses. */
-
-static void
-c_parser_statement_after_labels (c_parser *parser, bool *if_p,
- vec<tree> *chain)
-{
- location_t loc = c_parser_peek_token (parser)->location;
- tree stmt = NULL_TREE;
- bool in_if_block = parser->in_if_block;
- parser->in_if_block = false;
- if (if_p != NULL)
- *if_p = false;
-
- if (c_parser_peek_token (parser)->type != CPP_OPEN_BRACE)
- add_debug_begin_stmt (loc);
-
- restart:
- switch (c_parser_peek_token (parser)->type)
- {
- case CPP_OPEN_BRACE:
- add_stmt (c_parser_compound_statement (parser));
- break;
- case CPP_KEYWORD:
- switch (c_parser_peek_token (parser)->keyword)
- {
- case RID_IF:
- c_parser_if_statement (parser, if_p, chain);
- break;
- case RID_SWITCH:
- c_parser_switch_statement (parser, if_p);
- break;
- case RID_WHILE:
- c_parser_while_statement (parser, false, 0, if_p);
- break;
- case RID_DO:
- c_parser_do_statement (parser, false, 0);
- break;
- case RID_FOR:
- c_parser_for_statement (parser, false, 0, if_p);
- break;
- case RID_GOTO:
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- stmt = c_finish_goto_label (loc,
- c_parser_peek_token (parser)->value);
- c_parser_consume_token (parser);
- }
- else if (c_parser_next_token_is (parser, CPP_MULT))
- {
- struct c_expr val;
-
- c_parser_consume_token (parser);
- val = c_parser_expression (parser);
- val = convert_lvalue_to_rvalue (loc, val, false, true);
- stmt = c_finish_goto_ptr (loc, val);
- }
- else
- c_parser_error (parser, "expected identifier or %<*%>");
- goto expect_semicolon;
- case RID_CONTINUE:
- c_parser_consume_token (parser);
- stmt = c_finish_bc_stmt (loc, objc_foreach_continue_label, false);
- goto expect_semicolon;
- case RID_BREAK:
- c_parser_consume_token (parser);
- stmt = c_finish_bc_stmt (loc, objc_foreach_break_label, true);
- goto expect_semicolon;
- case RID_RETURN:
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_SEMICOLON))
- {
- stmt = c_finish_return (loc, NULL_TREE, NULL_TREE);
- c_parser_consume_token (parser);
- }
- else
- {
- location_t xloc = c_parser_peek_token (parser)->location;
- struct c_expr expr = c_parser_expression_conv (parser);
- mark_exp_read (expr.value);
- stmt = c_finish_return (EXPR_LOC_OR_LOC (expr.value, xloc),
- expr.value, expr.original_type);
- goto expect_semicolon;
- }
- break;
- case RID_ASM:
- stmt = c_parser_asm_statement (parser);
- break;
- case RID_TRANSACTION_ATOMIC:
- case RID_TRANSACTION_RELAXED:
- stmt = c_parser_transaction (parser,
- c_parser_peek_token (parser)->keyword);
- break;
- case RID_TRANSACTION_CANCEL:
- stmt = c_parser_transaction_cancel (parser);
- goto expect_semicolon;
- case RID_AT_THROW:
- gcc_assert (c_dialect_objc ());
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_SEMICOLON))
- {
- stmt = objc_build_throw_stmt (loc, NULL_TREE);
- c_parser_consume_token (parser);
- }
- else
- {
- struct c_expr expr = c_parser_expression (parser);
- expr = convert_lvalue_to_rvalue (loc, expr, false, false);
- expr.value = c_fully_fold (expr.value, false, NULL);
- stmt = objc_build_throw_stmt (loc, expr.value);
- goto expect_semicolon;
- }
- break;
- case RID_AT_TRY:
- gcc_assert (c_dialect_objc ());
- c_parser_objc_try_catch_finally_statement (parser);
- break;
- case RID_AT_SYNCHRONIZED:
- gcc_assert (c_dialect_objc ());
- c_parser_objc_synchronized_statement (parser);
- break;
- case RID_ATTRIBUTE:
- {
- /* Allow '__attribute__((fallthrough));'. */
- tree attrs = c_parser_gnu_attributes (parser);
- if (attribute_fallthrough_p (attrs))
- {
- if (c_parser_next_token_is (parser, CPP_SEMICOLON))
- {
- tree fn = build_call_expr_internal_loc (loc,
- IFN_FALLTHROUGH,
- void_type_node, 0);
- add_stmt (fn);
- /* Eat the ';'. */
- c_parser_consume_token (parser);
- }
- else
- warning_at (loc, OPT_Wattributes,
- "%<fallthrough%> attribute not followed "
- "by %<;%>");
- }
- else if (attrs != NULL_TREE)
- warning_at (loc, OPT_Wattributes, "only attribute %<fallthrough%>"
- " can be applied to a null statement");
- break;
- }
- default:
- goto expr_stmt;
- }
- break;
- case CPP_SEMICOLON:
- c_parser_consume_token (parser);
- break;
- case CPP_CLOSE_PAREN:
- case CPP_CLOSE_SQUARE:
- /* Avoid infinite loop in error recovery:
- c_parser_skip_until_found stops at a closing nesting
- delimiter without consuming it, but here we need to consume
- it to proceed further. */
- c_parser_error (parser, "expected statement");
- c_parser_consume_token (parser);
- break;
- case CPP_PRAGMA:
- if (!c_parser_pragma (parser, pragma_stmt, if_p))
- goto restart;
- break;
- default:
- expr_stmt:
- stmt = c_finish_expr_stmt (loc, c_parser_expression_conv (parser).value);
- expect_semicolon:
- c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
- break;
- }
- /* Two cases cannot and do not have line numbers associated: If stmt
- is degenerate, such as "2;", then stmt is an INTEGER_CST, which
- cannot hold line numbers. But that's OK because the statement
- will either be changed to a MODIFY_EXPR during gimplification of
- the statement expr, or discarded. If stmt was compound, but
- without new variables, we will have skipped the creation of a
- BIND and will have a bare STATEMENT_LIST. But that's OK because
- (recursively) all of the component statements should already have
- line numbers assigned. ??? Can we discard no-op statements
- earlier? */
- if (EXPR_LOCATION (stmt) == UNKNOWN_LOCATION)
- protected_set_expr_location (stmt, loc);
-
- parser->in_if_block = in_if_block;
-}
-
-/* Parse the condition from an if, do, while or for statements. */
-
-static tree
-c_parser_condition (c_parser *parser)
-{
- location_t loc = c_parser_peek_token (parser)->location;
- tree cond;
- cond = c_parser_expression_conv (parser).value;
- cond = c_objc_common_truthvalue_conversion (loc, cond);
- cond = c_fully_fold (cond, false, NULL);
- if (warn_sequence_point)
- verify_sequence_points (cond);
- return cond;
-}
-
-/* Parse a parenthesized condition from an if, do or while statement.
-
- condition:
- ( expression )
-*/
-static tree
-c_parser_paren_condition (c_parser *parser)
-{
- tree cond;
- matching_parens parens;
- if (!parens.require_open (parser))
- return error_mark_node;
- cond = c_parser_condition (parser);
- parens.skip_until_found_close (parser);
- return cond;
-}
-
-/* Parse a statement which is a block in C99.
-
- IF_P is used to track whether there's a (possibly labeled) if statement
- which is not enclosed in braces and has an else clause. This is used to
- implement -Wparentheses. */
-
-static tree
-c_parser_c99_block_statement (c_parser *parser, bool *if_p,
- location_t *loc_after_labels)
-{
- tree block = c_begin_compound_stmt (flag_isoc99);
- location_t loc = c_parser_peek_token (parser)->location;
- c_parser_statement (parser, if_p, loc_after_labels);
- return c_end_compound_stmt (loc, block, flag_isoc99);
-}
-
-/* Parse the body of an if statement. This is just parsing a
- statement but (a) it is a block in C99, (b) we track whether the
- body is an if statement for the sake of -Wparentheses warnings, (c)
- we handle an empty body specially for the sake of -Wempty-body
- warnings, and (d) we call parser_compound_statement directly
- because c_parser_statement_after_labels resets
- parser->in_if_block.
-
- IF_P is used to track whether there's a (possibly labeled) if statement
- which is not enclosed in braces and has an else clause. This is used to
- implement -Wparentheses. */
-
-static tree
-c_parser_if_body (c_parser *parser, bool *if_p,
- const token_indent_info &if_tinfo)
-{
- tree block = c_begin_compound_stmt (flag_isoc99);
- location_t body_loc = c_parser_peek_token (parser)->location;
- location_t body_loc_after_labels = UNKNOWN_LOCATION;
- token_indent_info body_tinfo
- = get_token_indent_info (c_parser_peek_token (parser));
-
- c_parser_all_labels (parser);
- if (c_parser_next_token_is (parser, CPP_SEMICOLON))
- {
- location_t loc = c_parser_peek_token (parser)->location;
- add_stmt (build_empty_stmt (loc));
- c_parser_consume_token (parser);
- if (!c_parser_next_token_is_keyword (parser, RID_ELSE))
- warning_at (loc, OPT_Wempty_body,
- "suggest braces around empty body in an %<if%> statement");
- }
- else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
- add_stmt (c_parser_compound_statement (parser));
- else
- {
- body_loc_after_labels = c_parser_peek_token (parser)->location;
- c_parser_statement_after_labels (parser, if_p);
- }
-
- token_indent_info next_tinfo
- = get_token_indent_info (c_parser_peek_token (parser));
- warn_for_misleading_indentation (if_tinfo, body_tinfo, next_tinfo);
- if (body_loc_after_labels != UNKNOWN_LOCATION
- && next_tinfo.type != CPP_SEMICOLON)
- warn_for_multistatement_macros (body_loc_after_labels, next_tinfo.location,
- if_tinfo.location, RID_IF);
-
- return c_end_compound_stmt (body_loc, block, flag_isoc99);
-}
-
-/* Parse the else body of an if statement. This is just parsing a
- statement but (a) it is a block in C99, (b) we handle an empty body
- specially for the sake of -Wempty-body warnings. CHAIN is a vector
- of if-else-if conditions. */
-
-static tree
-c_parser_else_body (c_parser *parser, const token_indent_info &else_tinfo,
- vec<tree> *chain)
-{
- location_t body_loc = c_parser_peek_token (parser)->location;
- tree block = c_begin_compound_stmt (flag_isoc99);
- token_indent_info body_tinfo
- = get_token_indent_info (c_parser_peek_token (parser));
- location_t body_loc_after_labels = UNKNOWN_LOCATION;
-
- c_parser_all_labels (parser);
- if (c_parser_next_token_is (parser, CPP_SEMICOLON))
- {
- location_t loc = c_parser_peek_token (parser)->location;
- warning_at (loc,
- OPT_Wempty_body,
- "suggest braces around empty body in an %<else%> statement");
- add_stmt (build_empty_stmt (loc));
- c_parser_consume_token (parser);
- }
- else
- {
- if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE))
- body_loc_after_labels = c_parser_peek_token (parser)->location;
- c_parser_statement_after_labels (parser, NULL, chain);
- }
-
- token_indent_info next_tinfo
- = get_token_indent_info (c_parser_peek_token (parser));
- warn_for_misleading_indentation (else_tinfo, body_tinfo, next_tinfo);
- if (body_loc_after_labels != UNKNOWN_LOCATION
- && next_tinfo.type != CPP_SEMICOLON)
- warn_for_multistatement_macros (body_loc_after_labels, next_tinfo.location,
- else_tinfo.location, RID_ELSE);
-
- return c_end_compound_stmt (body_loc, block, flag_isoc99);
-}
-
-/* We might need to reclassify any previously-lexed identifier, e.g.
- when we've left a for loop with an if-statement without else in the
- body - we might have used a wrong scope for the token. See PR67784. */
-
-static void
-c_parser_maybe_reclassify_token (c_parser *parser)
-{
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- c_token *token = c_parser_peek_token (parser);
-
- if (token->id_kind != C_ID_CLASSNAME)
- {
- tree decl = lookup_name (token->value);
-
- token->id_kind = C_ID_ID;
- if (decl)
- {
- if (TREE_CODE (decl) == TYPE_DECL)
- token->id_kind = C_ID_TYPENAME;
- }
- else if (c_dialect_objc ())
- {
- tree objc_interface_decl = objc_is_class_name (token->value);
- /* Objective-C class names are in the same namespace as
- variables and typedefs, and hence are shadowed by local
- declarations. */
- if (objc_interface_decl)
- {
- token->value = objc_interface_decl;
- token->id_kind = C_ID_CLASSNAME;
- }
- }
- }
- }
-}
-
-/* Parse an if statement (C90 6.6.4, C99 6.8.4, C11 6.8.4).
-
- if-statement:
- if ( expression ) statement
- if ( expression ) statement else statement
-
- CHAIN is a vector of if-else-if conditions.
- IF_P is used to track whether there's a (possibly labeled) if statement
- which is not enclosed in braces and has an else clause. This is used to
- implement -Wparentheses. */
-
-static void
-c_parser_if_statement (c_parser *parser, bool *if_p, vec<tree> *chain)
-{
- tree block;
- location_t loc;
- tree cond;
- bool nested_if = false;
- tree first_body, second_body;
- bool in_if_block;
-
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_IF));
- token_indent_info if_tinfo
- = get_token_indent_info (c_parser_peek_token (parser));
- c_parser_consume_token (parser);
- block = c_begin_compound_stmt (flag_isoc99);
- loc = c_parser_peek_token (parser)->location;
- cond = c_parser_paren_condition (parser);
- in_if_block = parser->in_if_block;
- parser->in_if_block = true;
- first_body = c_parser_if_body (parser, &nested_if, if_tinfo);
- parser->in_if_block = in_if_block;
-
- if (warn_duplicated_cond)
- warn_duplicated_cond_add_or_warn (EXPR_LOCATION (cond), cond, &chain);
-
- if (c_parser_next_token_is_keyword (parser, RID_ELSE))
- {
- token_indent_info else_tinfo
- = get_token_indent_info (c_parser_peek_token (parser));
- c_parser_consume_token (parser);
- if (warn_duplicated_cond)
- {
- if (c_parser_next_token_is_keyword (parser, RID_IF)
- && chain == NULL)
- {
- /* We've got "if (COND) else if (COND2)". Start the
- condition chain and add COND as the first element. */
- chain = new vec<tree> ();
- if (!CONSTANT_CLASS_P (cond) && !TREE_SIDE_EFFECTS (cond))
- chain->safe_push (cond);
- }
- else if (!c_parser_next_token_is_keyword (parser, RID_IF))
- /* This is if-else without subsequent if. Zap the condition
- chain; we would have already warned at this point. */
- vec_free (chain);
- }
- second_body = c_parser_else_body (parser, else_tinfo, chain);
- /* Set IF_P to true to indicate that this if statement has an
- else clause. This may trigger the Wparentheses warning
- below when we get back up to the parent if statement. */
- if (if_p != NULL)
- *if_p = true;
- }
- else
- {
- second_body = NULL_TREE;
-
- /* Diagnose an ambiguous else if if-then-else is nested inside
- if-then. */
- if (nested_if)
- warning_at (loc, OPT_Wdangling_else,
- "suggest explicit braces to avoid ambiguous %<else%>");
-
- if (warn_duplicated_cond)
- /* This if statement does not have an else clause. We don't
- need the condition chain anymore. */
- vec_free (chain);
- }
- c_finish_if_stmt (loc, cond, first_body, second_body);
- add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
-
- c_parser_maybe_reclassify_token (parser);
-}
-
-/* Parse a switch statement (C90 6.6.4, C99 6.8.4, C11 6.8.4).
-
- switch-statement:
- switch (expression) statement
-*/
-
-static void
-c_parser_switch_statement (c_parser *parser, bool *if_p)
-{
- struct c_expr ce;
- tree block, expr, body;
- unsigned char save_in_statement;
- location_t switch_loc = c_parser_peek_token (parser)->location;
- location_t switch_cond_loc;
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_SWITCH));
- c_parser_consume_token (parser);
- block = c_begin_compound_stmt (flag_isoc99);
- bool explicit_cast_p = false;
- matching_parens parens;
- if (parens.require_open (parser))
- {
- switch_cond_loc = c_parser_peek_token (parser)->location;
- if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
- && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
- explicit_cast_p = true;
- ce = c_parser_expression (parser);
- ce = convert_lvalue_to_rvalue (switch_cond_loc, ce, true, true);
- expr = ce.value;
- /* ??? expr has no valid location? */
- parens.skip_until_found_close (parser);
- }
- else
- {
- switch_cond_loc = UNKNOWN_LOCATION;
- expr = error_mark_node;
- ce.original_type = error_mark_node;
- }
- c_start_switch (switch_loc, switch_cond_loc, expr, explicit_cast_p);
- save_in_statement = in_statement;
- in_statement |= IN_SWITCH_STMT;
- location_t loc_after_labels;
- bool open_brace_p = c_parser_peek_token (parser)->type == CPP_OPEN_BRACE;
- body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels);
- location_t next_loc = c_parser_peek_token (parser)->location;
- if (!open_brace_p && c_parser_peek_token (parser)->type != CPP_SEMICOLON)
- warn_for_multistatement_macros (loc_after_labels, next_loc, switch_loc,
- RID_SWITCH);
- c_finish_switch (body, ce.original_type);
- in_statement = save_in_statement;
- add_stmt (c_end_compound_stmt (switch_loc, block, flag_isoc99));
- c_parser_maybe_reclassify_token (parser);
-}
-
-/* Parse a while statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
-
- while-statement:
- while (expression) statement
-
- IF_P is used to track whether there's a (possibly labeled) if statement
- which is not enclosed in braces and has an else clause. This is used to
- implement -Wparentheses. */
-
-static void
-c_parser_while_statement (c_parser *parser, bool ivdep, unsigned short unroll,
- bool *if_p)
-{
- tree block, cond, body;
- unsigned char save_in_statement;
- location_t loc;
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_WHILE));
- token_indent_info while_tinfo
- = get_token_indent_info (c_parser_peek_token (parser));
- c_parser_consume_token (parser);
- block = c_begin_compound_stmt (flag_isoc99);
- loc = c_parser_peek_token (parser)->location;
- cond = c_parser_paren_condition (parser);
- 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));
- save_in_statement = in_statement;
- in_statement = IN_ITERATION_STMT;
-
- token_indent_info body_tinfo
- = get_token_indent_info (c_parser_peek_token (parser));
-
- location_t loc_after_labels;
- bool open_brace = c_parser_next_token_is (parser, CPP_OPEN_BRACE);
- body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels);
- add_stmt (build_stmt (loc, WHILE_STMT, cond, body));
- add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
- c_parser_maybe_reclassify_token (parser);
-
- token_indent_info next_tinfo
- = get_token_indent_info (c_parser_peek_token (parser));
- warn_for_misleading_indentation (while_tinfo, body_tinfo, next_tinfo);
-
- if (next_tinfo.type != CPP_SEMICOLON && !open_brace)
- warn_for_multistatement_macros (loc_after_labels, next_tinfo.location,
- while_tinfo.location, RID_WHILE);
-
- in_statement = save_in_statement;
-}
-
-/* Parse a do statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
-
- do-statement:
- do statement while ( expression ) ;
-*/
-
-static void
-c_parser_do_statement (c_parser *parser, bool ivdep, unsigned short unroll)
-{
- tree block, cond, body;
- unsigned char save_in_statement;
- location_t loc;
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_DO));
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_SEMICOLON))
- warning_at (c_parser_peek_token (parser)->location,
- OPT_Wempty_body,
- "suggest braces around empty body in %<do%> statement");
- block = c_begin_compound_stmt (flag_isoc99);
- loc = c_parser_peek_token (parser)->location;
- save_in_statement = in_statement;
- in_statement = IN_ITERATION_STMT;
- body = c_parser_c99_block_statement (parser, NULL);
- c_parser_require_keyword (parser, RID_WHILE, "expected %<while%>");
- in_statement = save_in_statement;
- cond = c_parser_paren_condition (parser);
- 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));
- if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
- c_parser_skip_to_end_of_block_or_statement (parser);
-
- add_stmt (build_stmt (loc, DO_STMT, cond, body));
- add_stmt (c_end_compound_stmt (loc, block, flag_isoc99));
-}
-
-/* Parse a for statement (C90 6.6.5, C99 6.8.5, C11 6.8.5).
-
- for-statement:
- for ( expression[opt] ; expression[opt] ; expression[opt] ) statement
- for ( nested-declaration expression[opt] ; expression[opt] ) statement
-
- The form with a declaration is new in C99.
-
- ??? In accordance with the old parser, the declaration may be a
- nested function, which is then rejected in check_for_loop_decls,
- but does it make any sense for this to be included in the grammar?
- Note in particular that the nested function does not include a
- trailing ';', whereas the "declaration" production includes one.
- Also, can we reject bad declarations earlier and cheaper than
- check_for_loop_decls?
-
- In Objective-C, there are two additional variants:
-
- foreach-statement:
- for ( expression in expresssion ) statement
- for ( declaration in expression ) statement
-
- This is inconsistent with C, because the second variant is allowed
- even if c99 is not enabled.
-
- The rest of the comment documents these Objective-C foreach-statement.
-
- Here is the canonical example of the first variant:
- for (object in array) { do something with object }
- we call the first expression ("object") the "object_expression" and
- the second expression ("array") the "collection_expression".
- object_expression must be an lvalue of type "id" (a generic Objective-C
- object) because the loop works by assigning to object_expression the
- various objects from the collection_expression. collection_expression
- must evaluate to something of type "id" which responds to the method
- countByEnumeratingWithState:objects:count:.
-
- The canonical example of the second variant is:
- for (id object in array) { do something with object }
- which is completely equivalent to
- {
- id object;
- for (object in array) { do something with object }
- }
- Note that initizializing 'object' in some way (eg, "for ((object =
- xxx) in array) { do something with object }") is possibly
- technically valid, but completely pointless as 'object' will be
- assigned to something else as soon as the loop starts. We should
- most likely reject it (TODO).
-
- The beginning of the Objective-C foreach-statement looks exactly
- like the beginning of the for-statement, and we can tell it is a
- foreach-statement only because the initial declaration or
- expression is terminated by 'in' instead of ';'.
-
- IF_P is used to track whether there's a (possibly labeled) if statement
- which is not enclosed in braces and has an else clause. This is used to
- implement -Wparentheses. */
-
-static void
-c_parser_for_statement (c_parser *parser, bool ivdep, unsigned short unroll,
- bool *if_p)
-{
- tree block, cond, incr, body;
- unsigned char save_in_statement;
- tree save_objc_foreach_break_label, save_objc_foreach_continue_label;
- /* The following are only used when parsing an ObjC foreach statement. */
- tree object_expression;
- /* Silence the bogus uninitialized warning. */
- tree collection_expression = NULL;
- location_t loc = c_parser_peek_token (parser)->location;
- location_t for_loc = loc;
- bool is_foreach_statement = false;
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_FOR));
- token_indent_info for_tinfo
- = get_token_indent_info (c_parser_peek_token (parser));
- c_parser_consume_token (parser);
- /* Open a compound statement in Objective-C as well, just in case this is
- as foreach expression. */
- block = c_begin_compound_stmt (flag_isoc99 || c_dialect_objc ());
- cond = error_mark_node;
- incr = error_mark_node;
- matching_parens parens;
- if (parens.require_open (parser))
- {
- /* Parse the initialization declaration or expression. */
- object_expression = error_mark_node;
- parser->objc_could_be_foreach_context = c_dialect_objc ();
- if (c_parser_next_token_is (parser, CPP_SEMICOLON))
- {
- parser->objc_could_be_foreach_context = false;
- c_parser_consume_token (parser);
- c_finish_expr_stmt (loc, NULL_TREE);
- }
- else if (c_parser_next_tokens_start_declaration (parser)
- || c_parser_nth_token_starts_std_attributes (parser, 1))
- {
- c_parser_declaration_or_fndef (parser, true, true, true, true, true,
- &object_expression);
- parser->objc_could_be_foreach_context = false;
-
- if (c_parser_next_token_is_keyword (parser, RID_IN))
- {
- c_parser_consume_token (parser);
- is_foreach_statement = true;
- if (check_for_loop_decls (for_loc, true) == NULL_TREE)
- c_parser_error (parser, "multiple iterating variables in "
- "fast enumeration");
- }
- else
- check_for_loop_decls (for_loc, flag_isoc99);
- }
- else if (c_parser_next_token_is_keyword (parser, RID_EXTENSION))
- {
- /* __extension__ can start a declaration, but is also an
- unary operator that can start an expression. Consume all
- but the last of a possible series of __extension__ to
- determine which. */
- while (c_parser_peek_2nd_token (parser)->type == CPP_KEYWORD
- && (c_parser_peek_2nd_token (parser)->keyword
- == RID_EXTENSION))
- c_parser_consume_token (parser);
- if (c_token_starts_declaration (c_parser_peek_2nd_token (parser))
- || c_parser_nth_token_starts_std_attributes (parser, 2))
- {
- int ext;
- ext = disable_extension_diagnostics ();
- c_parser_consume_token (parser);
- c_parser_declaration_or_fndef (parser, true, true, true, true,
- true, &object_expression);
- parser->objc_could_be_foreach_context = false;
-
- restore_extension_diagnostics (ext);
- if (c_parser_next_token_is_keyword (parser, RID_IN))
- {
- c_parser_consume_token (parser);
- is_foreach_statement = true;
- if (check_for_loop_decls (for_loc, true) == NULL_TREE)
- c_parser_error (parser, "multiple iterating variables in "
- "fast enumeration");
- }
- else
- check_for_loop_decls (for_loc, flag_isoc99);
- }
- else
- goto init_expr;
- }
- else
- {
- init_expr:
- {
- struct c_expr ce;
- tree init_expression;
- ce = c_parser_expression (parser);
- init_expression = ce.value;
- parser->objc_could_be_foreach_context = false;
- if (c_parser_next_token_is_keyword (parser, RID_IN))
- {
- c_parser_consume_token (parser);
- is_foreach_statement = true;
- if (! lvalue_p (init_expression))
- c_parser_error (parser, "invalid iterating variable in "
- "fast enumeration");
- object_expression
- = c_fully_fold (init_expression, false, NULL);
- }
- else
- {
- ce = convert_lvalue_to_rvalue (loc, ce, true, false);
- init_expression = ce.value;
- c_finish_expr_stmt (loc, init_expression);
- c_parser_skip_until_found (parser, CPP_SEMICOLON,
- "expected %<;%>");
- }
- }
- }
- /* Parse the loop condition. In the case of a foreach
- statement, there is no loop condition. */
- gcc_assert (!parser->objc_could_be_foreach_context);
- if (!is_foreach_statement)
- {
- if (c_parser_next_token_is (parser, CPP_SEMICOLON))
- {
- if (ivdep)
- {
- c_parser_error (parser, "missing loop condition in loop "
- "with %<GCC ivdep%> pragma");
- cond = error_mark_node;
- }
- else if (unroll)
- {
- c_parser_error (parser, "missing loop condition in loop "
- "with %<GCC unroll%> pragma");
- cond = error_mark_node;
- }
- else
- {
- c_parser_consume_token (parser);
- cond = NULL_TREE;
- }
- }
- else
- {
- cond = c_parser_condition (parser);
- c_parser_skip_until_found (parser, CPP_SEMICOLON,
- "expected %<;%>");
- }
- 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));
- }
- /* Parse the increment expression (the third expression in a
- for-statement). In the case of a foreach-statement, this is
- the expression that follows the 'in'. */
- loc = c_parser_peek_token (parser)->location;
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- {
- if (is_foreach_statement)
- {
- c_parser_error (parser,
- "missing collection in fast enumeration");
- collection_expression = error_mark_node;
- }
- else
- incr = c_process_expr_stmt (loc, NULL_TREE);
- }
- else
- {
- if (is_foreach_statement)
- collection_expression
- = c_fully_fold (c_parser_expression (parser).value, false, NULL);
- else
- {
- struct c_expr ce = c_parser_expression (parser);
- ce = convert_lvalue_to_rvalue (loc, ce, true, false);
- incr = c_process_expr_stmt (loc, ce.value);
- }
- }
- parens.skip_until_found_close (parser);
- }
- save_in_statement = in_statement;
- if (is_foreach_statement)
- {
- in_statement = IN_OBJC_FOREACH;
- save_objc_foreach_break_label = objc_foreach_break_label;
- save_objc_foreach_continue_label = objc_foreach_continue_label;
- objc_foreach_break_label = create_artificial_label (loc);
- objc_foreach_continue_label = create_artificial_label (loc);
- }
- else
- in_statement = IN_ITERATION_STMT;
-
- token_indent_info body_tinfo
- = get_token_indent_info (c_parser_peek_token (parser));
-
- location_t loc_after_labels;
- bool open_brace = c_parser_next_token_is (parser, CPP_OPEN_BRACE);
- body = c_parser_c99_block_statement (parser, if_p, &loc_after_labels);
-
- if (is_foreach_statement)
- objc_finish_foreach_loop (for_loc, object_expression,
- collection_expression, body,
- objc_foreach_break_label,
- objc_foreach_continue_label);
- else
- add_stmt (build_stmt (for_loc, FOR_STMT, NULL_TREE, cond, incr,
- body, NULL_TREE));
- add_stmt (c_end_compound_stmt (for_loc, block,
- flag_isoc99 || c_dialect_objc ()));
- c_parser_maybe_reclassify_token (parser);
-
- token_indent_info next_tinfo
- = get_token_indent_info (c_parser_peek_token (parser));
- warn_for_misleading_indentation (for_tinfo, body_tinfo, next_tinfo);
-
- if (next_tinfo.type != CPP_SEMICOLON && !open_brace)
- warn_for_multistatement_macros (loc_after_labels, next_tinfo.location,
- for_tinfo.location, RID_FOR);
-
- in_statement = save_in_statement;
- if (is_foreach_statement)
- {
- objc_foreach_break_label = save_objc_foreach_break_label;
- objc_foreach_continue_label = save_objc_foreach_continue_label;
- }
-}
-
-/* Parse an asm statement, a GNU extension. This is a full-blown asm
- statement with inputs, outputs, clobbers, and volatile, inline, and goto
- tags allowed.
-
- asm-qualifier:
- volatile
- inline
- goto
-
- asm-qualifier-list:
- asm-qualifier-list asm-qualifier
- asm-qualifier
-
- asm-statement:
- asm asm-qualifier-list[opt] ( asm-argument ) ;
-
- asm-argument:
- asm-string-literal
- asm-string-literal : asm-operands[opt]
- asm-string-literal : asm-operands[opt] : asm-operands[opt]
- asm-string-literal : asm-operands[opt] : asm-operands[opt] \
- : asm-clobbers[opt]
- asm-string-literal : : asm-operands[opt] : asm-clobbers[opt] \
- : asm-goto-operands
-
- The form with asm-goto-operands is valid if and only if the
- asm-qualifier-list contains goto, and is the only allowed form in that case.
- Duplicate asm-qualifiers are not allowed.
-
- The :: token is considered equivalent to two consecutive : tokens. */
-
-static tree
-c_parser_asm_statement (c_parser *parser)
-{
- tree str, outputs, inputs, clobbers, labels, ret;
- bool simple;
- location_t asm_loc = c_parser_peek_token (parser)->location;
- int section, nsections;
-
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_ASM));
- c_parser_consume_token (parser);
-
- /* Handle the asm-qualifier-list. */
- location_t volatile_loc = UNKNOWN_LOCATION;
- location_t inline_loc = UNKNOWN_LOCATION;
- location_t goto_loc = UNKNOWN_LOCATION;
- for (;;)
- {
- c_token *token = c_parser_peek_token (parser);
- location_t loc = token->location;
- switch (token->keyword)
- {
- case RID_VOLATILE:
- if (volatile_loc)
- {
- error_at (loc, "duplicate %<asm%> qualifier %qE", token->value);
- inform (volatile_loc, "first seen here");
- }
- else
- volatile_loc = loc;
- c_parser_consume_token (parser);
- continue;
-
- case RID_INLINE:
- if (inline_loc)
- {
- error_at (loc, "duplicate %<asm%> qualifier %qE", token->value);
- inform (inline_loc, "first seen here");
- }
- else
- inline_loc = loc;
- c_parser_consume_token (parser);
- continue;
-
- case RID_GOTO:
- if (goto_loc)
- {
- error_at (loc, "duplicate %<asm%> qualifier %qE", token->value);
- inform (goto_loc, "first seen here");
- }
- else
- goto_loc = loc;
- c_parser_consume_token (parser);
- continue;
-
- case RID_CONST:
- case RID_RESTRICT:
- error_at (loc, "%qE is not a valid %<asm%> qualifier", token->value);
- c_parser_consume_token (parser);
- continue;
-
- default:
- break;
- }
- break;
- }
-
- bool is_volatile = (volatile_loc != UNKNOWN_LOCATION);
- bool is_inline = (inline_loc != UNKNOWN_LOCATION);
- bool is_goto = (goto_loc != UNKNOWN_LOCATION);
-
- ret = NULL;
-
- matching_parens parens;
- if (!parens.require_open (parser))
- goto error;
-
- str = c_parser_asm_string_literal (parser);
- if (str == NULL_TREE)
- goto error_close_paren;
-
- simple = true;
- outputs = NULL_TREE;
- inputs = NULL_TREE;
- clobbers = NULL_TREE;
- labels = NULL_TREE;
-
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto)
- goto done_asm;
-
- /* Parse each colon-delimited section of operands. */
- nsections = 3 + is_goto;
- for (section = 0; section < nsections; ++section)
- {
- if (c_parser_next_token_is (parser, CPP_SCOPE))
- {
- ++section;
- if (section == nsections)
- {
- c_parser_error (parser, "expected %<)%>");
- goto error_close_paren;
- }
- c_parser_consume_token (parser);
- }
- else if (!c_parser_require (parser, CPP_COLON,
- is_goto
- ? G_("expected %<:%>")
- : G_("expected %<:%> or %<)%>"),
- UNKNOWN_LOCATION, is_goto))
- goto error_close_paren;
-
- /* Once past any colon, we're no longer a simple asm. */
- simple = false;
-
- if ((!c_parser_next_token_is (parser, CPP_COLON)
- && !c_parser_next_token_is (parser, CPP_SCOPE)
- && !c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- || section == 3)
- switch (section)
- {
- case 0:
- outputs = c_parser_asm_operands (parser);
- break;
- case 1:
- inputs = c_parser_asm_operands (parser);
- break;
- case 2:
- clobbers = c_parser_asm_clobbers (parser);
- break;
- case 3:
- labels = c_parser_asm_goto_operands (parser);
- break;
- default:
- gcc_unreachable ();
- }
-
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN) && !is_goto)
- goto done_asm;
- }
-
- done_asm:
- if (!parens.require_close (parser))
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- goto error;
- }
-
- if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
- c_parser_skip_to_end_of_block_or_statement (parser);
-
- ret = build_asm_stmt (is_volatile,
- build_asm_expr (asm_loc, str, outputs, inputs,
- clobbers, labels, simple, is_inline));
-
- error:
- return ret;
-
- error_close_paren:
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- goto error;
-}
-
-/* Parse asm operands, a GNU extension.
-
- asm-operands:
- asm-operand
- asm-operands , asm-operand
-
- asm-operand:
- asm-string-literal ( expression )
- [ identifier ] asm-string-literal ( expression )
-*/
-
-static tree
-c_parser_asm_operands (c_parser *parser)
-{
- tree list = NULL_TREE;
- while (true)
- {
- tree name, str;
- struct c_expr expr;
- if (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
- {
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- tree id = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- name = build_string (IDENTIFIER_LENGTH (id),
- IDENTIFIER_POINTER (id));
- }
- else
- {
- c_parser_error (parser, "expected identifier");
- c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, NULL);
- return NULL_TREE;
- }
- c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
- "expected %<]%>");
- }
- else
- name = NULL_TREE;
- str = c_parser_asm_string_literal (parser);
- if (str == NULL_TREE)
- return NULL_TREE;
- matching_parens parens;
- if (!parens.require_open (parser))
- return NULL_TREE;
- expr = c_parser_expression (parser);
- mark_exp_read (expr.value);
- if (!parens.require_close (parser))
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- return NULL_TREE;
- }
- list = chainon (list, build_tree_list (build_tree_list (name, str),
- expr.value));
- if (c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
- else
- break;
- }
- return list;
-}
-
-/* Parse asm clobbers, a GNU extension.
-
- asm-clobbers:
- asm-string-literal
- asm-clobbers , asm-string-literal
-*/
-
-static tree
-c_parser_asm_clobbers (c_parser *parser)
-{
- tree list = NULL_TREE;
- while (true)
- {
- tree str = c_parser_asm_string_literal (parser);
- if (str)
- list = tree_cons (NULL_TREE, str, list);
- else
- return NULL_TREE;
- if (c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
- else
- break;
- }
- return list;
-}
-
-/* Parse asm goto labels, a GNU extension.
-
- asm-goto-operands:
- identifier
- asm-goto-operands , identifier
-*/
-
-static tree
-c_parser_asm_goto_operands (c_parser *parser)
-{
- tree list = NULL_TREE;
- while (true)
- {
- tree name, label;
-
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- c_token *tok = c_parser_peek_token (parser);
- name = tok->value;
- label = lookup_label_for_goto (tok->location, name);
- c_parser_consume_token (parser);
- TREE_USED (label) = 1;
- }
- else
- {
- c_parser_error (parser, "expected identifier");
- return NULL_TREE;
- }
-
- name = build_string (IDENTIFIER_LENGTH (name),
- IDENTIFIER_POINTER (name));
- list = tree_cons (name, label, list);
- if (c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
- else
- return nreverse (list);
- }
-}
-
-/* Parse a possibly concatenated sequence of string literals.
- TRANSLATE says whether to translate them to the execution character
- set; WIDE_OK says whether any kind of prefixed string literal is
- permitted in this context. This code is based on that in
- lex_string. */
-
-struct c_expr
-c_parser_string_literal (c_parser *parser, bool translate, bool wide_ok)
-{
- struct c_expr ret;
- size_t count;
- struct obstack str_ob;
- struct obstack loc_ob;
- cpp_string str, istr, *strs;
- c_token *tok;
- location_t loc, last_tok_loc;
- enum cpp_ttype type;
- tree value, string_tree;
-
- tok = c_parser_peek_token (parser);
- loc = tok->location;
- last_tok_loc = linemap_resolve_location (line_table, loc,
- LRK_MACRO_DEFINITION_LOCATION,
- NULL);
- type = tok->type;
- switch (type)
- {
- case CPP_STRING:
- case CPP_WSTRING:
- case CPP_STRING16:
- case CPP_STRING32:
- case CPP_UTF8STRING:
- string_tree = tok->value;
- break;
-
- default:
- c_parser_error (parser, "expected string literal");
- ret.set_error ();
- ret.value = NULL_TREE;
- ret.original_code = ERROR_MARK;
- ret.original_type = NULL_TREE;
- return ret;
- }
-
- /* Try to avoid the overhead of creating and destroying an obstack
- for the common case of just one string. */
- switch (c_parser_peek_2nd_token (parser)->type)
- {
- default:
- c_parser_consume_token (parser);
- str.text = (const unsigned char *) TREE_STRING_POINTER (string_tree);
- str.len = TREE_STRING_LENGTH (string_tree);
- count = 1;
- strs = &str;
- break;
-
- case CPP_STRING:
- case CPP_WSTRING:
- case CPP_STRING16:
- case CPP_STRING32:
- case CPP_UTF8STRING:
- gcc_obstack_init (&str_ob);
- gcc_obstack_init (&loc_ob);
- count = 0;
- do
- {
- c_parser_consume_token (parser);
- count++;
- str.text = (const unsigned char *) TREE_STRING_POINTER (string_tree);
- str.len = TREE_STRING_LENGTH (string_tree);
- if (type != tok->type)
- {
- if (type == CPP_STRING)
- type = tok->type;
- else if (tok->type != CPP_STRING)
- error ("unsupported non-standard concatenation "
- "of string literals");
- }
- obstack_grow (&str_ob, &str, sizeof (cpp_string));
- obstack_grow (&loc_ob, &last_tok_loc, sizeof (location_t));
- tok = c_parser_peek_token (parser);
- string_tree = tok->value;
- last_tok_loc
- = linemap_resolve_location (line_table, tok->location,
- LRK_MACRO_DEFINITION_LOCATION, NULL);
- }
- while (tok->type == CPP_STRING
- || tok->type == CPP_WSTRING
- || tok->type == CPP_STRING16
- || tok->type == CPP_STRING32
- || tok->type == CPP_UTF8STRING);
- strs = (cpp_string *) obstack_finish (&str_ob);
- }
-
- if (count > 1 && !in_system_header_at (input_location))
- warning (OPT_Wtraditional,
- "traditional C rejects string constant concatenation");
-
- if ((type == CPP_STRING || wide_ok)
- && ((translate
- ? cpp_interpret_string : cpp_interpret_string_notranslate)
- (parse_in, strs, count, &istr, type)))
- {
- value = build_string (istr.len, (const char *) istr.text);
- free (CONST_CAST (unsigned char *, istr.text));
- if (count > 1)
- {
- location_t *locs = (location_t *) obstack_finish (&loc_ob);
- gcc_assert (g_string_concat_db);
- g_string_concat_db->record_string_concatenation (count, locs);
- }
- }
- else
- {
- if (type != CPP_STRING && !wide_ok)
- {
- error_at (loc, "a wide string is invalid in this context");
- type = CPP_STRING;
- }
- /* Callers cannot generally handle error_mark_node in this
- context, so return the empty string instead. An error has
- been issued, either above or from cpp_interpret_string. */
- switch (type)
- {
- default:
- case CPP_STRING:
- case CPP_UTF8STRING:
- value = build_string (1, "");
- break;
- case CPP_STRING16:
- value = build_string (TYPE_PRECISION (char16_type_node)
- / TYPE_PRECISION (char_type_node),
- "\0"); /* char16_t is 16 bits */
- break;
- case CPP_STRING32:
- value = build_string (TYPE_PRECISION (char32_type_node)
- / TYPE_PRECISION (char_type_node),
- "\0\0\0"); /* char32_t is 32 bits */
- break;
- case CPP_WSTRING:
- value = build_string (TYPE_PRECISION (wchar_type_node)
- / TYPE_PRECISION (char_type_node),
- "\0\0\0"); /* widest supported wchar_t
- is 32 bits */
- break;
- }
- }
-
- switch (type)
- {
- default:
- case CPP_STRING:
- case CPP_UTF8STRING:
- TREE_TYPE (value) = char_array_type_node;
- break;
- case CPP_STRING16:
- TREE_TYPE (value) = char16_array_type_node;
- break;
- case CPP_STRING32:
- TREE_TYPE (value) = char32_array_type_node;
- break;
- case CPP_WSTRING:
- TREE_TYPE (value) = wchar_array_type_node;
- }
- value = fix_string_type (value);
-
- if (count > 1)
- {
- obstack_free (&str_ob, 0);
- obstack_free (&loc_ob, 0);
- }
-
- ret.value = value;
- ret.original_code = STRING_CST;
- ret.original_type = NULL_TREE;
- set_c_expr_source_range (&ret, get_range_from_loc (line_table, loc));
- parser->seen_string_literal = true;
- return ret;
-}
-
-/* Parse an expression other than a compound expression; that is, an
- assignment expression (C90 6.3.16, C99 6.5.16, C11 6.5.16). If
- AFTER is not NULL then it is an Objective-C message expression which
- is the primary-expression starting the expression as an initializer.
-
- assignment-expression:
- conditional-expression
- unary-expression assignment-operator assignment-expression
-
- assignment-operator: one of
- = *= /= %= += -= <<= >>= &= ^= |=
-
- In GNU C we accept any conditional expression on the LHS and
- diagnose the invalid lvalue rather than producing a syntax
- error. */
-
-static struct c_expr
-c_parser_expr_no_commas (c_parser *parser, struct c_expr *after,
- tree omp_atomic_lhs)
-{
- struct c_expr lhs, rhs, ret;
- enum tree_code code;
- location_t op_location, exp_location;
- bool save_in_omp_for = c_in_omp_for;
- c_in_omp_for = false;
- gcc_assert (!after || c_dialect_objc ());
- lhs = c_parser_conditional_expression (parser, after, omp_atomic_lhs);
- op_location = c_parser_peek_token (parser)->location;
- switch (c_parser_peek_token (parser)->type)
- {
- case CPP_EQ:
- code = NOP_EXPR;
- break;
- case CPP_MULT_EQ:
- code = MULT_EXPR;
- break;
- case CPP_DIV_EQ:
- code = TRUNC_DIV_EXPR;
- break;
- case CPP_MOD_EQ:
- code = TRUNC_MOD_EXPR;
- break;
- case CPP_PLUS_EQ:
- code = PLUS_EXPR;
- break;
- case CPP_MINUS_EQ:
- code = MINUS_EXPR;
- break;
- case CPP_LSHIFT_EQ:
- code = LSHIFT_EXPR;
- break;
- case CPP_RSHIFT_EQ:
- code = RSHIFT_EXPR;
- break;
- case CPP_AND_EQ:
- code = BIT_AND_EXPR;
- break;
- case CPP_XOR_EQ:
- code = BIT_XOR_EXPR;
- break;
- case CPP_OR_EQ:
- code = BIT_IOR_EXPR;
- break;
- default:
- c_in_omp_for = save_in_omp_for;
- return lhs;
- }
- c_parser_consume_token (parser);
- exp_location = c_parser_peek_token (parser)->location;
- rhs = c_parser_expr_no_commas (parser, NULL);
- rhs = convert_lvalue_to_rvalue (exp_location, rhs, true, true);
-
- ret.value = build_modify_expr (op_location, lhs.value, lhs.original_type,
- code, exp_location, rhs.value,
- rhs.original_type);
- set_c_expr_source_range (&ret, lhs.get_start (), rhs.get_finish ());
- if (code == NOP_EXPR)
- ret.original_code = MODIFY_EXPR;
- else
- {
- suppress_warning (ret.value, OPT_Wparentheses);
- ret.original_code = ERROR_MARK;
- }
- ret.original_type = NULL;
- c_in_omp_for = save_in_omp_for;
- return ret;
-}
-
-/* Parse a conditional expression (C90 6.3.15, C99 6.5.15, C11 6.5.15). If
- AFTER is not NULL then it is an Objective-C message expression which is
- the primary-expression starting the expression as an initializer.
-
- conditional-expression:
- logical-OR-expression
- logical-OR-expression ? expression : conditional-expression
-
- GNU extensions:
-
- conditional-expression:
- logical-OR-expression ? : conditional-expression
-*/
-
-static struct c_expr
-c_parser_conditional_expression (c_parser *parser, struct c_expr *after,
- tree omp_atomic_lhs)
-{
- struct c_expr cond, exp1, exp2, ret;
- location_t start, cond_loc, colon_loc;
-
- gcc_assert (!after || c_dialect_objc ());
-
- cond = c_parser_binary_expression (parser, after, omp_atomic_lhs);
-
- if (c_parser_next_token_is_not (parser, CPP_QUERY))
- return cond;
- if (cond.value != error_mark_node)
- start = cond.get_start ();
- else
- start = UNKNOWN_LOCATION;
- cond_loc = c_parser_peek_token (parser)->location;
- cond = convert_lvalue_to_rvalue (cond_loc, cond, true, true);
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_COLON))
- {
- tree eptype = NULL_TREE;
-
- location_t middle_loc = c_parser_peek_token (parser)->location;
- pedwarn (middle_loc, OPT_Wpedantic,
- "ISO C forbids omitting the middle term of a %<?:%> expression");
- if (TREE_CODE (cond.value) == EXCESS_PRECISION_EXPR)
- {
- eptype = TREE_TYPE (cond.value);
- cond.value = TREE_OPERAND (cond.value, 0);
- }
- tree e = cond.value;
- while (TREE_CODE (e) == COMPOUND_EXPR)
- e = TREE_OPERAND (e, 1);
- warn_for_omitted_condop (middle_loc, e);
- /* Make sure first operand is calculated only once. */
- exp1.value = save_expr (default_conversion (cond.value));
- if (eptype)
- exp1.value = build1 (EXCESS_PRECISION_EXPR, eptype, exp1.value);
- exp1.original_type = NULL;
- exp1.src_range = cond.src_range;
- cond.value = c_objc_common_truthvalue_conversion (cond_loc, exp1.value);
- c_inhibit_evaluation_warnings += cond.value == truthvalue_true_node;
- }
- else
- {
- cond.value
- = c_objc_common_truthvalue_conversion
- (cond_loc, default_conversion (cond.value));
- c_inhibit_evaluation_warnings += cond.value == truthvalue_false_node;
- exp1 = c_parser_expression_conv (parser);
- mark_exp_read (exp1.value);
- c_inhibit_evaluation_warnings +=
- ((cond.value == truthvalue_true_node)
- - (cond.value == truthvalue_false_node));
- }
-
- colon_loc = c_parser_peek_token (parser)->location;
- if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
- {
- c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
- ret.set_error ();
- ret.original_code = ERROR_MARK;
- ret.original_type = NULL;
- return ret;
- }
- {
- location_t exp2_loc = c_parser_peek_token (parser)->location;
- exp2 = c_parser_conditional_expression (parser, NULL, NULL_TREE);
- exp2 = convert_lvalue_to_rvalue (exp2_loc, exp2, true, true);
- }
- c_inhibit_evaluation_warnings -= cond.value == truthvalue_true_node;
- location_t loc1 = make_location (exp1.get_start (), exp1.src_range);
- location_t loc2 = make_location (exp2.get_start (), exp2.src_range);
- if (__builtin_expect (omp_atomic_lhs != NULL, 0)
- && (TREE_CODE (cond.value) == GT_EXPR
- || TREE_CODE (cond.value) == LT_EXPR
- || TREE_CODE (cond.value) == EQ_EXPR)
- && c_tree_equal (exp2.value, omp_atomic_lhs)
- && (c_tree_equal (TREE_OPERAND (cond.value, 0), omp_atomic_lhs)
- || c_tree_equal (TREE_OPERAND (cond.value, 1), omp_atomic_lhs)))
- ret.value = build3_loc (colon_loc, COND_EXPR, TREE_TYPE (omp_atomic_lhs),
- cond.value, exp1.value, exp2.value);
- else
- ret.value
- = build_conditional_expr (colon_loc, cond.value,
- cond.original_code == C_MAYBE_CONST_EXPR,
- exp1.value, exp1.original_type, loc1,
- exp2.value, exp2.original_type, loc2);
- ret.original_code = ERROR_MARK;
- if (exp1.value == error_mark_node || exp2.value == error_mark_node)
- ret.original_type = NULL;
- else
- {
- tree t1, t2;
-
- /* If both sides are enum type, the default conversion will have
- made the type of the result be an integer type. We want to
- remember the enum types we started with. */
- t1 = exp1.original_type ? exp1.original_type : TREE_TYPE (exp1.value);
- t2 = exp2.original_type ? exp2.original_type : TREE_TYPE (exp2.value);
- ret.original_type = ((t1 != error_mark_node
- && t2 != error_mark_node
- && (TYPE_MAIN_VARIANT (t1)
- == TYPE_MAIN_VARIANT (t2)))
- ? t1
- : NULL);
- }
- set_c_expr_source_range (&ret, start, exp2.get_finish ());
- return ret;
-}
-
-/* Parse a binary expression; that is, a logical-OR-expression (C90
- 6.3.5-6.3.14, C99 6.5.5-6.5.14, C11 6.5.5-6.5.14). If AFTER is not
- NULL then it is an Objective-C message expression which is the
- primary-expression starting the expression as an initializer.
-
- OMP_ATOMIC_LHS is NULL, unless parsing OpenMP #pragma omp atomic,
- when it should be the unfolded lhs. In a valid OpenMP source,
- one of the operands of the toplevel binary expression must be equal
- to it. In that case, just return a build2 created binary operation
- rather than result of parser_build_binary_op.
-
- multiplicative-expression:
- cast-expression
- multiplicative-expression * cast-expression
- multiplicative-expression / cast-expression
- multiplicative-expression % cast-expression
-
- additive-expression:
- multiplicative-expression
- additive-expression + multiplicative-expression
- additive-expression - multiplicative-expression
-
- shift-expression:
- additive-expression
- shift-expression << additive-expression
- shift-expression >> additive-expression
-
- relational-expression:
- shift-expression
- relational-expression < shift-expression
- relational-expression > shift-expression
- relational-expression <= shift-expression
- relational-expression >= shift-expression
-
- equality-expression:
- relational-expression
- equality-expression == relational-expression
- equality-expression != relational-expression
-
- AND-expression:
- equality-expression
- AND-expression & equality-expression
-
- exclusive-OR-expression:
- AND-expression
- exclusive-OR-expression ^ AND-expression
-
- inclusive-OR-expression:
- exclusive-OR-expression
- inclusive-OR-expression | exclusive-OR-expression
-
- logical-AND-expression:
- inclusive-OR-expression
- logical-AND-expression && inclusive-OR-expression
-
- logical-OR-expression:
- logical-AND-expression
- logical-OR-expression || logical-AND-expression
-*/
-
-static struct c_expr
-c_parser_binary_expression (c_parser *parser, struct c_expr *after,
- tree omp_atomic_lhs)
-{
- /* A binary expression is parsed using operator-precedence parsing,
- with the operands being cast expressions. All the binary
- operators are left-associative. Thus a binary expression is of
- form:
-
- E0 op1 E1 op2 E2 ...
-
- which we represent on a stack. On the stack, the precedence
- levels are strictly increasing. When a new operator is
- encountered of higher precedence than that at the top of the
- stack, it is pushed; its LHS is the top expression, and its RHS
- is everything parsed until it is popped. When a new operator is
- encountered with precedence less than or equal to that at the top
- of the stack, triples E[i-1] op[i] E[i] are popped and replaced
- by the result of the operation until the operator at the top of
- the stack has lower precedence than the new operator or there is
- only one element on the stack; then the top expression is the LHS
- of the new operator. In the case of logical AND and OR
- expressions, we also need to adjust c_inhibit_evaluation_warnings
- as appropriate when the operators are pushed and popped. */
-
- struct {
- /* The expression at this stack level. */
- struct c_expr expr;
- /* The precedence of the operator on its left, PREC_NONE at the
- bottom of the stack. */
- enum c_parser_prec prec;
- /* The operation on its left. */
- enum tree_code op;
- /* The source location of this operation. */
- location_t loc;
- /* The sizeof argument if expr.original_code == {PAREN_,}SIZEOF_EXPR. */
- tree sizeof_arg;
- } stack[NUM_PRECS];
- int sp;
- /* Location of the binary operator. */
- location_t binary_loc = UNKNOWN_LOCATION; /* Quiet warning. */
-#define POP \
- do { \
- switch (stack[sp].op) \
- { \
- case TRUTH_ANDIF_EXPR: \
- c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \
- == truthvalue_false_node); \
- break; \
- case TRUTH_ORIF_EXPR: \
- c_inhibit_evaluation_warnings -= (stack[sp - 1].expr.value \
- == truthvalue_true_node); \
- break; \
- case TRUNC_DIV_EXPR: \
- if ((stack[sp - 1].expr.original_code == SIZEOF_EXPR \
- || stack[sp - 1].expr.original_code == PAREN_SIZEOF_EXPR) \
- && (stack[sp].expr.original_code == SIZEOF_EXPR \
- || stack[sp].expr.original_code == PAREN_SIZEOF_EXPR)) \
- { \
- tree type0 = stack[sp - 1].sizeof_arg; \
- tree type1 = stack[sp].sizeof_arg; \
- tree first_arg = type0; \
- if (!TYPE_P (type0)) \
- type0 = TREE_TYPE (type0); \
- if (!TYPE_P (type1)) \
- type1 = TREE_TYPE (type1); \
- if (POINTER_TYPE_P (type0) \
- && comptypes (TREE_TYPE (type0), type1) \
- && !(TREE_CODE (first_arg) == PARM_DECL \
- && C_ARRAY_PARAMETER (first_arg) \
- && warn_sizeof_array_argument)) \
- { \
- auto_diagnostic_group d; \
- if (warning_at (stack[sp].loc, OPT_Wsizeof_pointer_div, \
- "division %<sizeof (%T) / sizeof (%T)%> " \
- "does not compute the number of array " \
- "elements", \
- type0, type1)) \
- if (DECL_P (first_arg)) \
- inform (DECL_SOURCE_LOCATION (first_arg), \
- "first %<sizeof%> operand was declared here"); \
- } \
- else if (TREE_CODE (type0) == ARRAY_TYPE \
- && !char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type0))) \
- && stack[sp].expr.original_code != PAREN_SIZEOF_EXPR) \
- maybe_warn_sizeof_array_div (stack[sp].loc, first_arg, type0, \
- stack[sp].sizeof_arg, type1); \
- } \
- break; \
- default: \
- break; \
- } \
- stack[sp - 1].expr \
- = convert_lvalue_to_rvalue (stack[sp - 1].loc, \
- stack[sp - 1].expr, true, true); \
- stack[sp].expr \
- = convert_lvalue_to_rvalue (stack[sp].loc, \
- stack[sp].expr, true, true); \
- if (__builtin_expect (omp_atomic_lhs != NULL_TREE, 0) && sp == 1 \
- && ((c_parser_next_token_is (parser, CPP_SEMICOLON) \
- && ((1 << stack[sp].prec) \
- & ((1 << PREC_BITOR) | (1 << PREC_BITXOR) \
- | (1 << PREC_BITAND) | (1 << PREC_SHIFT) \
- | (1 << PREC_ADD) | (1 << PREC_MULT) \
- | (1 << PREC_EQ)))) \
- || ((c_parser_next_token_is (parser, CPP_QUERY) \
- || (omp_atomic_lhs == void_list_node \
- && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))) \
- && (stack[sp].prec == PREC_REL || stack[sp].prec == PREC_EQ)))\
- && stack[sp].op != TRUNC_MOD_EXPR \
- && stack[sp].op != GE_EXPR \
- && stack[sp].op != LE_EXPR \
- && stack[sp].op != NE_EXPR \
- && stack[0].expr.value != error_mark_node \
- && stack[1].expr.value != error_mark_node \
- && (omp_atomic_lhs == void_list_node \
- || c_tree_equal (stack[0].expr.value, omp_atomic_lhs) \
- || c_tree_equal (stack[1].expr.value, omp_atomic_lhs) \
- || (stack[sp].op == EQ_EXPR \
- && c_parser_peek_2nd_token (parser)->keyword == RID_IF))) \
- { \
- tree t = make_node (stack[1].op); \
- TREE_TYPE (t) = TREE_TYPE (stack[0].expr.value); \
- TREE_OPERAND (t, 0) = stack[0].expr.value; \
- TREE_OPERAND (t, 1) = stack[1].expr.value; \
- stack[0].expr.value = t; \
- } \
- else \
- stack[sp - 1].expr = parser_build_binary_op (stack[sp].loc, \
- stack[sp].op, \
- stack[sp - 1].expr, \
- stack[sp].expr); \
- sp--; \
- } while (0)
- gcc_assert (!after || c_dialect_objc ());
- stack[0].loc = c_parser_peek_token (parser)->location;
- stack[0].expr = c_parser_cast_expression (parser, after);
- stack[0].prec = PREC_NONE;
- stack[0].sizeof_arg = c_last_sizeof_arg;
- sp = 0;
- while (true)
- {
- enum c_parser_prec oprec;
- enum tree_code ocode;
- source_range src_range;
- if (parser->error)
- goto out;
- switch (c_parser_peek_token (parser)->type)
- {
- case CPP_MULT:
- oprec = PREC_MULT;
- ocode = MULT_EXPR;
- break;
- case CPP_DIV:
- oprec = PREC_MULT;
- ocode = TRUNC_DIV_EXPR;
- break;
- case CPP_MOD:
- oprec = PREC_MULT;
- ocode = TRUNC_MOD_EXPR;
- break;
- case CPP_PLUS:
- oprec = PREC_ADD;
- ocode = PLUS_EXPR;
- break;
- case CPP_MINUS:
- oprec = PREC_ADD;
- ocode = MINUS_EXPR;
- break;
- case CPP_LSHIFT:
- oprec = PREC_SHIFT;
- ocode = LSHIFT_EXPR;
- break;
- case CPP_RSHIFT:
- oprec = PREC_SHIFT;
- ocode = RSHIFT_EXPR;
- break;
- case CPP_LESS:
- oprec = PREC_REL;
- ocode = LT_EXPR;
- break;
- case CPP_GREATER:
- oprec = PREC_REL;
- ocode = GT_EXPR;
- break;
- case CPP_LESS_EQ:
- oprec = PREC_REL;
- ocode = LE_EXPR;
- break;
- case CPP_GREATER_EQ:
- oprec = PREC_REL;
- ocode = GE_EXPR;
- break;
- case CPP_EQ_EQ:
- oprec = PREC_EQ;
- ocode = EQ_EXPR;
- break;
- case CPP_NOT_EQ:
- oprec = PREC_EQ;
- ocode = NE_EXPR;
- break;
- case CPP_AND:
- oprec = PREC_BITAND;
- ocode = BIT_AND_EXPR;
- break;
- case CPP_XOR:
- oprec = PREC_BITXOR;
- ocode = BIT_XOR_EXPR;
- break;
- case CPP_OR:
- oprec = PREC_BITOR;
- ocode = BIT_IOR_EXPR;
- break;
- case CPP_AND_AND:
- oprec = PREC_LOGAND;
- ocode = TRUTH_ANDIF_EXPR;
- break;
- case CPP_OR_OR:
- oprec = PREC_LOGOR;
- ocode = TRUTH_ORIF_EXPR;
- break;
- default:
- /* Not a binary operator, so end of the binary
- expression. */
- goto out;
- }
- binary_loc = c_parser_peek_token (parser)->location;
- while (oprec <= stack[sp].prec)
- POP;
- c_parser_consume_token (parser);
- switch (ocode)
- {
- case TRUTH_ANDIF_EXPR:
- src_range = stack[sp].expr.src_range;
- stack[sp].expr
- = convert_lvalue_to_rvalue (stack[sp].loc,
- stack[sp].expr, true, true);
- stack[sp].expr.value = c_objc_common_truthvalue_conversion
- (stack[sp].loc, default_conversion (stack[sp].expr.value));
- c_inhibit_evaluation_warnings += (stack[sp].expr.value
- == truthvalue_false_node);
- set_c_expr_source_range (&stack[sp].expr, src_range);
- break;
- case TRUTH_ORIF_EXPR:
- src_range = stack[sp].expr.src_range;
- stack[sp].expr
- = convert_lvalue_to_rvalue (stack[sp].loc,
- stack[sp].expr, true, true);
- stack[sp].expr.value = c_objc_common_truthvalue_conversion
- (stack[sp].loc, default_conversion (stack[sp].expr.value));
- c_inhibit_evaluation_warnings += (stack[sp].expr.value
- == truthvalue_true_node);
- set_c_expr_source_range (&stack[sp].expr, src_range);
- break;
- default:
- break;
- }
- sp++;
- stack[sp].loc = binary_loc;
- stack[sp].expr = c_parser_cast_expression (parser, NULL);
- stack[sp].prec = oprec;
- stack[sp].op = ocode;
- stack[sp].sizeof_arg = c_last_sizeof_arg;
- }
- out:
- while (sp > 0)
- POP;
- return stack[0].expr;
-#undef POP
-}
-
-/* Parse a cast expression (C90 6.3.4, C99 6.5.4, C11 6.5.4). If AFTER
- is not NULL then it is an Objective-C message expression which is the
- primary-expression starting the expression as an initializer.
-
- cast-expression:
- unary-expression
- ( type-name ) unary-expression
-*/
-
-static struct c_expr
-c_parser_cast_expression (c_parser *parser, struct c_expr *after)
-{
- location_t cast_loc = c_parser_peek_token (parser)->location;
- gcc_assert (!after || c_dialect_objc ());
- if (after)
- return c_parser_postfix_expression_after_primary (parser,
- cast_loc, *after);
- /* If the expression begins with a parenthesized type name, it may
- be either a cast or a compound literal; we need to see whether
- the next character is '{' to tell the difference. If not, it is
- an unary expression. Full detection of unknown typenames here
- would require a 3-token lookahead. */
- if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
- && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
- {
- struct c_type_name *type_name;
- struct c_expr ret;
- struct c_expr expr;
- matching_parens parens;
- parens.consume_open (parser);
- type_name = c_parser_type_name (parser, true);
- parens.skip_until_found_close (parser);
- if (type_name == NULL)
- {
- ret.set_error ();
- ret.original_code = ERROR_MARK;
- ret.original_type = NULL;
- return ret;
- }
-
- /* Save casted types in the function's used types hash table. */
- used_types_insert (type_name->specs->type);
-
- if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
- return c_parser_postfix_expression_after_paren_type (parser, type_name,
- cast_loc);
- if (type_name->specs->alignas_p)
- error_at (type_name->specs->locations[cdw_alignas],
- "alignment specified for type name in cast");
- {
- location_t expr_loc = c_parser_peek_token (parser)->location;
- expr = c_parser_cast_expression (parser, NULL);
- expr = convert_lvalue_to_rvalue (expr_loc, expr, true, true);
- }
- ret.value = c_cast_expr (cast_loc, type_name, expr.value);
- if (ret.value && expr.value)
- set_c_expr_source_range (&ret, cast_loc, expr.get_finish ());
- ret.original_code = ERROR_MARK;
- ret.original_type = NULL;
- return ret;
- }
- else
- return c_parser_unary_expression (parser);
-}
-
-/* Parse an unary expression (C90 6.3.3, C99 6.5.3, C11 6.5.3).
-
- unary-expression:
- postfix-expression
- ++ unary-expression
- -- unary-expression
- unary-operator cast-expression
- sizeof unary-expression
- sizeof ( type-name )
-
- unary-operator: one of
- & * + - ~ !
-
- GNU extensions:
-
- unary-expression:
- __alignof__ unary-expression
- __alignof__ ( type-name )
- && identifier
-
- (C11 permits _Alignof with type names only.)
-
- unary-operator: one of
- __extension__ __real__ __imag__
-
- Transactional Memory:
-
- unary-expression:
- transaction-expression
-
- In addition, the GNU syntax treats ++ and -- as unary operators, so
- they may be applied to cast expressions with errors for non-lvalues
- given later. */
-
-static struct c_expr
-c_parser_unary_expression (c_parser *parser)
-{
- int ext;
- struct c_expr ret, op;
- location_t op_loc = c_parser_peek_token (parser)->location;
- location_t exp_loc;
- location_t finish;
- ret.original_code = ERROR_MARK;
- ret.original_type = NULL;
- switch (c_parser_peek_token (parser)->type)
- {
- case CPP_PLUS_PLUS:
- c_parser_consume_token (parser);
- exp_loc = c_parser_peek_token (parser)->location;
- op = c_parser_cast_expression (parser, NULL);
-
- op = default_function_array_read_conversion (exp_loc, op);
- return parser_build_unary_op (op_loc, PREINCREMENT_EXPR, op);
- case CPP_MINUS_MINUS:
- c_parser_consume_token (parser);
- exp_loc = c_parser_peek_token (parser)->location;
- op = c_parser_cast_expression (parser, NULL);
-
- op = default_function_array_read_conversion (exp_loc, op);
- return parser_build_unary_op (op_loc, PREDECREMENT_EXPR, op);
- case CPP_AND:
- c_parser_consume_token (parser);
- op = c_parser_cast_expression (parser, NULL);
- mark_exp_read (op.value);
- return parser_build_unary_op (op_loc, ADDR_EXPR, op);
- case CPP_MULT:
- {
- c_parser_consume_token (parser);
- exp_loc = c_parser_peek_token (parser)->location;
- op = c_parser_cast_expression (parser, NULL);
- finish = op.get_finish ();
- op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
- location_t combined_loc = make_location (op_loc, op_loc, finish);
- ret.value = build_indirect_ref (combined_loc, op.value, RO_UNARY_STAR);
- ret.src_range.m_start = op_loc;
- ret.src_range.m_finish = finish;
- return ret;
- }
- case CPP_PLUS:
- if (!c_dialect_objc () && !in_system_header_at (input_location))
- warning_at (op_loc,
- OPT_Wtraditional,
- "traditional C rejects the unary plus operator");
- c_parser_consume_token (parser);
- exp_loc = c_parser_peek_token (parser)->location;
- op = c_parser_cast_expression (parser, NULL);
- op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
- return parser_build_unary_op (op_loc, CONVERT_EXPR, op);
- case CPP_MINUS:
- c_parser_consume_token (parser);
- exp_loc = c_parser_peek_token (parser)->location;
- op = c_parser_cast_expression (parser, NULL);
- op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
- return parser_build_unary_op (op_loc, NEGATE_EXPR, op);
- case CPP_COMPL:
- c_parser_consume_token (parser);
- exp_loc = c_parser_peek_token (parser)->location;
- op = c_parser_cast_expression (parser, NULL);
- op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
- return parser_build_unary_op (op_loc, BIT_NOT_EXPR, op);
- case CPP_NOT:
- c_parser_consume_token (parser);
- exp_loc = c_parser_peek_token (parser)->location;
- op = c_parser_cast_expression (parser, NULL);
- op = convert_lvalue_to_rvalue (exp_loc, op, true, true);
- return parser_build_unary_op (op_loc, TRUTH_NOT_EXPR, op);
- case CPP_AND_AND:
- /* Refer to the address of a label as a pointer. */
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- ret.value = finish_label_address_expr
- (c_parser_peek_token (parser)->value, op_loc);
- set_c_expr_source_range (&ret, op_loc,
- c_parser_peek_token (parser)->get_finish ());
- c_parser_consume_token (parser);
- }
- else
- {
- c_parser_error (parser, "expected identifier");
- ret.set_error ();
- }
- return ret;
- case CPP_KEYWORD:
- switch (c_parser_peek_token (parser)->keyword)
- {
- case RID_SIZEOF:
- return c_parser_sizeof_expression (parser);
- case RID_ALIGNOF:
- return c_parser_alignof_expression (parser);
- case RID_BUILTIN_HAS_ATTRIBUTE:
- return c_parser_has_attribute_expression (parser);
- case RID_EXTENSION:
- c_parser_consume_token (parser);
- ext = disable_extension_diagnostics ();
- ret = c_parser_cast_expression (parser, NULL);
- restore_extension_diagnostics (ext);
- return ret;
- case RID_REALPART:
- c_parser_consume_token (parser);
- exp_loc = c_parser_peek_token (parser)->location;
- op = c_parser_cast_expression (parser, NULL);
- op = default_function_array_conversion (exp_loc, op);
- return parser_build_unary_op (op_loc, REALPART_EXPR, op);
- case RID_IMAGPART:
- c_parser_consume_token (parser);
- exp_loc = c_parser_peek_token (parser)->location;
- op = c_parser_cast_expression (parser, NULL);
- op = default_function_array_conversion (exp_loc, op);
- return parser_build_unary_op (op_loc, IMAGPART_EXPR, op);
- case RID_TRANSACTION_ATOMIC:
- case RID_TRANSACTION_RELAXED:
- return c_parser_transaction_expression (parser,
- c_parser_peek_token (parser)->keyword);
- default:
- return c_parser_postfix_expression (parser);
- }
- default:
- return c_parser_postfix_expression (parser);
- }
-}
-
-/* Parse a sizeof expression. */
-
-static struct c_expr
-c_parser_sizeof_expression (c_parser *parser)
-{
- struct c_expr expr;
- struct c_expr result;
- location_t expr_loc;
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_SIZEOF));
-
- location_t start;
- location_t finish = UNKNOWN_LOCATION;
-
- start = c_parser_peek_token (parser)->location;
-
- c_parser_consume_token (parser);
- c_inhibit_evaluation_warnings++;
- in_sizeof++;
- if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
- && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
- {
- /* Either sizeof ( type-name ) or sizeof unary-expression
- starting with a compound literal. */
- struct c_type_name *type_name;
- matching_parens parens;
- parens.consume_open (parser);
- expr_loc = c_parser_peek_token (parser)->location;
- type_name = c_parser_type_name (parser, true);
- parens.skip_until_found_close (parser);
- finish = parser->tokens_buf[0].location;
- if (type_name == NULL)
- {
- struct c_expr ret;
- c_inhibit_evaluation_warnings--;
- in_sizeof--;
- ret.set_error ();
- ret.original_code = ERROR_MARK;
- ret.original_type = NULL;
- return ret;
- }
- if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
- {
- expr = c_parser_postfix_expression_after_paren_type (parser,
- type_name,
- expr_loc);
- finish = expr.get_finish ();
- goto sizeof_expr;
- }
- /* sizeof ( type-name ). */
- if (type_name->specs->alignas_p)
- error_at (type_name->specs->locations[cdw_alignas],
- "alignment specified for type name in %<sizeof%>");
- c_inhibit_evaluation_warnings--;
- in_sizeof--;
- result = c_expr_sizeof_type (expr_loc, type_name);
- }
- else
- {
- expr_loc = c_parser_peek_token (parser)->location;
- expr = c_parser_unary_expression (parser);
- finish = expr.get_finish ();
- sizeof_expr:
- c_inhibit_evaluation_warnings--;
- in_sizeof--;
- mark_exp_read (expr.value);
- if (TREE_CODE (expr.value) == COMPONENT_REF
- && DECL_C_BIT_FIELD (TREE_OPERAND (expr.value, 1)))
- error_at (expr_loc, "%<sizeof%> applied to a bit-field");
- result = c_expr_sizeof_expr (expr_loc, expr);
- }
- if (finish == UNKNOWN_LOCATION)
- finish = start;
- set_c_expr_source_range (&result, start, finish);
- return result;
-}
-
-/* Parse an alignof expression. */
-
-static struct c_expr
-c_parser_alignof_expression (c_parser *parser)
-{
- struct c_expr expr;
- location_t start_loc = c_parser_peek_token (parser)->location;
- location_t end_loc;
- tree alignof_spelling = c_parser_peek_token (parser)->value;
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF));
- bool is_c11_alignof = strcmp (IDENTIFIER_POINTER (alignof_spelling),
- "_Alignof") == 0;
- /* A diagnostic is not required for the use of this identifier in
- the implementation namespace; only diagnose it for the C11
- spelling because of existing code using the other spellings. */
- if (is_c11_alignof)
- {
- if (flag_isoc99)
- pedwarn_c99 (start_loc, OPT_Wpedantic, "ISO C99 does not support %qE",
- alignof_spelling);
- else
- pedwarn_c99 (start_loc, OPT_Wpedantic, "ISO C90 does not support %qE",
- alignof_spelling);
- }
- c_parser_consume_token (parser);
- c_inhibit_evaluation_warnings++;
- in_alignof++;
- if (c_parser_next_token_is (parser, CPP_OPEN_PAREN)
- && c_token_starts_typename (c_parser_peek_2nd_token (parser)))
- {
- /* Either __alignof__ ( type-name ) or __alignof__
- unary-expression starting with a compound literal. */
- location_t loc;
- struct c_type_name *type_name;
- struct c_expr ret;
- matching_parens parens;
- parens.consume_open (parser);
- loc = c_parser_peek_token (parser)->location;
- type_name = c_parser_type_name (parser, true);
- end_loc = c_parser_peek_token (parser)->location;
- parens.skip_until_found_close (parser);
- if (type_name == NULL)
- {
- struct c_expr ret;
- c_inhibit_evaluation_warnings--;
- in_alignof--;
- ret.set_error ();
- ret.original_code = ERROR_MARK;
- ret.original_type = NULL;
- return ret;
- }
- if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
- {
- expr = c_parser_postfix_expression_after_paren_type (parser,
- type_name,
- loc);
- goto alignof_expr;
- }
- /* alignof ( type-name ). */
- if (type_name->specs->alignas_p)
- error_at (type_name->specs->locations[cdw_alignas],
- "alignment specified for type name in %qE",
- alignof_spelling);
- c_inhibit_evaluation_warnings--;
- in_alignof--;
- ret.value = c_sizeof_or_alignof_type (loc, groktypename (type_name,
- NULL, NULL),
- false, is_c11_alignof, 1);
- ret.original_code = ERROR_MARK;
- ret.original_type = NULL;
- set_c_expr_source_range (&ret, start_loc, end_loc);
- return ret;
- }
- else
- {
- struct c_expr ret;
- expr = c_parser_unary_expression (parser);
- end_loc = expr.src_range.m_finish;
- alignof_expr:
- mark_exp_read (expr.value);
- c_inhibit_evaluation_warnings--;
- in_alignof--;
- if (is_c11_alignof)
- pedwarn (start_loc,
- OPT_Wpedantic, "ISO C does not allow %<%E (expression)%>",
- alignof_spelling);
- ret.value = c_alignof_expr (start_loc, expr.value);
- ret.original_code = ERROR_MARK;
- ret.original_type = NULL;
- set_c_expr_source_range (&ret, start_loc, end_loc);
- return ret;
- }
-}
-
-/* Parse the __builtin_has_attribute ([expr|type], attribute-spec)
- expression. */
-
-static struct c_expr
-c_parser_has_attribute_expression (c_parser *parser)
-{
- gcc_assert (c_parser_next_token_is_keyword (parser,
- RID_BUILTIN_HAS_ATTRIBUTE));
- location_t start = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
-
- c_inhibit_evaluation_warnings++;
-
- matching_parens parens;
- if (!parens.require_open (parser))
- {
- c_inhibit_evaluation_warnings--;
- in_typeof--;
-
- struct c_expr result;
- result.set_error ();
- result.original_code = ERROR_MARK;
- result.original_type = NULL;
- return result;
- }
-
- /* Treat the type argument the same way as in typeof for the purposes
- of warnings. FIXME: Generalize this so the warning refers to
- __builtin_has_attribute rather than typeof. */
- in_typeof++;
-
- /* The first operand: one of DECL, EXPR, or TYPE. */
- tree oper = NULL_TREE;
- if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
- {
- struct c_type_name *tname = c_parser_type_name (parser);
- in_typeof--;
- if (tname)
- {
- oper = groktypename (tname, NULL, NULL);
- pop_maybe_used (variably_modified_type_p (oper, NULL_TREE));
- }
- }
- else
- {
- struct c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
- c_inhibit_evaluation_warnings--;
- in_typeof--;
- if (cexpr.value != error_mark_node)
- {
- mark_exp_read (cexpr.value);
- oper = cexpr.value;
- tree etype = TREE_TYPE (oper);
- bool was_vm = variably_modified_type_p (etype, NULL_TREE);
- /* This is returned with the type so that when the type is
- evaluated, this can be evaluated. */
- if (was_vm)
- oper = c_fully_fold (oper, false, NULL);
- pop_maybe_used (was_vm);
- }
- }
-
- struct c_expr result;
- result.original_code = ERROR_MARK;
- result.original_type = NULL;
-
- if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
- {
- /* Consume the closing parenthesis if that's the next token
- in the likely case the built-in was invoked with fewer
- than two arguments. */
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- c_parser_consume_token (parser);
- c_inhibit_evaluation_warnings--;
- result.set_error ();
- return result;
- }
-
- bool save_translate_strings_p = parser->translate_strings_p;
-
- location_t atloc = c_parser_peek_token (parser)->location;
- /* Parse a single attribute. Require no leading comma and do not
- allow empty attributes. */
- tree attr = c_parser_gnu_attribute (parser, NULL_TREE, false, false);
-
- parser->translate_strings_p = save_translate_strings_p;
-
- location_t finish = c_parser_peek_token (parser)->location;
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- c_parser_consume_token (parser);
- else
- {
- c_parser_error (parser, "expected identifier");
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
-
- result.set_error ();
- return result;
- }
-
- if (!attr)
- {
- error_at (atloc, "expected identifier");
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>");
- result.set_error ();
- return result;
- }
-
- result.original_code = INTEGER_CST;
- result.original_type = boolean_type_node;
-
- if (has_attribute (atloc, oper, attr, default_conversion))
- result.value = boolean_true_node;
- else
- result.value = boolean_false_node;
-
- set_c_expr_source_range (&result, start, finish);
- return result;
-}
-
-/* Helper function to read arguments of builtins which are interfaces
- for the middle-end nodes like COMPLEX_EXPR, VEC_PERM_EXPR and
- others. The name of the builtin is passed using BNAME parameter.
- Function returns true if there were no errors while parsing and
- stores the arguments in CEXPR_LIST. If it returns true,
- *OUT_CLOSE_PAREN_LOC is written to with the location of the closing
- parenthesis. */
-static bool
-c_parser_get_builtin_args (c_parser *parser, const char *bname,
- vec<c_expr_t, va_gc> **ret_cexpr_list,
- bool choose_expr_p,
- location_t *out_close_paren_loc)
-{
- location_t loc = c_parser_peek_token (parser)->location;
- vec<c_expr_t, va_gc> *cexpr_list;
- c_expr_t expr;
- bool saved_force_folding_builtin_constant_p;
-
- *ret_cexpr_list = NULL;
- if (c_parser_next_token_is_not (parser, CPP_OPEN_PAREN))
- {
- error_at (loc, "cannot take address of %qs", bname);
- return false;
- }
-
- c_parser_consume_token (parser);
-
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- {
- *out_close_paren_loc = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
- return true;
- }
-
- saved_force_folding_builtin_constant_p
- = force_folding_builtin_constant_p;
- force_folding_builtin_constant_p |= choose_expr_p;
- expr = c_parser_expr_no_commas (parser, NULL);
- force_folding_builtin_constant_p
- = saved_force_folding_builtin_constant_p;
- vec_alloc (cexpr_list, 1);
- vec_safe_push (cexpr_list, expr);
- while (c_parser_next_token_is (parser, CPP_COMMA))
- {
- c_parser_consume_token (parser);
- expr = c_parser_expr_no_commas (parser, NULL);
- vec_safe_push (cexpr_list, expr);
- }
-
- *out_close_paren_loc = c_parser_peek_token (parser)->location;
- if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
- return false;
-
- *ret_cexpr_list = cexpr_list;
- return true;
-}
-
-/* This represents a single generic-association. */
-
-struct c_generic_association
-{
- /* The location of the starting token of the type. */
- location_t type_location;
- /* The association's type, or NULL_TREE for 'default'. */
- tree type;
- /* The association's expression. */
- struct c_expr expression;
-};
-
-/* Parse a generic-selection. (C11 6.5.1.1).
-
- generic-selection:
- _Generic ( assignment-expression , generic-assoc-list )
-
- generic-assoc-list:
- generic-association
- generic-assoc-list , generic-association
-
- generic-association:
- type-name : assignment-expression
- default : assignment-expression
-*/
-
-static struct c_expr
-c_parser_generic_selection (c_parser *parser)
-{
- struct c_expr selector, error_expr;
- tree selector_type;
- struct c_generic_association matched_assoc;
- int match_found = -1;
- location_t generic_loc, selector_loc;
-
- error_expr.original_code = ERROR_MARK;
- error_expr.original_type = NULL;
- error_expr.set_error ();
- matched_assoc.type_location = UNKNOWN_LOCATION;
- matched_assoc.type = NULL_TREE;
- matched_assoc.expression = error_expr;
-
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_GENERIC));
- generic_loc = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
- if (flag_isoc99)
- pedwarn_c99 (generic_loc, OPT_Wpedantic,
- "ISO C99 does not support %<_Generic%>");
- else
- pedwarn_c99 (generic_loc, OPT_Wpedantic,
- "ISO C90 does not support %<_Generic%>");
-
- matching_parens parens;
- if (!parens.require_open (parser))
- return error_expr;
-
- c_inhibit_evaluation_warnings++;
- selector_loc = c_parser_peek_token (parser)->location;
- selector = c_parser_expr_no_commas (parser, NULL);
- selector = default_function_array_conversion (selector_loc, selector);
- c_inhibit_evaluation_warnings--;
-
- if (selector.value == error_mark_node)
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- return selector;
- }
- mark_exp_read (selector.value);
- selector_type = TREE_TYPE (selector.value);
- /* In ISO C terms, rvalues (including the controlling expression of
- _Generic) do not have qualified types. */
- if (TREE_CODE (selector_type) != ARRAY_TYPE)
- selector_type = TYPE_MAIN_VARIANT (selector_type);
- /* In ISO C terms, _Noreturn is not part of the type of expressions
- such as &abort, but in GCC it is represented internally as a type
- qualifier. */
- if (FUNCTION_POINTER_TYPE_P (selector_type)
- && TYPE_QUALS (TREE_TYPE (selector_type)) != TYPE_UNQUALIFIED)
- selector_type
- = build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (selector_type)));
-
- if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- return error_expr;
- }
-
- auto_vec<c_generic_association> associations;
- while (1)
- {
- struct c_generic_association assoc, *iter;
- unsigned int ix;
- c_token *token = c_parser_peek_token (parser);
-
- assoc.type_location = token->location;
- if (token->type == CPP_KEYWORD && token->keyword == RID_DEFAULT)
- {
- c_parser_consume_token (parser);
- assoc.type = NULL_TREE;
- }
- else
- {
- struct c_type_name *type_name;
-
- type_name = c_parser_type_name (parser);
- if (type_name == NULL)
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- return error_expr;
- }
- assoc.type = groktypename (type_name, NULL, NULL);
- if (assoc.type == error_mark_node)
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- return error_expr;
- }
-
- if (TREE_CODE (assoc.type) == FUNCTION_TYPE)
- error_at (assoc.type_location,
- "%<_Generic%> association has function type");
- else if (!COMPLETE_TYPE_P (assoc.type))
- error_at (assoc.type_location,
- "%<_Generic%> association has incomplete type");
-
- if (variably_modified_type_p (assoc.type, NULL_TREE))
- error_at (assoc.type_location,
- "%<_Generic%> association has "
- "variable length type");
- }
-
- if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- return error_expr;
- }
-
- assoc.expression = c_parser_expr_no_commas (parser, NULL);
- if (assoc.expression.value == error_mark_node)
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- return error_expr;
- }
-
- for (ix = 0; associations.iterate (ix, &iter); ++ix)
- {
- if (assoc.type == NULL_TREE)
- {
- if (iter->type == NULL_TREE)
- {
- error_at (assoc.type_location,
- "duplicate %<default%> case in %<_Generic%>");
- inform (iter->type_location, "original %<default%> is here");
- }
- }
- else if (iter->type != NULL_TREE)
- {
- if (comptypes (assoc.type, iter->type))
- {
- error_at (assoc.type_location,
- "%<_Generic%> specifies two compatible types");
- inform (iter->type_location, "compatible type is here");
- }
- }
- }
-
- if (assoc.type == NULL_TREE)
- {
- if (match_found < 0)
- {
- matched_assoc = assoc;
- match_found = associations.length ();
- }
- }
- else if (comptypes (assoc.type, selector_type))
- {
- if (match_found < 0 || matched_assoc.type == NULL_TREE)
- {
- matched_assoc = assoc;
- match_found = associations.length ();
- }
- else
- {
- error_at (assoc.type_location,
- "%<_Generic%> selector matches multiple associations");
- inform (matched_assoc.type_location,
- "other match is here");
- }
- }
-
- associations.safe_push (assoc);
-
- if (c_parser_peek_token (parser)->type != CPP_COMMA)
- break;
- c_parser_consume_token (parser);
- }
-
- unsigned int ix;
- struct c_generic_association *iter;
- FOR_EACH_VEC_ELT (associations, ix, iter)
- if (ix != (unsigned) match_found)
- mark_exp_read (iter->expression.value);
-
- if (!parens.require_close (parser))
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- return error_expr;
- }
-
- if (match_found < 0)
- {
- error_at (selector_loc, "%<_Generic%> selector of type %qT is not "
- "compatible with any association",
- selector_type);
- return error_expr;
- }
-
- return matched_assoc.expression;
-}
-
-/* Check the validity of a function pointer argument *EXPR (argument
- position POS) to __builtin_tgmath. Return the number of function
- arguments if possibly valid; return 0 having reported an error if
- not valid. */
-
-static unsigned int
-check_tgmath_function (c_expr *expr, unsigned int pos)
-{
- tree type = TREE_TYPE (expr->value);
- if (!FUNCTION_POINTER_TYPE_P (type))
- {
- error_at (expr->get_location (),
- "argument %u of %<__builtin_tgmath%> is not a function pointer",
- pos);
- return 0;
- }
- type = TREE_TYPE (type);
- if (!prototype_p (type))
- {
- error_at (expr->get_location (),
- "argument %u of %<__builtin_tgmath%> is unprototyped", pos);
- return 0;
- }
- if (stdarg_p (type))
- {
- error_at (expr->get_location (),
- "argument %u of %<__builtin_tgmath%> has variable arguments",
- pos);
- return 0;
- }
- unsigned int nargs = 0;
- function_args_iterator iter;
- tree t;
- FOREACH_FUNCTION_ARGS (type, t, iter)
- {
- if (t == void_type_node)
- break;
- nargs++;
- }
- if (nargs == 0)
- {
- error_at (expr->get_location (),
- "argument %u of %<__builtin_tgmath%> has no arguments", pos);
- return 0;
- }
- return nargs;
-}
-
-/* Ways in which a parameter or return value of a type-generic macro
- may vary between the different functions the macro may call. */
-enum tgmath_parm_kind
- {
- tgmath_fixed, tgmath_real, tgmath_complex
- };
-
-/* Helper function for c_parser_postfix_expression. Parse predefined
- identifiers. */
-
-static struct c_expr
-c_parser_predefined_identifier (c_parser *parser)
-{
- location_t loc = c_parser_peek_token (parser)->location;
- switch (c_parser_peek_token (parser)->keyword)
- {
- case RID_FUNCTION_NAME:
- pedwarn (loc, OPT_Wpedantic, "ISO C does not support %qs predefined "
- "identifier", "__FUNCTION__");
- break;
- case RID_PRETTY_FUNCTION_NAME:
- pedwarn (loc, OPT_Wpedantic, "ISO C does not support %qs predefined "
- "identifier", "__PRETTY_FUNCTION__");
- break;
- case RID_C99_FUNCTION_NAME:
- pedwarn_c90 (loc, OPT_Wpedantic, "ISO C90 does not support "
- "%<__func__%> predefined identifier");
- break;
- default:
- gcc_unreachable ();
- }
-
- struct c_expr expr;
- expr.original_code = ERROR_MARK;
- expr.original_type = NULL;
- expr.value = fname_decl (loc, c_parser_peek_token (parser)->keyword,
- c_parser_peek_token (parser)->value);
- set_c_expr_source_range (&expr, loc, loc);
- c_parser_consume_token (parser);
- return expr;
-}
-
-/* Parse a postfix expression (C90 6.3.1-6.3.2, C99 6.5.1-6.5.2,
- C11 6.5.1-6.5.2). Compound literals aren't handled here; callers have to
- call c_parser_postfix_expression_after_paren_type on encountering them.
-
- postfix-expression:
- primary-expression
- postfix-expression [ expression ]
- postfix-expression ( argument-expression-list[opt] )
- postfix-expression . identifier
- postfix-expression -> identifier
- postfix-expression ++
- postfix-expression --
- ( type-name ) { initializer-list }
- ( type-name ) { initializer-list , }
-
- argument-expression-list:
- argument-expression
- argument-expression-list , argument-expression
-
- primary-expression:
- identifier
- constant
- string-literal
- ( expression )
- generic-selection
-
- GNU extensions:
-
- primary-expression:
- __func__
- (treated as a keyword in GNU C)
- __FUNCTION__
- __PRETTY_FUNCTION__
- ( compound-statement )
- __builtin_va_arg ( assignment-expression , type-name )
- __builtin_offsetof ( type-name , offsetof-member-designator )
- __builtin_choose_expr ( assignment-expression ,
- assignment-expression ,
- assignment-expression )
- __builtin_types_compatible_p ( type-name , type-name )
- __builtin_tgmath ( expr-list )
- __builtin_complex ( assignment-expression , assignment-expression )
- __builtin_shuffle ( assignment-expression , assignment-expression )
- __builtin_shuffle ( assignment-expression ,
- assignment-expression ,
- assignment-expression, )
- __builtin_convertvector ( assignment-expression , type-name )
- __builtin_assoc_barrier ( assignment-expression )
-
- offsetof-member-designator:
- identifier
- offsetof-member-designator . identifier
- offsetof-member-designator [ expression ]
-
- Objective-C:
-
- primary-expression:
- [ objc-receiver objc-message-args ]
- @selector ( objc-selector-arg )
- @protocol ( identifier )
- @encode ( type-name )
- objc-string-literal
- Classname . identifier
-*/
-
-static struct c_expr
-c_parser_postfix_expression (c_parser *parser)
-{
- struct c_expr expr, e1;
- struct c_type_name *t1, *t2;
- location_t loc = c_parser_peek_token (parser)->location;
- source_range tok_range = c_parser_peek_token (parser)->get_range ();
- expr.original_code = ERROR_MARK;
- expr.original_type = NULL;
- switch (c_parser_peek_token (parser)->type)
- {
- case CPP_NUMBER:
- expr.value = c_parser_peek_token (parser)->value;
- set_c_expr_source_range (&expr, tok_range);
- loc = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
- if (TREE_CODE (expr.value) == FIXED_CST
- && !targetm.fixed_point_supported_p ())
- {
- error_at (loc, "fixed-point types not supported for this target");
- expr.set_error ();
- }
- break;
- case CPP_CHAR:
- case CPP_CHAR16:
- case CPP_CHAR32:
- case CPP_UTF8CHAR:
- case CPP_WCHAR:
- expr.value = c_parser_peek_token (parser)->value;
- /* For the purpose of warning when a pointer is compared with
- a zero character constant. */
- expr.original_type = char_type_node;
- set_c_expr_source_range (&expr, tok_range);
- c_parser_consume_token (parser);
- break;
- case CPP_STRING:
- case CPP_STRING16:
- case CPP_STRING32:
- case CPP_WSTRING:
- case CPP_UTF8STRING:
- expr = c_parser_string_literal (parser, parser->translate_strings_p,
- true);
- break;
- case CPP_OBJC_STRING:
- gcc_assert (c_dialect_objc ());
- expr.value
- = objc_build_string_object (c_parser_peek_token (parser)->value);
- set_c_expr_source_range (&expr, tok_range);
- c_parser_consume_token (parser);
- break;
- case CPP_NAME:
- switch (c_parser_peek_token (parser)->id_kind)
- {
- case C_ID_ID:
- {
- tree id = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- expr.value = build_external_ref (loc, id,
- (c_parser_peek_token (parser)->type
- == CPP_OPEN_PAREN),
- &expr.original_type);
- set_c_expr_source_range (&expr, tok_range);
- break;
- }
- case C_ID_CLASSNAME:
- {
- /* Here we parse the Objective-C 2.0 Class.name dot
- syntax. */
- tree class_name = c_parser_peek_token (parser)->value;
- tree component;
- c_parser_consume_token (parser);
- gcc_assert (c_dialect_objc ());
- if (!c_parser_require (parser, CPP_DOT, "expected %<.%>"))
- {
- expr.set_error ();
- break;
- }
- if (c_parser_next_token_is_not (parser, CPP_NAME))
- {
- c_parser_error (parser, "expected identifier");
- expr.set_error ();
- break;
- }
- c_token *component_tok = c_parser_peek_token (parser);
- component = component_tok->value;
- location_t end_loc = component_tok->get_finish ();
- c_parser_consume_token (parser);
- expr.value = objc_build_class_component_ref (class_name,
- component);
- set_c_expr_source_range (&expr, loc, end_loc);
- break;
- }
- default:
- c_parser_error (parser, "expected expression");
- expr.set_error ();
- break;
- }
- break;
- case CPP_OPEN_PAREN:
- /* A parenthesized expression, statement expression or compound
- literal. */
- if (c_parser_peek_2nd_token (parser)->type == CPP_OPEN_BRACE)
- {
- /* A statement expression. */
- tree stmt;
- location_t brace_loc;
- c_parser_consume_token (parser);
- brace_loc = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
- /* If we've not yet started the current function's statement list,
- or we're in the parameter scope of an old-style function
- declaration, statement expressions are not allowed. */
- if (!building_stmt_list_p () || old_style_parameter_scope ())
- {
- error_at (loc, "braced-group within expression allowed "
- "only inside a function");
- parser->error = true;
- c_parser_skip_until_found (parser, CPP_CLOSE_BRACE, NULL);
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- expr.set_error ();
- break;
- }
- stmt = c_begin_stmt_expr ();
- c_parser_compound_statement_nostart (parser);
- location_t close_loc = c_parser_peek_token (parser)->location;
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>");
- pedwarn (loc, OPT_Wpedantic,
- "ISO C forbids braced-groups within expressions");
- expr.value = c_finish_stmt_expr (brace_loc, stmt);
- set_c_expr_source_range (&expr, loc, close_loc);
- mark_exp_read (expr.value);
- }
- else
- {
- /* A parenthesized expression. */
- location_t loc_open_paren = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
- expr = c_parser_expression (parser);
- if (TREE_CODE (expr.value) == MODIFY_EXPR)
- suppress_warning (expr.value, OPT_Wparentheses);
- if (expr.original_code != C_MAYBE_CONST_EXPR
- && expr.original_code != SIZEOF_EXPR)
- expr.original_code = ERROR_MARK;
- /* Remember that we saw ( ) around the sizeof. */
- if (expr.original_code == SIZEOF_EXPR)
- expr.original_code = PAREN_SIZEOF_EXPR;
- /* Don't change EXPR.ORIGINAL_TYPE. */
- location_t loc_close_paren = c_parser_peek_token (parser)->location;
- set_c_expr_source_range (&expr, loc_open_paren, loc_close_paren);
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>", loc_open_paren);
- }
- break;
- case CPP_KEYWORD:
- switch (c_parser_peek_token (parser)->keyword)
- {
- case RID_FUNCTION_NAME:
- case RID_PRETTY_FUNCTION_NAME:
- case RID_C99_FUNCTION_NAME:
- expr = c_parser_predefined_identifier (parser);
- break;
- case RID_VA_ARG:
- {
- location_t start_loc = loc;
- c_parser_consume_token (parser);
- matching_parens parens;
- if (!parens.require_open (parser))
- {
- expr.set_error ();
- break;
- }
- e1 = c_parser_expr_no_commas (parser, NULL);
- mark_exp_read (e1.value);
- e1.value = c_fully_fold (e1.value, false, NULL);
- if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- expr.set_error ();
- break;
- }
- loc = c_parser_peek_token (parser)->location;
- t1 = c_parser_type_name (parser);
- location_t end_loc = c_parser_peek_token (parser)->get_finish ();
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>");
- if (t1 == NULL)
- {
- expr.set_error ();
- }
- else
- {
- tree type_expr = NULL_TREE;
- expr.value = c_build_va_arg (start_loc, e1.value, loc,
- groktypename (t1, &type_expr, NULL));
- if (type_expr)
- {
- expr.value = build2 (C_MAYBE_CONST_EXPR,
- TREE_TYPE (expr.value), type_expr,
- expr.value);
- C_MAYBE_CONST_EXPR_NON_CONST (expr.value) = true;
- }
- set_c_expr_source_range (&expr, start_loc, end_loc);
- }
- }
- break;
- case RID_OFFSETOF:
- {
- c_parser_consume_token (parser);
- matching_parens parens;
- if (!parens.require_open (parser))
- {
- expr.set_error ();
- break;
- }
- t1 = c_parser_type_name (parser);
- if (t1 == NULL)
- parser->error = true;
- if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
- gcc_assert (parser->error);
- if (parser->error)
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- expr.set_error ();
- break;
- }
- tree type = groktypename (t1, NULL, NULL);
- tree offsetof_ref;
- if (type == error_mark_node)
- offsetof_ref = error_mark_node;
- else
- {
- offsetof_ref = build1 (INDIRECT_REF, type, null_pointer_node);
- SET_EXPR_LOCATION (offsetof_ref, loc);
- }
- /* Parse the second argument to __builtin_offsetof. We
- must have one identifier, and beyond that we want to
- accept sub structure and sub array references. */
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- c_token *comp_tok = c_parser_peek_token (parser);
- offsetof_ref = build_component_ref
- (loc, offsetof_ref, comp_tok->value, comp_tok->location);
- c_parser_consume_token (parser);
- while (c_parser_next_token_is (parser, CPP_DOT)
- || c_parser_next_token_is (parser,
- CPP_OPEN_SQUARE)
- || c_parser_next_token_is (parser,
- CPP_DEREF))
- {
- if (c_parser_next_token_is (parser, CPP_DEREF))
- {
- loc = c_parser_peek_token (parser)->location;
- offsetof_ref = build_array_ref (loc,
- offsetof_ref,
- integer_zero_node);
- goto do_dot;
- }
- else if (c_parser_next_token_is (parser, CPP_DOT))
- {
- do_dot:
- c_parser_consume_token (parser);
- if (c_parser_next_token_is_not (parser,
- CPP_NAME))
- {
- c_parser_error (parser, "expected identifier");
- break;
- }
- c_token *comp_tok = c_parser_peek_token (parser);
- offsetof_ref = build_component_ref
- (loc, offsetof_ref, comp_tok->value,
- comp_tok->location);
- c_parser_consume_token (parser);
- }
- else
- {
- struct c_expr ce;
- tree idx;
- loc = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
- ce = c_parser_expression (parser);
- ce = convert_lvalue_to_rvalue (loc, ce, false, false);
- idx = ce.value;
- idx = c_fully_fold (idx, false, NULL);
- c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
- "expected %<]%>");
- offsetof_ref = build_array_ref (loc, offsetof_ref, idx);
- }
- }
- }
- else
- c_parser_error (parser, "expected identifier");
- location_t end_loc = c_parser_peek_token (parser)->get_finish ();
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>");
- expr.value = fold_offsetof (offsetof_ref);
- set_c_expr_source_range (&expr, loc, end_loc);
- }
- break;
- case RID_CHOOSE_EXPR:
- {
- vec<c_expr_t, va_gc> *cexpr_list;
- c_expr_t *e1_p, *e2_p, *e3_p;
- tree c;
- location_t close_paren_loc;
-
- c_parser_consume_token (parser);
- if (!c_parser_get_builtin_args (parser,
- "__builtin_choose_expr",
- &cexpr_list, true,
- &close_paren_loc))
- {
- expr.set_error ();
- break;
- }
-
- if (vec_safe_length (cexpr_list) != 3)
- {
- error_at (loc, "wrong number of arguments to "
- "%<__builtin_choose_expr%>");
- expr.set_error ();
- break;
- }
-
- e1_p = &(*cexpr_list)[0];
- e2_p = &(*cexpr_list)[1];
- e3_p = &(*cexpr_list)[2];
-
- c = e1_p->value;
- mark_exp_read (e2_p->value);
- mark_exp_read (e3_p->value);
- if (TREE_CODE (c) != INTEGER_CST
- || !INTEGRAL_TYPE_P (TREE_TYPE (c)))
- error_at (loc,
- "first argument to %<__builtin_choose_expr%> not"
- " a constant");
- constant_expression_warning (c);
- expr = integer_zerop (c) ? *e3_p : *e2_p;
- set_c_expr_source_range (&expr, loc, close_paren_loc);
- break;
- }
- case RID_TYPES_COMPATIBLE_P:
- {
- c_parser_consume_token (parser);
- matching_parens parens;
- if (!parens.require_open (parser))
- {
- expr.set_error ();
- break;
- }
- t1 = c_parser_type_name (parser);
- if (t1 == NULL)
- {
- expr.set_error ();
- break;
- }
- if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- expr.set_error ();
- break;
- }
- t2 = c_parser_type_name (parser);
- if (t2 == NULL)
- {
- expr.set_error ();
- break;
- }
- location_t close_paren_loc = c_parser_peek_token (parser)->location;
- parens.skip_until_found_close (parser);
- tree e1, e2;
- e1 = groktypename (t1, NULL, NULL);
- e2 = groktypename (t2, NULL, NULL);
- if (e1 == error_mark_node || e2 == error_mark_node)
- {
- expr.set_error ();
- break;
- }
-
- e1 = TYPE_MAIN_VARIANT (e1);
- e2 = TYPE_MAIN_VARIANT (e2);
-
- expr.value
- = comptypes (e1, e2) ? integer_one_node : integer_zero_node;
- set_c_expr_source_range (&expr, loc, close_paren_loc);
- }
- break;
- case RID_BUILTIN_TGMATH:
- {
- vec<c_expr_t, va_gc> *cexpr_list;
- location_t close_paren_loc;
-
- c_parser_consume_token (parser);
- if (!c_parser_get_builtin_args (parser,
- "__builtin_tgmath",
- &cexpr_list, false,
- &close_paren_loc))
- {
- expr.set_error ();
- break;
- }
-
- if (vec_safe_length (cexpr_list) < 3)
- {
- error_at (loc, "too few arguments to %<__builtin_tgmath%>");
- expr.set_error ();
- break;
- }
-
- unsigned int i;
- c_expr_t *p;
- FOR_EACH_VEC_ELT (*cexpr_list, i, p)
- *p = convert_lvalue_to_rvalue (loc, *p, true, true);
- unsigned int nargs = check_tgmath_function (&(*cexpr_list)[0], 1);
- if (nargs == 0)
- {
- expr.set_error ();
- break;
- }
- if (vec_safe_length (cexpr_list) < nargs)
- {
- error_at (loc, "too few arguments to %<__builtin_tgmath%>");
- expr.set_error ();
- break;
- }
- unsigned int num_functions = vec_safe_length (cexpr_list) - nargs;
- if (num_functions < 2)
- {
- error_at (loc, "too few arguments to %<__builtin_tgmath%>");
- expr.set_error ();
- break;
- }
-
- /* The first NUM_FUNCTIONS expressions are the function
- pointers. The remaining NARGS expressions are the
- arguments that are to be passed to one of those
- functions, chosen following <tgmath.h> rules. */
- for (unsigned int j = 1; j < num_functions; j++)
- {
- unsigned int this_nargs
- = check_tgmath_function (&(*cexpr_list)[j], j + 1);
- if (this_nargs == 0)
- {
- expr.set_error ();
- goto out;
- }
- if (this_nargs != nargs)
- {
- error_at ((*cexpr_list)[j].get_location (),
- "argument %u of %<__builtin_tgmath%> has "
- "wrong number of arguments", j + 1);
- expr.set_error ();
- goto out;
- }
- }
-
- /* The functions all have the same number of arguments.
- Determine whether arguments and return types vary in
- ways permitted for <tgmath.h> functions. */
- /* The first entry in each of these vectors is for the
- return type, subsequent entries for parameter
- types. */
- auto_vec<enum tgmath_parm_kind> parm_kind (nargs + 1);
- auto_vec<tree> parm_first (nargs + 1);
- auto_vec<bool> parm_complex (nargs + 1);
- auto_vec<bool> parm_varies (nargs + 1);
- tree first_type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[0].value));
- tree first_ret = TYPE_MAIN_VARIANT (TREE_TYPE (first_type));
- parm_first.quick_push (first_ret);
- parm_complex.quick_push (TREE_CODE (first_ret) == COMPLEX_TYPE);
- parm_varies.quick_push (false);
- function_args_iterator iter;
- tree t;
- unsigned int argpos;
- FOREACH_FUNCTION_ARGS (first_type, t, iter)
- {
- if (t == void_type_node)
- break;
- parm_first.quick_push (TYPE_MAIN_VARIANT (t));
- parm_complex.quick_push (TREE_CODE (t) == COMPLEX_TYPE);
- parm_varies.quick_push (false);
- }
- for (unsigned int j = 1; j < num_functions; j++)
- {
- tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value));
- tree ret = TYPE_MAIN_VARIANT (TREE_TYPE (type));
- if (ret != parm_first[0])
- {
- parm_varies[0] = true;
- if (!SCALAR_FLOAT_TYPE_P (parm_first[0])
- && !COMPLEX_FLOAT_TYPE_P (parm_first[0]))
- {
- error_at ((*cexpr_list)[0].get_location (),
- "invalid type-generic return type for "
- "argument %u of %<__builtin_tgmath%>",
- 1);
- expr.set_error ();
- goto out;
- }
- if (!SCALAR_FLOAT_TYPE_P (ret)
- && !COMPLEX_FLOAT_TYPE_P (ret))
- {
- error_at ((*cexpr_list)[j].get_location (),
- "invalid type-generic return type for "
- "argument %u of %<__builtin_tgmath%>",
- j + 1);
- expr.set_error ();
- goto out;
- }
- }
- if (TREE_CODE (ret) == COMPLEX_TYPE)
- parm_complex[0] = true;
- argpos = 1;
- FOREACH_FUNCTION_ARGS (type, t, iter)
- {
- if (t == void_type_node)
- break;
- t = TYPE_MAIN_VARIANT (t);
- if (t != parm_first[argpos])
- {
- parm_varies[argpos] = true;
- if (!SCALAR_FLOAT_TYPE_P (parm_first[argpos])
- && !COMPLEX_FLOAT_TYPE_P (parm_first[argpos]))
- {
- error_at ((*cexpr_list)[0].get_location (),
- "invalid type-generic type for "
- "argument %u of argument %u of "
- "%<__builtin_tgmath%>", argpos, 1);
- expr.set_error ();
- goto out;
- }
- if (!SCALAR_FLOAT_TYPE_P (t)
- && !COMPLEX_FLOAT_TYPE_P (t))
- {
- error_at ((*cexpr_list)[j].get_location (),
- "invalid type-generic type for "
- "argument %u of argument %u of "
- "%<__builtin_tgmath%>", argpos, j + 1);
- expr.set_error ();
- goto out;
- }
- }
- if (TREE_CODE (t) == COMPLEX_TYPE)
- parm_complex[argpos] = true;
- argpos++;
- }
- }
- enum tgmath_parm_kind max_variation = tgmath_fixed;
- for (unsigned int j = 0; j <= nargs; j++)
- {
- enum tgmath_parm_kind this_kind;
- if (parm_varies[j])
- {
- if (parm_complex[j])
- max_variation = this_kind = tgmath_complex;
- else
- {
- this_kind = tgmath_real;
- if (max_variation != tgmath_complex)
- max_variation = tgmath_real;
- }
- }
- else
- this_kind = tgmath_fixed;
- parm_kind.quick_push (this_kind);
- }
- if (max_variation == tgmath_fixed)
- {
- error_at (loc, "function arguments of %<__builtin_tgmath%> "
- "all have the same type");
- expr.set_error ();
- break;
- }
-
- /* Identify a parameter (not the return type) that varies,
- including with complex types if any variation includes
- complex types; there must be at least one such
- parameter. */
- unsigned int tgarg = 0;
- for (unsigned int j = 1; j <= nargs; j++)
- if (parm_kind[j] == max_variation)
- {
- tgarg = j;
- break;
- }
- if (tgarg == 0)
- {
- error_at (loc, "function arguments of %<__builtin_tgmath%> "
- "lack type-generic parameter");
- expr.set_error ();
- break;
- }
-
- /* Determine the type of the relevant parameter for each
- function. */
- auto_vec<tree> tg_type (num_functions);
- for (unsigned int j = 0; j < num_functions; j++)
- {
- tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value));
- argpos = 1;
- FOREACH_FUNCTION_ARGS (type, t, iter)
- {
- if (argpos == tgarg)
- {
- tg_type.quick_push (TYPE_MAIN_VARIANT (t));
- break;
- }
- argpos++;
- }
- }
-
- /* Verify that the corresponding types are different for
- all the listed functions. Also determine whether all
- the types are complex, whether all the types are
- standard or binary, and whether all the types are
- decimal. */
- bool all_complex = true;
- bool all_binary = true;
- bool all_decimal = true;
- hash_set<tree> tg_types;
- FOR_EACH_VEC_ELT (tg_type, i, t)
- {
- if (TREE_CODE (t) == COMPLEX_TYPE)
- all_decimal = false;
- else
- {
- all_complex = false;
- if (DECIMAL_FLOAT_TYPE_P (t))
- all_binary = false;
- else
- all_decimal = false;
- }
- if (tg_types.add (t))
- {
- error_at ((*cexpr_list)[i].get_location (),
- "duplicate type-generic parameter type for "
- "function argument %u of %<__builtin_tgmath%>",
- i + 1);
- expr.set_error ();
- goto out;
- }
- }
-
- /* Verify that other parameters and the return type whose
- types vary have their types varying in the correct
- way. */
- for (unsigned int j = 0; j < num_functions; j++)
- {
- tree exp_type = tg_type[j];
- tree exp_real_type = exp_type;
- if (TREE_CODE (exp_type) == COMPLEX_TYPE)
- exp_real_type = TREE_TYPE (exp_type);
- tree type = TREE_TYPE (TREE_TYPE ((*cexpr_list)[j].value));
- tree ret = TYPE_MAIN_VARIANT (TREE_TYPE (type));
- if ((parm_kind[0] == tgmath_complex && ret != exp_type)
- || (parm_kind[0] == tgmath_real && ret != exp_real_type))
- {
- error_at ((*cexpr_list)[j].get_location (),
- "bad return type for function argument %u "
- "of %<__builtin_tgmath%>", j + 1);
- expr.set_error ();
- goto out;
- }
- argpos = 1;
- FOREACH_FUNCTION_ARGS (type, t, iter)
- {
- if (t == void_type_node)
- break;
- t = TYPE_MAIN_VARIANT (t);
- if ((parm_kind[argpos] == tgmath_complex
- && t != exp_type)
- || (parm_kind[argpos] == tgmath_real
- && t != exp_real_type))
- {
- error_at ((*cexpr_list)[j].get_location (),
- "bad type for argument %u of "
- "function argument %u of "
- "%<__builtin_tgmath%>", argpos, j + 1);
- expr.set_error ();
- goto out;
- }
- argpos++;
- }
- }
-
- /* The functions listed are a valid set of functions for a
- <tgmath.h> macro to select between. Identify the
- matching function, if any. First, the argument types
- must be combined following <tgmath.h> rules. Integer
- types are treated as _Decimal64 if any type-generic
- argument is decimal, or if the only alternatives for
- type-generic arguments are of decimal types, and are
- otherwise treated as double (or _Complex double for
- complex integer types, or _Float64 or _Complex _Float64
- if all the return types are the same _FloatN or
- _FloatNx type). After that adjustment, types are
- combined following the usual arithmetic conversions.
- If the function only accepts complex arguments, a
- complex type is produced. */
- bool arg_complex = all_complex;
- bool arg_binary = all_binary;
- bool arg_int_decimal = all_decimal;
- for (unsigned int j = 1; j <= nargs; j++)
- {
- if (parm_kind[j] == tgmath_fixed)
- continue;
- c_expr_t *ce = &(*cexpr_list)[num_functions + j - 1];
- tree type = TREE_TYPE (ce->value);
- if (!INTEGRAL_TYPE_P (type)
- && !SCALAR_FLOAT_TYPE_P (type)
- && TREE_CODE (type) != COMPLEX_TYPE)
- {
- error_at (ce->get_location (),
- "invalid type of argument %u of type-generic "
- "function", j);
- expr.set_error ();
- goto out;
- }
- if (DECIMAL_FLOAT_TYPE_P (type))
- {
- arg_int_decimal = true;
- if (all_complex)
- {
- error_at (ce->get_location (),
- "decimal floating-point argument %u to "
- "complex-only type-generic function", j);
- expr.set_error ();
- goto out;
- }
- else if (all_binary)
- {
- error_at (ce->get_location (),
- "decimal floating-point argument %u to "
- "binary-only type-generic function", j);
- expr.set_error ();
- goto out;
- }
- else if (arg_complex)
- {
- error_at (ce->get_location (),
- "both complex and decimal floating-point "
- "arguments to type-generic function");
- expr.set_error ();
- goto out;
- }
- else if (arg_binary)
- {
- error_at (ce->get_location (),
- "both binary and decimal floating-point "
- "arguments to type-generic function");
- expr.set_error ();
- goto out;
- }
- }
- else if (TREE_CODE (type) == COMPLEX_TYPE)
- {
- arg_complex = true;
- if (COMPLEX_FLOAT_TYPE_P (type))
- arg_binary = true;
- if (all_decimal)
- {
- error_at (ce->get_location (),
- "complex argument %u to "
- "decimal-only type-generic function", j);
- expr.set_error ();
- goto out;
- }
- else if (arg_int_decimal)
- {
- error_at (ce->get_location (),
- "both complex and decimal floating-point "
- "arguments to type-generic function");
- expr.set_error ();
- goto out;
- }
- }
- else if (SCALAR_FLOAT_TYPE_P (type))
- {
- arg_binary = true;
- if (all_decimal)
- {
- error_at (ce->get_location (),
- "binary argument %u to "
- "decimal-only type-generic function", j);
- expr.set_error ();
- goto out;
- }
- else if (arg_int_decimal)
- {
- error_at (ce->get_location (),
- "both binary and decimal floating-point "
- "arguments to type-generic function");
- expr.set_error ();
- goto out;
- }
- }
- }
- /* For a macro rounding its result to a narrower type, map
- integer types to _Float64 not double if the return type
- is a _FloatN or _FloatNx type. */
- bool arg_int_float64 = false;
- if (parm_kind[0] == tgmath_fixed
- && SCALAR_FLOAT_TYPE_P (parm_first[0])
- && float64_type_node != NULL_TREE)
- for (unsigned int j = 0; j < NUM_FLOATN_NX_TYPES; j++)
- if (parm_first[0] == FLOATN_TYPE_NODE (j))
- {
- arg_int_float64 = true;
- break;
- }
- tree arg_real = NULL_TREE;
- for (unsigned int j = 1; j <= nargs; j++)
- {
- if (parm_kind[j] == tgmath_fixed)
- continue;
- c_expr_t *ce = &(*cexpr_list)[num_functions + j - 1];
- tree type = TYPE_MAIN_VARIANT (TREE_TYPE (ce->value));
- if (TREE_CODE (type) == COMPLEX_TYPE)
- type = TREE_TYPE (type);
- if (INTEGRAL_TYPE_P (type))
- type = (arg_int_decimal
- ? dfloat64_type_node
- : arg_int_float64
- ? float64_type_node
- : double_type_node);
- if (arg_real == NULL_TREE)
- arg_real = type;
- else
- arg_real = common_type (arg_real, type);
- if (arg_real == error_mark_node)
- {
- expr.set_error ();
- goto out;
- }
- }
- tree arg_type = (arg_complex
- ? build_complex_type (arg_real)
- : arg_real);
-
- /* Look for a function to call with type-generic parameter
- type ARG_TYPE. */
- c_expr_t *fn = NULL;
- for (unsigned int j = 0; j < num_functions; j++)
- {
- if (tg_type[j] == arg_type)
- {
- fn = &(*cexpr_list)[j];
- break;
- }
- }
- if (fn == NULL
- && parm_kind[0] == tgmath_fixed
- && SCALAR_FLOAT_TYPE_P (parm_first[0]))
- {
- /* Presume this is a macro that rounds its result to a
- narrower type, and look for the first function with
- at least the range and precision of the argument
- type. */
- for (unsigned int j = 0; j < num_functions; j++)
- {
- if (arg_complex
- != (TREE_CODE (tg_type[j]) == COMPLEX_TYPE))
- continue;
- tree real_tg_type = (arg_complex
- ? TREE_TYPE (tg_type[j])
- : tg_type[j]);
- if (DECIMAL_FLOAT_TYPE_P (arg_real)
- != DECIMAL_FLOAT_TYPE_P (real_tg_type))
- continue;
- scalar_float_mode arg_mode
- = SCALAR_FLOAT_TYPE_MODE (arg_real);
- scalar_float_mode tg_mode
- = SCALAR_FLOAT_TYPE_MODE (real_tg_type);
- const real_format *arg_fmt = REAL_MODE_FORMAT (arg_mode);
- const real_format *tg_fmt = REAL_MODE_FORMAT (tg_mode);
- if (arg_fmt->b == tg_fmt->b
- && arg_fmt->p <= tg_fmt->p
- && arg_fmt->emax <= tg_fmt->emax
- && (arg_fmt->emin - arg_fmt->p
- >= tg_fmt->emin - tg_fmt->p))
- {
- fn = &(*cexpr_list)[j];
- break;
- }
- }
- }
- if (fn == NULL)
- {
- error_at (loc, "no matching function for type-generic call");
- expr.set_error ();
- break;
- }
-
- /* Construct a call to FN. */
- vec<tree, va_gc> *args;
- vec_alloc (args, nargs);
- vec<tree, va_gc> *origtypes;
- vec_alloc (origtypes, nargs);
- auto_vec<location_t> arg_loc (nargs);
- for (unsigned int j = 0; j < nargs; j++)
- {
- c_expr_t *ce = &(*cexpr_list)[num_functions + j];
- args->quick_push (ce->value);
- arg_loc.quick_push (ce->get_location ());
- origtypes->quick_push (ce->original_type);
- }
- expr.value = c_build_function_call_vec (loc, arg_loc, fn->value,
- args, origtypes);
- set_c_expr_source_range (&expr, loc, close_paren_loc);
- break;
- }
- case RID_BUILTIN_CALL_WITH_STATIC_CHAIN:
- {
- vec<c_expr_t, va_gc> *cexpr_list;
- c_expr_t *e2_p;
- tree chain_value;
- location_t close_paren_loc;
-
- c_parser_consume_token (parser);
- if (!c_parser_get_builtin_args (parser,
- "__builtin_call_with_static_chain",
- &cexpr_list, false,
- &close_paren_loc))
- {
- expr.set_error ();
- break;
- }
- if (vec_safe_length (cexpr_list) != 2)
- {
- error_at (loc, "wrong number of arguments to "
- "%<__builtin_call_with_static_chain%>");
- expr.set_error ();
- break;
- }
-
- expr = (*cexpr_list)[0];
- e2_p = &(*cexpr_list)[1];
- *e2_p = convert_lvalue_to_rvalue (loc, *e2_p, true, true);
- chain_value = e2_p->value;
- mark_exp_read (chain_value);
-
- if (TREE_CODE (expr.value) != CALL_EXPR)
- error_at (loc, "first argument to "
- "%<__builtin_call_with_static_chain%> "
- "must be a call expression");
- else if (TREE_CODE (TREE_TYPE (chain_value)) != POINTER_TYPE)
- error_at (loc, "second argument to "
- "%<__builtin_call_with_static_chain%> "
- "must be a pointer type");
- else
- CALL_EXPR_STATIC_CHAIN (expr.value) = chain_value;
- set_c_expr_source_range (&expr, loc, close_paren_loc);
- break;
- }
- case RID_BUILTIN_COMPLEX:
- {
- vec<c_expr_t, va_gc> *cexpr_list;
- c_expr_t *e1_p, *e2_p;
- location_t close_paren_loc;
-
- c_parser_consume_token (parser);
- if (!c_parser_get_builtin_args (parser,
- "__builtin_complex",
- &cexpr_list, false,
- &close_paren_loc))
- {
- expr.set_error ();
- break;
- }
-
- if (vec_safe_length (cexpr_list) != 2)
- {
- error_at (loc, "wrong number of arguments to "
- "%<__builtin_complex%>");
- expr.set_error ();
- break;
- }
-
- e1_p = &(*cexpr_list)[0];
- e2_p = &(*cexpr_list)[1];
-
- *e1_p = convert_lvalue_to_rvalue (loc, *e1_p, true, true);
- if (TREE_CODE (e1_p->value) == EXCESS_PRECISION_EXPR)
- e1_p->value = convert (TREE_TYPE (e1_p->value),
- TREE_OPERAND (e1_p->value, 0));
- *e2_p = convert_lvalue_to_rvalue (loc, *e2_p, true, true);
- if (TREE_CODE (e2_p->value) == EXCESS_PRECISION_EXPR)
- e2_p->value = convert (TREE_TYPE (e2_p->value),
- TREE_OPERAND (e2_p->value, 0));
- if (!SCALAR_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
- || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e1_p->value))
- || !SCALAR_FLOAT_TYPE_P (TREE_TYPE (e2_p->value))
- || DECIMAL_FLOAT_TYPE_P (TREE_TYPE (e2_p->value)))
- {
- error_at (loc, "%<__builtin_complex%> operand "
- "not of real binary floating-point type");
- expr.set_error ();
- break;
- }
- if (TYPE_MAIN_VARIANT (TREE_TYPE (e1_p->value))
- != TYPE_MAIN_VARIANT (TREE_TYPE (e2_p->value)))
- {
- error_at (loc,
- "%<__builtin_complex%> operands of different types");
- expr.set_error ();
- break;
- }
- pedwarn_c90 (loc, OPT_Wpedantic,
- "ISO C90 does not support complex types");
- expr.value = build2_loc (loc, COMPLEX_EXPR,
- build_complex_type
- (TYPE_MAIN_VARIANT
- (TREE_TYPE (e1_p->value))),
- e1_p->value, e2_p->value);
- set_c_expr_source_range (&expr, loc, close_paren_loc);
- break;
- }
- case RID_BUILTIN_SHUFFLE:
- {
- vec<c_expr_t, va_gc> *cexpr_list;
- unsigned int i;
- c_expr_t *p;
- location_t close_paren_loc;
-
- c_parser_consume_token (parser);
- if (!c_parser_get_builtin_args (parser,
- "__builtin_shuffle",
- &cexpr_list, false,
- &close_paren_loc))
- {
- expr.set_error ();
- break;
- }
-
- FOR_EACH_VEC_SAFE_ELT (cexpr_list, i, p)
- *p = convert_lvalue_to_rvalue (loc, *p, true, true);
-
- if (vec_safe_length (cexpr_list) == 2)
- expr.value = c_build_vec_perm_expr (loc, (*cexpr_list)[0].value,
- NULL_TREE,
- (*cexpr_list)[1].value);
-
- else if (vec_safe_length (cexpr_list) == 3)
- expr.value = c_build_vec_perm_expr (loc, (*cexpr_list)[0].value,
- (*cexpr_list)[1].value,
- (*cexpr_list)[2].value);
- else
- {
- error_at (loc, "wrong number of arguments to "
- "%<__builtin_shuffle%>");
- expr.set_error ();
- }
- set_c_expr_source_range (&expr, loc, close_paren_loc);
- break;
- }
- case RID_BUILTIN_SHUFFLEVECTOR:
- {
- vec<c_expr_t, va_gc> *cexpr_list;
- unsigned int i;
- c_expr_t *p;
- location_t close_paren_loc;
-
- c_parser_consume_token (parser);
- if (!c_parser_get_builtin_args (parser,
- "__builtin_shufflevector",
- &cexpr_list, false,
- &close_paren_loc))
- {
- expr.set_error ();
- break;
- }
-
- FOR_EACH_VEC_SAFE_ELT (cexpr_list, i, p)
- *p = convert_lvalue_to_rvalue (loc, *p, true, true);
-
- if (vec_safe_length (cexpr_list) < 3)
- {
- error_at (loc, "wrong number of arguments to "
- "%<__builtin_shuffle%>");
- expr.set_error ();
- }
- else
- {
- auto_vec<tree, 16> mask;
- for (i = 2; i < cexpr_list->length (); ++i)
- mask.safe_push ((*cexpr_list)[i].value);
- expr.value = c_build_shufflevector (loc, (*cexpr_list)[0].value,
- (*cexpr_list)[1].value,
- mask);
- }
- set_c_expr_source_range (&expr, loc, close_paren_loc);
- break;
- }
- case RID_BUILTIN_CONVERTVECTOR:
- {
- location_t start_loc = loc;
- c_parser_consume_token (parser);
- matching_parens parens;
- if (!parens.require_open (parser))
- {
- expr.set_error ();
- break;
- }
- e1 = c_parser_expr_no_commas (parser, NULL);
- mark_exp_read (e1.value);
- if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- expr.set_error ();
- break;
- }
- loc = c_parser_peek_token (parser)->location;
- t1 = c_parser_type_name (parser);
- location_t end_loc = c_parser_peek_token (parser)->get_finish ();
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>");
- if (t1 == NULL)
- expr.set_error ();
- else
- {
- tree type_expr = NULL_TREE;
- expr.value = c_build_vec_convert (start_loc, e1.value, loc,
- groktypename (t1, &type_expr,
- NULL));
- set_c_expr_source_range (&expr, start_loc, end_loc);
- }
- }
- break;
- case RID_BUILTIN_ASSOC_BARRIER:
- {
- location_t start_loc = loc;
- c_parser_consume_token (parser);
- matching_parens parens;
- if (!parens.require_open (parser))
- {
- expr.set_error ();
- break;
- }
- e1 = c_parser_expr_no_commas (parser, NULL);
- mark_exp_read (e1.value);
- location_t end_loc = c_parser_peek_token (parser)->get_finish ();
- parens.skip_until_found_close (parser);
- expr.value = build1_loc (loc, PAREN_EXPR, TREE_TYPE (e1.value),
- e1.value);
- set_c_expr_source_range (&expr, start_loc, end_loc);
- }
- break;
- case RID_AT_SELECTOR:
- {
- gcc_assert (c_dialect_objc ());
- c_parser_consume_token (parser);
- matching_parens parens;
- if (!parens.require_open (parser))
- {
- expr.set_error ();
- break;
- }
- tree sel = c_parser_objc_selector_arg (parser);
- location_t close_loc = c_parser_peek_token (parser)->location;
- parens.skip_until_found_close (parser);
- expr.value = objc_build_selector_expr (loc, sel);
- set_c_expr_source_range (&expr, loc, close_loc);
- }
- break;
- case RID_AT_PROTOCOL:
- {
- gcc_assert (c_dialect_objc ());
- c_parser_consume_token (parser);
- matching_parens parens;
- if (!parens.require_open (parser))
- {
- expr.set_error ();
- break;
- }
- if (c_parser_next_token_is_not (parser, CPP_NAME))
- {
- c_parser_error (parser, "expected identifier");
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- expr.set_error ();
- break;
- }
- tree id = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- location_t close_loc = c_parser_peek_token (parser)->location;
- parens.skip_until_found_close (parser);
- expr.value = objc_build_protocol_expr (id);
- set_c_expr_source_range (&expr, loc, close_loc);
- }
- break;
- case RID_AT_ENCODE:
- {
- /* Extension to support C-structures in the archiver. */
- gcc_assert (c_dialect_objc ());
- c_parser_consume_token (parser);
- matching_parens parens;
- if (!parens.require_open (parser))
- {
- expr.set_error ();
- break;
- }
- t1 = c_parser_type_name (parser);
- if (t1 == NULL)
- {
- expr.set_error ();
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- break;
- }
- location_t close_loc = c_parser_peek_token (parser)->location;
- parens.skip_until_found_close (parser);
- tree type = groktypename (t1, NULL, NULL);
- expr.value = objc_build_encode_expr (type);
- set_c_expr_source_range (&expr, loc, close_loc);
- }
- break;
- case RID_GENERIC:
- expr = c_parser_generic_selection (parser);
- break;
- default:
- c_parser_error (parser, "expected expression");
- expr.set_error ();
- break;
- }
- break;
- case CPP_OPEN_SQUARE:
- if (c_dialect_objc ())
- {
- tree receiver, args;
- c_parser_consume_token (parser);
- receiver = c_parser_objc_receiver (parser);
- args = c_parser_objc_message_args (parser);
- location_t close_loc = c_parser_peek_token (parser)->location;
- c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
- "expected %<]%>");
- expr.value = objc_build_message_expr (receiver, args);
- set_c_expr_source_range (&expr, loc, close_loc);
- break;
- }
- /* Else fall through to report error. */
- /* FALLTHRU */
- default:
- c_parser_error (parser, "expected expression");
- expr.set_error ();
- break;
- }
- out:
- return c_parser_postfix_expression_after_primary
- (parser, EXPR_LOC_OR_LOC (expr.value, loc), expr);
-}
-
-/* Parse a postfix expression after a parenthesized type name: the
- brace-enclosed initializer of a compound literal, possibly followed
- by some postfix operators. This is separate because it is not
- possible to tell until after the type name whether a cast
- expression has a cast or a compound literal, or whether the operand
- of sizeof is a parenthesized type name or starts with a compound
- literal. TYPE_LOC is the location where TYPE_NAME starts--the
- location of the first token after the parentheses around the type
- name. */
-
-static struct c_expr
-c_parser_postfix_expression_after_paren_type (c_parser *parser,
- struct c_type_name *type_name,
- location_t type_loc)
-{
- tree type;
- struct c_expr init;
- bool non_const;
- struct c_expr expr;
- location_t start_loc;
- tree type_expr = NULL_TREE;
- bool type_expr_const = true;
- check_compound_literal_type (type_loc, type_name);
- rich_location richloc (line_table, type_loc);
- start_init (NULL_TREE, NULL, 0, &richloc);
- type = groktypename (type_name, &type_expr, &type_expr_const);
- start_loc = c_parser_peek_token (parser)->location;
- if (type != error_mark_node && C_TYPE_VARIABLE_SIZE (type))
- {
- error_at (type_loc, "compound literal has variable size");
- type = error_mark_node;
- }
- init = c_parser_braced_init (parser, type, false, NULL);
- finish_init ();
- maybe_warn_string_init (type_loc, type, init);
-
- if (type != error_mark_node
- && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type))
- && current_function_decl)
- {
- error ("compound literal qualified by address-space qualifier");
- type = error_mark_node;
- }
-
- pedwarn_c90 (start_loc, OPT_Wpedantic, "ISO C90 forbids compound literals");
- non_const = ((init.value && TREE_CODE (init.value) == CONSTRUCTOR)
- ? CONSTRUCTOR_NON_CONST (init.value)
- : init.original_code == C_MAYBE_CONST_EXPR);
- non_const |= !type_expr_const;
- unsigned int alignas_align = 0;
- if (type != error_mark_node
- && type_name->specs->align_log != -1)
- {
- alignas_align = 1U << type_name->specs->align_log;
- if (alignas_align < min_align_of_type (type))
- {
- error_at (type_name->specs->locations[cdw_alignas],
- "%<_Alignas%> specifiers cannot reduce "
- "alignment of compound literal");
- alignas_align = 0;
- }
- }
- expr.value = build_compound_literal (start_loc, type, init.value, non_const,
- alignas_align);
- set_c_expr_source_range (&expr, init.src_range);
- expr.original_code = ERROR_MARK;
- expr.original_type = NULL;
- if (type != error_mark_node
- && expr.value != error_mark_node
- && type_expr)
- {
- if (TREE_CODE (expr.value) == C_MAYBE_CONST_EXPR)
- {
- gcc_assert (C_MAYBE_CONST_EXPR_PRE (expr.value) == NULL_TREE);
- C_MAYBE_CONST_EXPR_PRE (expr.value) = type_expr;
- }
- else
- {
- gcc_assert (!non_const);
- expr.value = build2 (C_MAYBE_CONST_EXPR, type,
- type_expr, expr.value);
- }
- }
- return c_parser_postfix_expression_after_primary (parser, start_loc, expr);
-}
-
-/* Callback function for sizeof_pointer_memaccess_warning to compare
- types. */
-
-static bool
-sizeof_ptr_memacc_comptypes (tree type1, tree type2)
-{
- return comptypes (type1, type2) == 1;
-}
-
-/* Warn for patterns where abs-like function appears to be used incorrectly,
- gracefully ignore any non-abs-like function. The warning location should
- be LOC. FNDECL is the declaration of called function, it must be a
- BUILT_IN_NORMAL function. ARG is the first and only argument of the
- call. */
-
-static void
-warn_for_abs (location_t loc, tree fndecl, tree arg)
-{
- /* Avoid warning in unreachable subexpressions. */
- if (c_inhibit_evaluation_warnings)
- return;
-
- tree atype = TREE_TYPE (arg);
-
- /* Casts from pointers (and thus arrays and fndecls) will generate
- -Wint-conversion warnings. Most other wrong types hopefully lead to type
- mismatch errors. TODO: Think about what to do with FIXED_POINT_TYPE_P
- types and possibly other exotic types. */
- if (!INTEGRAL_TYPE_P (atype)
- && !SCALAR_FLOAT_TYPE_P (atype)
- && TREE_CODE (atype) != COMPLEX_TYPE)
- return;
-
- enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
-
- switch (fcode)
- {
- case BUILT_IN_ABS:
- case BUILT_IN_LABS:
- case BUILT_IN_LLABS:
- case BUILT_IN_IMAXABS:
- if (!INTEGRAL_TYPE_P (atype))
- {
- if (SCALAR_FLOAT_TYPE_P (atype))
- warning_at (loc, OPT_Wabsolute_value,
- "using integer absolute value function %qD when "
- "argument is of floating-point type %qT",
- fndecl, atype);
- else if (TREE_CODE (atype) == COMPLEX_TYPE)
- warning_at (loc, OPT_Wabsolute_value,
- "using integer absolute value function %qD when "
- "argument is of complex type %qT", fndecl, atype);
- else
- gcc_unreachable ();
- return;
- }
- if (TYPE_UNSIGNED (atype))
- warning_at (loc, OPT_Wabsolute_value,
- "taking the absolute value of unsigned type %qT "
- "has no effect", atype);
- break;
-
- CASE_FLT_FN (BUILT_IN_FABS):
- CASE_FLT_FN_FLOATN_NX (BUILT_IN_FABS):
- if (!SCALAR_FLOAT_TYPE_P (atype)
- || DECIMAL_FLOAT_MODE_P (TYPE_MODE (atype)))
- {
- if (INTEGRAL_TYPE_P (atype))
- warning_at (loc, OPT_Wabsolute_value,
- "using floating-point absolute value function %qD "
- "when argument is of integer type %qT", fndecl, atype);
- else if (DECIMAL_FLOAT_TYPE_P (atype))
- warning_at (loc, OPT_Wabsolute_value,
- "using floating-point absolute value function %qD "
- "when argument is of decimal floating-point type %qT",
- fndecl, atype);
- else if (TREE_CODE (atype) == COMPLEX_TYPE)
- warning_at (loc, OPT_Wabsolute_value,
- "using floating-point absolute value function %qD when "
- "argument is of complex type %qT", fndecl, atype);
- else
- gcc_unreachable ();
- return;
- }
- break;
-
- CASE_FLT_FN (BUILT_IN_CABS):
- if (TREE_CODE (atype) != COMPLEX_TYPE)
- {
- if (INTEGRAL_TYPE_P (atype))
- warning_at (loc, OPT_Wabsolute_value,
- "using complex absolute value function %qD when "
- "argument is of integer type %qT", fndecl, atype);
- else if (SCALAR_FLOAT_TYPE_P (atype))
- warning_at (loc, OPT_Wabsolute_value,
- "using complex absolute value function %qD when "
- "argument is of floating-point type %qT",
- fndecl, atype);
- else
- gcc_unreachable ();
-
- return;
- }
- break;
-
- case BUILT_IN_FABSD32:
- case BUILT_IN_FABSD64:
- case BUILT_IN_FABSD128:
- if (!DECIMAL_FLOAT_TYPE_P (atype))
- {
- if (INTEGRAL_TYPE_P (atype))
- warning_at (loc, OPT_Wabsolute_value,
- "using decimal floating-point absolute value "
- "function %qD when argument is of integer type %qT",
- fndecl, atype);
- else if (SCALAR_FLOAT_TYPE_P (atype))
- warning_at (loc, OPT_Wabsolute_value,
- "using decimal floating-point absolute value "
- "function %qD when argument is of floating-point "
- "type %qT", fndecl, atype);
- else if (TREE_CODE (atype) == COMPLEX_TYPE)
- warning_at (loc, OPT_Wabsolute_value,
- "using decimal floating-point absolute value "
- "function %qD when argument is of complex type %qT",
- fndecl, atype);
- else
- gcc_unreachable ();
- return;
- }
- break;
-
- default:
- return;
- }
-
- if (!TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
- return;
-
- tree ftype = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (fndecl)));
- if (TREE_CODE (atype) == COMPLEX_TYPE)
- {
- gcc_assert (TREE_CODE (ftype) == COMPLEX_TYPE);
- atype = TREE_TYPE (atype);
- ftype = TREE_TYPE (ftype);
- }
-
- if (TYPE_PRECISION (ftype) < TYPE_PRECISION (atype))
- warning_at (loc, OPT_Wabsolute_value,
- "absolute value function %qD given an argument of type %qT "
- "but has parameter of type %qT which may cause truncation "
- "of value", fndecl, atype, ftype);
-}
-
-
-/* Parse a postfix expression after the initial primary or compound
- literal; that is, parse a series of postfix operators.
-
- EXPR_LOC is the location of the primary expression. */
-
-static struct c_expr
-c_parser_postfix_expression_after_primary (c_parser *parser,
- location_t expr_loc,
- struct c_expr expr)
-{
- struct c_expr orig_expr;
- tree ident, idx;
- location_t sizeof_arg_loc[3], comp_loc;
- tree sizeof_arg[3];
- unsigned int literal_zero_mask;
- unsigned int i;
- vec<tree, va_gc> *exprlist;
- vec<tree, va_gc> *origtypes = NULL;
- vec<location_t> arg_loc = vNULL;
- location_t start;
- location_t finish;
-
- while (true)
- {
- location_t op_loc = c_parser_peek_token (parser)->location;
- switch (c_parser_peek_token (parser)->type)
- {
- case CPP_OPEN_SQUARE:
- /* Array reference. */
- c_parser_consume_token (parser);
- idx = c_parser_expression (parser).value;
- c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE,
- "expected %<]%>");
- start = expr.get_start ();
- finish = parser->tokens_buf[0].location;
- expr.value = build_array_ref (op_loc, expr.value, idx);
- set_c_expr_source_range (&expr, start, finish);
- expr.original_code = ERROR_MARK;
- expr.original_type = NULL;
- break;
- case CPP_OPEN_PAREN:
- /* Function call. */
- {
- matching_parens parens;
- parens.consume_open (parser);
- for (i = 0; i < 3; i++)
- {
- sizeof_arg[i] = NULL_TREE;
- sizeof_arg_loc[i] = UNKNOWN_LOCATION;
- }
- literal_zero_mask = 0;
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- exprlist = NULL;
- else
- exprlist = c_parser_expr_list (parser, true, false, &origtypes,
- sizeof_arg_loc, sizeof_arg,
- &arg_loc, &literal_zero_mask);
- parens.skip_until_found_close (parser);
- }
- orig_expr = expr;
- mark_exp_read (expr.value);
- if (warn_sizeof_pointer_memaccess)
- sizeof_pointer_memaccess_warning (sizeof_arg_loc,
- expr.value, exprlist,
- sizeof_arg,
- sizeof_ptr_memacc_comptypes);
- if (TREE_CODE (expr.value) == FUNCTION_DECL)
- {
- if (fndecl_built_in_p (expr.value, BUILT_IN_MEMSET)
- && vec_safe_length (exprlist) == 3)
- {
- tree arg0 = (*exprlist)[0];
- tree arg2 = (*exprlist)[2];
- warn_for_memset (expr_loc, arg0, arg2, literal_zero_mask);
- }
- if (warn_absolute_value
- && fndecl_built_in_p (expr.value, BUILT_IN_NORMAL)
- && vec_safe_length (exprlist) == 1)
- warn_for_abs (expr_loc, expr.value, (*exprlist)[0]);
- }
-
- start = expr.get_start ();
- finish = parser->tokens_buf[0].get_finish ();
- expr.value
- = c_build_function_call_vec (expr_loc, arg_loc, expr.value,
- exprlist, origtypes);
- set_c_expr_source_range (&expr, start, finish);
-
- expr.original_code = ERROR_MARK;
- if (TREE_CODE (expr.value) == INTEGER_CST
- && TREE_CODE (orig_expr.value) == FUNCTION_DECL
- && fndecl_built_in_p (orig_expr.value, BUILT_IN_CONSTANT_P))
- expr.original_code = C_MAYBE_CONST_EXPR;
- expr.original_type = NULL;
- if (exprlist)
- {
- release_tree_vector (exprlist);
- release_tree_vector (origtypes);
- }
- arg_loc.release ();
- break;
- case CPP_DOT:
- /* Structure element reference. */
- c_parser_consume_token (parser);
- expr = default_function_array_conversion (expr_loc, expr);
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- c_token *comp_tok = c_parser_peek_token (parser);
- ident = comp_tok->value;
- comp_loc = comp_tok->location;
- }
- else
- {
- c_parser_error (parser, "expected identifier");
- expr.set_error ();
- expr.original_code = ERROR_MARK;
- expr.original_type = NULL;
- return expr;
- }
- start = expr.get_start ();
- finish = c_parser_peek_token (parser)->get_finish ();
- c_parser_consume_token (parser);
- expr.value = build_component_ref (op_loc, expr.value, ident,
- comp_loc);
- set_c_expr_source_range (&expr, start, finish);
- expr.original_code = ERROR_MARK;
- if (TREE_CODE (expr.value) != COMPONENT_REF)
- expr.original_type = NULL;
- else
- {
- /* Remember the original type of a bitfield. */
- tree field = TREE_OPERAND (expr.value, 1);
- if (TREE_CODE (field) != FIELD_DECL)
- expr.original_type = NULL;
- else
- expr.original_type = DECL_BIT_FIELD_TYPE (field);
- }
- break;
- case CPP_DEREF:
- /* Structure element reference. */
- c_parser_consume_token (parser);
- expr = convert_lvalue_to_rvalue (expr_loc, expr, true, false);
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- c_token *comp_tok = c_parser_peek_token (parser);
- ident = comp_tok->value;
- comp_loc = comp_tok->location;
- }
- else
- {
- c_parser_error (parser, "expected identifier");
- expr.set_error ();
- expr.original_code = ERROR_MARK;
- expr.original_type = NULL;
- return expr;
- }
- start = expr.get_start ();
- finish = c_parser_peek_token (parser)->get_finish ();
- c_parser_consume_token (parser);
- expr.value = build_component_ref (op_loc,
- build_indirect_ref (op_loc,
- expr.value,
- RO_ARROW),
- ident, comp_loc);
- set_c_expr_source_range (&expr, start, finish);
- expr.original_code = ERROR_MARK;
- if (TREE_CODE (expr.value) != COMPONENT_REF)
- expr.original_type = NULL;
- else
- {
- /* Remember the original type of a bitfield. */
- tree field = TREE_OPERAND (expr.value, 1);
- if (TREE_CODE (field) != FIELD_DECL)
- expr.original_type = NULL;
- else
- expr.original_type = DECL_BIT_FIELD_TYPE (field);
- }
- break;
- case CPP_PLUS_PLUS:
- /* Postincrement. */
- start = expr.get_start ();
- finish = c_parser_peek_token (parser)->get_finish ();
- c_parser_consume_token (parser);
- expr = default_function_array_read_conversion (expr_loc, expr);
- expr.value = build_unary_op (op_loc, POSTINCREMENT_EXPR,
- expr.value, false);
- set_c_expr_source_range (&expr, start, finish);
- expr.original_code = ERROR_MARK;
- expr.original_type = NULL;
- break;
- case CPP_MINUS_MINUS:
- /* Postdecrement. */
- start = expr.get_start ();
- finish = c_parser_peek_token (parser)->get_finish ();
- c_parser_consume_token (parser);
- expr = default_function_array_read_conversion (expr_loc, expr);
- expr.value = build_unary_op (op_loc, POSTDECREMENT_EXPR,
- expr.value, false);
- set_c_expr_source_range (&expr, start, finish);
- expr.original_code = ERROR_MARK;
- expr.original_type = NULL;
- break;
- default:
- return expr;
- }
- }
-}
-
-/* Parse an expression (C90 6.3.17, C99 6.5.17, C11 6.5.17).
-
- expression:
- assignment-expression
- expression , assignment-expression
-*/
-
-static struct c_expr
-c_parser_expression (c_parser *parser)
-{
- location_t tloc = c_parser_peek_token (parser)->location;
- struct c_expr expr;
- expr = c_parser_expr_no_commas (parser, NULL);
- if (c_parser_next_token_is (parser, CPP_COMMA))
- expr = convert_lvalue_to_rvalue (tloc, expr, true, false);
- while (c_parser_next_token_is (parser, CPP_COMMA))
- {
- struct c_expr next;
- tree lhsval;
- location_t loc = c_parser_peek_token (parser)->location;
- location_t expr_loc;
- c_parser_consume_token (parser);
- expr_loc = c_parser_peek_token (parser)->location;
- lhsval = expr.value;
- while (TREE_CODE (lhsval) == COMPOUND_EXPR
- || TREE_CODE (lhsval) == NOP_EXPR)
- {
- if (TREE_CODE (lhsval) == COMPOUND_EXPR)
- lhsval = TREE_OPERAND (lhsval, 1);
- else
- lhsval = TREE_OPERAND (lhsval, 0);
- }
- if (DECL_P (lhsval) || handled_component_p (lhsval))
- mark_exp_read (lhsval);
- next = c_parser_expr_no_commas (parser, NULL);
- next = convert_lvalue_to_rvalue (expr_loc, next, true, false);
- expr.value = build_compound_expr (loc, expr.value, next.value);
- expr.original_code = COMPOUND_EXPR;
- expr.original_type = next.original_type;
- }
- return expr;
-}
-
-/* Parse an expression and convert functions or arrays to pointers and
- lvalues to rvalues. */
-
-static struct c_expr
-c_parser_expression_conv (c_parser *parser)
-{
- struct c_expr expr;
- location_t loc = c_parser_peek_token (parser)->location;
- expr = c_parser_expression (parser);
- expr = convert_lvalue_to_rvalue (loc, expr, true, false);
- return expr;
-}
-
-/* Helper function of c_parser_expr_list. Check if IDXth (0 based)
- argument is a literal zero alone and if so, set it in literal_zero_mask. */
-
-static inline void
-c_parser_check_literal_zero (c_parser *parser, unsigned *literal_zero_mask,
- unsigned int idx)
-{
- if (idx >= HOST_BITS_PER_INT)
- return;
-
- c_token *tok = c_parser_peek_token (parser);
- switch (tok->type)
- {
- case CPP_NUMBER:
- case CPP_CHAR:
- case CPP_WCHAR:
- case CPP_CHAR16:
- case CPP_CHAR32:
- case CPP_UTF8CHAR:
- /* If a parameter is literal zero alone, remember it
- for -Wmemset-transposed-args warning. */
- if (integer_zerop (tok->value)
- && !TREE_OVERFLOW (tok->value)
- && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
- || c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_PAREN))
- *literal_zero_mask |= 1U << idx;
- default:
- break;
- }
-}
-
-/* Parse a non-empty list of expressions. If CONVERT_P, convert
- functions and arrays to pointers and lvalues to rvalues. If
- FOLD_P, fold the expressions. If LOCATIONS is non-NULL, save the
- locations of function arguments into this vector.
-
- nonempty-expr-list:
- assignment-expression
- nonempty-expr-list , assignment-expression
-*/
-
-static vec<tree, va_gc> *
-c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
- vec<tree, va_gc> **p_orig_types,
- location_t *sizeof_arg_loc, tree *sizeof_arg,
- vec<location_t> *locations,
- unsigned int *literal_zero_mask)
-{
- vec<tree, va_gc> *ret;
- vec<tree, va_gc> *orig_types;
- struct c_expr expr;
- unsigned int idx = 0;
-
- ret = make_tree_vector ();
- if (p_orig_types == NULL)
- orig_types = NULL;
- else
- orig_types = make_tree_vector ();
-
- if (literal_zero_mask)
- c_parser_check_literal_zero (parser, literal_zero_mask, 0);
- expr = c_parser_expr_no_commas (parser, NULL);
- if (convert_p)
- expr = convert_lvalue_to_rvalue (expr.get_location (), expr, true, true);
- if (fold_p)
- expr.value = c_fully_fold (expr.value, false, NULL);
- ret->quick_push (expr.value);
- if (orig_types)
- orig_types->quick_push (expr.original_type);
- if (locations)
- locations->safe_push (expr.get_location ());
- if (sizeof_arg != NULL
- && (expr.original_code == SIZEOF_EXPR
- || expr.original_code == PAREN_SIZEOF_EXPR))
- {
- sizeof_arg[0] = c_last_sizeof_arg;
- sizeof_arg_loc[0] = c_last_sizeof_loc;
- }
- while (c_parser_next_token_is (parser, CPP_COMMA))
- {
- c_parser_consume_token (parser);
- if (literal_zero_mask)
- c_parser_check_literal_zero (parser, literal_zero_mask, idx + 1);
- expr = c_parser_expr_no_commas (parser, NULL);
- if (convert_p)
- expr = convert_lvalue_to_rvalue (expr.get_location (), expr, true,
- true);
- if (fold_p)
- expr.value = c_fully_fold (expr.value, false, NULL);
- vec_safe_push (ret, expr.value);
- if (orig_types)
- vec_safe_push (orig_types, expr.original_type);
- if (locations)
- locations->safe_push (expr.get_location ());
- if (++idx < 3
- && sizeof_arg != NULL
- && (expr.original_code == SIZEOF_EXPR
- || expr.original_code == PAREN_SIZEOF_EXPR))
- {
- sizeof_arg[idx] = c_last_sizeof_arg;
- sizeof_arg_loc[idx] = c_last_sizeof_loc;
- }
- }
- if (orig_types)
- *p_orig_types = orig_types;
- return ret;
-}
-
-/* Parse Objective-C-specific constructs. */
-
-/* Parse an objc-class-definition.
-
- objc-class-definition:
- @interface identifier objc-superclass[opt] objc-protocol-refs[opt]
- objc-class-instance-variables[opt] objc-methodprotolist @end
- @implementation identifier objc-superclass[opt]
- objc-class-instance-variables[opt]
- @interface identifier ( identifier ) objc-protocol-refs[opt]
- objc-methodprotolist @end
- @interface identifier ( ) objc-protocol-refs[opt]
- objc-methodprotolist @end
- @implementation identifier ( identifier )
-
- objc-superclass:
- : identifier
-
- "@interface identifier (" must start "@interface identifier (
- identifier ) ...": objc-methodprotolist in the first production may
- not start with a parenthesized identifier as a declarator of a data
- definition with no declaration specifiers if the objc-superclass,
- objc-protocol-refs and objc-class-instance-variables are omitted. */
-
-static void
-c_parser_objc_class_definition (c_parser *parser, tree attributes)
-{
- bool iface_p;
- tree id1;
- tree superclass;
- if (c_parser_next_token_is_keyword (parser, RID_AT_INTERFACE))
- iface_p = true;
- else if (c_parser_next_token_is_keyword (parser, RID_AT_IMPLEMENTATION))
- iface_p = false;
- else
- gcc_unreachable ();
-
- c_parser_consume_token (parser);
- if (c_parser_next_token_is_not (parser, CPP_NAME))
- {
- c_parser_error (parser, "expected identifier");
- return;
- }
- id1 = c_parser_peek_token (parser)->value;
- location_t loc1 = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
- {
- /* We have a category or class extension. */
- tree id2;
- tree proto = NULL_TREE;
- matching_parens parens;
- parens.consume_open (parser);
- if (c_parser_next_token_is_not (parser, CPP_NAME))
- {
- if (iface_p && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- {
- /* We have a class extension. */
- id2 = NULL_TREE;
- }
- else
- {
- c_parser_error (parser, "expected identifier or %<)%>");
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- return;
- }
- }
- else
- {
- id2 = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- }
- parens.skip_until_found_close (parser);
- if (!iface_p)
- {
- objc_start_category_implementation (id1, id2);
- return;
- }
- if (c_parser_next_token_is (parser, CPP_LESS))
- proto = c_parser_objc_protocol_refs (parser);
- objc_start_category_interface (id1, id2, proto, attributes);
- c_parser_objc_methodprotolist (parser);
- c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
- objc_finish_interface ();
- return;
- }
- if (c_parser_next_token_is (parser, CPP_COLON))
- {
- c_parser_consume_token (parser);
- if (c_parser_next_token_is_not (parser, CPP_NAME))
- {
- c_parser_error (parser, "expected identifier");
- return;
- }
- superclass = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- }
- else
- superclass = NULL_TREE;
- if (iface_p)
- {
- tree proto = NULL_TREE;
- if (c_parser_next_token_is (parser, CPP_LESS))
- proto = c_parser_objc_protocol_refs (parser);
- objc_start_class_interface (id1, loc1, superclass, proto, attributes);
- }
- else
- objc_start_class_implementation (id1, superclass);
- if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
- c_parser_objc_class_instance_variables (parser);
- if (iface_p)
- {
- objc_continue_interface ();
- c_parser_objc_methodprotolist (parser);
- c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
- objc_finish_interface ();
- }
- else
- {
- objc_continue_implementation ();
- return;
- }
-}
-
-/* Parse objc-class-instance-variables.
-
- objc-class-instance-variables:
- { objc-instance-variable-decl-list[opt] }
-
- objc-instance-variable-decl-list:
- objc-visibility-spec
- objc-instance-variable-decl ;
- ;
- objc-instance-variable-decl-list objc-visibility-spec
- objc-instance-variable-decl-list objc-instance-variable-decl ;
- objc-instance-variable-decl-list ;
-
- objc-visibility-spec:
- @private
- @protected
- @public
-
- objc-instance-variable-decl:
- struct-declaration
-*/
-
-static void
-c_parser_objc_class_instance_variables (c_parser *parser)
-{
- gcc_assert (c_parser_next_token_is (parser, CPP_OPEN_BRACE));
- c_parser_consume_token (parser);
- while (c_parser_next_token_is_not (parser, CPP_EOF))
- {
- tree decls;
- /* Parse any stray semicolon. */
- if (c_parser_next_token_is (parser, CPP_SEMICOLON))
- {
- pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
- "extra semicolon");
- c_parser_consume_token (parser);
- continue;
- }
- /* Stop if at the end of the instance variables. */
- if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
- {
- c_parser_consume_token (parser);
- break;
- }
- /* Parse any objc-visibility-spec. */
- if (c_parser_next_token_is_keyword (parser, RID_AT_PRIVATE))
- {
- c_parser_consume_token (parser);
- objc_set_visibility (OBJC_IVAR_VIS_PRIVATE);
- continue;
- }
- else if (c_parser_next_token_is_keyword (parser, RID_AT_PROTECTED))
- {
- c_parser_consume_token (parser);
- objc_set_visibility (OBJC_IVAR_VIS_PROTECTED);
- continue;
- }
- else if (c_parser_next_token_is_keyword (parser, RID_AT_PUBLIC))
- {
- c_parser_consume_token (parser);
- objc_set_visibility (OBJC_IVAR_VIS_PUBLIC);
- continue;
- }
- else if (c_parser_next_token_is_keyword (parser, RID_AT_PACKAGE))
- {
- c_parser_consume_token (parser);
- objc_set_visibility (OBJC_IVAR_VIS_PACKAGE);
- continue;
- }
- else if (c_parser_next_token_is (parser, CPP_PRAGMA))
- {
- c_parser_pragma (parser, pragma_external, NULL);
- continue;
- }
-
- /* Parse some comma-separated declarations. */
- decls = c_parser_struct_declaration (parser);
- if (decls == NULL)
- {
- /* There is a syntax error. We want to skip the offending
- tokens up to the next ';' (included) or '}'
- (excluded). */
-
- /* First, skip manually a ')' or ']'. This is because they
- reduce the nesting level, so c_parser_skip_until_found()
- wouldn't be able to skip past them. */
- c_token *token = c_parser_peek_token (parser);
- if (token->type == CPP_CLOSE_PAREN || token->type == CPP_CLOSE_SQUARE)
- c_parser_consume_token (parser);
-
- /* Then, do the standard skipping. */
- c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
-
- /* We hopefully recovered. Start normal parsing again. */
- parser->error = false;
- continue;
- }
- else
- {
- /* Comma-separated instance variables are chained together
- in reverse order; add them one by one. */
- tree ivar = nreverse (decls);
- for (; ivar; ivar = DECL_CHAIN (ivar))
- objc_add_instance_variable (copy_node (ivar));
- }
- c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
- }
-}
-
-/* Parse an objc-class-declaration.
-
- objc-class-declaration:
- @class identifier-list ;
-*/
-
-static void
-c_parser_objc_class_declaration (c_parser *parser)
-{
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_CLASS));
- c_parser_consume_token (parser);
- /* Any identifiers, including those declared as type names, are OK
- here. */
- while (true)
- {
- tree id;
- if (c_parser_next_token_is_not (parser, CPP_NAME))
- {
- c_parser_error (parser, "expected identifier");
- c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
- parser->error = false;
- return;
- }
- id = c_parser_peek_token (parser)->value;
- objc_declare_class (id);
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
- else
- break;
- }
- c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-}
-
-/* Parse an objc-alias-declaration.
-
- objc-alias-declaration:
- @compatibility_alias identifier identifier ;
-*/
-
-static void
-c_parser_objc_alias_declaration (c_parser *parser)
-{
- tree id1, id2;
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_ALIAS));
- c_parser_consume_token (parser);
- if (c_parser_next_token_is_not (parser, CPP_NAME))
- {
- c_parser_error (parser, "expected identifier");
- c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
- return;
- }
- id1 = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- if (c_parser_next_token_is_not (parser, CPP_NAME))
- {
- c_parser_error (parser, "expected identifier");
- c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
- return;
- }
- id2 = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
- objc_declare_alias (id1, id2);
-}
-
-/* Parse an objc-protocol-definition.
-
- objc-protocol-definition:
- @protocol identifier objc-protocol-refs[opt] objc-methodprotolist @end
- @protocol identifier-list ;
-
- "@protocol identifier ;" should be resolved as "@protocol
- identifier-list ;": objc-methodprotolist may not start with a
- semicolon in the first alternative if objc-protocol-refs are
- omitted. */
-
-static void
-c_parser_objc_protocol_definition (c_parser *parser, tree attributes)
-{
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROTOCOL));
-
- c_parser_consume_token (parser);
- if (c_parser_next_token_is_not (parser, CPP_NAME))
- {
- c_parser_error (parser, "expected identifier");
- return;
- }
- if (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
- || c_parser_peek_2nd_token (parser)->type == CPP_SEMICOLON)
- {
- /* Any identifiers, including those declared as type names, are
- OK here. */
- while (true)
- {
- tree id;
- if (c_parser_next_token_is_not (parser, CPP_NAME))
- {
- c_parser_error (parser, "expected identifier");
- break;
- }
- id = c_parser_peek_token (parser)->value;
- objc_declare_protocol (id, attributes);
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
- else
- break;
- }
- c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
- }
- else
- {
- tree id = c_parser_peek_token (parser)->value;
- tree proto = NULL_TREE;
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_LESS))
- proto = c_parser_objc_protocol_refs (parser);
- parser->objc_pq_context = true;
- objc_start_protocol (id, proto, attributes);
- c_parser_objc_methodprotolist (parser);
- c_parser_require_keyword (parser, RID_AT_END, "expected %<@end%>");
- parser->objc_pq_context = false;
- objc_finish_interface ();
- }
-}
-
-/* Parse an objc-method-type.
-
- objc-method-type:
- +
- -
-
- Return true if it is a class method (+) and false if it is
- an instance method (-).
-*/
-static inline bool
-c_parser_objc_method_type (c_parser *parser)
-{
- switch (c_parser_peek_token (parser)->type)
- {
- case CPP_PLUS:
- c_parser_consume_token (parser);
- return true;
- case CPP_MINUS:
- c_parser_consume_token (parser);
- return false;
- default:
- gcc_unreachable ();
- }
-}
-
-/* Parse an objc-method-definition.
-
- objc-method-definition:
- objc-method-type objc-method-decl ;[opt] compound-statement
-*/
-
-static void
-c_parser_objc_method_definition (c_parser *parser)
-{
- bool is_class_method = c_parser_objc_method_type (parser);
- tree decl, attributes = NULL_TREE, expr = NULL_TREE;
- parser->objc_pq_context = true;
- decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
- &expr);
- if (decl == error_mark_node)
- return; /* Bail here. */
-
- if (c_parser_next_token_is (parser, CPP_SEMICOLON))
- {
- c_parser_consume_token (parser);
- pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
- "extra semicolon in method definition specified");
- }
-
- if (!c_parser_next_token_is (parser, CPP_OPEN_BRACE))
- {
- c_parser_error (parser, "expected %<{%>");
- return;
- }
-
- parser->objc_pq_context = false;
- if (objc_start_method_definition (is_class_method, decl, attributes, expr))
- {
- add_stmt (c_parser_compound_statement (parser));
- objc_finish_method_definition (current_function_decl);
- }
- else
- {
- /* This code is executed when we find a method definition
- outside of an @implementation context (or invalid for other
- reasons). Parse the method (to keep going) but do not emit
- any code.
- */
- c_parser_compound_statement (parser);
- }
-}
-
-/* Parse an objc-methodprotolist.
-
- objc-methodprotolist:
- empty
- objc-methodprotolist objc-methodproto
- objc-methodprotolist declaration
- objc-methodprotolist ;
- @optional
- @required
-
- The declaration is a data definition, which may be missing
- declaration specifiers under the same rules and diagnostics as
- other data definitions outside functions, and the stray semicolon
- is diagnosed the same way as a stray semicolon outside a
- function. */
-
-static void
-c_parser_objc_methodprotolist (c_parser *parser)
-{
- while (true)
- {
- /* The list is terminated by @end. */
- switch (c_parser_peek_token (parser)->type)
- {
- case CPP_SEMICOLON:
- pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
- "ISO C does not allow extra %<;%> outside of a function");
- c_parser_consume_token (parser);
- break;
- case CPP_PLUS:
- case CPP_MINUS:
- c_parser_objc_methodproto (parser);
- break;
- case CPP_PRAGMA:
- c_parser_pragma (parser, pragma_external, NULL);
- break;
- case CPP_EOF:
- return;
- default:
- if (c_parser_next_token_is_keyword (parser, RID_AT_END))
- return;
- else if (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY))
- c_parser_objc_at_property_declaration (parser);
- else if (c_parser_next_token_is_keyword (parser, RID_AT_OPTIONAL))
- {
- objc_set_method_opt (true);
- c_parser_consume_token (parser);
- }
- else if (c_parser_next_token_is_keyword (parser, RID_AT_REQUIRED))
- {
- objc_set_method_opt (false);
- c_parser_consume_token (parser);
- }
- else
- c_parser_declaration_or_fndef (parser, false, false, true,
- false, true);
- break;
- }
- }
-}
-
-/* Parse an objc-methodproto.
-
- objc-methodproto:
- objc-method-type objc-method-decl ;
-*/
-
-static void
-c_parser_objc_methodproto (c_parser *parser)
-{
- bool is_class_method = c_parser_objc_method_type (parser);
- tree decl, attributes = NULL_TREE;
-
- /* Remember protocol qualifiers in prototypes. */
- parser->objc_pq_context = true;
- decl = c_parser_objc_method_decl (parser, is_class_method, &attributes,
- NULL);
- /* Forget protocol qualifiers now. */
- parser->objc_pq_context = false;
-
- /* Do not allow the presence of attributes to hide an erroneous
- method implementation in the interface section. */
- if (!c_parser_next_token_is (parser, CPP_SEMICOLON))
- {
- c_parser_error (parser, "expected %<;%>");
- return;
- }
-
- if (decl != error_mark_node)
- objc_add_method_declaration (is_class_method, decl, attributes);
-
- c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-}
-
-/* If we are at a position that method attributes may be present, check that
- there are not any parsed already (a syntax error) and then collect any
- specified at the current location. Finally, if new attributes were present,
- check that the next token is legal ( ';' for decls and '{' for defs). */
-
-static bool
-c_parser_objc_maybe_method_attributes (c_parser* parser, tree* attributes)
-{
- bool bad = false;
- if (*attributes)
- {
- c_parser_error (parser,
- "method attributes must be specified at the end only");
- *attributes = NULL_TREE;
- bad = true;
- }
-
- if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
- *attributes = c_parser_gnu_attributes (parser);
-
- /* If there were no attributes here, just report any earlier error. */
- if (*attributes == NULL_TREE || bad)
- return bad;
-
- /* If the attributes are followed by a ; or {, then just report any earlier
- error. */
- if (c_parser_next_token_is (parser, CPP_SEMICOLON)
- || c_parser_next_token_is (parser, CPP_OPEN_BRACE))
- return bad;
-
- /* We've got attributes, but not at the end. */
- c_parser_error (parser,
- "expected %<;%> or %<{%> after method attribute definition");
- return true;
-}
-
-/* Parse an objc-method-decl.
-
- objc-method-decl:
- ( objc-type-name ) objc-selector
- objc-selector
- ( objc-type-name ) objc-keyword-selector objc-optparmlist
- objc-keyword-selector objc-optparmlist
- gnu-attributes
-
- objc-keyword-selector:
- objc-keyword-decl
- objc-keyword-selector objc-keyword-decl
-
- objc-keyword-decl:
- objc-selector : ( objc-type-name ) identifier
- objc-selector : identifier
- : ( objc-type-name ) identifier
- : identifier
-
- objc-optparmlist:
- objc-optparms objc-optellipsis
-
- objc-optparms:
- empty
- objc-opt-parms , parameter-declaration
-
- objc-optellipsis:
- empty
- , ...
-*/
-
-static tree
-c_parser_objc_method_decl (c_parser *parser, bool is_class_method,
- tree *attributes, tree *expr)
-{
- tree type = NULL_TREE;
- tree sel;
- tree parms = NULL_TREE;
- bool ellipsis = false;
- bool attr_err = false;
-
- *attributes = NULL_TREE;
- if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
- {
- matching_parens parens;
- parens.consume_open (parser);
- type = c_parser_objc_type_name (parser);
- parens.skip_until_found_close (parser);
- }
- sel = c_parser_objc_selector (parser);
- /* If there is no selector, or a colon follows, we have an
- objc-keyword-selector. If there is a selector, and a colon does
- not follow, that selector ends the objc-method-decl. */
- if (!sel || c_parser_next_token_is (parser, CPP_COLON))
- {
- tree tsel = sel;
- tree list = NULL_TREE;
- while (true)
- {
- tree atype = NULL_TREE, id, keyworddecl;
- tree param_attr = NULL_TREE;
- if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
- break;
- if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
- {
- c_parser_consume_token (parser);
- atype = c_parser_objc_type_name (parser);
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>");
- }
- /* New ObjC allows attributes on method parameters. */
- if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
- param_attr = c_parser_gnu_attributes (parser);
- if (c_parser_next_token_is_not (parser, CPP_NAME))
- {
- c_parser_error (parser, "expected identifier");
- return error_mark_node;
- }
- id = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- keyworddecl = objc_build_keyword_decl (tsel, atype, id, param_attr);
- list = chainon (list, keyworddecl);
- tsel = c_parser_objc_selector (parser);
- if (!tsel && c_parser_next_token_is_not (parser, CPP_COLON))
- break;
- }
-
- attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
-
- /* Parse the optional parameter list. Optional Objective-C
- method parameters follow the C syntax, and may include '...'
- to denote a variable number of arguments. */
- parms = make_node (TREE_LIST);
- while (c_parser_next_token_is (parser, CPP_COMMA))
- {
- struct c_parm *parm;
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
- {
- ellipsis = true;
- c_parser_consume_token (parser);
- attr_err |= c_parser_objc_maybe_method_attributes
- (parser, attributes) ;
- break;
- }
- parm = c_parser_parameter_declaration (parser, NULL_TREE, false);
- if (parm == NULL)
- break;
- parms = chainon (parms,
- build_tree_list (NULL_TREE, grokparm (parm, expr)));
- }
- sel = list;
- }
- else
- attr_err |= c_parser_objc_maybe_method_attributes (parser, attributes) ;
-
- if (sel == NULL)
- {
- c_parser_error (parser, "objective-c method declaration is expected");
- return error_mark_node;
- }
-
- if (attr_err)
- return error_mark_node;
-
- return objc_build_method_signature (is_class_method, type, sel, parms, ellipsis);
-}
-
-/* Parse an objc-type-name.
-
- objc-type-name:
- objc-type-qualifiers[opt] type-name
- objc-type-qualifiers[opt]
-
- objc-type-qualifiers:
- objc-type-qualifier
- objc-type-qualifiers objc-type-qualifier
-
- objc-type-qualifier: one of
- in out inout bycopy byref oneway
-*/
-
-static tree
-c_parser_objc_type_name (c_parser *parser)
-{
- tree quals = NULL_TREE;
- struct c_type_name *type_name = NULL;
- tree type = NULL_TREE;
- while (true)
- {
- c_token *token = c_parser_peek_token (parser);
- if (token->type == CPP_KEYWORD
- && (token->keyword == RID_IN
- || token->keyword == RID_OUT
- || token->keyword == RID_INOUT
- || token->keyword == RID_BYCOPY
- || token->keyword == RID_BYREF
- || token->keyword == RID_ONEWAY))
- {
- quals = chainon (build_tree_list (NULL_TREE, token->value), quals);
- c_parser_consume_token (parser);
- }
- else
- break;
- }
- if (c_parser_next_tokens_start_typename (parser, cla_prefer_type))
- type_name = c_parser_type_name (parser);
- if (type_name)
- type = groktypename (type_name, NULL, NULL);
-
- /* If the type is unknown, and error has already been produced and
- we need to recover from the error. In that case, use NULL_TREE
- for the type, as if no type had been specified; this will use the
- default type ('id') which is good for error recovery. */
- if (type == error_mark_node)
- type = NULL_TREE;
-
- return build_tree_list (quals, type);
-}
-
-/* Parse objc-protocol-refs.
-
- objc-protocol-refs:
- < identifier-list >
-*/
-
-static tree
-c_parser_objc_protocol_refs (c_parser *parser)
-{
- tree list = NULL_TREE;
- gcc_assert (c_parser_next_token_is (parser, CPP_LESS));
- c_parser_consume_token (parser);
- /* Any identifiers, including those declared as type names, are OK
- here. */
- while (true)
- {
- tree id;
- if (c_parser_next_token_is_not (parser, CPP_NAME))
- {
- c_parser_error (parser, "expected identifier");
- break;
- }
- id = c_parser_peek_token (parser)->value;
- list = chainon (list, build_tree_list (NULL_TREE, id));
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
- else
- break;
- }
- c_parser_require (parser, CPP_GREATER, "expected %<>%>");
- return list;
-}
-
-/* Parse an objc-try-catch-finally-statement.
-
- objc-try-catch-finally-statement:
- @try compound-statement objc-catch-list[opt]
- @try compound-statement objc-catch-list[opt] @finally compound-statement
-
- objc-catch-list:
- @catch ( objc-catch-parameter-declaration ) compound-statement
- objc-catch-list @catch ( objc-catch-parameter-declaration ) compound-statement
-
- objc-catch-parameter-declaration:
- parameter-declaration
- '...'
-
- where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS.
-
- PS: This function is identical to cp_parser_objc_try_catch_finally_statement
- for C++. Keep them in sync. */
-
-static void
-c_parser_objc_try_catch_finally_statement (c_parser *parser)
-{
- location_t location;
- tree stmt;
-
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_TRY));
- c_parser_consume_token (parser);
- location = c_parser_peek_token (parser)->location;
- objc_maybe_warn_exceptions (location);
- stmt = c_parser_compound_statement (parser);
- objc_begin_try_stmt (location, stmt);
-
- while (c_parser_next_token_is_keyword (parser, RID_AT_CATCH))
- {
- struct c_parm *parm;
- tree parameter_declaration = error_mark_node;
- bool seen_open_paren = false;
-
- c_parser_consume_token (parser);
- matching_parens parens;
- if (!parens.require_open (parser))
- seen_open_paren = true;
- if (c_parser_next_token_is (parser, CPP_ELLIPSIS))
- {
- /* We have "@catch (...)" (where the '...' are literally
- what is in the code). Skip the '...'.
- parameter_declaration is set to NULL_TREE, and
- objc_being_catch_clauses() knows that that means
- '...'. */
- c_parser_consume_token (parser);
- parameter_declaration = NULL_TREE;
- }
- else
- {
- /* We have "@catch (NSException *exception)" or something
- like that. Parse the parameter declaration. */
- parm = c_parser_parameter_declaration (parser, NULL_TREE, false);
- if (parm == NULL)
- parameter_declaration = error_mark_node;
- else
- parameter_declaration = grokparm (parm, NULL);
- }
- if (seen_open_paren)
- parens.require_close (parser);
- else
- {
- /* If there was no open parenthesis, we are recovering from
- an error, and we are trying to figure out what mistake
- the user has made. */
-
- /* If there is an immediate closing parenthesis, the user
- probably forgot the opening one (ie, they typed "@catch
- NSException *e)". Parse the closing parenthesis and keep
- going. */
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- c_parser_consume_token (parser);
-
- /* If these is no immediate closing parenthesis, the user
- probably doesn't know that parenthesis are required at
- all (ie, they typed "@catch NSException *e"). So, just
- forget about the closing parenthesis and keep going. */
- }
- objc_begin_catch_clause (parameter_declaration);
- if (c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
- c_parser_compound_statement_nostart (parser);
- objc_finish_catch_clause ();
- }
- if (c_parser_next_token_is_keyword (parser, RID_AT_FINALLY))
- {
- c_parser_consume_token (parser);
- location = c_parser_peek_token (parser)->location;
- stmt = c_parser_compound_statement (parser);
- objc_build_finally_clause (location, stmt);
- }
- objc_finish_try_stmt ();
-}
-
-/* Parse an objc-synchronized-statement.
-
- objc-synchronized-statement:
- @synchronized ( expression ) compound-statement
-*/
-
-static void
-c_parser_objc_synchronized_statement (c_parser *parser)
-{
- location_t loc;
- tree expr, stmt;
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNCHRONIZED));
- c_parser_consume_token (parser);
- loc = c_parser_peek_token (parser)->location;
- objc_maybe_warn_exceptions (loc);
- matching_parens parens;
- if (parens.require_open (parser))
- {
- struct c_expr ce = c_parser_expression (parser);
- ce = convert_lvalue_to_rvalue (loc, ce, false, false);
- expr = ce.value;
- expr = c_fully_fold (expr, false, NULL);
- parens.skip_until_found_close (parser);
- }
- else
- expr = error_mark_node;
- stmt = c_parser_compound_statement (parser);
- objc_build_synchronized (loc, expr, stmt);
-}
-
-/* Parse an objc-selector; return NULL_TREE without an error if the
- next token is not an objc-selector.
-
- objc-selector:
- identifier
- one of
- enum struct union if else while do for switch case default
- break continue return goto asm sizeof typeof __alignof
- unsigned long const short volatile signed restrict _Complex
- in out inout bycopy byref oneway int char float double void _Bool
- _Atomic
-
- ??? Why this selection of keywords but not, for example, storage
- class specifiers? */
-
-static tree
-c_parser_objc_selector (c_parser *parser)
-{
- c_token *token = c_parser_peek_token (parser);
- tree value = token->value;
- if (token->type == CPP_NAME)
- {
- c_parser_consume_token (parser);
- return value;
- }
- if (token->type != CPP_KEYWORD)
- return NULL_TREE;
- switch (token->keyword)
- {
- case RID_ENUM:
- case RID_STRUCT:
- case RID_UNION:
- case RID_IF:
- case RID_ELSE:
- case RID_WHILE:
- case RID_DO:
- case RID_FOR:
- case RID_SWITCH:
- case RID_CASE:
- case RID_DEFAULT:
- case RID_BREAK:
- case RID_CONTINUE:
- case RID_RETURN:
- case RID_GOTO:
- case RID_ASM:
- case RID_SIZEOF:
- case RID_TYPEOF:
- case RID_ALIGNOF:
- case RID_UNSIGNED:
- case RID_LONG:
- case RID_CONST:
- case RID_SHORT:
- case RID_VOLATILE:
- case RID_SIGNED:
- case RID_RESTRICT:
- case RID_COMPLEX:
- case RID_IN:
- case RID_OUT:
- case RID_INOUT:
- case RID_BYCOPY:
- case RID_BYREF:
- case RID_ONEWAY:
- case RID_INT:
- case RID_CHAR:
- case RID_FLOAT:
- case RID_DOUBLE:
- CASE_RID_FLOATN_NX:
- case RID_VOID:
- case RID_BOOL:
- case RID_ATOMIC:
- case RID_AUTO_TYPE:
- case RID_INT_N_0:
- case RID_INT_N_1:
- case RID_INT_N_2:
- case RID_INT_N_3:
- c_parser_consume_token (parser);
- return value;
- default:
- return NULL_TREE;
- }
-}
-
-/* Parse an objc-selector-arg.
-
- objc-selector-arg:
- objc-selector
- objc-keywordname-list
-
- objc-keywordname-list:
- objc-keywordname
- objc-keywordname-list objc-keywordname
-
- objc-keywordname:
- objc-selector :
- :
-*/
-
-static tree
-c_parser_objc_selector_arg (c_parser *parser)
-{
- tree sel = c_parser_objc_selector (parser);
- tree list = NULL_TREE;
- if (sel
- && c_parser_next_token_is_not (parser, CPP_COLON)
- && c_parser_next_token_is_not (parser, CPP_SCOPE))
- return sel;
- while (true)
- {
- if (c_parser_next_token_is (parser, CPP_SCOPE))
- {
- c_parser_consume_token (parser);
- list = chainon (list, build_tree_list (sel, NULL_TREE));
- list = chainon (list, build_tree_list (NULL_TREE, NULL_TREE));
- }
- else
- {
- if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
- return list;
- list = chainon (list, build_tree_list (sel, NULL_TREE));
- }
- sel = c_parser_objc_selector (parser);
- if (!sel
- && c_parser_next_token_is_not (parser, CPP_COLON)
- && c_parser_next_token_is_not (parser, CPP_SCOPE))
- break;
- }
- return list;
-}
-
-/* Parse an objc-receiver.
-
- objc-receiver:
- expression
- class-name
- type-name
-*/
-
-static tree
-c_parser_objc_receiver (c_parser *parser)
-{
- location_t loc = c_parser_peek_token (parser)->location;
-
- if (c_parser_peek_token (parser)->type == CPP_NAME
- && (c_parser_peek_token (parser)->id_kind == C_ID_TYPENAME
- || c_parser_peek_token (parser)->id_kind == C_ID_CLASSNAME))
- {
- tree id = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- return objc_get_class_reference (id);
- }
- struct c_expr ce = c_parser_expression (parser);
- ce = convert_lvalue_to_rvalue (loc, ce, false, false);
- return c_fully_fold (ce.value, false, NULL);
-}
-
-/* Parse objc-message-args.
-
- objc-message-args:
- objc-selector
- objc-keywordarg-list
-
- objc-keywordarg-list:
- objc-keywordarg
- objc-keywordarg-list objc-keywordarg
-
- objc-keywordarg:
- objc-selector : objc-keywordexpr
- : objc-keywordexpr
-*/
-
-static tree
-c_parser_objc_message_args (c_parser *parser)
-{
- tree sel = c_parser_objc_selector (parser);
- tree list = NULL_TREE;
- if (sel && c_parser_next_token_is_not (parser, CPP_COLON))
- return sel;
- while (true)
- {
- tree keywordexpr;
- if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
- return error_mark_node;
- keywordexpr = c_parser_objc_keywordexpr (parser);
- list = chainon (list, build_tree_list (sel, keywordexpr));
- sel = c_parser_objc_selector (parser);
- if (!sel && c_parser_next_token_is_not (parser, CPP_COLON))
- break;
- }
- return list;
-}
-
-/* Parse an objc-keywordexpr.
-
- objc-keywordexpr:
- nonempty-expr-list
-*/
-
-static tree
-c_parser_objc_keywordexpr (c_parser *parser)
-{
- tree ret;
- vec<tree, va_gc> *expr_list = c_parser_expr_list (parser, true, true,
- NULL, NULL, NULL, NULL);
- if (vec_safe_length (expr_list) == 1)
- {
- /* Just return the expression, remove a level of
- indirection. */
- ret = (*expr_list)[0];
- }
- else
- {
- /* We have a comma expression, we will collapse later. */
- ret = build_tree_list_vec (expr_list);
- }
- release_tree_vector (expr_list);
- return ret;
-}
-
-/* A check, needed in several places, that ObjC interface, implementation or
- method definitions are not prefixed by incorrect items. */
-static bool
-c_parser_objc_diagnose_bad_element_prefix (c_parser *parser,
- struct c_declspecs *specs)
-{
- if (!specs->declspecs_seen_p || specs->non_sc_seen_p
- || specs->typespec_kind != ctsk_none)
- {
- c_parser_error (parser,
- "no type or storage class may be specified here,");
- c_parser_skip_to_end_of_block_or_statement (parser);
- return true;
- }
- return false;
-}
-
-/* Parse an Objective-C @property declaration. The syntax is:
-
- objc-property-declaration:
- '@property' objc-property-attributes[opt] struct-declaration ;
-
- objc-property-attributes:
- '(' objc-property-attribute-list ')'
-
- objc-property-attribute-list:
- objc-property-attribute
- objc-property-attribute-list, objc-property-attribute
-
- objc-property-attribute
- 'getter' = identifier
- 'setter' = identifier
- 'readonly'
- 'readwrite'
- 'assign'
- 'retain'
- 'copy'
- 'nonatomic'
-
- For example:
- @property NSString *name;
- @property (readonly) id object;
- @property (retain, nonatomic, getter=getTheName) id name;
- @property int a, b, c;
-
- PS: This function is identical to cp_parser_objc_at_propery_declaration
- for C++. Keep them in sync. */
-static void
-c_parser_objc_at_property_declaration (c_parser *parser)
-{
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_PROPERTY));
- location_t loc = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser); /* Eat '@property'. */
-
- /* Parse the optional attribute list.
-
- A list of parsed, but not verified, attributes. */
- vec<property_attribute_info *> prop_attr_list = vNULL;
-
- bool syntax_error = false;
- if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
- {
- matching_parens parens;
-
- location_t attr_start = c_parser_peek_token (parser)->location;
- /* Eat the '(' */
- parens.consume_open (parser);
-
- /* Property attribute keywords are valid now. */
- parser->objc_property_attr_context = true;
-
- /* Allow @property (), with a warning. */
- location_t attr_end = c_parser_peek_token (parser)->location;
-
- if (c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- {
- location_t attr_comb = make_location (attr_end, attr_start, attr_end);
- warning_at (attr_comb, OPT_Wattributes,
- "empty property attribute list");
- }
- else
- while (true)
- {
- c_token *token = c_parser_peek_token (parser);
- attr_start = token->location;
- attr_end = get_finish (token->location);
- location_t attr_comb = make_location (attr_start, attr_start,
- attr_end);
-
- if (token->type == CPP_CLOSE_PAREN || token->type == CPP_COMMA)
- {
- warning_at (attr_comb, OPT_Wattributes,
- "missing property attribute");
- if (token->type == CPP_CLOSE_PAREN)
- break;
- c_parser_consume_token (parser);
- continue;
- }
-
- tree attr_name = NULL_TREE;
- enum rid keyword = RID_MAX; /* Not a valid property attribute. */
- bool add_at = false;
- if (token->type == CPP_KEYWORD)
- {
- keyword = token->keyword;
- if (OBJC_IS_AT_KEYWORD (keyword))
- {
- /* For '@' keywords the token value has the keyword,
- prepend the '@' for diagnostics. */
- attr_name = token->value;
- add_at = true;
- }
- else
- attr_name = ridpointers[(int)keyword];
- }
- else if (token->type == CPP_NAME)
- attr_name = token->value;
- c_parser_consume_token (parser);
-
- enum objc_property_attribute_kind prop_kind
- = objc_prop_attr_kind_for_rid (keyword);
- property_attribute_info *prop
- = new property_attribute_info (attr_name, attr_comb, prop_kind);
- prop_attr_list.safe_push (prop);
-
- tree meth_name;
- switch (prop->prop_kind)
- {
- default: break;
- case OBJC_PROPERTY_ATTR_UNKNOWN:
- if (attr_name)
- error_at (attr_comb, "unknown property attribute %<%s%s%>",
- add_at ? "@" : "", IDENTIFIER_POINTER (attr_name));
- else
- error_at (attr_comb, "unknown property attribute");
- prop->parse_error = syntax_error = true;
- break;
-
- case OBJC_PROPERTY_ATTR_GETTER:
- case OBJC_PROPERTY_ATTR_SETTER:
- if (c_parser_next_token_is_not (parser, CPP_EQ))
- {
- attr_comb = make_location (attr_end, attr_start, attr_end);
- error_at (attr_comb, "expected %<=%> after Objective-C %qE",
- attr_name);
- prop->parse_error = syntax_error = true;
- break;
- }
- token = c_parser_peek_token (parser);
- attr_end = token->location;
- c_parser_consume_token (parser); /* eat the = */
- if (c_parser_next_token_is_not (parser, CPP_NAME))
- {
- attr_comb = make_location (attr_end, attr_start, attr_end);
- error_at (attr_comb, "expected %qE selector name",
- attr_name);
- prop->parse_error = syntax_error = true;
- break;
- }
- /* Get the end of the method name, and consume the name. */
- token = c_parser_peek_token (parser);
- attr_end = get_finish (token->location);
- meth_name = token->value;
- c_parser_consume_token (parser);
- if (prop->prop_kind == OBJC_PROPERTY_ATTR_SETTER)
- {
- if (c_parser_next_token_is_not (parser, CPP_COLON))
- {
- attr_comb = make_location (attr_end, attr_start,
- attr_end);
- error_at (attr_comb, "setter method names must"
- " terminate with %<:%>");
- prop->parse_error = syntax_error = true;
- }
- else
- {
- attr_end = get_finish (c_parser_peek_token
- (parser)->location);
- c_parser_consume_token (parser);
- }
- attr_comb = make_location (attr_start, attr_start,
- attr_end);
- }
- else
- attr_comb = make_location (attr_start, attr_start,
- attr_end);
- prop->ident = meth_name;
- /* Updated location including all that was successfully
- parsed. */
- prop->prop_loc = attr_comb;
- break;
- }
-
- /* If we see a comma here, then keep going - even if we already
- saw a syntax error. For simple mistakes e.g. (asign, getter=x)
- this makes a more useful output and avoid spurious warnings about
- missing attributes that are, in fact, specified after the one with
- the syntax error. */
- if (c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
- else
- break;
- }
- parser->objc_property_attr_context = false;
-
- if (syntax_error && c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
- /* We don't really want to chew the whole of the file looking for a
- matching closing parenthesis, so we will try to read the decl and
- let the error handling for that close out the statement. */
- ;
- else
- syntax_error = false, parens.skip_until_found_close (parser);
- }
-
- /* 'properties' is the list of properties that we read. Usually a
- single one, but maybe more (eg, in "@property int a, b, c;" there
- are three). */
- tree properties = c_parser_struct_declaration (parser);
-
- if (properties == error_mark_node)
- c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
- else
- {
- if (properties == NULL_TREE)
- c_parser_error (parser, "expected identifier");
- else
- {
- /* Comma-separated properties are chained together in reverse order;
- add them one by one. */
- properties = nreverse (properties);
- for (; properties; properties = TREE_CHAIN (properties))
- objc_add_property_declaration (loc, copy_node (properties),
- prop_attr_list);
- }
- c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
- }
-
- while (!prop_attr_list.is_empty())
- delete prop_attr_list.pop ();
- prop_attr_list.release ();
- parser->error = false;
-}
-
-/* Parse an Objective-C @synthesize declaration. The syntax is:
-
- objc-synthesize-declaration:
- @synthesize objc-synthesize-identifier-list ;
-
- objc-synthesize-identifier-list:
- objc-synthesize-identifier
- objc-synthesize-identifier-list, objc-synthesize-identifier
-
- objc-synthesize-identifier
- identifier
- identifier = identifier
-
- For example:
- @synthesize MyProperty;
- @synthesize OneProperty, AnotherProperty=MyIvar, YetAnotherProperty;
-
- PS: This function is identical to cp_parser_objc_at_synthesize_declaration
- for C++. Keep them in sync.
-*/
-static void
-c_parser_objc_at_synthesize_declaration (c_parser *parser)
-{
- tree list = NULL_TREE;
- location_t loc;
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_SYNTHESIZE));
- loc = c_parser_peek_token (parser)->location;
-
- c_parser_consume_token (parser);
- while (true)
- {
- tree property, ivar;
- if (c_parser_next_token_is_not (parser, CPP_NAME))
- {
- c_parser_error (parser, "expected identifier");
- c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
- /* Once we find the semicolon, we can resume normal parsing.
- We have to reset parser->error manually because
- c_parser_skip_until_found() won't reset it for us if the
- next token is precisely a semicolon. */
- parser->error = false;
- return;
- }
- property = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_EQ))
- {
- c_parser_consume_token (parser);
- if (c_parser_next_token_is_not (parser, CPP_NAME))
- {
- c_parser_error (parser, "expected identifier");
- c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
- parser->error = false;
- return;
- }
- ivar = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- }
- else
- ivar = NULL_TREE;
- list = chainon (list, build_tree_list (ivar, property));
- if (c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
- else
- break;
- }
- c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
- objc_add_synthesize_declaration (loc, list);
-}
-
-/* Parse an Objective-C @dynamic declaration. The syntax is:
-
- objc-dynamic-declaration:
- @dynamic identifier-list ;
-
- For example:
- @dynamic MyProperty;
- @dynamic MyProperty, AnotherProperty;
-
- PS: This function is identical to cp_parser_objc_at_dynamic_declaration
- for C++. Keep them in sync.
-*/
-static void
-c_parser_objc_at_dynamic_declaration (c_parser *parser)
-{
- tree list = NULL_TREE;
- location_t loc;
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_AT_DYNAMIC));
- loc = c_parser_peek_token (parser)->location;
-
- c_parser_consume_token (parser);
- while (true)
- {
- tree property;
- if (c_parser_next_token_is_not (parser, CPP_NAME))
- {
- c_parser_error (parser, "expected identifier");
- c_parser_skip_until_found (parser, CPP_SEMICOLON, NULL);
- parser->error = false;
- return;
- }
- property = c_parser_peek_token (parser)->value;
- list = chainon (list, build_tree_list (NULL_TREE, property));
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
- else
- break;
- }
- c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
- objc_add_dynamic_declaration (loc, list);
-}
-
-
-/* Parse a pragma GCC ivdep. */
-
-static bool
-c_parse_pragma_ivdep (c_parser *parser)
-{
- c_parser_consume_pragma (parser);
- c_parser_skip_to_pragma_eol (parser);
- return true;
-}
-
-/* Parse a pragma GCC unroll. */
-
-static unsigned short
-c_parser_pragma_unroll (c_parser *parser)
-{
- unsigned short unroll;
- c_parser_consume_pragma (parser);
- location_t location = c_parser_peek_token (parser)->location;
- tree expr = c_parser_expr_no_commas (parser, NULL).value;
- mark_exp_read (expr);
- expr = c_fully_fold (expr, false, NULL);
- HOST_WIDE_INT lunroll = 0;
- if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
- || TREE_CODE (expr) != INTEGER_CST
- || (lunroll = tree_to_shwi (expr)) < 0
- || lunroll >= USHRT_MAX)
- {
- error_at (location, "%<#pragma GCC unroll%> requires an"
- " assignment-expression that evaluates to a non-negative"
- " integral constant less than %u", USHRT_MAX);
- unroll = 0;
- }
- else
- {
- unroll = (unsigned short)lunroll;
- if (unroll == 0)
- unroll = 1;
- }
-
- c_parser_skip_to_pragma_eol (parser);
- return unroll;
-}
-
-/* Handle pragmas. Some OpenMP pragmas are associated with, and therefore
- should be considered, statements. ALLOW_STMT is true if we're within
- the context of a function and such pragmas are to be allowed. Returns
- true if we actually parsed such a pragma. */
-
-static bool
-c_parser_pragma (c_parser *parser, enum pragma_context context, bool *if_p)
-{
- unsigned int id;
- const char *construct = NULL;
-
- id = c_parser_peek_token (parser)->pragma_kind;
- gcc_assert (id != PRAGMA_NONE);
-
- switch (id)
- {
- case PRAGMA_OACC_DECLARE:
- c_parser_oacc_declare (parser);
- return false;
-
- case PRAGMA_OACC_ENTER_DATA:
- if (context != pragma_compound)
- {
- construct = "acc enter data";
- in_compound:
- if (context == pragma_stmt)
- {
- error_at (c_parser_peek_token (parser)->location,
- "%<#pragma %s%> may only be used in compound "
- "statements", construct);
- c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
- return true;
- }
- goto bad_stmt;
- }
- c_parser_oacc_enter_exit_data (parser, true);
- return false;
-
- case PRAGMA_OACC_EXIT_DATA:
- if (context != pragma_compound)
- {
- construct = "acc exit data";
- goto in_compound;
- }
- c_parser_oacc_enter_exit_data (parser, false);
- return false;
-
- case PRAGMA_OACC_ROUTINE:
- if (context != pragma_external)
- {
- error_at (c_parser_peek_token (parser)->location,
- "%<#pragma acc routine%> must be at file scope");
- c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
- return false;
- }
- c_parser_oacc_routine (parser, context);
- return false;
-
- case PRAGMA_OACC_UPDATE:
- if (context != pragma_compound)
- {
- construct = "acc update";
- goto in_compound;
- }
- c_parser_oacc_update (parser);
- return false;
-
- case PRAGMA_OMP_BARRIER:
- if (context != pragma_compound)
- {
- construct = "omp barrier";
- goto in_compound;
- }
- c_parser_omp_barrier (parser);
- return false;
-
- case PRAGMA_OMP_DEPOBJ:
- if (context != pragma_compound)
- {
- construct = "omp depobj";
- goto in_compound;
- }
- c_parser_omp_depobj (parser);
- return false;
-
- case PRAGMA_OMP_FLUSH:
- if (context != pragma_compound)
- {
- construct = "omp flush";
- goto in_compound;
- }
- c_parser_omp_flush (parser);
- return false;
-
- case PRAGMA_OMP_TASKWAIT:
- if (context != pragma_compound)
- {
- construct = "omp taskwait";
- goto in_compound;
- }
- c_parser_omp_taskwait (parser);
- return false;
-
- case PRAGMA_OMP_TASKYIELD:
- if (context != pragma_compound)
- {
- construct = "omp taskyield";
- goto in_compound;
- }
- c_parser_omp_taskyield (parser);
- return false;
-
- case PRAGMA_OMP_CANCEL:
- if (context != pragma_compound)
- {
- construct = "omp cancel";
- goto in_compound;
- }
- c_parser_omp_cancel (parser);
- return false;
-
- case PRAGMA_OMP_CANCELLATION_POINT:
- return c_parser_omp_cancellation_point (parser, context);
-
- case PRAGMA_OMP_THREADPRIVATE:
- c_parser_omp_threadprivate (parser);
- return false;
-
- case PRAGMA_OMP_TARGET:
- return c_parser_omp_target (parser, context, if_p);
-
- case PRAGMA_OMP_END_DECLARE_TARGET:
- c_parser_omp_end_declare_target (parser);
- return false;
-
- case PRAGMA_OMP_SCAN:
- error_at (c_parser_peek_token (parser)->location,
- "%<#pragma omp scan%> may only be used in "
- "a loop construct with %<inscan%> %<reduction%> clause");
- c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
- return false;
-
- case PRAGMA_OMP_SECTION:
- error_at (c_parser_peek_token (parser)->location,
- "%<#pragma omp section%> may only be used in "
- "%<#pragma omp sections%> construct");
- c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
- return false;
-
- case PRAGMA_OMP_DECLARE:
- return c_parser_omp_declare (parser, context);
-
- case PRAGMA_OMP_REQUIRES:
- if (context != pragma_external)
- {
- error_at (c_parser_peek_token (parser)->location,
- "%<#pragma omp requires%> may only be used at file scope");
- c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
- return false;
- }
- c_parser_omp_requires (parser);
- return false;
-
- case PRAGMA_OMP_NOTHING:
- c_parser_omp_nothing (parser);
- return false;
-
- case PRAGMA_OMP_ERROR:
- return c_parser_omp_error (parser, context);
-
- case PRAGMA_OMP_ORDERED:
- return c_parser_omp_ordered (parser, context, if_p);
-
- case PRAGMA_IVDEP:
- {
- const bool ivdep = c_parse_pragma_ivdep (parser);
- unsigned short unroll;
- if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_UNROLL)
- unroll = c_parser_pragma_unroll (parser);
- else
- unroll = 0;
- if (!c_parser_next_token_is_keyword (parser, RID_FOR)
- && !c_parser_next_token_is_keyword (parser, RID_WHILE)
- && !c_parser_next_token_is_keyword (parser, RID_DO))
- {
- c_parser_error (parser, "for, while or do statement expected");
- return false;
- }
- if (c_parser_next_token_is_keyword (parser, RID_FOR))
- c_parser_for_statement (parser, ivdep, unroll, if_p);
- else if (c_parser_next_token_is_keyword (parser, RID_WHILE))
- c_parser_while_statement (parser, ivdep, unroll, if_p);
- else
- c_parser_do_statement (parser, ivdep, unroll);
- }
- return true;
-
- case PRAGMA_UNROLL:
- {
- unsigned short unroll = c_parser_pragma_unroll (parser);
- bool ivdep;
- if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_IVDEP)
- ivdep = c_parse_pragma_ivdep (parser);
- else
- ivdep = false;
- if (!c_parser_next_token_is_keyword (parser, RID_FOR)
- && !c_parser_next_token_is_keyword (parser, RID_WHILE)
- && !c_parser_next_token_is_keyword (parser, RID_DO))
- {
- c_parser_error (parser, "for, while or do statement expected");
- return false;
- }
- if (c_parser_next_token_is_keyword (parser, RID_FOR))
- c_parser_for_statement (parser, ivdep, unroll, if_p);
- else if (c_parser_next_token_is_keyword (parser, RID_WHILE))
- c_parser_while_statement (parser, ivdep, unroll, if_p);
- else
- c_parser_do_statement (parser, ivdep, unroll);
- }
- return true;
-
- case PRAGMA_GCC_PCH_PREPROCESS:
- c_parser_error (parser, "%<#pragma GCC pch_preprocess%> must be first");
- c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
- return false;
-
- case PRAGMA_OACC_WAIT:
- if (context != pragma_compound)
- {
- construct = "acc wait";
- goto in_compound;
- }
- /* FALL THROUGH. */
-
- default:
- if (id < PRAGMA_FIRST_EXTERNAL)
- {
- if (context != pragma_stmt && context != pragma_compound)
- {
- bad_stmt:
- c_parser_error (parser, "expected declaration specifiers");
- c_parser_skip_until_found (parser, CPP_PRAGMA_EOL, NULL);
- return false;
- }
- c_parser_omp_construct (parser, if_p);
- return true;
- }
- break;
- }
-
- c_parser_consume_pragma (parser);
- c_invoke_pragma_handler (id);
-
- /* Skip to EOL, but suppress any error message. Those will have been
- generated by the handler routine through calling error, as opposed
- to calling c_parser_error. */
- parser->error = true;
- c_parser_skip_to_pragma_eol (parser);
-
- return false;
-}
-
-/* The interface the pragma parsers have to the lexer. */
-
-enum cpp_ttype
-pragma_lex (tree *value, location_t *loc)
-{
- c_token *tok = c_parser_peek_token (the_parser);
- enum cpp_ttype ret = tok->type;
-
- *value = tok->value;
- if (loc)
- *loc = tok->location;
-
- if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF)
- ret = CPP_EOF;
- else if (ret == CPP_STRING)
- *value = c_parser_string_literal (the_parser, false, false).value;
- else
- {
- if (ret == CPP_KEYWORD)
- ret = CPP_NAME;
- c_parser_consume_token (the_parser);
- }
-
- return ret;
-}
-
-static void
-c_parser_pragma_pch_preprocess (c_parser *parser)
-{
- tree name = NULL;
-
- parser->lex_joined_string = true;
- c_parser_consume_pragma (parser);
- if (c_parser_next_token_is (parser, CPP_STRING))
- {
- name = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- }
- else
- c_parser_error (parser, "expected string literal");
- c_parser_skip_to_pragma_eol (parser);
- parser->lex_joined_string = false;
-
- if (name)
- c_common_pch_pragma (parse_in, TREE_STRING_POINTER (name));
-}
-
-/* OpenACC and OpenMP parsing routines. */
-
-/* Returns name of the next clause.
- If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and
- the token is not consumed. Otherwise appropriate pragma_omp_clause is
- returned and the token is consumed. */
-
-static pragma_omp_clause
-c_parser_omp_clause_name (c_parser *parser)
-{
- pragma_omp_clause result = PRAGMA_OMP_CLAUSE_NONE;
-
- if (c_parser_next_token_is_keyword (parser, RID_AUTO))
- result = PRAGMA_OACC_CLAUSE_AUTO;
- else if (c_parser_next_token_is_keyword (parser, RID_IF))
- result = PRAGMA_OMP_CLAUSE_IF;
- else if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
- result = PRAGMA_OMP_CLAUSE_DEFAULT;
- else if (c_parser_next_token_is_keyword (parser, RID_FOR))
- result = PRAGMA_OMP_CLAUSE_FOR;
- else if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-
- switch (p[0])
- {
- case 'a':
- if (!strcmp ("affinity", p))
- result = PRAGMA_OMP_CLAUSE_AFFINITY;
- else if (!strcmp ("aligned", p))
- result = PRAGMA_OMP_CLAUSE_ALIGNED;
- else if (!strcmp ("allocate", p))
- result = PRAGMA_OMP_CLAUSE_ALLOCATE;
- else if (!strcmp ("async", p))
- result = PRAGMA_OACC_CLAUSE_ASYNC;
- else if (!strcmp ("attach", p))
- result = PRAGMA_OACC_CLAUSE_ATTACH;
- break;
- case 'b':
- if (!strcmp ("bind", p))
- result = PRAGMA_OMP_CLAUSE_BIND;
- break;
- case 'c':
- if (!strcmp ("collapse", p))
- result = PRAGMA_OMP_CLAUSE_COLLAPSE;
- else if (!strcmp ("copy", p))
- result = PRAGMA_OACC_CLAUSE_COPY;
- else if (!strcmp ("copyin", p))
- result = PRAGMA_OMP_CLAUSE_COPYIN;
- else if (!strcmp ("copyout", p))
- result = PRAGMA_OACC_CLAUSE_COPYOUT;
- else if (!strcmp ("copyprivate", p))
- result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
- else if (!strcmp ("create", p))
- result = PRAGMA_OACC_CLAUSE_CREATE;
- break;
- case 'd':
- if (!strcmp ("defaultmap", p))
- result = PRAGMA_OMP_CLAUSE_DEFAULTMAP;
- else if (!strcmp ("delete", p))
- result = PRAGMA_OACC_CLAUSE_DELETE;
- else if (!strcmp ("depend", p))
- result = PRAGMA_OMP_CLAUSE_DEPEND;
- else if (!strcmp ("detach", p))
- result = PRAGMA_OACC_CLAUSE_DETACH;
- else if (!strcmp ("device", p))
- result = PRAGMA_OMP_CLAUSE_DEVICE;
- else if (!strcmp ("deviceptr", p))
- result = PRAGMA_OACC_CLAUSE_DEVICEPTR;
- else if (!strcmp ("device_resident", p))
- result = PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT;
- else if (!strcmp ("device_type", p))
- result = PRAGMA_OMP_CLAUSE_DEVICE_TYPE;
- else if (!strcmp ("dist_schedule", p))
- result = PRAGMA_OMP_CLAUSE_DIST_SCHEDULE;
- break;
- case 'f':
- if (!strcmp ("filter", p))
- result = PRAGMA_OMP_CLAUSE_FILTER;
- else if (!strcmp ("final", p))
- result = PRAGMA_OMP_CLAUSE_FINAL;
- else if (!strcmp ("finalize", p))
- result = PRAGMA_OACC_CLAUSE_FINALIZE;
- else if (!strcmp ("firstprivate", p))
- result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
- else if (!strcmp ("from", p))
- result = PRAGMA_OMP_CLAUSE_FROM;
- break;
- case 'g':
- if (!strcmp ("gang", p))
- result = PRAGMA_OACC_CLAUSE_GANG;
- else if (!strcmp ("grainsize", p))
- result = PRAGMA_OMP_CLAUSE_GRAINSIZE;
- break;
- case 'h':
- if (!strcmp ("hint", p))
- result = PRAGMA_OMP_CLAUSE_HINT;
- else if (!strcmp ("host", p))
- result = PRAGMA_OACC_CLAUSE_HOST;
- break;
- case 'i':
- if (!strcmp ("if_present", p))
- result = PRAGMA_OACC_CLAUSE_IF_PRESENT;
- else if (!strcmp ("in_reduction", p))
- result = PRAGMA_OMP_CLAUSE_IN_REDUCTION;
- else if (!strcmp ("inbranch", p))
- result = PRAGMA_OMP_CLAUSE_INBRANCH;
- else if (!strcmp ("independent", p))
- result = PRAGMA_OACC_CLAUSE_INDEPENDENT;
- else if (!strcmp ("is_device_ptr", p))
- result = PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR;
- break;
- case 'l':
- if (!strcmp ("lastprivate", p))
- result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
- else if (!strcmp ("linear", p))
- result = PRAGMA_OMP_CLAUSE_LINEAR;
- else if (!strcmp ("link", p))
- result = PRAGMA_OMP_CLAUSE_LINK;
- break;
- case 'm':
- if (!strcmp ("map", p))
- result = PRAGMA_OMP_CLAUSE_MAP;
- else if (!strcmp ("mergeable", p))
- result = PRAGMA_OMP_CLAUSE_MERGEABLE;
- break;
- case 'n':
- if (!strcmp ("no_create", p))
- result = PRAGMA_OACC_CLAUSE_NO_CREATE;
- else if (!strcmp ("nogroup", p))
- result = PRAGMA_OMP_CLAUSE_NOGROUP;
- else if (!strcmp ("nohost", p))
- result = PRAGMA_OACC_CLAUSE_NOHOST;
- else if (!strcmp ("nontemporal", p))
- result = PRAGMA_OMP_CLAUSE_NONTEMPORAL;
- else if (!strcmp ("notinbranch", p))
- result = PRAGMA_OMP_CLAUSE_NOTINBRANCH;
- else if (!strcmp ("nowait", p))
- result = PRAGMA_OMP_CLAUSE_NOWAIT;
- else if (!strcmp ("num_gangs", p))
- result = PRAGMA_OACC_CLAUSE_NUM_GANGS;
- else if (!strcmp ("num_tasks", p))
- result = PRAGMA_OMP_CLAUSE_NUM_TASKS;
- else if (!strcmp ("num_teams", p))
- result = PRAGMA_OMP_CLAUSE_NUM_TEAMS;
- else if (!strcmp ("num_threads", p))
- result = PRAGMA_OMP_CLAUSE_NUM_THREADS;
- else if (!strcmp ("num_workers", p))
- result = PRAGMA_OACC_CLAUSE_NUM_WORKERS;
- break;
- case 'o':
- if (!strcmp ("ordered", p))
- result = PRAGMA_OMP_CLAUSE_ORDERED;
- else if (!strcmp ("order", p))
- result = PRAGMA_OMP_CLAUSE_ORDER;
- break;
- case 'p':
- if (!strcmp ("parallel", p))
- result = PRAGMA_OMP_CLAUSE_PARALLEL;
- else if (!strcmp ("present", p))
- result = PRAGMA_OACC_CLAUSE_PRESENT;
- /* As of OpenACC 2.5, these are now aliases of the non-present_or
- clauses. */
- else if (!strcmp ("present_or_copy", p)
- || !strcmp ("pcopy", p))
- result = PRAGMA_OACC_CLAUSE_COPY;
- else if (!strcmp ("present_or_copyin", p)
- || !strcmp ("pcopyin", p))
- result = PRAGMA_OACC_CLAUSE_COPYIN;
- else if (!strcmp ("present_or_copyout", p)
- || !strcmp ("pcopyout", p))
- result = PRAGMA_OACC_CLAUSE_COPYOUT;
- else if (!strcmp ("present_or_create", p)
- || !strcmp ("pcreate", p))
- result = PRAGMA_OACC_CLAUSE_CREATE;
- else if (!strcmp ("priority", p))
- result = PRAGMA_OMP_CLAUSE_PRIORITY;
- else if (!strcmp ("private", p))
- result = PRAGMA_OMP_CLAUSE_PRIVATE;
- else if (!strcmp ("proc_bind", p))
- result = PRAGMA_OMP_CLAUSE_PROC_BIND;
- break;
- case 'r':
- if (!strcmp ("reduction", p))
- result = PRAGMA_OMP_CLAUSE_REDUCTION;
- break;
- case 's':
- if (!strcmp ("safelen", p))
- result = PRAGMA_OMP_CLAUSE_SAFELEN;
- else if (!strcmp ("schedule", p))
- result = PRAGMA_OMP_CLAUSE_SCHEDULE;
- else if (!strcmp ("sections", p))
- result = PRAGMA_OMP_CLAUSE_SECTIONS;
- else if (!strcmp ("self", p)) /* "self" is a synonym for "host". */
- result = PRAGMA_OACC_CLAUSE_HOST;
- else if (!strcmp ("seq", p))
- result = PRAGMA_OACC_CLAUSE_SEQ;
- else if (!strcmp ("shared", p))
- result = PRAGMA_OMP_CLAUSE_SHARED;
- else if (!strcmp ("simd", p))
- result = PRAGMA_OMP_CLAUSE_SIMD;
- else if (!strcmp ("simdlen", p))
- result = PRAGMA_OMP_CLAUSE_SIMDLEN;
- break;
- case 't':
- if (!strcmp ("task_reduction", p))
- result = PRAGMA_OMP_CLAUSE_TASK_REDUCTION;
- else if (!strcmp ("taskgroup", p))
- result = PRAGMA_OMP_CLAUSE_TASKGROUP;
- else if (!strcmp ("thread_limit", p))
- result = PRAGMA_OMP_CLAUSE_THREAD_LIMIT;
- else if (!strcmp ("threads", p))
- result = PRAGMA_OMP_CLAUSE_THREADS;
- else if (!strcmp ("tile", p))
- result = PRAGMA_OACC_CLAUSE_TILE;
- else if (!strcmp ("to", p))
- result = PRAGMA_OMP_CLAUSE_TO;
- break;
- case 'u':
- if (!strcmp ("uniform", p))
- result = PRAGMA_OMP_CLAUSE_UNIFORM;
- else if (!strcmp ("untied", p))
- result = PRAGMA_OMP_CLAUSE_UNTIED;
- else if (!strcmp ("use_device", p))
- result = PRAGMA_OACC_CLAUSE_USE_DEVICE;
- else if (!strcmp ("use_device_addr", p))
- result = PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR;
- else if (!strcmp ("use_device_ptr", p))
- result = PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR;
- break;
- case 'v':
- if (!strcmp ("vector", p))
- result = PRAGMA_OACC_CLAUSE_VECTOR;
- else if (!strcmp ("vector_length", p))
- result = PRAGMA_OACC_CLAUSE_VECTOR_LENGTH;
- break;
- case 'w':
- if (!strcmp ("wait", p))
- result = PRAGMA_OACC_CLAUSE_WAIT;
- else if (!strcmp ("worker", p))
- result = PRAGMA_OACC_CLAUSE_WORKER;
- break;
- }
- }
-
- if (result != PRAGMA_OMP_CLAUSE_NONE)
- c_parser_consume_token (parser);
-
- return result;
-}
-
-/* Validate that a clause of the given type does not already exist. */
-
-static void
-check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
- const char *name)
-{
- if (tree c = omp_find_clause (clauses, code))
- error_at (OMP_CLAUSE_LOCATION (c), "too many %qs clauses", name);
-}
-
-/* OpenACC 2.0
- Parse wait clause or wait directive parameters. */
-
-static tree
-c_parser_oacc_wait_list (c_parser *parser, location_t clause_loc, tree list)
-{
- vec<tree, va_gc> *args;
- tree t, args_tree;
-
- matching_parens parens;
- if (!parens.require_open (parser))
- return list;
-
- args = c_parser_expr_list (parser, false, true, NULL, NULL, NULL, NULL);
- args_tree = build_tree_list_vec (args);
-
- for (t = args_tree; t; t = TREE_CHAIN (t))
- {
- tree targ = TREE_VALUE (t);
-
- if (targ != error_mark_node)
- {
- if (!INTEGRAL_TYPE_P (TREE_TYPE (targ)))
- {
- c_parser_error (parser, "expression must be integral");
- targ = error_mark_node;
- }
- else
- {
- tree c = build_omp_clause (clause_loc, OMP_CLAUSE_WAIT);
-
- OMP_CLAUSE_DECL (c) = targ;
- OMP_CLAUSE_CHAIN (c) = list;
- list = c;
- }
- }
- }
-
- release_tree_vector (args);
- parens.require_close (parser);
- return list;
-}
-
-/* OpenACC 2.0, OpenMP 2.5:
- variable-list:
- identifier
- variable-list , identifier
-
- If KIND is nonzero, create the appropriate node and install the
- decl in OMP_CLAUSE_DECL and add the node to the head of the list.
- If KIND is nonzero, CLAUSE_LOC is the location of the clause.
-
- If KIND is zero, create a TREE_LIST with the decl in TREE_PURPOSE;
- return the list created.
-
- The optional ALLOW_DEREF argument is true if list items can use the deref
- (->) operator. */
-
-struct omp_dim
-{
- tree low_bound, length;
- location_t loc;
- bool no_colon;
- omp_dim (tree lb, tree len, location_t lo, bool nc)
- : low_bound (lb), length (len), loc (lo), no_colon (nc) {}
-};
-
-static tree
-c_parser_omp_variable_list (c_parser *parser,
- location_t clause_loc,
- enum omp_clause_code kind, tree list,
- bool allow_deref = false)
-{
- auto_vec<omp_dim> dims;
- bool array_section_p;
- auto_vec<c_token> tokens;
- unsigned int tokens_avail = 0;
- bool first = true;
-
- while (1)
- {
- if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
- {
- if (c_parser_next_token_is_not (parser, CPP_NAME)
- || c_parser_peek_token (parser)->id_kind != C_ID_ID)
- {
- struct c_expr expr = c_parser_expr_no_commas (parser, NULL);
- if (expr.value != error_mark_node)
- {
- tree u = build_omp_clause (clause_loc, kind);
- OMP_CLAUSE_DECL (u) = expr.value;
- OMP_CLAUSE_CHAIN (u) = list;
- list = u;
- }
-
- if (c_parser_next_token_is_not (parser, CPP_COMMA))
- break;
-
- c_parser_consume_token (parser);
- first = false;
- continue;
- }
-
- tokens.truncate (0);
- unsigned int nesting_depth = 0;
- while (1)
- {
- c_token *token = c_parser_peek_token (parser);
- switch (token->type)
- {
- case CPP_EOF:
- case CPP_PRAGMA_EOL:
- break;
- case CPP_OPEN_BRACE:
- case CPP_OPEN_PAREN:
- case CPP_OPEN_SQUARE:
- ++nesting_depth;
- goto add;
- case CPP_CLOSE_BRACE:
- case CPP_CLOSE_PAREN:
- case CPP_CLOSE_SQUARE:
- if (nesting_depth-- == 0)
- break;
- goto add;
- case CPP_COMMA:
- if (nesting_depth == 0)
- break;
- goto add;
- default:
- add:
- tokens.safe_push (*token);
- c_parser_consume_token (parser);
- continue;
- }
- break;
- }
-
- /* Make sure nothing tries to read past the end of the tokens. */
- c_token eof_token;
- memset (&eof_token, 0, sizeof (eof_token));
- eof_token.type = CPP_EOF;
- tokens.safe_push (eof_token);
- tokens.safe_push (eof_token);
-
- tokens_avail = parser->tokens_avail;
- gcc_assert (parser->tokens == &parser->tokens_buf[0]);
- parser->tokens = tokens.address ();
- parser->tokens_avail = tokens.length ();
- }
-
- tree t = NULL_TREE;
-
- if (c_parser_next_token_is (parser, CPP_NAME)
- && c_parser_peek_token (parser)->id_kind == C_ID_ID)
- {
- t = lookup_name (c_parser_peek_token (parser)->value);
-
- if (t == NULL_TREE)
- {
- undeclared_variable (c_parser_peek_token (parser)->location,
- c_parser_peek_token (parser)->value);
- t = error_mark_node;
- }
-
- c_parser_consume_token (parser);
- }
- else if (c_parser_next_token_is (parser, CPP_KEYWORD)
- && (c_parser_peek_token (parser)->keyword == RID_FUNCTION_NAME
- || (c_parser_peek_token (parser)->keyword
- == RID_PRETTY_FUNCTION_NAME)
- || (c_parser_peek_token (parser)->keyword
- == RID_C99_FUNCTION_NAME)))
- t = c_parser_predefined_identifier (parser).value;
- else
- {
- if (first)
- c_parser_error (parser, "expected identifier");
- break;
- }
-
- if (t == error_mark_node)
- ;
- else if (kind != 0)
- {
- switch (kind)
- {
- case OMP_CLAUSE__CACHE_:
- /* The OpenACC cache directive explicitly only allows "array
- elements or subarrays". */
- if (c_parser_peek_token (parser)->type != CPP_OPEN_SQUARE)
- {
- c_parser_error (parser, "expected %<[%>");
- t = error_mark_node;
- break;
- }
- /* FALLTHROUGH */
- case OMP_CLAUSE_MAP:
- case OMP_CLAUSE_FROM:
- case OMP_CLAUSE_TO:
- start_component_ref:
- while (c_parser_next_token_is (parser, CPP_DOT)
- || (allow_deref
- && c_parser_next_token_is (parser, CPP_DEREF)))
- {
- location_t op_loc = c_parser_peek_token (parser)->location;
- if (c_parser_next_token_is (parser, CPP_DEREF))
- t = build_simple_mem_ref (t);
- c_parser_consume_token (parser);
- if (!c_parser_next_token_is (parser, CPP_NAME))
- {
- c_parser_error (parser, "expected identifier");
- t = error_mark_node;
- break;
- }
-
- c_token *comp_tok = c_parser_peek_token (parser);
- tree ident = comp_tok->value;
- location_t comp_loc = comp_tok->location;
- c_parser_consume_token (parser);
- t = build_component_ref (op_loc, t, ident, comp_loc);
- }
- /* FALLTHROUGH */
- case OMP_CLAUSE_AFFINITY:
- case OMP_CLAUSE_DEPEND:
- case OMP_CLAUSE_REDUCTION:
- case OMP_CLAUSE_IN_REDUCTION:
- case OMP_CLAUSE_TASK_REDUCTION:
- array_section_p = false;
- dims.truncate (0);
- while (c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
- {
- location_t loc = UNKNOWN_LOCATION;
- tree low_bound = NULL_TREE, length = NULL_TREE;
- bool no_colon = false;
-
- c_parser_consume_token (parser);
- if (!c_parser_next_token_is (parser, CPP_COLON))
- {
- location_t expr_loc
- = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expression (parser);
- expr = convert_lvalue_to_rvalue (expr_loc, expr,
- false, true);
- low_bound = expr.value;
- loc = expr_loc;
- }
- if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
- {
- length = integer_one_node;
- no_colon = true;
- }
- else
- {
- /* Look for `:'. */
- if (!c_parser_require (parser, CPP_COLON,
- "expected %<:%>"))
- {
- t = error_mark_node;
- break;
- }
- array_section_p = true;
- if (!c_parser_next_token_is (parser, CPP_CLOSE_SQUARE))
- {
- location_t expr_loc
- = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expression (parser);
- expr = convert_lvalue_to_rvalue (expr_loc, expr,
- false, true);
- length = expr.value;
- }
- }
- /* Look for the closing `]'. */
- if (!c_parser_require (parser, CPP_CLOSE_SQUARE,
- "expected %<]%>"))
- {
- t = error_mark_node;
- break;
- }
-
- dims.safe_push (omp_dim (low_bound, length, loc, no_colon));
- }
-
- if (t != error_mark_node)
- {
- if ((kind == OMP_CLAUSE_MAP
- || kind == OMP_CLAUSE_FROM
- || kind == OMP_CLAUSE_TO)
- && !array_section_p
- && (c_parser_next_token_is (parser, CPP_DOT)
- || (allow_deref
- && c_parser_next_token_is (parser,
- CPP_DEREF))))
- {
- for (unsigned i = 0; i < dims.length (); i++)
- {
- gcc_assert (dims[i].length == integer_one_node);
- t = build_array_ref (dims[i].loc,
- t, dims[i].low_bound);
- }
- goto start_component_ref;
- }
- else
- for (unsigned i = 0; i < dims.length (); i++)
- t = tree_cons (dims[i].low_bound, dims[i].length, t);
- }
-
- if ((kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
- && t != error_mark_node
- && parser->tokens_avail != 2)
- {
- if (array_section_p)
- {
- error_at (c_parser_peek_token (parser)->location,
- "expected %<)%> or %<,%>");
- t = error_mark_node;
- }
- else
- {
- parser->tokens = tokens.address ();
- parser->tokens_avail = tokens.length ();
-
- t = c_parser_expr_no_commas (parser, NULL).value;
- if (t != error_mark_node && parser->tokens_avail != 2)
- {
- error_at (c_parser_peek_token (parser)->location,
- "expected %<)%> or %<,%>");
- t = error_mark_node;
- }
- }
- }
- break;
- default:
- break;
- }
-
- if (t != error_mark_node)
- {
- tree u = build_omp_clause (clause_loc, kind);
- OMP_CLAUSE_DECL (u) = t;
- OMP_CLAUSE_CHAIN (u) = list;
- list = u;
- }
- }
- else
- list = tree_cons (t, NULL_TREE, list);
-
- if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
- {
- parser->tokens = &parser->tokens_buf[0];
- parser->tokens_avail = tokens_avail;
- }
- if (c_parser_next_token_is_not (parser, CPP_COMMA))
- break;
-
- c_parser_consume_token (parser);
- first = false;
- }
-
- return list;
-}
-
-/* Similarly, but expect leading and trailing parenthesis. This is a very
- common case for OpenACC and OpenMP clauses. The optional ALLOW_DEREF
- argument is true if list items can use the deref (->) operator. */
-
-static tree
-c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind,
- tree list, bool allow_deref = false)
-{
- /* The clauses location. */
- location_t loc = c_parser_peek_token (parser)->location;
-
- matching_parens parens;
- if (parens.require_open (parser))
- {
- list = c_parser_omp_variable_list (parser, loc, kind, list, allow_deref);
- parens.skip_until_found_close (parser);
- }
- return list;
-}
-
-/* OpenACC 2.0:
- copy ( variable-list )
- copyin ( variable-list )
- copyout ( variable-list )
- create ( variable-list )
- delete ( variable-list )
- present ( variable-list )
-
- OpenACC 2.6:
- no_create ( variable-list )
- attach ( variable-list )
- detach ( variable-list ) */
-
-static tree
-c_parser_oacc_data_clause (c_parser *parser, pragma_omp_clause c_kind,
- tree list)
-{
- enum gomp_map_kind kind;
- switch (c_kind)
- {
- case PRAGMA_OACC_CLAUSE_ATTACH:
- kind = GOMP_MAP_ATTACH;
- break;
- case PRAGMA_OACC_CLAUSE_COPY:
- kind = GOMP_MAP_TOFROM;
- break;
- case PRAGMA_OACC_CLAUSE_COPYIN:
- kind = GOMP_MAP_TO;
- break;
- case PRAGMA_OACC_CLAUSE_COPYOUT:
- kind = GOMP_MAP_FROM;
- break;
- case PRAGMA_OACC_CLAUSE_CREATE:
- kind = GOMP_MAP_ALLOC;
- break;
- case PRAGMA_OACC_CLAUSE_DELETE:
- kind = GOMP_MAP_RELEASE;
- break;
- case PRAGMA_OACC_CLAUSE_DETACH:
- kind = GOMP_MAP_DETACH;
- break;
- case PRAGMA_OACC_CLAUSE_DEVICE:
- kind = GOMP_MAP_FORCE_TO;
- break;
- case PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT:
- kind = GOMP_MAP_DEVICE_RESIDENT;
- break;
- case PRAGMA_OACC_CLAUSE_HOST:
- kind = GOMP_MAP_FORCE_FROM;
- break;
- case PRAGMA_OACC_CLAUSE_LINK:
- kind = GOMP_MAP_LINK;
- break;
- case PRAGMA_OACC_CLAUSE_NO_CREATE:
- kind = GOMP_MAP_IF_PRESENT;
- break;
- case PRAGMA_OACC_CLAUSE_PRESENT:
- kind = GOMP_MAP_FORCE_PRESENT;
- break;
- default:
- gcc_unreachable ();
- }
- tree nl, c;
- nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_MAP, list, true);
-
- for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
- OMP_CLAUSE_SET_MAP_KIND (c, kind);
-
- return nl;
-}
-
-/* OpenACC 2.0:
- deviceptr ( variable-list ) */
-
-static tree
-c_parser_oacc_data_clause_deviceptr (c_parser *parser, tree list)
-{
- location_t loc = c_parser_peek_token (parser)->location;
- tree vars, t;
-
- /* Can't use OMP_CLAUSE_MAP here (that is, can't use the generic
- c_parser_oacc_data_clause), as for PRAGMA_OACC_CLAUSE_DEVICEPTR,
- variable-list must only allow for pointer variables. */
- vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
- for (t = vars; t && t; t = TREE_CHAIN (t))
- {
- tree v = TREE_PURPOSE (t);
-
- /* FIXME diagnostics: Ideally we should keep individual
- locations for all the variables in the var list to make the
- following errors more precise. Perhaps
- c_parser_omp_var_list_parens() should construct a list of
- locations to go along with the var list. */
-
- if (!VAR_P (v) && TREE_CODE (v) != PARM_DECL)
- error_at (loc, "%qD is not a variable", v);
- else if (TREE_TYPE (v) == error_mark_node)
- ;
- else if (!POINTER_TYPE_P (TREE_TYPE (v)))
- error_at (loc, "%qD is not a pointer variable", v);
-
- tree u = build_omp_clause (loc, OMP_CLAUSE_MAP);
- OMP_CLAUSE_SET_MAP_KIND (u, GOMP_MAP_FORCE_DEVICEPTR);
- OMP_CLAUSE_DECL (u) = v;
- OMP_CLAUSE_CHAIN (u) = list;
- list = u;
- }
-
- return list;
-}
-
-/* OpenACC 2.0, OpenMP 3.0:
- collapse ( constant-expression ) */
-
-static tree
-c_parser_omp_clause_collapse (c_parser *parser, tree list)
-{
- tree c, num = error_mark_node;
- HOST_WIDE_INT n;
- location_t loc;
-
- check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse");
- check_no_duplicate_clause (list, OMP_CLAUSE_TILE, "tile");
-
- loc = c_parser_peek_token (parser)->location;
- matching_parens parens;
- if (parens.require_open (parser))
- {
- num = c_parser_expr_no_commas (parser, NULL).value;
- parens.skip_until_found_close (parser);
- }
- if (num == error_mark_node)
- return list;
- mark_exp_read (num);
- num = c_fully_fold (num, false, NULL);
- if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
- || !tree_fits_shwi_p (num)
- || (n = tree_to_shwi (num)) <= 0
- || (int) n != n)
- {
- error_at (loc,
- "collapse argument needs positive constant integer expression");
- return list;
- }
- c = build_omp_clause (loc, OMP_CLAUSE_COLLAPSE);
- OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
- OMP_CLAUSE_CHAIN (c) = list;
- return c;
-}
-
-/* OpenMP 2.5:
- copyin ( variable-list ) */
-
-static tree
-c_parser_omp_clause_copyin (c_parser *parser, tree list)
-{
- return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_COPYIN, list);
-}
-
-/* OpenMP 2.5:
- copyprivate ( variable-list ) */
-
-static tree
-c_parser_omp_clause_copyprivate (c_parser *parser, tree list)
-{
- return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_COPYPRIVATE, list);
-}
-
-/* OpenMP 2.5:
- default ( none | shared )
-
- OpenMP 5.1:
- default ( private | firstprivate )
-
- OpenACC:
- default ( none | present ) */
-
-static tree
-c_parser_omp_clause_default (c_parser *parser, tree list, bool is_oacc)
-{
- enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
- location_t loc = c_parser_peek_token (parser)->location;
- tree c;
-
- matching_parens parens;
- if (!parens.require_open (parser))
- return list;
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-
- switch (p[0])
- {
- case 'n':
- if (strcmp ("none", p) != 0)
- goto invalid_kind;
- kind = OMP_CLAUSE_DEFAULT_NONE;
- break;
-
- case 'p':
- if (is_oacc)
- {
- if (strcmp ("present", p) != 0)
- goto invalid_kind;
- kind = OMP_CLAUSE_DEFAULT_PRESENT;
- }
- else
- {
- if (strcmp ("private", p) != 0)
- goto invalid_kind;
- kind = OMP_CLAUSE_DEFAULT_PRIVATE;
- }
- break;
-
- case 'f':
- if (strcmp ("firstprivate", p) != 0 || is_oacc)
- goto invalid_kind;
- kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
- break;
-
- case 's':
- if (strcmp ("shared", p) != 0 || is_oacc)
- goto invalid_kind;
- kind = OMP_CLAUSE_DEFAULT_SHARED;
- break;
-
- default:
- goto invalid_kind;
- }
-
- c_parser_consume_token (parser);
- }
- else
- {
- invalid_kind:
- if (is_oacc)
- c_parser_error (parser, "expected %<none%> or %<present%>");
- else
- c_parser_error (parser, "expected %<none%>, %<shared%>, "
- "%<private%> or %<firstprivate%>");
- }
- parens.skip_until_found_close (parser);
-
- if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED)
- return list;
-
- check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default");
- c = build_omp_clause (loc, OMP_CLAUSE_DEFAULT);
- OMP_CLAUSE_CHAIN (c) = list;
- OMP_CLAUSE_DEFAULT_KIND (c) = kind;
-
- return c;
-}
-
-/* OpenMP 2.5:
- firstprivate ( variable-list ) */
-
-static tree
-c_parser_omp_clause_firstprivate (c_parser *parser, tree list)
-{
- return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_FIRSTPRIVATE, list);
-}
-
-/* OpenMP 3.1:
- final ( expression ) */
-
-static tree
-c_parser_omp_clause_final (c_parser *parser, tree list)
-{
- location_t loc = c_parser_peek_token (parser)->location;
- if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
- {
- matching_parens parens;
- tree t, c;
- if (!parens.require_open (parser))
- t = error_mark_node;
- else
- {
- location_t eloc = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expr_no_commas (parser, NULL);
- t = convert_lvalue_to_rvalue (eloc, expr, true, true).value;
- t = c_objc_common_truthvalue_conversion (eloc, t);
- t = c_fully_fold (t, false, NULL);
- parens.skip_until_found_close (parser);
- }
-
- check_no_duplicate_clause (list, OMP_CLAUSE_FINAL, "final");
-
- c = build_omp_clause (loc, OMP_CLAUSE_FINAL);
- OMP_CLAUSE_FINAL_EXPR (c) = t;
- OMP_CLAUSE_CHAIN (c) = list;
- list = c;
- }
- else
- c_parser_error (parser, "expected %<(%>");
-
- return list;
-}
-
-/* OpenACC, OpenMP 2.5:
- if ( expression )
-
- OpenMP 4.5:
- if ( directive-name-modifier : expression )
-
- directive-name-modifier:
- parallel | task | taskloop | target data | target | target update
- | target enter data | target exit data
-
- OpenMP 5.0:
- directive-name-modifier:
- ... | simd | cancel */
-
-static tree
-c_parser_omp_clause_if (c_parser *parser, tree list, bool is_omp)
-{
- location_t location = c_parser_peek_token (parser)->location;
- enum tree_code if_modifier = ERROR_MARK;
-
- matching_parens parens;
- if (!parens.require_open (parser))
- return list;
-
- if (is_omp && c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- int n = 2;
- if (strcmp (p, "cancel") == 0)
- if_modifier = VOID_CST;
- else if (strcmp (p, "parallel") == 0)
- if_modifier = OMP_PARALLEL;
- else if (strcmp (p, "simd") == 0)
- if_modifier = OMP_SIMD;
- else if (strcmp (p, "task") == 0)
- if_modifier = OMP_TASK;
- else if (strcmp (p, "taskloop") == 0)
- if_modifier = OMP_TASKLOOP;
- else if (strcmp (p, "target") == 0)
- {
- if_modifier = OMP_TARGET;
- if (c_parser_peek_2nd_token (parser)->type == CPP_NAME)
- {
- p = IDENTIFIER_POINTER (c_parser_peek_2nd_token (parser)->value);
- if (strcmp ("data", p) == 0)
- if_modifier = OMP_TARGET_DATA;
- else if (strcmp ("update", p) == 0)
- if_modifier = OMP_TARGET_UPDATE;
- else if (strcmp ("enter", p) == 0)
- if_modifier = OMP_TARGET_ENTER_DATA;
- else if (strcmp ("exit", p) == 0)
- if_modifier = OMP_TARGET_EXIT_DATA;
- if (if_modifier != OMP_TARGET)
- {
- n = 3;
- c_parser_consume_token (parser);
- }
- else
- {
- location_t loc = c_parser_peek_2nd_token (parser)->location;
- error_at (loc, "expected %<data%>, %<update%>, %<enter%> "
- "or %<exit%>");
- if_modifier = ERROR_MARK;
- }
- if (if_modifier == OMP_TARGET_ENTER_DATA
- || if_modifier == OMP_TARGET_EXIT_DATA)
- {
- if (c_parser_peek_2nd_token (parser)->type == CPP_NAME)
- {
- p = IDENTIFIER_POINTER
- (c_parser_peek_2nd_token (parser)->value);
- if (strcmp ("data", p) == 0)
- n = 4;
- }
- if (n == 4)
- c_parser_consume_token (parser);
- else
- {
- location_t loc
- = c_parser_peek_2nd_token (parser)->location;
- error_at (loc, "expected %<data%>");
- if_modifier = ERROR_MARK;
- }
- }
- }
- }
- if (if_modifier != ERROR_MARK)
- {
- if (c_parser_peek_2nd_token (parser)->type == CPP_COLON)
- {
- c_parser_consume_token (parser);
- c_parser_consume_token (parser);
- }
- else
- {
- if (n > 2)
- {
- location_t loc = c_parser_peek_2nd_token (parser)->location;
- error_at (loc, "expected %<:%>");
- }
- if_modifier = ERROR_MARK;
- }
- }
- }
-
- location_t loc = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (loc, expr, true, true);
- tree t = c_objc_common_truthvalue_conversion (loc, expr.value), c;
- t = c_fully_fold (t, false, NULL);
- parens.skip_until_found_close (parser);
-
- for (c = list; c ; c = OMP_CLAUSE_CHAIN (c))
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IF)
- {
- if (if_modifier != ERROR_MARK
- && OMP_CLAUSE_IF_MODIFIER (c) == if_modifier)
- {
- const char *p = NULL;
- switch (if_modifier)
- {
- case VOID_CST: p = "cancel"; break;
- case OMP_PARALLEL: p = "parallel"; break;
- case OMP_SIMD: p = "simd"; break;
- case OMP_TASK: p = "task"; break;
- case OMP_TASKLOOP: p = "taskloop"; break;
- case OMP_TARGET_DATA: p = "target data"; break;
- case OMP_TARGET: p = "target"; break;
- case OMP_TARGET_UPDATE: p = "target update"; break;
- case OMP_TARGET_ENTER_DATA: p = "target enter data"; break;
- case OMP_TARGET_EXIT_DATA: p = "target exit data"; break;
- default: gcc_unreachable ();
- }
- error_at (location, "too many %<if%> clauses with %qs modifier",
- p);
- return list;
- }
- else if (OMP_CLAUSE_IF_MODIFIER (c) == if_modifier)
- {
- if (!is_omp)
- error_at (location, "too many %<if%> clauses");
- else
- error_at (location, "too many %<if%> clauses without modifier");
- return list;
- }
- else if (if_modifier == ERROR_MARK
- || OMP_CLAUSE_IF_MODIFIER (c) == ERROR_MARK)
- {
- error_at (location, "if any %<if%> clause has modifier, then all "
- "%<if%> clauses have to use modifier");
- return list;
- }
- }
-
- c = build_omp_clause (location, OMP_CLAUSE_IF);
- OMP_CLAUSE_IF_MODIFIER (c) = if_modifier;
- OMP_CLAUSE_IF_EXPR (c) = t;
- OMP_CLAUSE_CHAIN (c) = list;
- return c;
-}
-
-/* OpenMP 2.5:
- lastprivate ( variable-list )
-
- OpenMP 5.0:
- lastprivate ( [ lastprivate-modifier : ] variable-list ) */
-
-static tree
-c_parser_omp_clause_lastprivate (c_parser *parser, tree list)
-{
- /* The clauses location. */
- location_t loc = c_parser_peek_token (parser)->location;
-
- if (c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
- {
- bool conditional = false;
- if (c_parser_next_token_is (parser, CPP_NAME)
- && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
- {
- const char *p
- = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (strcmp (p, "conditional") == 0)
- {
- conditional = true;
- c_parser_consume_token (parser);
- c_parser_consume_token (parser);
- }
- }
- tree nlist = c_parser_omp_variable_list (parser, loc,
- OMP_CLAUSE_LASTPRIVATE, list);
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
- if (conditional)
- for (tree c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
- OMP_CLAUSE_LASTPRIVATE_CONDITIONAL (c) = 1;
- return nlist;
- }
- return list;
-}
-
-/* OpenMP 3.1:
- mergeable */
-
-static tree
-c_parser_omp_clause_mergeable (c_parser *parser ATTRIBUTE_UNUSED, tree list)
-{
- tree c;
-
- /* FIXME: Should we allow duplicates? */
- check_no_duplicate_clause (list, OMP_CLAUSE_MERGEABLE, "mergeable");
-
- c = build_omp_clause (c_parser_peek_token (parser)->location,
- OMP_CLAUSE_MERGEABLE);
- OMP_CLAUSE_CHAIN (c) = list;
-
- return c;
-}
-
-/* OpenMP 2.5:
- nowait */
-
-static tree
-c_parser_omp_clause_nowait (c_parser *parser ATTRIBUTE_UNUSED, tree list)
-{
- tree c;
- location_t loc = c_parser_peek_token (parser)->location;
-
- check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait");
-
- c = build_omp_clause (loc, OMP_CLAUSE_NOWAIT);
- OMP_CLAUSE_CHAIN (c) = list;
- return c;
-}
-
-/* OpenMP 2.5:
- num_threads ( expression ) */
-
-static tree
-c_parser_omp_clause_num_threads (c_parser *parser, tree list)
-{
- location_t num_threads_loc = c_parser_peek_token (parser)->location;
- matching_parens parens;
- if (parens.require_open (parser))
- {
- location_t expr_loc = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
- tree c, t = expr.value;
- t = c_fully_fold (t, false, NULL);
-
- parens.skip_until_found_close (parser);
-
- if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
- {
- c_parser_error (parser, "expected integer expression");
- return list;
- }
-
- /* Attempt to statically determine when the number isn't positive. */
- c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
- build_int_cst (TREE_TYPE (t), 0));
- protected_set_expr_location (c, expr_loc);
- if (c == boolean_true_node)
- {
- warning_at (expr_loc, 0,
- "%<num_threads%> value must be positive");
- t = integer_one_node;
- }
-
- check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads");
-
- c = build_omp_clause (num_threads_loc, OMP_CLAUSE_NUM_THREADS);
- OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
- OMP_CLAUSE_CHAIN (c) = list;
- list = c;
- }
-
- return list;
-}
-
-/* OpenMP 4.5:
- num_tasks ( expression )
-
- OpenMP 5.1:
- num_tasks ( strict : expression ) */
-
-static tree
-c_parser_omp_clause_num_tasks (c_parser *parser, tree list)
-{
- location_t num_tasks_loc = c_parser_peek_token (parser)->location;
- matching_parens parens;
- if (parens.require_open (parser))
- {
- bool strict = false;
- if (c_parser_next_token_is (parser, CPP_NAME)
- && c_parser_peek_2nd_token (parser)->type == CPP_COLON
- && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
- "strict") == 0)
- {
- strict = true;
- c_parser_consume_token (parser);
- c_parser_consume_token (parser);
- }
-
- location_t expr_loc = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
- tree c, t = expr.value;
- t = c_fully_fold (t, false, NULL);
-
- parens.skip_until_found_close (parser);
-
- if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
- {
- c_parser_error (parser, "expected integer expression");
- return list;
- }
-
- /* Attempt to statically determine when the number isn't positive. */
- c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
- build_int_cst (TREE_TYPE (t), 0));
- if (CAN_HAVE_LOCATION_P (c))
- SET_EXPR_LOCATION (c, expr_loc);
- if (c == boolean_true_node)
- {
- warning_at (expr_loc, 0, "%<num_tasks%> value must be positive");
- t = integer_one_node;
- }
-
- check_no_duplicate_clause (list, OMP_CLAUSE_NUM_TASKS, "num_tasks");
-
- c = build_omp_clause (num_tasks_loc, OMP_CLAUSE_NUM_TASKS);
- OMP_CLAUSE_NUM_TASKS_EXPR (c) = t;
- OMP_CLAUSE_NUM_TASKS_STRICT (c) = strict;
- OMP_CLAUSE_CHAIN (c) = list;
- list = c;
- }
-
- return list;
-}
-
-/* OpenMP 4.5:
- grainsize ( expression )
-
- OpenMP 5.1:
- grainsize ( strict : expression ) */
-
-static tree
-c_parser_omp_clause_grainsize (c_parser *parser, tree list)
-{
- location_t grainsize_loc = c_parser_peek_token (parser)->location;
- matching_parens parens;
- if (parens.require_open (parser))
- {
- bool strict = false;
- if (c_parser_next_token_is (parser, CPP_NAME)
- && c_parser_peek_2nd_token (parser)->type == CPP_COLON
- && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
- "strict") == 0)
- {
- strict = true;
- c_parser_consume_token (parser);
- c_parser_consume_token (parser);
- }
-
- location_t expr_loc = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
- tree c, t = expr.value;
- t = c_fully_fold (t, false, NULL);
-
- parens.skip_until_found_close (parser);
-
- if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
- {
- c_parser_error (parser, "expected integer expression");
- return list;
- }
-
- /* Attempt to statically determine when the number isn't positive. */
- c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
- build_int_cst (TREE_TYPE (t), 0));
- if (CAN_HAVE_LOCATION_P (c))
- SET_EXPR_LOCATION (c, expr_loc);
- if (c == boolean_true_node)
- {
- warning_at (expr_loc, 0, "%<grainsize%> value must be positive");
- t = integer_one_node;
- }
-
- check_no_duplicate_clause (list, OMP_CLAUSE_GRAINSIZE, "grainsize");
-
- c = build_omp_clause (grainsize_loc, OMP_CLAUSE_GRAINSIZE);
- OMP_CLAUSE_GRAINSIZE_EXPR (c) = t;
- OMP_CLAUSE_GRAINSIZE_STRICT (c) = strict;
- OMP_CLAUSE_CHAIN (c) = list;
- list = c;
- }
-
- return list;
-}
-
-/* OpenMP 4.5:
- priority ( expression ) */
-
-static tree
-c_parser_omp_clause_priority (c_parser *parser, tree list)
-{
- location_t priority_loc = c_parser_peek_token (parser)->location;
- matching_parens parens;
- if (parens.require_open (parser))
- {
- location_t expr_loc = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
- tree c, t = expr.value;
- t = c_fully_fold (t, false, NULL);
-
- parens.skip_until_found_close (parser);
-
- if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
- {
- c_parser_error (parser, "expected integer expression");
- return list;
- }
-
- /* Attempt to statically determine when the number isn't
- non-negative. */
- c = fold_build2_loc (expr_loc, LT_EXPR, boolean_type_node, t,
- build_int_cst (TREE_TYPE (t), 0));
- if (CAN_HAVE_LOCATION_P (c))
- SET_EXPR_LOCATION (c, expr_loc);
- if (c == boolean_true_node)
- {
- warning_at (expr_loc, 0, "%<priority%> value must be non-negative");
- t = integer_one_node;
- }
-
- check_no_duplicate_clause (list, OMP_CLAUSE_PRIORITY, "priority");
-
- c = build_omp_clause (priority_loc, OMP_CLAUSE_PRIORITY);
- OMP_CLAUSE_PRIORITY_EXPR (c) = t;
- OMP_CLAUSE_CHAIN (c) = list;
- list = c;
- }
-
- return list;
-}
-
-/* OpenMP 4.5:
- hint ( expression ) */
-
-static tree
-c_parser_omp_clause_hint (c_parser *parser, tree list)
-{
- location_t hint_loc = c_parser_peek_token (parser)->location;
- matching_parens parens;
- if (parens.require_open (parser))
- {
- location_t expr_loc = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
- tree c, t = expr.value;
- t = c_fully_fold (t, false, NULL);
- if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
- || TREE_CODE (t) != INTEGER_CST
- || tree_int_cst_sgn (t) == -1)
- {
- c_parser_error (parser, "expected constant integer expression "
- "with valid sync-hint value");
- return list;
- }
- parens.skip_until_found_close (parser);
- check_no_duplicate_clause (list, OMP_CLAUSE_HINT, "hint");
-
- c = build_omp_clause (hint_loc, OMP_CLAUSE_HINT);
- OMP_CLAUSE_HINT_EXPR (c) = t;
- OMP_CLAUSE_CHAIN (c) = list;
- list = c;
- }
-
- return list;
-}
-
-/* OpenMP 5.1:
- filter ( integer-expression ) */
-
-static tree
-c_parser_omp_clause_filter (c_parser *parser, tree list)
-{
- location_t hint_loc = c_parser_peek_token (parser)->location;
- matching_parens parens;
- if (parens.require_open (parser))
- {
- location_t expr_loc = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
- tree c, t = expr.value;
- t = c_fully_fold (t, false, NULL);
- if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
- {
- c_parser_error (parser, "expected integer expression");
- return list;
- }
- parens.skip_until_found_close (parser);
- check_no_duplicate_clause (list, OMP_CLAUSE_FILTER, "filter");
-
- c = build_omp_clause (hint_loc, OMP_CLAUSE_FILTER);
- OMP_CLAUSE_FILTER_EXPR (c) = t;
- OMP_CLAUSE_CHAIN (c) = list;
- list = c;
- }
-
- return list;
-}
-
-/* OpenMP 4.5:
- defaultmap ( tofrom : scalar )
-
- OpenMP 5.0:
- defaultmap ( implicit-behavior [ : variable-category ] ) */
-
-static tree
-c_parser_omp_clause_defaultmap (c_parser *parser, tree list)
-{
- location_t loc = c_parser_peek_token (parser)->location;
- tree c;
- const char *p;
- enum omp_clause_defaultmap_kind behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
- enum omp_clause_defaultmap_kind category
- = OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED;
-
- matching_parens parens;
- if (!parens.require_open (parser))
- return list;
- if (c_parser_next_token_is_keyword (parser, RID_DEFAULT))
- p = "default";
- else if (!c_parser_next_token_is (parser, CPP_NAME))
- {
- invalid_behavior:
- c_parser_error (parser, "expected %<alloc%>, %<to%>, %<from%>, "
- "%<tofrom%>, %<firstprivate%>, %<none%> "
- "or %<default%>");
- goto out_err;
- }
- else
- p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-
- switch (p[0])
- {
- case 'a':
- if (strcmp ("alloc", p) == 0)
- behavior = OMP_CLAUSE_DEFAULTMAP_ALLOC;
- else
- goto invalid_behavior;
- break;
-
- case 'd':
- if (strcmp ("default", p) == 0)
- behavior = OMP_CLAUSE_DEFAULTMAP_DEFAULT;
- else
- goto invalid_behavior;
- break;
-
- case 'f':
- if (strcmp ("firstprivate", p) == 0)
- behavior = OMP_CLAUSE_DEFAULTMAP_FIRSTPRIVATE;
- else if (strcmp ("from", p) == 0)
- behavior = OMP_CLAUSE_DEFAULTMAP_FROM;
- else
- goto invalid_behavior;
- break;
-
- case 'n':
- if (strcmp ("none", p) == 0)
- behavior = OMP_CLAUSE_DEFAULTMAP_NONE;
- else
- goto invalid_behavior;
- break;
-
- case 't':
- if (strcmp ("tofrom", p) == 0)
- behavior = OMP_CLAUSE_DEFAULTMAP_TOFROM;
- else if (strcmp ("to", p) == 0)
- behavior = OMP_CLAUSE_DEFAULTMAP_TO;
- else
- goto invalid_behavior;
- break;
-
- default:
- goto invalid_behavior;
- }
- c_parser_consume_token (parser);
-
- if (!c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- {
- if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
- goto out_err;
- if (!c_parser_next_token_is (parser, CPP_NAME))
- {
- invalid_category:
- c_parser_error (parser, "expected %<scalar%>, %<aggregate%> or "
- "%<pointer%>");
- goto out_err;
- }
- p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- switch (p[0])
- {
- case 'a':
- if (strcmp ("aggregate", p) == 0)
- category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE;
- else
- goto invalid_category;
- break;
-
- case 'p':
- if (strcmp ("pointer", p) == 0)
- category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER;
- else
- goto invalid_category;
- break;
-
- case 's':
- if (strcmp ("scalar", p) == 0)
- category = OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR;
- else
- goto invalid_category;
- break;
-
- default:
- goto invalid_category;
- }
-
- c_parser_consume_token (parser);
- }
- parens.skip_until_found_close (parser);
-
- for (c = list; c ; c = OMP_CLAUSE_CHAIN (c))
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEFAULTMAP
- && (category == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED
- || OMP_CLAUSE_DEFAULTMAP_CATEGORY (c) == category
- || (OMP_CLAUSE_DEFAULTMAP_CATEGORY (c)
- == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)))
- {
- enum omp_clause_defaultmap_kind cat = category;
- location_t loc = OMP_CLAUSE_LOCATION (c);
- if (cat == OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED)
- cat = OMP_CLAUSE_DEFAULTMAP_CATEGORY (c);
- p = NULL;
- switch (cat)
- {
- case OMP_CLAUSE_DEFAULTMAP_CATEGORY_UNSPECIFIED:
- p = NULL;
- break;
- case OMP_CLAUSE_DEFAULTMAP_CATEGORY_AGGREGATE:
- p = "aggregate";
- break;
- case OMP_CLAUSE_DEFAULTMAP_CATEGORY_POINTER:
- p = "pointer";
- break;
- case OMP_CLAUSE_DEFAULTMAP_CATEGORY_SCALAR:
- p = "scalar";
- break;
- default:
- gcc_unreachable ();
- }
- if (p)
- error_at (loc, "too many %<defaultmap%> clauses with %qs category",
- p);
- else
- error_at (loc, "too many %<defaultmap%> clauses with unspecified "
- "category");
- break;
- }
-
- c = build_omp_clause (loc, OMP_CLAUSE_DEFAULTMAP);
- OMP_CLAUSE_DEFAULTMAP_SET_KIND (c, behavior, category);
- OMP_CLAUSE_CHAIN (c) = list;
- return c;
-
- out_err:
- parens.skip_until_found_close (parser);
- return list;
-}
-
-/* OpenACC 2.0:
- use_device ( variable-list )
-
- OpenMP 4.5:
- use_device_ptr ( variable-list ) */
-
-static tree
-c_parser_omp_clause_use_device_ptr (c_parser *parser, tree list)
-{
- return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_USE_DEVICE_PTR,
- list);
-}
-
-/* OpenMP 5.0:
- use_device_addr ( variable-list ) */
-
-static tree
-c_parser_omp_clause_use_device_addr (c_parser *parser, tree list)
-{
- return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_USE_DEVICE_ADDR,
- list);
-}
-
-/* OpenMP 4.5:
- is_device_ptr ( variable-list ) */
-
-static tree
-c_parser_omp_clause_is_device_ptr (c_parser *parser, tree list)
-{
- return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_IS_DEVICE_PTR, list);
-}
-
-/* OpenACC:
- num_gangs ( expression )
- num_workers ( expression )
- vector_length ( expression ) */
-
-static tree
-c_parser_oacc_single_int_clause (c_parser *parser, omp_clause_code code,
- tree list)
-{
- location_t loc = c_parser_peek_token (parser)->location;
-
- matching_parens parens;
- if (!parens.require_open (parser))
- return list;
-
- location_t expr_loc = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expression (parser);
- expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
- tree c, t = expr.value;
- t = c_fully_fold (t, false, NULL);
-
- parens.skip_until_found_close (parser);
-
- if (t == error_mark_node)
- return list;
- else if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
- {
- error_at (expr_loc, "%qs expression must be integral",
- omp_clause_code_name[code]);
- return list;
- }
-
- /* Attempt to statically determine when the number isn't positive. */
- c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
- build_int_cst (TREE_TYPE (t), 0));
- protected_set_expr_location (c, expr_loc);
- if (c == boolean_true_node)
- {
- warning_at (expr_loc, 0,
- "%qs value must be positive",
- omp_clause_code_name[code]);
- t = integer_one_node;
- }
-
- check_no_duplicate_clause (list, code, omp_clause_code_name[code]);
-
- c = build_omp_clause (loc, code);
- OMP_CLAUSE_OPERAND (c, 0) = t;
- OMP_CLAUSE_CHAIN (c) = list;
- return c;
-}
-
-/* OpenACC:
-
- gang [( gang-arg-list )]
- worker [( [num:] int-expr )]
- vector [( [length:] int-expr )]
-
- where gang-arg is one of:
-
- [num:] int-expr
- static: size-expr
-
- and size-expr may be:
-
- *
- int-expr
-*/
-
-static tree
-c_parser_oacc_shape_clause (c_parser *parser, location_t loc,
- omp_clause_code kind,
- const char *str, tree list)
-{
- const char *id = "num";
- tree ops[2] = { NULL_TREE, NULL_TREE }, c;
-
- if (kind == OMP_CLAUSE_VECTOR)
- id = "length";
-
- if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
- {
- c_parser_consume_token (parser);
-
- do
- {
- c_token *next = c_parser_peek_token (parser);
- int idx = 0;
-
- /* Gang static argument. */
- if (kind == OMP_CLAUSE_GANG
- && c_parser_next_token_is_keyword (parser, RID_STATIC))
- {
- c_parser_consume_token (parser);
-
- if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
- goto cleanup_error;
-
- idx = 1;
- if (ops[idx] != NULL_TREE)
- {
- c_parser_error (parser, "too many %<static%> arguments");
- goto cleanup_error;
- }
-
- /* Check for the '*' argument. */
- if (c_parser_next_token_is (parser, CPP_MULT)
- && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
- || c_parser_peek_2nd_token (parser)->type
- == CPP_CLOSE_PAREN))
- {
- c_parser_consume_token (parser);
- ops[idx] = integer_minus_one_node;
-
- if (c_parser_next_token_is (parser, CPP_COMMA))
- {
- c_parser_consume_token (parser);
- continue;
- }
- else
- break;
- }
- }
- /* Worker num: argument and vector length: arguments. */
- else if (c_parser_next_token_is (parser, CPP_NAME)
- && strcmp (id, IDENTIFIER_POINTER (next->value)) == 0
- && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
- {
- c_parser_consume_token (parser); /* id */
- c_parser_consume_token (parser); /* ':' */
- }
-
- /* Now collect the actual argument. */
- if (ops[idx] != NULL_TREE)
- {
- c_parser_error (parser, "unexpected argument");
- goto cleanup_error;
- }
-
- location_t expr_loc = c_parser_peek_token (parser)->location;
- c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
- cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true);
- tree expr = cexpr.value;
- if (expr == error_mark_node)
- goto cleanup_error;
-
- expr = c_fully_fold (expr, false, NULL);
-
- /* Attempt to statically determine when the number isn't a
- positive integer. */
-
- if (!INTEGRAL_TYPE_P (TREE_TYPE (expr)))
- {
- c_parser_error (parser, "expected integer expression");
- return list;
- }
-
- tree c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, expr,
- build_int_cst (TREE_TYPE (expr), 0));
- if (c == boolean_true_node)
- {
- warning_at (loc, 0,
- "%qs value must be positive", str);
- expr = integer_one_node;
- }
-
- ops[idx] = expr;
-
- if (kind == OMP_CLAUSE_GANG
- && c_parser_next_token_is (parser, CPP_COMMA))
- {
- c_parser_consume_token (parser);
- continue;
- }
- break;
- }
- while (1);
-
- if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
- goto cleanup_error;
- }
-
- check_no_duplicate_clause (list, kind, str);
-
- c = build_omp_clause (loc, kind);
-
- if (ops[1])
- OMP_CLAUSE_OPERAND (c, 1) = ops[1];
-
- OMP_CLAUSE_OPERAND (c, 0) = ops[0];
- OMP_CLAUSE_CHAIN (c) = list;
-
- return c;
-
- cleanup_error:
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
- return list;
-}
-
-/* OpenACC 2.5:
- auto
- finalize
- independent
- nohost
- seq */
-
-static tree
-c_parser_oacc_simple_clause (location_t loc, enum omp_clause_code code,
- tree list)
-{
- check_no_duplicate_clause (list, code, omp_clause_code_name[code]);
-
- tree c = build_omp_clause (loc, code);
- OMP_CLAUSE_CHAIN (c) = list;
-
- return c;
-}
-
-/* OpenACC:
- async [( int-expr )] */
-
-static tree
-c_parser_oacc_clause_async (c_parser *parser, tree list)
-{
- tree c, t;
- location_t loc = c_parser_peek_token (parser)->location;
-
- t = build_int_cst (integer_type_node, GOMP_ASYNC_NOVAL);
-
- if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
- {
- c_parser_consume_token (parser);
-
- t = c_parser_expr_no_commas (parser, NULL).value;
- if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
- c_parser_error (parser, "expected integer expression");
- else if (t == error_mark_node
- || !c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
- return list;
- }
- else
- t = c_fully_fold (t, false, NULL);
-
- check_no_duplicate_clause (list, OMP_CLAUSE_ASYNC, "async");
-
- c = build_omp_clause (loc, OMP_CLAUSE_ASYNC);
- OMP_CLAUSE_ASYNC_EXPR (c) = t;
- OMP_CLAUSE_CHAIN (c) = list;
- list = c;
-
- return list;
-}
-
-/* OpenACC 2.0:
- tile ( size-expr-list ) */
-
-static tree
-c_parser_oacc_clause_tile (c_parser *parser, tree list)
-{
- tree c, expr = error_mark_node;
- location_t loc;
- tree tile = NULL_TREE;
-
- check_no_duplicate_clause (list, OMP_CLAUSE_TILE, "tile");
- check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse");
-
- loc = c_parser_peek_token (parser)->location;
- if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
- return list;
-
- do
- {
- if (tile && !c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
- return list;
-
- if (c_parser_next_token_is (parser, CPP_MULT)
- && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
- || c_parser_peek_2nd_token (parser)->type == CPP_CLOSE_PAREN))
- {
- c_parser_consume_token (parser);
- expr = integer_zero_node;
- }
- else
- {
- location_t expr_loc = c_parser_peek_token (parser)->location;
- c_expr cexpr = c_parser_expr_no_commas (parser, NULL);
- cexpr = convert_lvalue_to_rvalue (expr_loc, cexpr, false, true);
- expr = cexpr.value;
-
- if (expr == error_mark_node)
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>");
- return list;
- }
-
- expr = c_fully_fold (expr, false, NULL);
-
- if (!INTEGRAL_TYPE_P (TREE_TYPE (expr))
- || !tree_fits_shwi_p (expr)
- || tree_to_shwi (expr) <= 0)
- {
- error_at (expr_loc, "%<tile%> argument needs positive"
- " integral constant");
- expr = integer_zero_node;
- }
- }
-
- tile = tree_cons (NULL_TREE, expr, tile);
- }
- while (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN));
-
- /* Consume the trailing ')'. */
- c_parser_consume_token (parser);
-
- c = build_omp_clause (loc, OMP_CLAUSE_TILE);
- tile = nreverse (tile);
- OMP_CLAUSE_TILE_LIST (c) = tile;
- OMP_CLAUSE_CHAIN (c) = list;
- return c;
-}
-
-/* OpenACC:
- wait [( int-expr-list )] */
-
-static tree
-c_parser_oacc_clause_wait (c_parser *parser, tree list)
-{
- location_t clause_loc = c_parser_peek_token (parser)->location;
-
- if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
- list = c_parser_oacc_wait_list (parser, clause_loc, list);
- else
- {
- tree c = build_omp_clause (clause_loc, OMP_CLAUSE_WAIT);
-
- OMP_CLAUSE_DECL (c) = build_int_cst (integer_type_node, GOMP_ASYNC_NOVAL);
- OMP_CLAUSE_CHAIN (c) = list;
- list = c;
- }
-
- return list;
-}
-
-
-/* OpenMP 5.0:
- order ( concurrent )
-
- OpenMP 5.1:
- order ( order-modifier : concurrent )
-
- order-modifier:
- reproducible
- unconstrained */
-
-static tree
-c_parser_omp_clause_order (c_parser *parser, tree list)
-{
- location_t loc = c_parser_peek_token (parser)->location;
- tree c;
- const char *p;
- bool unconstrained = false;
- bool reproducible = false;
-
- matching_parens parens;
- if (!parens.require_open (parser))
- return list;
- if (c_parser_next_token_is (parser, CPP_NAME)
- && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
- {
- p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (strcmp (p, "unconstrained") == 0)
- unconstrained = true;
- else if (strcmp (p, "reproducible") == 0)
- reproducible = true;
- else
- {
- c_parser_error (parser, "expected %<reproducible%> or "
- "%<unconstrained%>");
- goto out_err;
- }
- c_parser_consume_token (parser);
- c_parser_consume_token (parser);
- }
- if (!c_parser_next_token_is (parser, CPP_NAME))
- {
- c_parser_error (parser, "expected %<concurrent%>");
- goto out_err;
- }
- p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (strcmp (p, "concurrent") != 0)
- {
- c_parser_error (parser, "expected %<concurrent%>");
- goto out_err;
- }
- c_parser_consume_token (parser);
- parens.skip_until_found_close (parser);
- check_no_duplicate_clause (list, OMP_CLAUSE_ORDER, "order");
- c = build_omp_clause (loc, OMP_CLAUSE_ORDER);
- OMP_CLAUSE_ORDER_UNCONSTRAINED (c) = unconstrained;
- OMP_CLAUSE_ORDER_REPRODUCIBLE (c) = reproducible;
- OMP_CLAUSE_CHAIN (c) = list;
- return c;
-
- out_err:
- parens.skip_until_found_close (parser);
- return list;
-}
-
-
-/* OpenMP 5.0:
- bind ( teams | parallel | thread ) */
-
-static tree
-c_parser_omp_clause_bind (c_parser *parser, tree list)
-{
- location_t loc = c_parser_peek_token (parser)->location;
- tree c;
- const char *p;
- enum omp_clause_bind_kind kind = OMP_CLAUSE_BIND_THREAD;
-
- matching_parens parens;
- if (!parens.require_open (parser))
- return list;
- if (!c_parser_next_token_is (parser, CPP_NAME))
- {
- invalid:
- c_parser_error (parser,
- "expected %<teams%>, %<parallel%> or %<thread%>");
- parens.skip_until_found_close (parser);
- return list;
- }
- p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (strcmp (p, "teams") == 0)
- kind = OMP_CLAUSE_BIND_TEAMS;
- else if (strcmp (p, "parallel") == 0)
- kind = OMP_CLAUSE_BIND_PARALLEL;
- else if (strcmp (p, "thread") != 0)
- goto invalid;
- c_parser_consume_token (parser);
- parens.skip_until_found_close (parser);
- /* check_no_duplicate_clause (list, OMP_CLAUSE_BIND, "bind"); */
- c = build_omp_clause (loc, OMP_CLAUSE_BIND);
- OMP_CLAUSE_BIND_KIND (c) = kind;
- OMP_CLAUSE_CHAIN (c) = list;
- return c;
-}
-
-
-/* OpenMP 2.5:
- ordered
-
- OpenMP 4.5:
- ordered ( constant-expression ) */
-
-static tree
-c_parser_omp_clause_ordered (c_parser *parser, tree list)
-{
- check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered");
-
- tree c, num = NULL_TREE;
- HOST_WIDE_INT n;
- location_t loc = c_parser_peek_token (parser)->location;
- if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
- {
- matching_parens parens;
- parens.consume_open (parser);
- num = c_parser_expr_no_commas (parser, NULL).value;
- parens.skip_until_found_close (parser);
- }
- if (num == error_mark_node)
- return list;
- if (num)
- {
- mark_exp_read (num);
- num = c_fully_fold (num, false, NULL);
- if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
- || !tree_fits_shwi_p (num)
- || (n = tree_to_shwi (num)) <= 0
- || (int) n != n)
- {
- error_at (loc, "ordered argument needs positive "
- "constant integer expression");
- return list;
- }
- }
- c = build_omp_clause (loc, OMP_CLAUSE_ORDERED);
- OMP_CLAUSE_ORDERED_EXPR (c) = num;
- OMP_CLAUSE_CHAIN (c) = list;
- return c;
-}
-
-/* OpenMP 2.5:
- private ( variable-list ) */
-
-static tree
-c_parser_omp_clause_private (c_parser *parser, tree list)
-{
- return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_PRIVATE, list);
-}
-
-/* OpenMP 2.5:
- reduction ( reduction-operator : variable-list )
-
- reduction-operator:
- One of: + * - & ^ | && ||
-
- OpenMP 3.1:
-
- reduction-operator:
- One of: + * - & ^ | && || max min
-
- OpenMP 4.0:
-
- reduction-operator:
- One of: + * - & ^ | && ||
- identifier
-
- OpenMP 5.0:
- reduction ( reduction-modifier, reduction-operator : variable-list )
- in_reduction ( reduction-operator : variable-list )
- task_reduction ( reduction-operator : variable-list ) */
-
-static tree
-c_parser_omp_clause_reduction (c_parser *parser, enum omp_clause_code kind,
- bool is_omp, tree list)
-{
- location_t clause_loc = c_parser_peek_token (parser)->location;
- matching_parens parens;
- if (parens.require_open (parser))
- {
- bool task = false;
- bool inscan = false;
- enum tree_code code = ERROR_MARK;
- tree reduc_id = NULL_TREE;
-
- if (kind == OMP_CLAUSE_REDUCTION && is_omp)
- {
- if (c_parser_next_token_is_keyword (parser, RID_DEFAULT)
- && c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
- {
- c_parser_consume_token (parser);
- c_parser_consume_token (parser);
- }
- else if (c_parser_next_token_is (parser, CPP_NAME)
- && c_parser_peek_2nd_token (parser)->type == CPP_COMMA)
- {
- const char *p
- = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (strcmp (p, "task") == 0)
- task = true;
- else if (strcmp (p, "inscan") == 0)
- inscan = true;
- if (task || inscan)
- {
- c_parser_consume_token (parser);
- c_parser_consume_token (parser);
- }
- }
- }
-
- switch (c_parser_peek_token (parser)->type)
- {
- case CPP_PLUS:
- code = PLUS_EXPR;
- break;
- case CPP_MULT:
- code = MULT_EXPR;
- break;
- case CPP_MINUS:
- code = MINUS_EXPR;
- break;
- case CPP_AND:
- code = BIT_AND_EXPR;
- break;
- case CPP_XOR:
- code = BIT_XOR_EXPR;
- break;
- case CPP_OR:
- code = BIT_IOR_EXPR;
- break;
- case CPP_AND_AND:
- code = TRUTH_ANDIF_EXPR;
- break;
- case CPP_OR_OR:
- code = TRUTH_ORIF_EXPR;
- break;
- case CPP_NAME:
- {
- const char *p
- = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (strcmp (p, "min") == 0)
- {
- code = MIN_EXPR;
- break;
- }
- if (strcmp (p, "max") == 0)
- {
- code = MAX_EXPR;
- break;
- }
- reduc_id = c_parser_peek_token (parser)->value;
- break;
- }
- default:
- c_parser_error (parser,
- "expected %<+%>, %<*%>, %<-%>, %<&%>, "
- "%<^%>, %<|%>, %<&&%>, %<||%> or identifier");
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
- return list;
- }
- c_parser_consume_token (parser);
- reduc_id = c_omp_reduction_id (code, reduc_id);
- if (c_parser_require (parser, CPP_COLON, "expected %<:%>"))
- {
- tree nl, c;
-
- nl = c_parser_omp_variable_list (parser, clause_loc, kind, list);
- for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
- {
- tree d = OMP_CLAUSE_DECL (c), type;
- if (TREE_CODE (d) != TREE_LIST)
- type = TREE_TYPE (d);
- else
- {
- int cnt = 0;
- tree t;
- for (t = d; TREE_CODE (t) == TREE_LIST; t = TREE_CHAIN (t))
- cnt++;
- type = TREE_TYPE (t);
- while (cnt > 0)
- {
- if (TREE_CODE (type) != POINTER_TYPE
- && TREE_CODE (type) != ARRAY_TYPE)
- break;
- type = TREE_TYPE (type);
- cnt--;
- }
- }
- while (TREE_CODE (type) == ARRAY_TYPE)
- type = TREE_TYPE (type);
- OMP_CLAUSE_REDUCTION_CODE (c) = code;
- if (task)
- OMP_CLAUSE_REDUCTION_TASK (c) = 1;
- else if (inscan)
- OMP_CLAUSE_REDUCTION_INSCAN (c) = 1;
- if (code == ERROR_MARK
- || !(INTEGRAL_TYPE_P (type)
- || TREE_CODE (type) == REAL_TYPE
- || TREE_CODE (type) == COMPLEX_TYPE))
- OMP_CLAUSE_REDUCTION_PLACEHOLDER (c)
- = c_omp_reduction_lookup (reduc_id,
- TYPE_MAIN_VARIANT (type));
- }
-
- list = nl;
- }
- parens.skip_until_found_close (parser);
- }
- return list;
-}
-
-/* OpenMP 2.5:
- schedule ( schedule-kind )
- schedule ( schedule-kind , expression )
-
- schedule-kind:
- static | dynamic | guided | runtime | auto
-
- OpenMP 4.5:
- schedule ( schedule-modifier : schedule-kind )
- schedule ( schedule-modifier [ , schedule-modifier ] : schedule-kind , expression )
-
- schedule-modifier:
- simd
- monotonic
- nonmonotonic */
-
-static tree
-c_parser_omp_clause_schedule (c_parser *parser, tree list)
-{
- tree c, t;
- location_t loc = c_parser_peek_token (parser)->location;
- int modifiers = 0, nmodifiers = 0;
-
- matching_parens parens;
- if (!parens.require_open (parser))
- return list;
-
- c = build_omp_clause (loc, OMP_CLAUSE_SCHEDULE);
-
- location_t comma = UNKNOWN_LOCATION;
- while (c_parser_next_token_is (parser, CPP_NAME))
- {
- tree kind = c_parser_peek_token (parser)->value;
- const char *p = IDENTIFIER_POINTER (kind);
- if (strcmp ("simd", p) == 0)
- OMP_CLAUSE_SCHEDULE_SIMD (c) = 1;
- else if (strcmp ("monotonic", p) == 0)
- modifiers |= OMP_CLAUSE_SCHEDULE_MONOTONIC;
- else if (strcmp ("nonmonotonic", p) == 0)
- modifiers |= OMP_CLAUSE_SCHEDULE_NONMONOTONIC;
- else
- break;
- comma = UNKNOWN_LOCATION;
- c_parser_consume_token (parser);
- if (nmodifiers++ == 0
- && c_parser_next_token_is (parser, CPP_COMMA))
- {
- comma = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
- }
- else
- {
- c_parser_require (parser, CPP_COLON, "expected %<:%>");
- break;
- }
- }
- if (comma != UNKNOWN_LOCATION)
- error_at (comma, "expected %<:%>");
-
- if ((modifiers & (OMP_CLAUSE_SCHEDULE_MONOTONIC
- | OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
- == (OMP_CLAUSE_SCHEDULE_MONOTONIC
- | OMP_CLAUSE_SCHEDULE_NONMONOTONIC))
- {
- error_at (loc, "both %<monotonic%> and %<nonmonotonic%> modifiers "
- "specified");
- modifiers = 0;
- }
-
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- tree kind = c_parser_peek_token (parser)->value;
- const char *p = IDENTIFIER_POINTER (kind);
-
- switch (p[0])
- {
- case 'd':
- if (strcmp ("dynamic", p) != 0)
- goto invalid_kind;
- OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
- break;
-
- case 'g':
- if (strcmp ("guided", p) != 0)
- goto invalid_kind;
- OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
- break;
-
- case 'r':
- if (strcmp ("runtime", p) != 0)
- goto invalid_kind;
- OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
- break;
-
- default:
- goto invalid_kind;
- }
- }
- else if (c_parser_next_token_is_keyword (parser, RID_STATIC))
- OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
- else if (c_parser_next_token_is_keyword (parser, RID_AUTO))
- OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
- else
- goto invalid_kind;
-
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_COMMA))
- {
- location_t here;
- c_parser_consume_token (parser);
-
- here = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (here, expr, false, true);
- t = expr.value;
- t = c_fully_fold (t, false, NULL);
-
- if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
- error_at (here, "schedule %<runtime%> does not take "
- "a %<chunk_size%> parameter");
- else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO)
- error_at (here,
- "schedule %<auto%> does not take "
- "a %<chunk_size%> parameter");
- else if (TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE)
- {
- /* Attempt to statically determine when the number isn't
- positive. */
- tree s = fold_build2_loc (loc, LE_EXPR, boolean_type_node, t,
- build_int_cst (TREE_TYPE (t), 0));
- protected_set_expr_location (s, loc);
- if (s == boolean_true_node)
- {
- warning_at (loc, 0,
- "chunk size value must be positive");
- t = integer_one_node;
- }
- OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
- }
- else
- c_parser_error (parser, "expected integer expression");
-
- parens.skip_until_found_close (parser);
- }
- else
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<,%> or %<)%>");
-
- OMP_CLAUSE_SCHEDULE_KIND (c)
- = (enum omp_clause_schedule_kind)
- (OMP_CLAUSE_SCHEDULE_KIND (c) | modifiers);
-
- check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule");
- OMP_CLAUSE_CHAIN (c) = list;
- return c;
-
- invalid_kind:
- c_parser_error (parser, "invalid schedule kind");
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, 0);
- return list;
-}
-
-/* OpenMP 2.5:
- shared ( variable-list ) */
-
-static tree
-c_parser_omp_clause_shared (c_parser *parser, tree list)
-{
- return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_SHARED, list);
-}
-
-/* OpenMP 3.0:
- untied */
-
-static tree
-c_parser_omp_clause_untied (c_parser *parser ATTRIBUTE_UNUSED, tree list)
-{
- tree c;
-
- /* FIXME: Should we allow duplicates? */
- check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied");
-
- c = build_omp_clause (c_parser_peek_token (parser)->location,
- OMP_CLAUSE_UNTIED);
- OMP_CLAUSE_CHAIN (c) = list;
-
- return c;
-}
-
-/* OpenMP 4.0:
- inbranch
- notinbranch */
-
-static tree
-c_parser_omp_clause_branch (c_parser *parser ATTRIBUTE_UNUSED,
- enum omp_clause_code code, tree list)
-{
- check_no_duplicate_clause (list, code, omp_clause_code_name[code]);
-
- tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
- OMP_CLAUSE_CHAIN (c) = list;
-
- return c;
-}
-
-/* OpenMP 4.0:
- parallel
- for
- sections
- taskgroup */
-
-static tree
-c_parser_omp_clause_cancelkind (c_parser *parser ATTRIBUTE_UNUSED,
- enum omp_clause_code code, tree list)
-{
- tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
- OMP_CLAUSE_CHAIN (c) = list;
-
- return c;
-}
-
-/* OpenMP 4.5:
- nogroup */
-
-static tree
-c_parser_omp_clause_nogroup (c_parser *parser ATTRIBUTE_UNUSED, tree list)
-{
- check_no_duplicate_clause (list, OMP_CLAUSE_NOGROUP, "nogroup");
- tree c = build_omp_clause (c_parser_peek_token (parser)->location,
- OMP_CLAUSE_NOGROUP);
- OMP_CLAUSE_CHAIN (c) = list;
- return c;
-}
-
-/* OpenMP 4.5:
- simd
- threads */
-
-static tree
-c_parser_omp_clause_orderedkind (c_parser *parser ATTRIBUTE_UNUSED,
- enum omp_clause_code code, tree list)
-{
- check_no_duplicate_clause (list, code, omp_clause_code_name[code]);
- tree c = build_omp_clause (c_parser_peek_token (parser)->location, code);
- OMP_CLAUSE_CHAIN (c) = list;
- return c;
-}
-
-/* OpenMP 4.0:
- num_teams ( expression )
-
- OpenMP 5.1:
- num_teams ( expression : expression ) */
-
-static tree
-c_parser_omp_clause_num_teams (c_parser *parser, tree list)
-{
- location_t num_teams_loc = c_parser_peek_token (parser)->location;
- matching_parens parens;
- if (parens.require_open (parser))
- {
- location_t upper_loc = c_parser_peek_token (parser)->location;
- location_t lower_loc = UNKNOWN_LOCATION;
- c_expr expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (upper_loc, expr, false, true);
- tree c, upper = expr.value, lower = NULL_TREE;
- upper = c_fully_fold (upper, false, NULL);
-
- if (c_parser_next_token_is (parser, CPP_COLON))
- {
- c_parser_consume_token (parser);
- lower_loc = upper_loc;
- lower = upper;
- upper_loc = c_parser_peek_token (parser)->location;
- expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (upper_loc, expr, false, true);
- upper = expr.value;
- upper = c_fully_fold (upper, false, NULL);
- }
-
- parens.skip_until_found_close (parser);
-
- if (!INTEGRAL_TYPE_P (TREE_TYPE (upper))
- || (lower && !INTEGRAL_TYPE_P (TREE_TYPE (lower))))
- {
- c_parser_error (parser, "expected integer expression");
- return list;
- }
-
- /* Attempt to statically determine when the number isn't positive. */
- c = fold_build2_loc (upper_loc, LE_EXPR, boolean_type_node, upper,
- build_int_cst (TREE_TYPE (upper), 0));
- protected_set_expr_location (c, upper_loc);
- if (c == boolean_true_node)
- {
- warning_at (upper_loc, 0, "%<num_teams%> value must be positive");
- upper = integer_one_node;
- }
- if (lower)
- {
- c = fold_build2_loc (lower_loc, LE_EXPR, boolean_type_node, lower,
- build_int_cst (TREE_TYPE (lower), 0));
- protected_set_expr_location (c, lower_loc);
- if (c == boolean_true_node)
- {
- warning_at (lower_loc, 0, "%<num_teams%> value must be positive");
- lower = NULL_TREE;
- }
- else if (TREE_CODE (lower) == INTEGER_CST
- && TREE_CODE (upper) == INTEGER_CST
- && tree_int_cst_lt (upper, lower))
- {
- warning_at (lower_loc, 0, "%<num_teams%> lower bound %qE bigger "
- "than upper bound %qE", lower, upper);
- lower = NULL_TREE;
- }
- }
-
- check_no_duplicate_clause (list, OMP_CLAUSE_NUM_TEAMS, "num_teams");
-
- c = build_omp_clause (num_teams_loc, OMP_CLAUSE_NUM_TEAMS);
- OMP_CLAUSE_NUM_TEAMS_UPPER_EXPR (c) = upper;
- OMP_CLAUSE_NUM_TEAMS_LOWER_EXPR (c) = lower;
- OMP_CLAUSE_CHAIN (c) = list;
- list = c;
- }
-
- return list;
-}
-
-/* OpenMP 4.0:
- thread_limit ( expression ) */
-
-static tree
-c_parser_omp_clause_thread_limit (c_parser *parser, tree list)
-{
- location_t num_thread_limit_loc = c_parser_peek_token (parser)->location;
- matching_parens parens;
- if (parens.require_open (parser))
- {
- location_t expr_loc = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
- tree c, t = expr.value;
- t = c_fully_fold (t, false, NULL);
-
- parens.skip_until_found_close (parser);
-
- if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
- {
- c_parser_error (parser, "expected integer expression");
- return list;
- }
-
- /* Attempt to statically determine when the number isn't positive. */
- c = fold_build2_loc (expr_loc, LE_EXPR, boolean_type_node, t,
- build_int_cst (TREE_TYPE (t), 0));
- protected_set_expr_location (c, expr_loc);
- if (c == boolean_true_node)
- {
- warning_at (expr_loc, 0, "%<thread_limit%> value must be positive");
- t = integer_one_node;
- }
-
- check_no_duplicate_clause (list, OMP_CLAUSE_THREAD_LIMIT,
- "thread_limit");
-
- c = build_omp_clause (num_thread_limit_loc, OMP_CLAUSE_THREAD_LIMIT);
- OMP_CLAUSE_THREAD_LIMIT_EXPR (c) = t;
- OMP_CLAUSE_CHAIN (c) = list;
- list = c;
- }
-
- return list;
-}
-
-/* OpenMP 4.0:
- aligned ( variable-list )
- aligned ( variable-list : constant-expression ) */
-
-static tree
-c_parser_omp_clause_aligned (c_parser *parser, tree list)
-{
- location_t clause_loc = c_parser_peek_token (parser)->location;
- tree nl, c;
-
- matching_parens parens;
- if (!parens.require_open (parser))
- return list;
-
- nl = c_parser_omp_variable_list (parser, clause_loc,
- OMP_CLAUSE_ALIGNED, list);
-
- if (c_parser_next_token_is (parser, CPP_COLON))
- {
- c_parser_consume_token (parser);
- location_t expr_loc = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
- tree alignment = expr.value;
- alignment = c_fully_fold (alignment, false, NULL);
- if (TREE_CODE (alignment) != INTEGER_CST
- || !INTEGRAL_TYPE_P (TREE_TYPE (alignment))
- || tree_int_cst_sgn (alignment) != 1)
- {
- error_at (clause_loc, "%<aligned%> clause alignment expression must "
- "be positive constant integer expression");
- alignment = NULL_TREE;
- }
-
- for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
- OMP_CLAUSE_ALIGNED_ALIGNMENT (c) = alignment;
- }
-
- parens.skip_until_found_close (parser);
- return nl;
-}
-
-/* OpenMP 5.0:
- allocate ( variable-list )
- allocate ( expression : variable-list )
-
- OpenMP 5.1:
- allocate ( allocator-modifier : variable-list )
- allocate ( allocator-modifier , allocator-modifier : variable-list )
-
- allocator-modifier:
- allocator ( expression )
- align ( expression ) */
-
-static tree
-c_parser_omp_clause_allocate (c_parser *parser, tree list)
-{
- location_t clause_loc = c_parser_peek_token (parser)->location;
- tree nl, c;
- tree allocator = NULL_TREE;
- tree align = NULL_TREE;
-
- matching_parens parens;
- if (!parens.require_open (parser))
- return list;
-
- if ((c_parser_next_token_is_not (parser, CPP_NAME)
- && c_parser_next_token_is_not (parser, CPP_KEYWORD))
- || (c_parser_peek_2nd_token (parser)->type != CPP_COMMA
- && c_parser_peek_2nd_token (parser)->type != CPP_CLOSE_PAREN))
- {
- bool has_modifiers = false;
- tree orig_type = NULL_TREE;
- if (c_parser_next_token_is (parser, CPP_NAME)
- && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
- {
- unsigned int n = 3;
- const char *p
- = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if ((strcmp (p, "allocator") == 0 || strcmp (p, "align") == 0)
- && c_parser_check_balanced_raw_token_sequence (parser, &n)
- && (c_parser_peek_nth_token_raw (parser, n)->type
- == CPP_CLOSE_PAREN))
- {
- if (c_parser_peek_nth_token_raw (parser, n + 1)->type
- == CPP_COLON)
- has_modifiers = true;
- else if (c_parser_peek_nth_token_raw (parser, n + 1)->type
- == CPP_COMMA
- && (c_parser_peek_nth_token_raw (parser, n + 2)->type
- == CPP_NAME)
- && (c_parser_peek_nth_token_raw (parser, n + 3)->type
- == CPP_OPEN_PAREN))
- {
- c_token *tok = c_parser_peek_nth_token_raw (parser, n + 2);
- const char *q = IDENTIFIER_POINTER (tok->value);
- n += 4;
- if ((strcmp (q, "allocator") == 0
- || strcmp (q, "align") == 0)
- && c_parser_check_balanced_raw_token_sequence (parser,
- &n)
- && (c_parser_peek_nth_token_raw (parser, n)->type
- == CPP_CLOSE_PAREN)
- && (c_parser_peek_nth_token_raw (parser, n + 1)->type
- == CPP_COLON))
- has_modifiers = true;
- }
- }
- if (has_modifiers)
- {
- c_parser_consume_token (parser);
- matching_parens parens2;;
- parens2.require_open (parser);
- location_t expr_loc = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
- if (strcmp (p, "allocator") == 0)
- {
- allocator = expr.value;
- allocator = c_fully_fold (allocator, false, NULL);
- orig_type = expr.original_type
- ? expr.original_type : TREE_TYPE (allocator);
- orig_type = TYPE_MAIN_VARIANT (orig_type);
- }
- else
- {
- align = expr.value;
- align = c_fully_fold (align, false, NULL);
- }
- parens2.skip_until_found_close (parser);
- if (c_parser_next_token_is (parser, CPP_COMMA))
- {
- c_parser_consume_token (parser);
- c_token *tok = c_parser_peek_token (parser);
- const char *q = "";
- if (c_parser_next_token_is (parser, CPP_NAME))
- q = IDENTIFIER_POINTER (tok->value);
- if (strcmp (q, "allocator") != 0 && strcmp (q, "align") != 0)
- {
- c_parser_error (parser, "expected %<allocator%> or "
- "%<align%>");
- parens.skip_until_found_close (parser);
- return list;
- }
- else if (strcmp (p, q) == 0)
- {
- error_at (tok->location, "duplicate %qs modifier", p);
- parens.skip_until_found_close (parser);
- return list;
- }
- c_parser_consume_token (parser);
- if (!parens2.require_open (parser))
- {
- parens.skip_until_found_close (parser);
- return list;
- }
- expr_loc = c_parser_peek_token (parser)->location;
- expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (expr_loc, expr, false,
- true);
- if (strcmp (q, "allocator") == 0)
- {
- allocator = expr.value;
- allocator = c_fully_fold (allocator, false, NULL);
- orig_type = expr.original_type
- ? expr.original_type : TREE_TYPE (allocator);
- orig_type = TYPE_MAIN_VARIANT (orig_type);
- }
- else
- {
- align = expr.value;
- align = c_fully_fold (align, false, NULL);
- }
- parens2.skip_until_found_close (parser);
- }
- }
- }
- if (!has_modifiers)
- {
- location_t expr_loc = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
- allocator = expr.value;
- allocator = c_fully_fold (allocator, false, NULL);
- orig_type = expr.original_type
- ? expr.original_type : TREE_TYPE (allocator);
- orig_type = TYPE_MAIN_VARIANT (orig_type);
- }
- if (allocator
- && (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
- || TREE_CODE (orig_type) != ENUMERAL_TYPE
- || (TYPE_NAME (orig_type)
- != get_identifier ("omp_allocator_handle_t"))))
- {
- error_at (clause_loc, "%<allocate%> clause allocator expression "
- "has type %qT rather than "
- "%<omp_allocator_handle_t%>",
- TREE_TYPE (allocator));
- allocator = NULL_TREE;
- }
- if (align
- && (!INTEGRAL_TYPE_P (TREE_TYPE (align))
- || !tree_fits_uhwi_p (align)
- || !integer_pow2p (align)))
- {
- error_at (clause_loc, "%<allocate%> clause %<align%> modifier "
- "argument needs to be positive constant "
- "power of two integer expression");
- align = NULL_TREE;
- }
- if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
- {
- parens.skip_until_found_close (parser);
- return list;
- }
- }
-
- nl = c_parser_omp_variable_list (parser, clause_loc,
- OMP_CLAUSE_ALLOCATE, list);
-
- if (allocator || align)
- for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
- {
- OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
- OMP_CLAUSE_ALLOCATE_ALIGN (c) = align;
- }
-
- parens.skip_until_found_close (parser);
- return nl;
-}
-
-/* OpenMP 4.0:
- linear ( variable-list )
- linear ( variable-list : expression )
-
- OpenMP 4.5:
- linear ( modifier ( variable-list ) )
- linear ( modifier ( variable-list ) : expression ) */
-
-static tree
-c_parser_omp_clause_linear (c_parser *parser, tree list)
-{
- location_t clause_loc = c_parser_peek_token (parser)->location;
- tree nl, c, step;
- enum omp_clause_linear_kind kind = OMP_CLAUSE_LINEAR_DEFAULT;
-
- matching_parens parens;
- if (!parens.require_open (parser))
- return list;
-
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- c_token *tok = c_parser_peek_token (parser);
- const char *p = IDENTIFIER_POINTER (tok->value);
- if (strcmp ("val", p) == 0)
- kind = OMP_CLAUSE_LINEAR_VAL;
- if (c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN)
- kind = OMP_CLAUSE_LINEAR_DEFAULT;
- if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
- {
- c_parser_consume_token (parser);
- c_parser_consume_token (parser);
- }
- }
-
- nl = c_parser_omp_variable_list (parser, clause_loc,
- OMP_CLAUSE_LINEAR, list);
-
- if (kind != OMP_CLAUSE_LINEAR_DEFAULT)
- parens.skip_until_found_close (parser);
-
- if (c_parser_next_token_is (parser, CPP_COLON))
- {
- c_parser_consume_token (parser);
- location_t expr_loc = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
- step = expr.value;
- step = c_fully_fold (step, false, NULL);
- if (!INTEGRAL_TYPE_P (TREE_TYPE (step)))
- {
- error_at (clause_loc, "%<linear%> clause step expression must "
- "be integral");
- step = integer_one_node;
- }
-
- }
- else
- step = integer_one_node;
-
- for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
- {
- OMP_CLAUSE_LINEAR_STEP (c) = step;
- OMP_CLAUSE_LINEAR_KIND (c) = kind;
- }
-
- parens.skip_until_found_close (parser);
- return nl;
-}
-
-/* OpenMP 5.0:
- nontemporal ( variable-list ) */
-
-static tree
-c_parser_omp_clause_nontemporal (c_parser *parser, tree list)
-{
- return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_NONTEMPORAL, list);
-}
-
-/* OpenMP 4.0:
- safelen ( constant-expression ) */
-
-static tree
-c_parser_omp_clause_safelen (c_parser *parser, tree list)
-{
- location_t clause_loc = c_parser_peek_token (parser)->location;
- tree c, t;
-
- matching_parens parens;
- if (!parens.require_open (parser))
- return list;
-
- location_t expr_loc = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
- t = expr.value;
- t = c_fully_fold (t, false, NULL);
- if (TREE_CODE (t) != INTEGER_CST
- || !INTEGRAL_TYPE_P (TREE_TYPE (t))
- || tree_int_cst_sgn (t) != 1)
- {
- error_at (clause_loc, "%<safelen%> clause expression must "
- "be positive constant integer expression");
- t = NULL_TREE;
- }
-
- parens.skip_until_found_close (parser);
- if (t == NULL_TREE || t == error_mark_node)
- return list;
-
- check_no_duplicate_clause (list, OMP_CLAUSE_SAFELEN, "safelen");
-
- c = build_omp_clause (clause_loc, OMP_CLAUSE_SAFELEN);
- OMP_CLAUSE_SAFELEN_EXPR (c) = t;
- OMP_CLAUSE_CHAIN (c) = list;
- return c;
-}
-
-/* OpenMP 4.0:
- simdlen ( constant-expression ) */
-
-static tree
-c_parser_omp_clause_simdlen (c_parser *parser, tree list)
-{
- location_t clause_loc = c_parser_peek_token (parser)->location;
- tree c, t;
-
- matching_parens parens;
- if (!parens.require_open (parser))
- return list;
-
- location_t expr_loc = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
- t = expr.value;
- t = c_fully_fold (t, false, NULL);
- if (TREE_CODE (t) != INTEGER_CST
- || !INTEGRAL_TYPE_P (TREE_TYPE (t))
- || tree_int_cst_sgn (t) != 1)
- {
- error_at (clause_loc, "%<simdlen%> clause expression must "
- "be positive constant integer expression");
- t = NULL_TREE;
- }
-
- parens.skip_until_found_close (parser);
- if (t == NULL_TREE || t == error_mark_node)
- return list;
-
- check_no_duplicate_clause (list, OMP_CLAUSE_SIMDLEN, "simdlen");
-
- c = build_omp_clause (clause_loc, OMP_CLAUSE_SIMDLEN);
- OMP_CLAUSE_SIMDLEN_EXPR (c) = t;
- OMP_CLAUSE_CHAIN (c) = list;
- return c;
-}
-
-/* OpenMP 4.5:
- vec:
- identifier [+/- integer]
- vec , identifier [+/- integer]
-*/
-
-static tree
-c_parser_omp_clause_depend_sink (c_parser *parser, location_t clause_loc,
- tree list)
-{
- tree vec = NULL;
- if (c_parser_next_token_is_not (parser, CPP_NAME)
- || c_parser_peek_token (parser)->id_kind != C_ID_ID)
- {
- c_parser_error (parser, "expected identifier");
- return list;
- }
-
- while (c_parser_next_token_is (parser, CPP_NAME)
- && c_parser_peek_token (parser)->id_kind == C_ID_ID)
- {
- tree t = lookup_name (c_parser_peek_token (parser)->value);
- tree addend = NULL;
-
- if (t == NULL_TREE)
- {
- undeclared_variable (c_parser_peek_token (parser)->location,
- c_parser_peek_token (parser)->value);
- t = error_mark_node;
- }
-
- c_parser_consume_token (parser);
-
- bool neg = false;
- if (c_parser_next_token_is (parser, CPP_MINUS))
- neg = true;
- else if (!c_parser_next_token_is (parser, CPP_PLUS))
- {
- addend = integer_zero_node;
- neg = false;
- goto add_to_vector;
- }
- c_parser_consume_token (parser);
-
- if (c_parser_next_token_is_not (parser, CPP_NUMBER))
- {
- c_parser_error (parser, "expected integer");
- return list;
- }
-
- addend = c_parser_peek_token (parser)->value;
- if (TREE_CODE (addend) != INTEGER_CST)
- {
- c_parser_error (parser, "expected integer");
- return list;
- }
- c_parser_consume_token (parser);
-
- add_to_vector:
- if (t != error_mark_node)
- {
- vec = tree_cons (addend, t, vec);
- if (neg)
- OMP_CLAUSE_DEPEND_SINK_NEGATIVE (vec) = 1;
- }
-
- if (c_parser_next_token_is_not (parser, CPP_COMMA)
- || c_parser_peek_2nd_token (parser)->type != CPP_NAME
- || c_parser_peek_2nd_token (parser)->id_kind != C_ID_ID)
- break;
-
- c_parser_consume_token (parser);
- }
-
- if (vec == NULL_TREE)
- return list;
-
- tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DEPEND);
- OMP_CLAUSE_DEPEND_KIND (u) = OMP_CLAUSE_DEPEND_SINK;
- OMP_CLAUSE_DECL (u) = nreverse (vec);
- OMP_CLAUSE_CHAIN (u) = list;
- return u;
-}
-
-/* OpenMP 5.0:
- iterators ( iterators-definition )
-
- iterators-definition:
- iterator-specifier
- iterator-specifier , iterators-definition
-
- iterator-specifier:
- identifier = range-specification
- iterator-type identifier = range-specification
-
- range-specification:
- begin : end
- begin : end : step */
-
-static tree
-c_parser_omp_iterators (c_parser *parser)
-{
- tree ret = NULL_TREE, *last = &ret;
- c_parser_consume_token (parser);
-
- push_scope ();
-
- matching_parens parens;
- if (!parens.require_open (parser))
- return error_mark_node;
-
- do
- {
- tree iter_type = NULL_TREE, type_expr = NULL_TREE;
- if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
- {
- struct c_type_name *type = c_parser_type_name (parser);
- if (type != NULL)
- iter_type = groktypename (type, &type_expr, NULL);
- }
- if (iter_type == NULL_TREE)
- iter_type = integer_type_node;
-
- location_t loc = c_parser_peek_token (parser)->location;
- if (!c_parser_next_token_is (parser, CPP_NAME))
- {
- c_parser_error (parser, "expected identifier");
- break;
- }
-
- tree id = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
-
- if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
- break;
-
- location_t eloc = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
- tree begin = expr.value;
-
- if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
- break;
-
- eloc = c_parser_peek_token (parser)->location;
- expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
- tree end = expr.value;
-
- tree step = integer_one_node;
- if (c_parser_next_token_is (parser, CPP_COLON))
- {
- c_parser_consume_token (parser);
- eloc = c_parser_peek_token (parser)->location;
- expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (eloc, expr, true, false);
- step = expr.value;
- }
-
- tree iter_var = build_decl (loc, VAR_DECL, id, iter_type);
- DECL_ARTIFICIAL (iter_var) = 1;
- DECL_CONTEXT (iter_var) = current_function_decl;
- pushdecl (iter_var);
-
- *last = make_tree_vec (6);
- TREE_VEC_ELT (*last, 0) = iter_var;
- TREE_VEC_ELT (*last, 1) = begin;
- TREE_VEC_ELT (*last, 2) = end;
- TREE_VEC_ELT (*last, 3) = step;
- last = &TREE_CHAIN (*last);
-
- if (c_parser_next_token_is (parser, CPP_COMMA))
- {
- c_parser_consume_token (parser);
- continue;
- }
- break;
- }
- while (1);
-
- parens.skip_until_found_close (parser);
- return ret ? ret : error_mark_node;
-}
-
-/* OpenMP 5.0:
- affinity ( [aff-modifier :] variable-list )
- aff-modifier:
- iterator ( iterators-definition ) */
-
-static tree
-c_parser_omp_clause_affinity (c_parser *parser, tree list)
-{
- location_t clause_loc = c_parser_peek_token (parser)->location;
- tree nl, iterators = NULL_TREE;
-
- matching_parens parens;
- if (!parens.require_open (parser))
- return list;
-
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- bool parse_iter = ((strcmp ("iterator", p) == 0)
- && (c_parser_peek_2nd_token (parser)->type
- == CPP_OPEN_PAREN));
- if (parse_iter)
- {
- unsigned n = 3;
- parse_iter = (c_parser_check_balanced_raw_token_sequence (parser, &n)
- && (c_parser_peek_nth_token_raw (parser, n)->type
- == CPP_CLOSE_PAREN)
- && (c_parser_peek_nth_token_raw (parser, n + 1)->type
- == CPP_COLON));
- }
- if (parse_iter)
- {
- iterators = c_parser_omp_iterators (parser);
- if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
- {
- if (iterators)
- pop_scope ();
- parens.skip_until_found_close (parser);
- return list;
- }
- }
- }
- nl = c_parser_omp_variable_list (parser, clause_loc, OMP_CLAUSE_AFFINITY,
- list);
- if (iterators)
- {
- tree block = pop_scope ();
- if (iterators != error_mark_node)
- {
- TREE_VEC_ELT (iterators, 5) = block;
- for (tree c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
- OMP_CLAUSE_DECL (c) = build_tree_list (iterators,
- OMP_CLAUSE_DECL (c));
- }
- }
-
- parens.skip_until_found_close (parser);
- return nl;
-}
-
-
-/* OpenMP 4.0:
- depend ( depend-kind: variable-list )
-
- depend-kind:
- in | out | inout
-
- OpenMP 4.5:
- depend ( source )
-
- depend ( sink : vec )
-
- OpenMP 5.0:
- depend ( depend-modifier , depend-kind: variable-list )
-
- depend-kind:
- in | out | inout | mutexinoutset | depobj
-
- depend-modifier:
- iterator ( iterators-definition ) */
-
-static tree
-c_parser_omp_clause_depend (c_parser *parser, tree list)
-{
- location_t clause_loc = c_parser_peek_token (parser)->location;
- enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_LAST;
- tree nl, c, iterators = NULL_TREE;
-
- matching_parens parens;
- if (!parens.require_open (parser))
- return list;
-
- do
- {
- if (c_parser_next_token_is_not (parser, CPP_NAME))
- goto invalid_kind;
-
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (strcmp ("iterator", p) == 0 && iterators == NULL_TREE)
- {
- iterators = c_parser_omp_iterators (parser);
- c_parser_require (parser, CPP_COMMA, "expected %<,%>");
- continue;
- }
- if (strcmp ("in", p) == 0)
- kind = OMP_CLAUSE_DEPEND_IN;
- else if (strcmp ("inout", p) == 0)
- kind = OMP_CLAUSE_DEPEND_INOUT;
- else if (strcmp ("mutexinoutset", p) == 0)
- kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
- else if (strcmp ("out", p) == 0)
- kind = OMP_CLAUSE_DEPEND_OUT;
- else if (strcmp ("depobj", p) == 0)
- kind = OMP_CLAUSE_DEPEND_DEPOBJ;
- else if (strcmp ("sink", p) == 0)
- kind = OMP_CLAUSE_DEPEND_SINK;
- else if (strcmp ("source", p) == 0)
- kind = OMP_CLAUSE_DEPEND_SOURCE;
- else
- goto invalid_kind;
- break;
- }
- while (1);
-
- c_parser_consume_token (parser);
-
- if (iterators
- && (kind == OMP_CLAUSE_DEPEND_SOURCE || kind == OMP_CLAUSE_DEPEND_SINK))
- {
- pop_scope ();
- error_at (clause_loc, "%<iterator%> modifier incompatible with %qs",
- kind == OMP_CLAUSE_DEPEND_SOURCE ? "source" : "sink");
- iterators = NULL_TREE;
- }
-
- if (kind == OMP_CLAUSE_DEPEND_SOURCE)
- {
- c = build_omp_clause (clause_loc, OMP_CLAUSE_DEPEND);
- OMP_CLAUSE_DEPEND_KIND (c) = kind;
- OMP_CLAUSE_DECL (c) = NULL_TREE;
- OMP_CLAUSE_CHAIN (c) = list;
- parens.skip_until_found_close (parser);
- return c;
- }
-
- if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
- goto resync_fail;
-
- if (kind == OMP_CLAUSE_DEPEND_SINK)
- nl = c_parser_omp_clause_depend_sink (parser, clause_loc, list);
- else
- {
- nl = c_parser_omp_variable_list (parser, clause_loc,
- OMP_CLAUSE_DEPEND, list);
-
- if (iterators)
- {
- tree block = pop_scope ();
- if (iterators == error_mark_node)
- iterators = NULL_TREE;
- else
- TREE_VEC_ELT (iterators, 5) = block;
- }
-
- for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
- {
- OMP_CLAUSE_DEPEND_KIND (c) = kind;
- if (iterators)
- OMP_CLAUSE_DECL (c)
- = build_tree_list (iterators, OMP_CLAUSE_DECL (c));
- }
- }
-
- parens.skip_until_found_close (parser);
- return nl;
-
- invalid_kind:
- c_parser_error (parser, "invalid depend kind");
- resync_fail:
- parens.skip_until_found_close (parser);
- if (iterators)
- pop_scope ();
- return list;
-}
-
-/* OpenMP 4.0:
- map ( map-kind: variable-list )
- map ( variable-list )
-
- map-kind:
- alloc | to | from | tofrom
-
- OpenMP 4.5:
- map-kind:
- alloc | to | from | tofrom | release | delete
-
- map ( always [,] map-kind: variable-list )
-
- OpenMP 5.0:
- map ( [map-type-modifier[,] ...] map-kind: variable-list )
-
- map-type-modifier:
- always | close */
-
-static tree
-c_parser_omp_clause_map (c_parser *parser, tree list)
-{
- location_t clause_loc = c_parser_peek_token (parser)->location;
- enum gomp_map_kind kind = GOMP_MAP_TOFROM;
- tree nl, c;
-
- matching_parens parens;
- if (!parens.require_open (parser))
- return list;
-
- int pos = 1;
- int map_kind_pos = 0;
- while (c_parser_peek_nth_token_raw (parser, pos)->type == CPP_NAME)
- {
- if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COLON)
- {
- map_kind_pos = pos;
- break;
- }
-
- if (c_parser_peek_nth_token_raw (parser, pos + 1)->type == CPP_COMMA)
- pos++;
- pos++;
- }
-
- int always_modifier = 0;
- int close_modifier = 0;
- for (int pos = 1; pos < map_kind_pos; ++pos)
- {
- c_token *tok = c_parser_peek_token (parser);
-
- if (tok->type == CPP_COMMA)
- {
- c_parser_consume_token (parser);
- continue;
- }
-
- const char *p = IDENTIFIER_POINTER (tok->value);
- if (strcmp ("always", p) == 0)
- {
- if (always_modifier)
- {
- c_parser_error (parser, "too many %<always%> modifiers");
- parens.skip_until_found_close (parser);
- return list;
- }
- always_modifier++;
- }
- else if (strcmp ("close", p) == 0)
- {
- if (close_modifier)
- {
- c_parser_error (parser, "too many %<close%> modifiers");
- parens.skip_until_found_close (parser);
- return list;
- }
- close_modifier++;
- }
- else
- {
- c_parser_error (parser, "%<#pragma omp target%> with "
- "modifier other than %<always%> or %<close%>"
- "on %<map%> clause");
- parens.skip_until_found_close (parser);
- return list;
- }
-
- c_parser_consume_token (parser);
- }
-
- if (c_parser_next_token_is (parser, CPP_NAME)
- && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
- {
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (strcmp ("alloc", p) == 0)
- kind = GOMP_MAP_ALLOC;
- else if (strcmp ("to", p) == 0)
- kind = always_modifier ? GOMP_MAP_ALWAYS_TO : GOMP_MAP_TO;
- else if (strcmp ("from", p) == 0)
- kind = always_modifier ? GOMP_MAP_ALWAYS_FROM : GOMP_MAP_FROM;
- else if (strcmp ("tofrom", p) == 0)
- kind = always_modifier ? GOMP_MAP_ALWAYS_TOFROM : GOMP_MAP_TOFROM;
- else if (strcmp ("release", p) == 0)
- kind = GOMP_MAP_RELEASE;
- else if (strcmp ("delete", p) == 0)
- kind = GOMP_MAP_DELETE;
- else
- {
- c_parser_error (parser, "invalid map kind");
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>");
- return list;
- }
- c_parser_consume_token (parser);
- c_parser_consume_token (parser);
- }
-
- nl = c_parser_omp_variable_list (parser, clause_loc, OMP_CLAUSE_MAP, list,
- true);
-
- for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c))
- OMP_CLAUSE_SET_MAP_KIND (c, kind);
-
- parens.skip_until_found_close (parser);
- return nl;
-}
-
-/* OpenMP 4.0:
- device ( expression )
-
- OpenMP 5.0:
- device ( [device-modifier :] integer-expression )
-
- device-modifier:
- ancestor | device_num */
-
-static tree
-c_parser_omp_clause_device (c_parser *parser, tree list)
-{
- location_t clause_loc = c_parser_peek_token (parser)->location;
- location_t expr_loc;
- c_expr expr;
- tree c, t;
- bool ancestor = false;
-
- matching_parens parens;
- if (!parens.require_open (parser))
- return list;
-
- if (c_parser_next_token_is (parser, CPP_NAME)
- && c_parser_peek_2nd_token (parser)->type == CPP_COLON)
- {
- c_token *tok = c_parser_peek_token (parser);
- const char *p = IDENTIFIER_POINTER (tok->value);
- if (strcmp ("ancestor", p) == 0)
- {
- /* A requires directive with the reverse_offload clause must be
- specified. */
- if ((omp_requires_mask & OMP_REQUIRES_REVERSE_OFFLOAD) == 0)
- {
- error_at (tok->location, "%<ancestor%> device modifier not "
- "preceded by %<requires%> directive "
- "with %<reverse_offload%> clause");
- parens.skip_until_found_close (parser);
- return list;
- }
- ancestor = true;
- }
- else if (strcmp ("device_num", p) == 0)
- ;
- else
- {
- error_at (tok->location, "expected %<ancestor%> or %<device_num%>");
- parens.skip_until_found_close (parser);
- return list;
- }
- c_parser_consume_token (parser);
- c_parser_consume_token (parser);
- }
-
- expr_loc = c_parser_peek_token (parser)->location;
- expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
- t = expr.value;
- t = c_fully_fold (t, false, NULL);
-
- parens.skip_until_found_close (parser);
-
- if (!INTEGRAL_TYPE_P (TREE_TYPE (t)))
- {
- c_parser_error (parser, "expected integer expression");
- return list;
- }
- if (ancestor && TREE_CODE (t) == INTEGER_CST && !integer_onep (t))
- {
- error_at (expr_loc, "the %<device%> clause expression must evaluate to "
- "%<1%>");
- return list;
- }
-
- check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE, "device");
-
- c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE);
-
- OMP_CLAUSE_DEVICE_ID (c) = t;
- OMP_CLAUSE_CHAIN (c) = list;
- OMP_CLAUSE_DEVICE_ANCESTOR (c) = ancestor;
-
- list = c;
- return list;
-}
-
-/* OpenMP 4.0:
- dist_schedule ( static )
- dist_schedule ( static , expression ) */
-
-static tree
-c_parser_omp_clause_dist_schedule (c_parser *parser, tree list)
-{
- tree c, t = NULL_TREE;
- location_t loc = c_parser_peek_token (parser)->location;
-
- matching_parens parens;
- if (!parens.require_open (parser))
- return list;
-
- if (!c_parser_next_token_is_keyword (parser, RID_STATIC))
- {
- c_parser_error (parser, "invalid dist_schedule kind");
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>");
- return list;
- }
-
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_COMMA))
- {
- c_parser_consume_token (parser);
-
- location_t expr_loc = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
- t = expr.value;
- t = c_fully_fold (t, false, NULL);
- parens.skip_until_found_close (parser);
- }
- else
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<,%> or %<)%>");
-
- /* check_no_duplicate_clause (list, OMP_CLAUSE_DIST_SCHEDULE,
- "dist_schedule"); */
- if (omp_find_clause (list, OMP_CLAUSE_DIST_SCHEDULE))
- warning_at (loc, 0, "too many %qs clauses", "dist_schedule");
- if (t == error_mark_node)
- return list;
-
- c = build_omp_clause (loc, OMP_CLAUSE_DIST_SCHEDULE);
- OMP_CLAUSE_DIST_SCHEDULE_CHUNK_EXPR (c) = t;
- OMP_CLAUSE_CHAIN (c) = list;
- return c;
-}
-
-/* OpenMP 4.0:
- proc_bind ( proc-bind-kind )
-
- proc-bind-kind:
- primary | master | close | spread
- where OpenMP 5.1 added 'primary' and deprecated the alias 'master'. */
-
-static tree
-c_parser_omp_clause_proc_bind (c_parser *parser, tree list)
-{
- location_t clause_loc = c_parser_peek_token (parser)->location;
- enum omp_clause_proc_bind_kind kind;
- tree c;
-
- matching_parens parens;
- if (!parens.require_open (parser))
- return list;
-
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (strcmp ("primary", p) == 0)
- kind = OMP_CLAUSE_PROC_BIND_PRIMARY;
- else if (strcmp ("master", p) == 0)
- kind = OMP_CLAUSE_PROC_BIND_MASTER;
- else if (strcmp ("close", p) == 0)
- kind = OMP_CLAUSE_PROC_BIND_CLOSE;
- else if (strcmp ("spread", p) == 0)
- kind = OMP_CLAUSE_PROC_BIND_SPREAD;
- else
- goto invalid_kind;
- }
- else
- goto invalid_kind;
-
- check_no_duplicate_clause (list, OMP_CLAUSE_PROC_BIND, "proc_bind");
- c_parser_consume_token (parser);
- parens.skip_until_found_close (parser);
- c = build_omp_clause (clause_loc, OMP_CLAUSE_PROC_BIND);
- OMP_CLAUSE_PROC_BIND_KIND (c) = kind;
- OMP_CLAUSE_CHAIN (c) = list;
- return c;
-
- invalid_kind:
- c_parser_error (parser, "invalid proc_bind kind");
- parens.skip_until_found_close (parser);
- return list;
-}
-
-/* OpenMP 5.0:
- device_type ( host | nohost | any ) */
-
-static tree
-c_parser_omp_clause_device_type (c_parser *parser, tree list)
-{
- location_t clause_loc = c_parser_peek_token (parser)->location;
- enum omp_clause_device_type_kind kind;
- tree c;
-
- matching_parens parens;
- if (!parens.require_open (parser))
- return list;
-
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (strcmp ("host", p) == 0)
- kind = OMP_CLAUSE_DEVICE_TYPE_HOST;
- else if (strcmp ("nohost", p) == 0)
- kind = OMP_CLAUSE_DEVICE_TYPE_NOHOST;
- else if (strcmp ("any", p) == 0)
- kind = OMP_CLAUSE_DEVICE_TYPE_ANY;
- else
- goto invalid_kind;
- }
- else
- goto invalid_kind;
-
- /* check_no_duplicate_clause (list, OMP_CLAUSE_DEVICE_TYPE,
- "device_type"); */
- c_parser_consume_token (parser);
- parens.skip_until_found_close (parser);
- c = build_omp_clause (clause_loc, OMP_CLAUSE_DEVICE_TYPE);
- OMP_CLAUSE_DEVICE_TYPE_KIND (c) = kind;
- OMP_CLAUSE_CHAIN (c) = list;
- return c;
-
- invalid_kind:
- c_parser_error (parser, "expected %<host%>, %<nohost%> or %<any%>");
- parens.skip_until_found_close (parser);
- return list;
-}
-
-/* OpenMP 4.0:
- to ( variable-list ) */
-
-static tree
-c_parser_omp_clause_to (c_parser *parser, tree list)
-{
- return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_TO, list, true);
-}
-
-/* OpenMP 4.0:
- from ( variable-list ) */
-
-static tree
-c_parser_omp_clause_from (c_parser *parser, tree list)
-{
- return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_FROM, list, true);
-}
-
-/* OpenMP 4.0:
- uniform ( variable-list ) */
-
-static tree
-c_parser_omp_clause_uniform (c_parser *parser, tree list)
-{
- /* The clauses location. */
- location_t loc = c_parser_peek_token (parser)->location;
-
- matching_parens parens;
- if (parens.require_open (parser))
- {
- list = c_parser_omp_variable_list (parser, loc, OMP_CLAUSE_UNIFORM,
- list);
- parens.skip_until_found_close (parser);
- }
- return list;
-}
-
-/* OpenMP 5.0:
- detach ( event-handle ) */
-
-static tree
-c_parser_omp_clause_detach (c_parser *parser, tree list)
-{
- matching_parens parens;
- location_t clause_loc = c_parser_peek_token (parser)->location;
-
- if (!parens.require_open (parser))
- return list;
-
- if (c_parser_next_token_is_not (parser, CPP_NAME)
- || c_parser_peek_token (parser)->id_kind != C_ID_ID)
- {
- c_parser_error (parser, "expected identifier");
- parens.skip_until_found_close (parser);
- return list;
- }
-
- tree t = lookup_name (c_parser_peek_token (parser)->value);
- if (t == NULL_TREE)
- {
- undeclared_variable (c_parser_peek_token (parser)->location,
- c_parser_peek_token (parser)->value);
- parens.skip_until_found_close (parser);
- return list;
- }
- c_parser_consume_token (parser);
-
- tree type = TYPE_MAIN_VARIANT (TREE_TYPE (t));
- if (!INTEGRAL_TYPE_P (type)
- || TREE_CODE (type) != ENUMERAL_TYPE
- || TYPE_NAME (type) != get_identifier ("omp_event_handle_t"))
- {
- error_at (clause_loc, "%<detach%> clause event handle "
- "has type %qT rather than "
- "%<omp_event_handle_t%>",
- type);
- parens.skip_until_found_close (parser);
- return list;
- }
-
- tree u = build_omp_clause (clause_loc, OMP_CLAUSE_DETACH);
- OMP_CLAUSE_DECL (u) = t;
- OMP_CLAUSE_CHAIN (u) = list;
- parens.skip_until_found_close (parser);
- return u;
-}
-
-/* Parse all OpenACC clauses. The set clauses allowed by the directive
- is a bitmask in MASK. Return the list of clauses found. */
-
-static tree
-c_parser_oacc_all_clauses (c_parser *parser, omp_clause_mask mask,
- const char *where, bool finish_p = true)
-{
- tree clauses = NULL;
- bool first = true;
-
- while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
- {
- location_t here;
- pragma_omp_clause c_kind;
- const char *c_name;
- tree prev = clauses;
-
- if (!first && c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
-
- here = c_parser_peek_token (parser)->location;
- c_kind = c_parser_omp_clause_name (parser);
-
- switch (c_kind)
- {
- case PRAGMA_OACC_CLAUSE_ASYNC:
- clauses = c_parser_oacc_clause_async (parser, clauses);
- c_name = "async";
- break;
- case PRAGMA_OACC_CLAUSE_AUTO:
- clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_AUTO,
- clauses);
- c_name = "auto";
- break;
- case PRAGMA_OACC_CLAUSE_ATTACH:
- clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
- c_name = "attach";
- break;
- case PRAGMA_OACC_CLAUSE_COLLAPSE:
- clauses = c_parser_omp_clause_collapse (parser, clauses);
- c_name = "collapse";
- break;
- case PRAGMA_OACC_CLAUSE_COPY:
- clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
- c_name = "copy";
- break;
- case PRAGMA_OACC_CLAUSE_COPYIN:
- clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
- c_name = "copyin";
- break;
- case PRAGMA_OACC_CLAUSE_COPYOUT:
- clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
- c_name = "copyout";
- break;
- case PRAGMA_OACC_CLAUSE_CREATE:
- clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
- c_name = "create";
- break;
- case PRAGMA_OACC_CLAUSE_DELETE:
- clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
- c_name = "delete";
- break;
- case PRAGMA_OMP_CLAUSE_DEFAULT:
- clauses = c_parser_omp_clause_default (parser, clauses, true);
- c_name = "default";
- break;
- case PRAGMA_OACC_CLAUSE_DETACH:
- clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
- c_name = "detach";
- break;
- case PRAGMA_OACC_CLAUSE_DEVICE:
- clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
- c_name = "device";
- break;
- case PRAGMA_OACC_CLAUSE_DEVICEPTR:
- clauses = c_parser_oacc_data_clause_deviceptr (parser, clauses);
- c_name = "deviceptr";
- break;
- case PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT:
- clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
- c_name = "device_resident";
- break;
- case PRAGMA_OACC_CLAUSE_FINALIZE:
- clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_FINALIZE,
- clauses);
- c_name = "finalize";
- break;
- case PRAGMA_OACC_CLAUSE_FIRSTPRIVATE:
- clauses = c_parser_omp_clause_firstprivate (parser, clauses);
- c_name = "firstprivate";
- break;
- case PRAGMA_OACC_CLAUSE_GANG:
- c_name = "gang";
- clauses = c_parser_oacc_shape_clause (parser, here, OMP_CLAUSE_GANG,
- c_name, clauses);
- break;
- case PRAGMA_OACC_CLAUSE_HOST:
- clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
- c_name = "host";
- break;
- case PRAGMA_OACC_CLAUSE_IF:
- clauses = c_parser_omp_clause_if (parser, clauses, false);
- c_name = "if";
- break;
- case PRAGMA_OACC_CLAUSE_IF_PRESENT:
- clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_IF_PRESENT,
- clauses);
- c_name = "if_present";
- break;
- case PRAGMA_OACC_CLAUSE_INDEPENDENT:
- clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_INDEPENDENT,
- clauses);
- c_name = "independent";
- break;
- case PRAGMA_OACC_CLAUSE_LINK:
- clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
- c_name = "link";
- break;
- case PRAGMA_OACC_CLAUSE_NO_CREATE:
- clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
- c_name = "no_create";
- break;
- case PRAGMA_OACC_CLAUSE_NOHOST:
- clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_NOHOST,
- clauses);
- c_name = "nohost";
- break;
- case PRAGMA_OACC_CLAUSE_NUM_GANGS:
- clauses = c_parser_oacc_single_int_clause (parser,
- OMP_CLAUSE_NUM_GANGS,
- clauses);
- c_name = "num_gangs";
- break;
- case PRAGMA_OACC_CLAUSE_NUM_WORKERS:
- clauses = c_parser_oacc_single_int_clause (parser,
- OMP_CLAUSE_NUM_WORKERS,
- clauses);
- c_name = "num_workers";
- break;
- case PRAGMA_OACC_CLAUSE_PRESENT:
- clauses = c_parser_oacc_data_clause (parser, c_kind, clauses);
- c_name = "present";
- break;
- case PRAGMA_OACC_CLAUSE_PRIVATE:
- clauses = c_parser_omp_clause_private (parser, clauses);
- c_name = "private";
- break;
- case PRAGMA_OACC_CLAUSE_REDUCTION:
- clauses
- = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
- false, clauses);
- c_name = "reduction";
- break;
- case PRAGMA_OACC_CLAUSE_SEQ:
- clauses = c_parser_oacc_simple_clause (here, OMP_CLAUSE_SEQ,
- clauses);
- c_name = "seq";
- break;
- case PRAGMA_OACC_CLAUSE_TILE:
- clauses = c_parser_oacc_clause_tile (parser, clauses);
- c_name = "tile";
- break;
- case PRAGMA_OACC_CLAUSE_USE_DEVICE:
- clauses = c_parser_omp_clause_use_device_ptr (parser, clauses);
- c_name = "use_device";
- break;
- case PRAGMA_OACC_CLAUSE_VECTOR:
- c_name = "vector";
- clauses = c_parser_oacc_shape_clause (parser, here, OMP_CLAUSE_VECTOR,
- c_name, clauses);
- break;
- case PRAGMA_OACC_CLAUSE_VECTOR_LENGTH:
- clauses = c_parser_oacc_single_int_clause (parser,
- OMP_CLAUSE_VECTOR_LENGTH,
- clauses);
- c_name = "vector_length";
- break;
- case PRAGMA_OACC_CLAUSE_WAIT:
- clauses = c_parser_oacc_clause_wait (parser, clauses);
- c_name = "wait";
- break;
- case PRAGMA_OACC_CLAUSE_WORKER:
- c_name = "worker";
- clauses = c_parser_oacc_shape_clause (parser, here, OMP_CLAUSE_WORKER,
- c_name, clauses);
- break;
- default:
- c_parser_error (parser, "expected %<#pragma acc%> clause");
- goto saw_error;
- }
-
- first = false;
-
- if (((mask >> c_kind) & 1) == 0)
- {
- /* Remove the invalid clause(s) from the list to avoid
- confusing the rest of the compiler. */
- clauses = prev;
- error_at (here, "%qs is not valid for %qs", c_name, where);
- }
- }
-
- saw_error:
- c_parser_skip_to_pragma_eol (parser);
-
- if (finish_p)
- return c_finish_omp_clauses (clauses, C_ORT_ACC);
-
- return clauses;
-}
-
-/* Parse all OpenMP clauses. The set clauses allowed by the directive
- is a bitmask in MASK. Return the list of clauses found.
- FINISH_P set if c_finish_omp_clauses should be called.
- NESTED non-zero if clauses should be terminated by closing paren instead
- of end of pragma. If it is 2, additionally commas are required in between
- the clauses. */
-
-static tree
-c_parser_omp_all_clauses (c_parser *parser, omp_clause_mask mask,
- const char *where, bool finish_p = true,
- int nested = 0)
-{
- tree clauses = NULL;
- bool first = true;
-
- while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
- {
- location_t here;
- pragma_omp_clause c_kind;
- const char *c_name;
- tree prev = clauses;
-
- if (nested && c_parser_next_token_is (parser, CPP_CLOSE_PAREN))
- break;
-
- if (!first)
- {
- if (c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
- else if (nested == 2)
- error_at (c_parser_peek_token (parser)->location,
- "clauses in %<simd%> trait should be separated "
- "by %<,%>");
- }
-
- here = c_parser_peek_token (parser)->location;
- c_kind = c_parser_omp_clause_name (parser);
-
- switch (c_kind)
- {
- case PRAGMA_OMP_CLAUSE_BIND:
- clauses = c_parser_omp_clause_bind (parser, clauses);
- c_name = "bind";
- break;
- case PRAGMA_OMP_CLAUSE_COLLAPSE:
- clauses = c_parser_omp_clause_collapse (parser, clauses);
- c_name = "collapse";
- break;
- case PRAGMA_OMP_CLAUSE_COPYIN:
- clauses = c_parser_omp_clause_copyin (parser, clauses);
- c_name = "copyin";
- break;
- case PRAGMA_OMP_CLAUSE_COPYPRIVATE:
- clauses = c_parser_omp_clause_copyprivate (parser, clauses);
- c_name = "copyprivate";
- break;
- case PRAGMA_OMP_CLAUSE_DEFAULT:
- clauses = c_parser_omp_clause_default (parser, clauses, false);
- c_name = "default";
- break;
- case PRAGMA_OMP_CLAUSE_DETACH:
- clauses = c_parser_omp_clause_detach (parser, clauses);
- c_name = "detach";
- break;
- case PRAGMA_OMP_CLAUSE_FILTER:
- clauses = c_parser_omp_clause_filter (parser, clauses);
- c_name = "filter";
- break;
- case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
- clauses = c_parser_omp_clause_firstprivate (parser, clauses);
- c_name = "firstprivate";
- break;
- case PRAGMA_OMP_CLAUSE_FINAL:
- clauses = c_parser_omp_clause_final (parser, clauses);
- c_name = "final";
- break;
- case PRAGMA_OMP_CLAUSE_GRAINSIZE:
- clauses = c_parser_omp_clause_grainsize (parser, clauses);
- c_name = "grainsize";
- break;
- case PRAGMA_OMP_CLAUSE_HINT:
- clauses = c_parser_omp_clause_hint (parser, clauses);
- c_name = "hint";
- break;
- case PRAGMA_OMP_CLAUSE_DEFAULTMAP:
- clauses = c_parser_omp_clause_defaultmap (parser, clauses);
- c_name = "defaultmap";
- break;
- case PRAGMA_OMP_CLAUSE_IF:
- clauses = c_parser_omp_clause_if (parser, clauses, true);
- c_name = "if";
- break;
- case PRAGMA_OMP_CLAUSE_IN_REDUCTION:
- clauses
- = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_IN_REDUCTION,
- true, clauses);
- c_name = "in_reduction";
- break;
- case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
- clauses = c_parser_omp_clause_lastprivate (parser, clauses);
- c_name = "lastprivate";
- break;
- case PRAGMA_OMP_CLAUSE_MERGEABLE:
- clauses = c_parser_omp_clause_mergeable (parser, clauses);
- c_name = "mergeable";
- break;
- case PRAGMA_OMP_CLAUSE_NOWAIT:
- clauses = c_parser_omp_clause_nowait (parser, clauses);
- c_name = "nowait";
- break;
- case PRAGMA_OMP_CLAUSE_NUM_TASKS:
- clauses = c_parser_omp_clause_num_tasks (parser, clauses);
- c_name = "num_tasks";
- break;
- case PRAGMA_OMP_CLAUSE_NUM_THREADS:
- clauses = c_parser_omp_clause_num_threads (parser, clauses);
- c_name = "num_threads";
- break;
- case PRAGMA_OMP_CLAUSE_ORDER:
- clauses = c_parser_omp_clause_order (parser, clauses);
- c_name = "order";
- break;
- case PRAGMA_OMP_CLAUSE_ORDERED:
- clauses = c_parser_omp_clause_ordered (parser, clauses);
- c_name = "ordered";
- break;
- case PRAGMA_OMP_CLAUSE_PRIORITY:
- clauses = c_parser_omp_clause_priority (parser, clauses);
- c_name = "priority";
- break;
- case PRAGMA_OMP_CLAUSE_PRIVATE:
- clauses = c_parser_omp_clause_private (parser, clauses);
- c_name = "private";
- break;
- case PRAGMA_OMP_CLAUSE_REDUCTION:
- clauses
- = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_REDUCTION,
- true, clauses);
- c_name = "reduction";
- break;
- case PRAGMA_OMP_CLAUSE_SCHEDULE:
- clauses = c_parser_omp_clause_schedule (parser, clauses);
- c_name = "schedule";
- break;
- case PRAGMA_OMP_CLAUSE_SHARED:
- clauses = c_parser_omp_clause_shared (parser, clauses);
- c_name = "shared";
- break;
- case PRAGMA_OMP_CLAUSE_TASK_REDUCTION:
- clauses
- = c_parser_omp_clause_reduction (parser, OMP_CLAUSE_TASK_REDUCTION,
- true, clauses);
- c_name = "task_reduction";
- break;
- case PRAGMA_OMP_CLAUSE_UNTIED:
- clauses = c_parser_omp_clause_untied (parser, clauses);
- c_name = "untied";
- break;
- case PRAGMA_OMP_CLAUSE_INBRANCH:
- clauses = c_parser_omp_clause_branch (parser, OMP_CLAUSE_INBRANCH,
- clauses);
- c_name = "inbranch";
- break;
- case PRAGMA_OMP_CLAUSE_NONTEMPORAL:
- clauses = c_parser_omp_clause_nontemporal (parser, clauses);
- c_name = "nontemporal";
- break;
- case PRAGMA_OMP_CLAUSE_NOTINBRANCH:
- clauses = c_parser_omp_clause_branch (parser, OMP_CLAUSE_NOTINBRANCH,
- clauses);
- c_name = "notinbranch";
- break;
- case PRAGMA_OMP_CLAUSE_PARALLEL:
- clauses
- = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_PARALLEL,
- clauses);
- c_name = "parallel";
- if (!first)
- {
- clause_not_first:
- error_at (here, "%qs must be the first clause of %qs",
- c_name, where);
- clauses = prev;
- }
- break;
- case PRAGMA_OMP_CLAUSE_FOR:
- clauses
- = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_FOR,
- clauses);
- c_name = "for";
- if (!first)
- goto clause_not_first;
- break;
- case PRAGMA_OMP_CLAUSE_SECTIONS:
- clauses
- = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_SECTIONS,
- clauses);
- c_name = "sections";
- if (!first)
- goto clause_not_first;
- break;
- case PRAGMA_OMP_CLAUSE_TASKGROUP:
- clauses
- = c_parser_omp_clause_cancelkind (parser, OMP_CLAUSE_TASKGROUP,
- clauses);
- c_name = "taskgroup";
- if (!first)
- goto clause_not_first;
- break;
- case PRAGMA_OMP_CLAUSE_LINK:
- clauses
- = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_LINK, clauses);
- c_name = "link";
- break;
- case PRAGMA_OMP_CLAUSE_TO:
- if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK)) != 0)
- clauses
- = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_TO_DECLARE,
- clauses);
- else
- clauses = c_parser_omp_clause_to (parser, clauses);
- c_name = "to";
- break;
- case PRAGMA_OMP_CLAUSE_FROM:
- clauses = c_parser_omp_clause_from (parser, clauses);
- c_name = "from";
- break;
- case PRAGMA_OMP_CLAUSE_UNIFORM:
- clauses = c_parser_omp_clause_uniform (parser, clauses);
- c_name = "uniform";
- break;
- case PRAGMA_OMP_CLAUSE_NUM_TEAMS:
- clauses = c_parser_omp_clause_num_teams (parser, clauses);
- c_name = "num_teams";
- break;
- case PRAGMA_OMP_CLAUSE_THREAD_LIMIT:
- clauses = c_parser_omp_clause_thread_limit (parser, clauses);
- c_name = "thread_limit";
- break;
- case PRAGMA_OMP_CLAUSE_ALIGNED:
- clauses = c_parser_omp_clause_aligned (parser, clauses);
- c_name = "aligned";
- break;
- case PRAGMA_OMP_CLAUSE_ALLOCATE:
- clauses = c_parser_omp_clause_allocate (parser, clauses);
- c_name = "allocate";
- break;
- case PRAGMA_OMP_CLAUSE_LINEAR:
- clauses = c_parser_omp_clause_linear (parser, clauses);
- c_name = "linear";
- break;
- case PRAGMA_OMP_CLAUSE_AFFINITY:
- clauses = c_parser_omp_clause_affinity (parser, clauses);
- c_name = "affinity";
- break;
- case PRAGMA_OMP_CLAUSE_DEPEND:
- clauses = c_parser_omp_clause_depend (parser, clauses);
- c_name = "depend";
- break;
- case PRAGMA_OMP_CLAUSE_MAP:
- clauses = c_parser_omp_clause_map (parser, clauses);
- c_name = "map";
- break;
- case PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR:
- clauses = c_parser_omp_clause_use_device_ptr (parser, clauses);
- c_name = "use_device_ptr";
- break;
- case PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR:
- clauses = c_parser_omp_clause_use_device_addr (parser, clauses);
- c_name = "use_device_addr";
- break;
- case PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR:
- clauses = c_parser_omp_clause_is_device_ptr (parser, clauses);
- c_name = "is_device_ptr";
- break;
- case PRAGMA_OMP_CLAUSE_DEVICE:
- clauses = c_parser_omp_clause_device (parser, clauses);
- c_name = "device";
- break;
- case PRAGMA_OMP_CLAUSE_DIST_SCHEDULE:
- clauses = c_parser_omp_clause_dist_schedule (parser, clauses);
- c_name = "dist_schedule";
- break;
- case PRAGMA_OMP_CLAUSE_PROC_BIND:
- clauses = c_parser_omp_clause_proc_bind (parser, clauses);
- c_name = "proc_bind";
- break;
- case PRAGMA_OMP_CLAUSE_DEVICE_TYPE:
- clauses = c_parser_omp_clause_device_type (parser, clauses);
- c_name = "device_type";
- break;
- case PRAGMA_OMP_CLAUSE_SAFELEN:
- clauses = c_parser_omp_clause_safelen (parser, clauses);
- c_name = "safelen";
- break;
- case PRAGMA_OMP_CLAUSE_SIMDLEN:
- clauses = c_parser_omp_clause_simdlen (parser, clauses);
- c_name = "simdlen";
- break;
- case PRAGMA_OMP_CLAUSE_NOGROUP:
- clauses = c_parser_omp_clause_nogroup (parser, clauses);
- c_name = "nogroup";
- break;
- case PRAGMA_OMP_CLAUSE_THREADS:
- clauses
- = c_parser_omp_clause_orderedkind (parser, OMP_CLAUSE_THREADS,
- clauses);
- c_name = "threads";
- break;
- case PRAGMA_OMP_CLAUSE_SIMD:
- clauses
- = c_parser_omp_clause_orderedkind (parser, OMP_CLAUSE_SIMD,
- clauses);
- c_name = "simd";
- break;
- default:
- c_parser_error (parser, "expected %<#pragma omp%> clause");
- goto saw_error;
- }
-
- first = false;
-
- if (((mask >> c_kind) & 1) == 0)
- {
- /* Remove the invalid clause(s) from the list to avoid
- confusing the rest of the compiler. */
- clauses = prev;
- error_at (here, "%qs is not valid for %qs", c_name, where);
- }
- }
-
- saw_error:
- if (!nested)
- c_parser_skip_to_pragma_eol (parser);
-
- if (finish_p)
- {
- if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM)) != 0)
- return c_finish_omp_clauses (clauses, C_ORT_OMP_DECLARE_SIMD);
- return c_finish_omp_clauses (clauses, C_ORT_OMP);
- }
-
- return clauses;
-}
-
-/* OpenACC 2.0, OpenMP 2.5:
- structured-block:
- statement
-
- In practice, we're also interested in adding the statement to an
- outer node. So it is convenient if we work around the fact that
- c_parser_statement calls add_stmt. */
-
-static tree
-c_parser_omp_structured_block (c_parser *parser, bool *if_p)
-{
- tree stmt = push_stmt_list ();
- c_parser_statement (parser, if_p);
- return pop_stmt_list (stmt);
-}
-
-/* OpenACC 2.0:
- # pragma acc cache (variable-list) new-line
-
- LOC is the location of the #pragma token.
-*/
-
-static tree
-c_parser_oacc_cache (location_t loc, c_parser *parser)
-{
- tree stmt, clauses;
-
- clauses = c_parser_omp_var_list_parens (parser, OMP_CLAUSE__CACHE_, NULL);
- clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
-
- c_parser_skip_to_pragma_eol (parser);
-
- stmt = make_node (OACC_CACHE);
- TREE_TYPE (stmt) = void_type_node;
- OACC_CACHE_CLAUSES (stmt) = clauses;
- SET_EXPR_LOCATION (stmt, loc);
- add_stmt (stmt);
-
- return stmt;
-}
-
-/* OpenACC 2.0:
- # pragma acc data oacc-data-clause[optseq] new-line
- structured-block
-
- LOC is the location of the #pragma token.
-*/
-
-#define OACC_DATA_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT))
-
-static tree
-c_parser_oacc_data (location_t loc, c_parser *parser, bool *if_p)
-{
- tree stmt, clauses, block;
-
- clauses = c_parser_oacc_all_clauses (parser, OACC_DATA_CLAUSE_MASK,
- "#pragma acc data");
-
- block = c_begin_omp_parallel ();
- add_stmt (c_parser_omp_structured_block (parser, if_p));
-
- stmt = c_finish_oacc_data (loc, clauses, block);
-
- return stmt;
-}
-
-/* OpenACC 2.0:
- # pragma acc declare oacc-data-clause[optseq] new-line
-*/
-
-#define OACC_DECLARE_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE_RESIDENT) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_LINK) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT))
-
-static void
-c_parser_oacc_declare (c_parser *parser)
-{
- location_t pragma_loc = c_parser_peek_token (parser)->location;
- tree clauses, stmt, t, decl;
-
- bool error = false;
-
- c_parser_consume_pragma (parser);
-
- clauses = c_parser_oacc_all_clauses (parser, OACC_DECLARE_CLAUSE_MASK,
- "#pragma acc declare");
- if (!clauses)
- {
- error_at (pragma_loc,
- "no valid clauses specified in %<#pragma acc declare%>");
- return;
- }
-
- for (t = clauses; t; t = OMP_CLAUSE_CHAIN (t))
- {
- location_t loc = OMP_CLAUSE_LOCATION (t);
- decl = OMP_CLAUSE_DECL (t);
- if (!DECL_P (decl))
- {
- error_at (loc, "array section in %<#pragma acc declare%>");
- error = true;
- continue;
- }
-
- switch (OMP_CLAUSE_MAP_KIND (t))
- {
- case GOMP_MAP_FIRSTPRIVATE_POINTER:
- case GOMP_MAP_ALLOC:
- case GOMP_MAP_TO:
- case GOMP_MAP_FORCE_DEVICEPTR:
- case GOMP_MAP_DEVICE_RESIDENT:
- break;
-
- case GOMP_MAP_LINK:
- if (!global_bindings_p ()
- && (TREE_STATIC (decl)
- || !DECL_EXTERNAL (decl)))
- {
- error_at (loc,
- "%qD must be a global variable in "
- "%<#pragma acc declare link%>",
- decl);
- error = true;
- continue;
- }
- break;
-
- default:
- if (global_bindings_p ())
- {
- error_at (loc, "invalid OpenACC clause at file scope");
- error = true;
- continue;
- }
- if (DECL_EXTERNAL (decl))
- {
- error_at (loc,
- "invalid use of %<extern%> variable %qD "
- "in %<#pragma acc declare%>", decl);
- error = true;
- continue;
- }
- else if (TREE_PUBLIC (decl))
- {
- error_at (loc,
- "invalid use of %<global%> variable %qD "
- "in %<#pragma acc declare%>", decl);
- error = true;
- continue;
- }
- break;
- }
-
- if (!c_check_in_current_scope (decl))
- {
- error_at (loc,
- "%qD must be a variable declared in the same scope as "
- "%<#pragma acc declare%>", decl);
- error = true;
- continue;
- }
-
- if (lookup_attribute ("omp declare target", DECL_ATTRIBUTES (decl))
- || lookup_attribute ("omp declare target link",
- DECL_ATTRIBUTES (decl)))
- {
- error_at (loc, "variable %qD used more than once with "
- "%<#pragma acc declare%>", decl);
- error = true;
- continue;
- }
-
- if (!error)
- {
- tree id;
-
- if (OMP_CLAUSE_MAP_KIND (t) == GOMP_MAP_LINK)
- id = get_identifier ("omp declare target link");
- else
- id = get_identifier ("omp declare target");
-
- DECL_ATTRIBUTES (decl)
- = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (decl));
-
- if (global_bindings_p ())
- {
- symtab_node *node = symtab_node::get (decl);
- if (node != NULL)
- {
- node->offloadable = 1;
- if (ENABLE_OFFLOADING)
- {
- g->have_offload = true;
- if (is_a <varpool_node *> (node))
- vec_safe_push (offload_vars, decl);
- }
- }
- }
- }
- }
-
- if (error || global_bindings_p ())
- return;
-
- stmt = make_node (OACC_DECLARE);
- TREE_TYPE (stmt) = void_type_node;
- OACC_DECLARE_CLAUSES (stmt) = clauses;
- SET_EXPR_LOCATION (stmt, pragma_loc);
-
- add_stmt (stmt);
-
- return;
-}
-
-/* OpenACC 2.0:
- # pragma acc enter data oacc-enter-data-clause[optseq] new-line
-
- or
-
- # pragma acc exit data oacc-exit-data-clause[optseq] new-line
-
-
- LOC is the location of the #pragma token.
-*/
-
-#define OACC_ENTER_DATA_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
-
-#define OACC_EXIT_DATA_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DELETE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DETACH) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FINALIZE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
-
-static void
-c_parser_oacc_enter_exit_data (c_parser *parser, bool enter)
-{
- location_t loc = c_parser_peek_token (parser)->location;
- tree clauses, stmt;
- const char *p = "";
-
- c_parser_consume_pragma (parser);
-
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- c_parser_consume_token (parser);
- }
-
- if (strcmp (p, "data") != 0)
- {
- error_at (loc, "expected %<data%> after %<#pragma acc %s%>",
- enter ? "enter" : "exit");
- parser->error = true;
- c_parser_skip_to_pragma_eol (parser);
- return;
- }
-
- if (enter)
- clauses = c_parser_oacc_all_clauses (parser, OACC_ENTER_DATA_CLAUSE_MASK,
- "#pragma acc enter data");
- else
- clauses = c_parser_oacc_all_clauses (parser, OACC_EXIT_DATA_CLAUSE_MASK,
- "#pragma acc exit data");
-
- if (omp_find_clause (clauses, OMP_CLAUSE_MAP) == NULL_TREE)
- {
- error_at (loc, "%<#pragma acc %s data%> has no data movement clause",
- enter ? "enter" : "exit");
- return;
- }
-
- stmt = enter ? make_node (OACC_ENTER_DATA) : make_node (OACC_EXIT_DATA);
- TREE_TYPE (stmt) = void_type_node;
- OMP_STANDALONE_CLAUSES (stmt) = clauses;
- SET_EXPR_LOCATION (stmt, loc);
- add_stmt (stmt);
-}
-
-
-/* OpenACC 2.0:
- # pragma acc host_data oacc-data-clause[optseq] new-line
- structured-block
-*/
-
-#define OACC_HOST_DATA_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_USE_DEVICE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF_PRESENT) )
-
-static tree
-c_parser_oacc_host_data (location_t loc, c_parser *parser, bool *if_p)
-{
- tree stmt, clauses, block;
-
- clauses = c_parser_oacc_all_clauses (parser, OACC_HOST_DATA_CLAUSE_MASK,
- "#pragma acc host_data");
-
- block = c_begin_omp_parallel ();
- add_stmt (c_parser_omp_structured_block (parser, if_p));
- stmt = c_finish_oacc_host_data (loc, clauses, block);
- return stmt;
-}
-
-
-/* OpenACC 2.0:
-
- # pragma acc loop oacc-loop-clause[optseq] new-line
- structured-block
-
- LOC is the location of the #pragma token.
-*/
-
-#define OACC_LOOP_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COLLAPSE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_AUTO) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_INDEPENDENT) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_TILE) )
-static tree
-c_parser_oacc_loop (location_t loc, c_parser *parser, char *p_name,
- omp_clause_mask mask, tree *cclauses, bool *if_p)
-{
- bool is_parallel = ((mask >> PRAGMA_OACC_CLAUSE_REDUCTION) & 1) == 1;
-
- strcat (p_name, " loop");
- mask |= OACC_LOOP_CLAUSE_MASK;
-
- tree clauses = c_parser_oacc_all_clauses (parser, mask, p_name,
- cclauses == NULL);
- if (cclauses)
- {
- clauses = c_oacc_split_loop_clauses (clauses, cclauses, is_parallel);
- if (*cclauses)
- *cclauses = c_finish_omp_clauses (*cclauses, C_ORT_ACC);
- if (clauses)
- clauses = c_finish_omp_clauses (clauses, C_ORT_ACC);
- }
-
- tree block = c_begin_compound_stmt (true);
- tree stmt = c_parser_omp_for_loop (loc, parser, OACC_LOOP, clauses, NULL,
- if_p);
- block = c_end_compound_stmt (loc, block, true);
- add_stmt (block);
-
- return stmt;
-}
-
-/* OpenACC 2.0:
- # pragma acc kernels oacc-kernels-clause[optseq] new-line
- structured-block
-
- or
-
- # pragma acc parallel oacc-parallel-clause[optseq] new-line
- structured-block
-
- OpenACC 2.6:
-
- # pragma acc serial oacc-serial-clause[optseq] new-line
- structured-block
-
- LOC is the location of the #pragma token.
-*/
-
-#define OACC_KERNELS_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR_LENGTH) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
-
-#define OACC_PARALLEL_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_GANGS) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NUM_WORKERS) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR_LENGTH) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
-
-#define OACC_SERIAL_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ATTACH) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPY) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYIN) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_COPYOUT) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_CREATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEFAULT) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICEPTR) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NO_CREATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_FIRSTPRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_PRESENT) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_REDUCTION) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
-
-static tree
-c_parser_oacc_compute (location_t loc, c_parser *parser,
- enum pragma_kind p_kind, char *p_name, bool *if_p)
-{
- omp_clause_mask mask;
- enum tree_code code;
- switch (p_kind)
- {
- case PRAGMA_OACC_KERNELS:
- strcat (p_name, " kernels");
- mask = OACC_KERNELS_CLAUSE_MASK;
- code = OACC_KERNELS;
- break;
- case PRAGMA_OACC_PARALLEL:
- strcat (p_name, " parallel");
- mask = OACC_PARALLEL_CLAUSE_MASK;
- code = OACC_PARALLEL;
- break;
- case PRAGMA_OACC_SERIAL:
- strcat (p_name, " serial");
- mask = OACC_SERIAL_CLAUSE_MASK;
- code = OACC_SERIAL;
- break;
- default:
- gcc_unreachable ();
- }
-
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (strcmp (p, "loop") == 0)
- {
- c_parser_consume_token (parser);
- tree block = c_begin_omp_parallel ();
- tree clauses;
- c_parser_oacc_loop (loc, parser, p_name, mask, &clauses, if_p);
- return c_finish_omp_construct (loc, code, block, clauses);
- }
- }
-
- tree clauses = c_parser_oacc_all_clauses (parser, mask, p_name);
-
- tree block = c_begin_omp_parallel ();
- add_stmt (c_parser_omp_structured_block (parser, if_p));
-
- return c_finish_omp_construct (loc, code, block, clauses);
-}
-
-/* OpenACC 2.0:
- # pragma acc routine oacc-routine-clause[optseq] new-line
- function-definition
-
- # pragma acc routine ( name ) oacc-routine-clause[optseq] new-line
-*/
-
-#define OACC_ROUTINE_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_GANG) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WORKER) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_VECTOR) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_SEQ) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_NOHOST) )
-
-/* Parse an OpenACC routine directive. For named directives, we apply
- immediately to the named function. For unnamed ones we then parse
- a declaration or definition, which must be for a function. */
-
-static void
-c_parser_oacc_routine (c_parser *parser, enum pragma_context context)
-{
- gcc_checking_assert (context == pragma_external);
-
- oacc_routine_data data;
- data.error_seen = false;
- data.fndecl_seen = false;
- data.loc = c_parser_peek_token (parser)->location;
-
- c_parser_consume_pragma (parser);
-
- /* Look for optional '( name )'. */
- if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
- {
- c_parser_consume_token (parser); /* '(' */
-
- tree decl = NULL_TREE;
- c_token *name_token = c_parser_peek_token (parser);
- location_t name_loc = name_token->location;
- if (name_token->type == CPP_NAME
- && (name_token->id_kind == C_ID_ID
- || name_token->id_kind == C_ID_TYPENAME))
- {
- decl = lookup_name (name_token->value);
- if (!decl)
- error_at (name_loc,
- "%qE has not been declared", name_token->value);
- c_parser_consume_token (parser);
- }
- else
- c_parser_error (parser, "expected function name");
-
- if (!decl
- || !c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
- {
- c_parser_skip_to_pragma_eol (parser, false);
- return;
- }
-
- data.clauses
- = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
- "#pragma acc routine");
- /* The clauses are in reverse order; fix that to make later diagnostic
- emission easier. */
- data.clauses = nreverse (data.clauses);
-
- if (TREE_CODE (decl) != FUNCTION_DECL)
- {
- error_at (name_loc, "%qD does not refer to a function", decl);
- return;
- }
-
- c_finish_oacc_routine (&data, decl, false);
- }
- else /* No optional '( name )'. */
- {
- data.clauses
- = c_parser_oacc_all_clauses (parser, OACC_ROUTINE_CLAUSE_MASK,
- "#pragma acc routine");
- /* The clauses are in reverse order; fix that to make later diagnostic
- emission easier. */
- data.clauses = nreverse (data.clauses);
-
- /* Emit a helpful diagnostic if there's another pragma following this
- one. Also don't allow a static assertion declaration, as in the
- following we'll just parse a *single* "declaration or function
- definition", and the static assertion counts an one. */
- if (c_parser_next_token_is (parser, CPP_PRAGMA)
- || c_parser_next_token_is_keyword (parser, RID_STATIC_ASSERT))
- {
- error_at (data.loc,
- "%<#pragma acc routine%> not immediately followed by"
- " function declaration or definition");
- /* ..., and then just keep going. */
- return;
- }
-
- /* We only have to consider the pragma_external case here. */
- if (c_parser_next_token_is (parser, CPP_KEYWORD)
- && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
- {
- int ext = disable_extension_diagnostics ();
- do
- c_parser_consume_token (parser);
- while (c_parser_next_token_is (parser, CPP_KEYWORD)
- && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
- c_parser_declaration_or_fndef (parser, true, true, true, false, true,
- NULL, NULL, false, NULL, &data);
- restore_extension_diagnostics (ext);
- }
- else
- c_parser_declaration_or_fndef (parser, true, true, true, false, true,
- NULL, NULL, false, NULL, &data);
- }
-}
-
-/* Finalize an OpenACC routine pragma, applying it to FNDECL.
- IS_DEFN is true if we're applying it to the definition. */
-
-static void
-c_finish_oacc_routine (struct oacc_routine_data *data, tree fndecl,
- bool is_defn)
-{
- /* Keep going if we're in error reporting mode. */
- if (data->error_seen
- || fndecl == error_mark_node)
- return;
-
- if (data->fndecl_seen)
- {
- error_at (data->loc,
- "%<#pragma acc routine%> not immediately followed by"
- " a single function declaration or definition");
- data->error_seen = true;
- return;
- }
- if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL)
- {
- error_at (data->loc,
- "%<#pragma acc routine%> not immediately followed by"
- " function declaration or definition");
- data->error_seen = true;
- return;
- }
-
- int compatible
- = oacc_verify_routine_clauses (fndecl, &data->clauses, data->loc,
- "#pragma acc routine");
- if (compatible < 0)
- {
- data->error_seen = true;
- return;
- }
- if (compatible > 0)
- {
- }
- else
- {
- if (TREE_USED (fndecl) || (!is_defn && DECL_SAVED_TREE (fndecl)))
- {
- error_at (data->loc,
- TREE_USED (fndecl)
- ? G_("%<#pragma acc routine%> must be applied before use")
- : G_("%<#pragma acc routine%> must be applied before"
- " definition"));
- data->error_seen = true;
- return;
- }
-
- /* Set the routine's level of parallelism. */
- tree dims = oacc_build_routine_dims (data->clauses);
- oacc_replace_fn_attrib (fndecl, dims);
-
- /* Add an "omp declare target" attribute. */
- DECL_ATTRIBUTES (fndecl)
- = tree_cons (get_identifier ("omp declare target"),
- data->clauses, DECL_ATTRIBUTES (fndecl));
- }
-
- /* Remember that we've used this "#pragma acc routine". */
- data->fndecl_seen = true;
-}
-
-/* OpenACC 2.0:
- # pragma acc update oacc-update-clause[optseq] new-line
-*/
-
-#define OACC_UPDATE_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_DEVICE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_HOST) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_IF_PRESENT) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_WAIT) )
-
-static void
-c_parser_oacc_update (c_parser *parser)
-{
- location_t loc = c_parser_peek_token (parser)->location;
-
- c_parser_consume_pragma (parser);
-
- tree clauses = c_parser_oacc_all_clauses (parser, OACC_UPDATE_CLAUSE_MASK,
- "#pragma acc update");
- if (omp_find_clause (clauses, OMP_CLAUSE_MAP) == NULL_TREE)
- {
- error_at (loc,
- "%<#pragma acc update%> must contain at least one "
- "%<device%> or %<host%> or %<self%> clause");
- return;
- }
-
- if (parser->error)
- return;
-
- tree stmt = make_node (OACC_UPDATE);
- TREE_TYPE (stmt) = void_type_node;
- OACC_UPDATE_CLAUSES (stmt) = clauses;
- SET_EXPR_LOCATION (stmt, loc);
- add_stmt (stmt);
-}
-
-/* OpenACC 2.0:
- # pragma acc wait [(intseq)] oacc-wait-clause[optseq] new-line
-
- LOC is the location of the #pragma token.
-*/
-
-#define OACC_WAIT_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OACC_CLAUSE_ASYNC) )
-
-static tree
-c_parser_oacc_wait (location_t loc, c_parser *parser, char *p_name)
-{
- tree clauses, list = NULL_TREE, stmt = NULL_TREE;
-
- if (c_parser_peek_token (parser)->type == CPP_OPEN_PAREN)
- list = c_parser_oacc_wait_list (parser, loc, list);
-
- strcpy (p_name, " wait");
- clauses = c_parser_oacc_all_clauses (parser, OACC_WAIT_CLAUSE_MASK, p_name);
- stmt = c_finish_oacc_wait (loc, list, clauses);
- add_stmt (stmt);
-
- return stmt;
-}
-
-/* OpenMP 5.0:
- # pragma omp allocate (list) [allocator(allocator)] */
-
-static void
-c_parser_omp_allocate (location_t loc, c_parser *parser)
-{
- tree allocator = NULL_TREE;
- tree nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ALLOCATE, NULL_TREE);
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- matching_parens parens;
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- c_parser_consume_token (parser);
- if (strcmp ("allocator", p) != 0)
- error_at (c_parser_peek_token (parser)->location,
- "expected %<allocator%>");
- else if (parens.require_open (parser))
- {
- location_t expr_loc = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (expr_loc, expr, false, true);
- allocator = expr.value;
- allocator = c_fully_fold (allocator, false, NULL);
- tree orig_type
- = expr.original_type ? expr.original_type : TREE_TYPE (allocator);
- orig_type = TYPE_MAIN_VARIANT (orig_type);
- if (!INTEGRAL_TYPE_P (TREE_TYPE (allocator))
- || TREE_CODE (orig_type) != ENUMERAL_TYPE
- || TYPE_NAME (orig_type)
- != get_identifier ("omp_allocator_handle_t"))
- {
- error_at (expr_loc, "%<allocator%> clause allocator expression "
- "has type %qT rather than "
- "%<omp_allocator_handle_t%>",
- TREE_TYPE (allocator));
- allocator = NULL_TREE;
- }
- parens.skip_until_found_close (parser);
- }
- }
- c_parser_skip_to_pragma_eol (parser);
-
- if (allocator)
- for (tree c = nl; c != NULL_TREE; c = OMP_CLAUSE_CHAIN (c))
- OMP_CLAUSE_ALLOCATE_ALLOCATOR (c) = allocator;
-
- sorry_at (loc, "%<#pragma omp allocate%> not yet supported");
-}
-
-/* OpenMP 2.5:
- # pragma omp atomic new-line
- expression-stmt
-
- expression-stmt:
- x binop= expr | x++ | ++x | x-- | --x
- binop:
- +, *, -, /, &, ^, |, <<, >>
-
- where x is an lvalue expression with scalar type.
-
- OpenMP 3.1:
- # pragma omp atomic new-line
- update-stmt
-
- # pragma omp atomic read new-line
- read-stmt
-
- # pragma omp atomic write new-line
- write-stmt
-
- # pragma omp atomic update new-line
- update-stmt
-
- # pragma omp atomic capture new-line
- capture-stmt
-
- # pragma omp atomic capture new-line
- capture-block
-
- read-stmt:
- v = x
- write-stmt:
- x = expr
- update-stmt:
- expression-stmt | x = x binop expr
- capture-stmt:
- v = expression-stmt
- capture-block:
- { v = x; update-stmt; } | { update-stmt; v = x; }
-
- OpenMP 4.0:
- update-stmt:
- expression-stmt | x = x binop expr | x = expr binop x
- capture-stmt:
- v = update-stmt
- capture-block:
- { v = x; update-stmt; } | { update-stmt; v = x; } | { v = x; x = expr; }
-
- OpenMP 5.1:
- # pragma omp atomic compare new-line
- conditional-update-atomic
-
- # pragma omp atomic compare capture new-line
- conditional-update-capture-atomic
-
- conditional-update-atomic:
- cond-expr-stmt | cond-update-stmt
- cond-expr-stmt:
- x = expr ordop x ? expr : x;
- x = x ordop expr ? expr : x;
- x = x == e ? d : x;
- cond-update-stmt:
- if (expr ordop x) { x = expr; }
- if (x ordop expr) { x = expr; }
- if (x == e) { x = d; }
- ordop:
- <, >
- conditional-update-capture-atomic:
- v = cond-expr-stmt
- { v = x; cond-expr-stmt }
- { cond-expr-stmt v = x; }
- { v = x; cond-update-stmt }
- { cond-update-stmt v = x; }
- if (x == e) { x = d; } else { v = x; }
- { r = x == e; if (r) { x = d; } }
- { r = x == e; if (r) { x = d; } else { v = x; } }
-
- where x, r and v are lvalue expressions with scalar type,
- expr, e and d are expressions with scalar type and e might be
- the same as v.
-
- LOC is the location of the #pragma token. */
-
-static void
-c_parser_omp_atomic (location_t loc, c_parser *parser, bool openacc)
-{
- tree lhs = NULL_TREE, rhs = NULL_TREE, v = NULL_TREE, r = NULL_TREE;
- tree lhs1 = NULL_TREE, rhs1 = NULL_TREE;
- tree stmt, orig_lhs, unfolded_lhs = NULL_TREE, unfolded_lhs1 = NULL_TREE;
- enum tree_code code = ERROR_MARK, opcode = NOP_EXPR;
- enum omp_memory_order memory_order = OMP_MEMORY_ORDER_UNSPECIFIED;
- struct c_expr expr;
- location_t eloc;
- bool structured_block = false;
- bool swapped = false;
- bool non_lvalue_p;
- bool first = true;
- tree clauses = NULL_TREE;
- bool capture = false;
- bool compare = false;
- bool weak = false;
- enum omp_memory_order fail = OMP_MEMORY_ORDER_UNSPECIFIED;
- bool no_semicolon = false;
- bool extra_scope = false;
-
- while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
- {
- if (!first
- && c_parser_next_token_is (parser, CPP_COMMA)
- && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
- c_parser_consume_token (parser);
-
- first = false;
-
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p
- = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- location_t cloc = c_parser_peek_token (parser)->location;
- enum tree_code new_code = ERROR_MARK;
- enum omp_memory_order new_memory_order
- = OMP_MEMORY_ORDER_UNSPECIFIED;
- bool new_capture = false;
- bool new_compare = false;
- bool new_weak = false;
- enum omp_memory_order new_fail = OMP_MEMORY_ORDER_UNSPECIFIED;
-
- if (!strcmp (p, "read"))
- new_code = OMP_ATOMIC_READ;
- else if (!strcmp (p, "write"))
- new_code = NOP_EXPR;
- else if (!strcmp (p, "update"))
- new_code = OMP_ATOMIC;
- else if (openacc && !strcmp (p, "capture"))
- new_code = OMP_ATOMIC_CAPTURE_NEW;
- else if (openacc)
- {
- p = NULL;
- error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
- "or %<capture%> clause");
- }
- else if (!strcmp (p, "capture"))
- new_capture = true;
- else if (!strcmp (p, "compare"))
- new_compare = true;
- else if (!strcmp (p, "weak"))
- new_weak = true;
- else if (!strcmp (p, "fail"))
- {
- matching_parens parens;
-
- c_parser_consume_token (parser);
- if (!parens.require_open (parser))
- continue;
-
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *q
- = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-
- if (!strcmp (q, "seq_cst"))
- new_fail = OMP_MEMORY_ORDER_SEQ_CST;
- else if (!strcmp (q, "acquire"))
- new_fail = OMP_MEMORY_ORDER_ACQUIRE;
- else if (!strcmp (q, "relaxed"))
- new_fail = OMP_MEMORY_ORDER_RELAXED;
- }
-
- if (new_fail != OMP_MEMORY_ORDER_UNSPECIFIED)
- {
- c_parser_consume_token (parser);
- if (fail != OMP_MEMORY_ORDER_UNSPECIFIED)
- error_at (cloc, "too many %qs clauses", "fail");
- else
- fail = new_fail;
- }
- else
- c_parser_error (parser, "expected %<seq_cst%>, %<acquire%> "
- "or %<relaxed%>");
- parens.skip_until_found_close (parser);
- continue;
- }
- else if (!strcmp (p, "seq_cst"))
- new_memory_order = OMP_MEMORY_ORDER_SEQ_CST;
- else if (!strcmp (p, "acq_rel"))
- new_memory_order = OMP_MEMORY_ORDER_ACQ_REL;
- else if (!strcmp (p, "release"))
- new_memory_order = OMP_MEMORY_ORDER_RELEASE;
- else if (!strcmp (p, "acquire"))
- new_memory_order = OMP_MEMORY_ORDER_ACQUIRE;
- else if (!strcmp (p, "relaxed"))
- new_memory_order = OMP_MEMORY_ORDER_RELAXED;
- else if (!strcmp (p, "hint"))
- {
- c_parser_consume_token (parser);
- clauses = c_parser_omp_clause_hint (parser, clauses);
- continue;
- }
- else
- {
- p = NULL;
- error_at (cloc, "expected %<read%>, %<write%>, %<update%>, "
- "%<capture%>, %<compare%>, %<weak%>, %<fail%>, "
- "%<seq_cst%>, %<acq_rel%>, %<release%>, "
- "%<relaxed%> or %<hint%> clause");
- }
- if (p)
- {
- if (new_code != ERROR_MARK)
- {
- /* OpenACC permits 'update capture'. */
- if (openacc
- && code == OMP_ATOMIC
- && new_code == OMP_ATOMIC_CAPTURE_NEW)
- code = new_code;
- else if (code != ERROR_MARK)
- error_at (cloc, "too many atomic clauses");
- else
- code = new_code;
- }
- else if (new_memory_order != OMP_MEMORY_ORDER_UNSPECIFIED)
- {
- if (memory_order != OMP_MEMORY_ORDER_UNSPECIFIED)
- error_at (cloc, "too many memory order clauses");
- else
- memory_order = new_memory_order;
- }
- else if (new_capture)
- {
- if (capture)
- error_at (cloc, "too many %qs clauses", "capture");
- else
- capture = true;
- }
- else if (new_compare)
- {
- if (compare)
- error_at (cloc, "too many %qs clauses", "compare");
- else
- compare = true;
- }
- else if (new_weak)
- {
- if (weak)
- error_at (cloc, "too many %qs clauses", "weak");
- else
- weak = true;
- }
- c_parser_consume_token (parser);
- continue;
- }
- }
- break;
- }
- c_parser_skip_to_pragma_eol (parser);
-
- if (code == ERROR_MARK)
- code = OMP_ATOMIC;
- if (capture)
- {
- if (code != OMP_ATOMIC)
- error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> "
- "clauses", "capture");
- else
- code = OMP_ATOMIC_CAPTURE_NEW;
- }
- if (compare && code != OMP_ATOMIC && code != OMP_ATOMIC_CAPTURE_NEW)
- {
- error_at (loc, "%qs clause is incompatible with %<read%> or %<write%> "
- "clauses", "compare");
- compare = false;
- }
- if (fail != OMP_MEMORY_ORDER_UNSPECIFIED && !compare)
- {
- error_at (loc, "%qs clause requires %qs clause", "fail", "compare");
- fail = OMP_MEMORY_ORDER_UNSPECIFIED;
- }
- if (weak && !compare)
- {
- error_at (loc, "%qs clause requires %qs clause", "weak", "compare");
- weak = false;
- }
- if (openacc)
- memory_order = OMP_MEMORY_ORDER_RELAXED;
- else if (memory_order == OMP_MEMORY_ORDER_UNSPECIFIED)
- {
- omp_requires_mask
- = (enum omp_requires) (omp_requires_mask
- | OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED);
- switch ((enum omp_memory_order)
- (omp_requires_mask & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER))
- {
- case OMP_MEMORY_ORDER_UNSPECIFIED:
- case OMP_MEMORY_ORDER_RELAXED:
- memory_order = OMP_MEMORY_ORDER_RELAXED;
- break;
- case OMP_MEMORY_ORDER_SEQ_CST:
- memory_order = OMP_MEMORY_ORDER_SEQ_CST;
- break;
- case OMP_MEMORY_ORDER_ACQ_REL:
- switch (code)
- {
- case OMP_ATOMIC_READ:
- memory_order = OMP_MEMORY_ORDER_ACQUIRE;
- break;
- case NOP_EXPR: /* atomic write */
- memory_order = OMP_MEMORY_ORDER_RELEASE;
- break;
- default:
- memory_order = OMP_MEMORY_ORDER_ACQ_REL;
- break;
- }
- break;
- default:
- gcc_unreachable ();
- }
- }
- else
- switch (code)
- {
- case OMP_ATOMIC_READ:
- if (memory_order == OMP_MEMORY_ORDER_RELEASE)
- {
- error_at (loc, "%<#pragma omp atomic read%> incompatible with "
- "%<release%> clause");
- memory_order = OMP_MEMORY_ORDER_SEQ_CST;
- }
- else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL)
- memory_order = OMP_MEMORY_ORDER_ACQUIRE;
- break;
- case NOP_EXPR: /* atomic write */
- if (memory_order == OMP_MEMORY_ORDER_ACQUIRE)
- {
- error_at (loc, "%<#pragma omp atomic write%> incompatible with "
- "%<acquire%> clause");
- memory_order = OMP_MEMORY_ORDER_SEQ_CST;
- }
- else if (memory_order == OMP_MEMORY_ORDER_ACQ_REL)
- memory_order = OMP_MEMORY_ORDER_RELEASE;
- break;
- default:
- break;
- }
- if (fail != OMP_MEMORY_ORDER_UNSPECIFIED)
- memory_order
- = (enum omp_memory_order) (memory_order
- | (fail << OMP_FAIL_MEMORY_ORDER_SHIFT));
-
- switch (code)
- {
- case OMP_ATOMIC_READ:
- case NOP_EXPR: /* atomic write */
- v = c_parser_cast_expression (parser, NULL).value;
- non_lvalue_p = !lvalue_p (v);
- v = c_fully_fold (v, false, NULL, true);
- if (v == error_mark_node)
- goto saw_error;
- if (non_lvalue_p)
- v = non_lvalue (v);
- loc = c_parser_peek_token (parser)->location;
- if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
- goto saw_error;
- if (code == NOP_EXPR)
- {
- lhs = c_parser_expression (parser).value;
- lhs = c_fully_fold (lhs, false, NULL);
- if (lhs == error_mark_node)
- goto saw_error;
- }
- else
- {
- lhs = c_parser_cast_expression (parser, NULL).value;
- non_lvalue_p = !lvalue_p (lhs);
- lhs = c_fully_fold (lhs, false, NULL, true);
- if (lhs == error_mark_node)
- goto saw_error;
- if (non_lvalue_p)
- lhs = non_lvalue (lhs);
- }
- if (code == NOP_EXPR)
- {
- /* atomic write is represented by OMP_ATOMIC with NOP_EXPR
- opcode. */
- code = OMP_ATOMIC;
- rhs = lhs;
- lhs = v;
- v = NULL_TREE;
- }
- goto done;
- case OMP_ATOMIC_CAPTURE_NEW:
- if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
- {
- c_parser_consume_token (parser);
- structured_block = true;
- }
- else if (compare
- && c_parser_next_token_is_keyword (parser, RID_IF))
- break;
- else
- {
- v = c_parser_cast_expression (parser, NULL).value;
- non_lvalue_p = !lvalue_p (v);
- v = c_fully_fold (v, false, NULL, true);
- if (v == error_mark_node)
- goto saw_error;
- if (non_lvalue_p)
- v = non_lvalue (v);
- if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
- goto saw_error;
- if (compare && c_parser_next_token_is_keyword (parser, RID_IF))
- {
- eloc = c_parser_peek_token (parser)->location;
- error_at (eloc, "expected expression");
- goto saw_error;
- }
- }
- break;
- default:
- break;
- }
-
- /* For structured_block case we don't know yet whether
- old or new x should be captured. */
-restart:
- if (compare && c_parser_next_token_is_keyword (parser, RID_IF))
- {
- c_parser_consume_token (parser);
-
- matching_parens parens;
- if (!parens.require_open (parser))
- goto saw_error;
- eloc = c_parser_peek_token (parser)->location;
- c_expr cmp_expr;
- if (r)
- {
- cmp_expr = c_parser_cast_expression (parser, NULL);
- cmp_expr = default_function_array_conversion (eloc, cmp_expr);
- }
- else
- cmp_expr = c_parser_binary_expression (parser, NULL, void_list_node);
- parens.skip_until_found_close (parser);
- if (cmp_expr.value == error_mark_node)
- goto saw_error;
- if (r)
- {
- if (!c_tree_equal (cmp_expr.value, unfolded_lhs))
- goto bad_if;
- cmp_expr.value = rhs1;
- rhs1 = NULL_TREE;
- gcc_assert (TREE_CODE (cmp_expr.value) == EQ_EXPR);
- }
- if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
- ;
- else if (!structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
- {
- error_at (EXPR_LOC_OR_LOC (cmp_expr.value, eloc),
- "expected %<==%> comparison in %<if%> condition");
- goto saw_error;
- }
- else if (TREE_CODE (cmp_expr.value) != GT_EXPR
- && TREE_CODE (cmp_expr.value) != LT_EXPR)
- {
- error_at (EXPR_LOC_OR_LOC (cmp_expr.value, eloc),
- "expected %<==%>, %<<%> or %<>%> comparison in %<if%> "
- "condition");
- goto saw_error;
- }
- if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
- goto saw_error;
-
- extra_scope = true;
- eloc = c_parser_peek_token (parser)->location;
- expr = c_parser_cast_expression (parser, NULL);
- lhs = expr.value;
- expr = default_function_array_conversion (eloc, expr);
- unfolded_lhs = expr.value;
- lhs = c_fully_fold (lhs, false, NULL, true);
- orig_lhs = lhs;
- if (lhs == error_mark_node)
- goto saw_error;
- if (!lvalue_p (unfolded_lhs))
- lhs = non_lvalue (lhs);
- if (!c_parser_next_token_is (parser, CPP_EQ))
- {
- c_parser_error (parser, "expected %<=%>");
- goto saw_error;
- }
- c_parser_consume_token (parser);
- eloc = c_parser_peek_token (parser)->location;
- expr = c_parser_expr_no_commas (parser, NULL);
- rhs1 = expr.value;
-
- if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
- goto saw_error;
-
- if (!c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>"))
- goto saw_error;
-
- extra_scope = false;
- no_semicolon = true;
-
- if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 0), unfolded_lhs))
- {
- if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
- {
- opcode = COND_EXPR;
- rhs = c_fully_fold (TREE_OPERAND (cmp_expr.value, 1),
- false, NULL, true);
- rhs1 = c_fully_fold (rhs1, false, NULL, true);
- }
- else if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 1), rhs1))
- {
- opcode = (TREE_CODE (cmp_expr.value) == GT_EXPR
- ? MIN_EXPR : MAX_EXPR);
- rhs = c_fully_fold (rhs1, false, NULL, true);
- rhs1 = c_fully_fold (TREE_OPERAND (cmp_expr.value, 0),
- false, NULL, true);
- }
- else
- goto bad_if;
- }
- else if (TREE_CODE (cmp_expr.value) == EQ_EXPR)
- goto bad_if;
- else if (c_tree_equal (TREE_OPERAND (cmp_expr.value, 1), unfolded_lhs)
- && c_tree_equal (TREE_OPERAND (cmp_expr.value, 0), rhs1))
- {
- opcode = (TREE_CODE (cmp_expr.value) == GT_EXPR
- ? MAX_EXPR : MIN_EXPR);
- rhs = c_fully_fold (rhs1, false, NULL, true);
- rhs1 = c_fully_fold (TREE_OPERAND (cmp_expr.value, 1),
- false, NULL, true);
- }
- else
- {
- bad_if:
- c_parser_error (parser,
- "invalid form of %<#pragma omp atomic compare%>");
- goto saw_error;
- }
-
- if (c_parser_next_token_is_keyword (parser, RID_ELSE))
- {
- if (code != OMP_ATOMIC_CAPTURE_NEW
- || (structured_block && r == NULL_TREE)
- || TREE_CODE (cmp_expr.value) != EQ_EXPR)
- {
- eloc = c_parser_peek_token (parser)->location;
- error_at (eloc, "unexpected %<else%>");
- goto saw_error;
- }
-
- c_parser_consume_token (parser);
-
- if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
- goto saw_error;
-
- extra_scope = true;
- v = c_parser_cast_expression (parser, NULL).value;
- non_lvalue_p = !lvalue_p (v);
- v = c_fully_fold (v, false, NULL, true);
- if (v == error_mark_node)
- goto saw_error;
- if (non_lvalue_p)
- v = non_lvalue (v);
- if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
- goto saw_error;
-
- expr = c_parser_expr_no_commas (parser, NULL);
-
- if (!c_tree_equal (expr.value, unfolded_lhs))
- goto bad_if;
-
- if (!c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
- goto saw_error;
-
- if (!c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>"))
- goto saw_error;
-
- extra_scope = false;
- code = OMP_ATOMIC_CAPTURE_OLD;
- if (r == NULL_TREE)
- /* Signal to c_finish_omp_atomic that in
- if (x == e) { x = d; } else { v = x; }
- case the store to v should be conditional. */
- r = void_list_node;
- }
- else if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
- {
- c_parser_require_keyword (parser, RID_ELSE, "expected %<else%>");
- goto saw_error;
- }
- else if (code == OMP_ATOMIC_CAPTURE_NEW
- && r != NULL_TREE
- && v == NULL_TREE)
- code = OMP_ATOMIC;
- goto stmt_done;
- }
- eloc = c_parser_peek_token (parser)->location;
- expr = c_parser_cast_expression (parser, NULL);
- lhs = expr.value;
- expr = default_function_array_conversion (eloc, expr);
- unfolded_lhs = expr.value;
- lhs = c_fully_fold (lhs, false, NULL, true);
- orig_lhs = lhs;
- switch (TREE_CODE (lhs))
- {
- invalid_compare:
- error_at (eloc, "invalid form of %<pragma omp atomic compare%>");
- /* FALLTHRU */
- case ERROR_MARK:
- saw_error:
- c_parser_skip_to_end_of_block_or_statement (parser);
- if (extra_scope && c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
- c_parser_consume_token (parser);
- if (structured_block)
- {
- if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
- c_parser_consume_token (parser);
- else if (code == OMP_ATOMIC_CAPTURE_NEW)
- {
- c_parser_skip_to_end_of_block_or_statement (parser);
- if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
- c_parser_consume_token (parser);
- }
- }
- return;
-
- case POSTINCREMENT_EXPR:
- if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
- code = OMP_ATOMIC_CAPTURE_OLD;
- /* FALLTHROUGH */
- case PREINCREMENT_EXPR:
- lhs = TREE_OPERAND (lhs, 0);
- unfolded_lhs = NULL_TREE;
- opcode = PLUS_EXPR;
- rhs = integer_one_node;
- if (compare)
- goto invalid_compare;
- break;
-
- case POSTDECREMENT_EXPR:
- if (code == OMP_ATOMIC_CAPTURE_NEW && !structured_block)
- code = OMP_ATOMIC_CAPTURE_OLD;
- /* FALLTHROUGH */
- case PREDECREMENT_EXPR:
- lhs = TREE_OPERAND (lhs, 0);
- unfolded_lhs = NULL_TREE;
- opcode = MINUS_EXPR;
- rhs = integer_one_node;
- if (compare)
- goto invalid_compare;
- break;
-
- case COMPOUND_EXPR:
- if (TREE_CODE (TREE_OPERAND (lhs, 0)) == SAVE_EXPR
- && TREE_CODE (TREE_OPERAND (lhs, 1)) == COMPOUND_EXPR
- && TREE_CODE (TREE_OPERAND (TREE_OPERAND (lhs, 1), 0)) == MODIFY_EXPR
- && TREE_OPERAND (TREE_OPERAND (lhs, 1), 1) == TREE_OPERAND (lhs, 0)
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND
- (TREE_OPERAND (lhs, 1), 0), 0)))
- == BOOLEAN_TYPE)
- /* Undo effects of boolean_increment for post {in,de}crement. */
- lhs = TREE_OPERAND (TREE_OPERAND (lhs, 1), 0);
- /* FALLTHRU */
- case MODIFY_EXPR:
- if (TREE_CODE (lhs) == MODIFY_EXPR
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) == BOOLEAN_TYPE)
- {
- /* Undo effects of boolean_increment. */
- if (integer_onep (TREE_OPERAND (lhs, 1)))
- {
- /* This is pre or post increment. */
- rhs = TREE_OPERAND (lhs, 1);
- lhs = TREE_OPERAND (lhs, 0);
- unfolded_lhs = NULL_TREE;
- opcode = NOP_EXPR;
- if (code == OMP_ATOMIC_CAPTURE_NEW
- && !structured_block
- && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
- code = OMP_ATOMIC_CAPTURE_OLD;
- if (compare)
- goto invalid_compare;
- break;
- }
- if (TREE_CODE (TREE_OPERAND (lhs, 1)) == TRUTH_NOT_EXPR
- && TREE_OPERAND (lhs, 0)
- == TREE_OPERAND (TREE_OPERAND (lhs, 1), 0))
- {
- /* This is pre or post decrement. */
- rhs = TREE_OPERAND (lhs, 1);
- lhs = TREE_OPERAND (lhs, 0);
- unfolded_lhs = NULL_TREE;
- opcode = NOP_EXPR;
- if (code == OMP_ATOMIC_CAPTURE_NEW
- && !structured_block
- && TREE_CODE (orig_lhs) == COMPOUND_EXPR)
- code = OMP_ATOMIC_CAPTURE_OLD;
- if (compare)
- goto invalid_compare;
- break;
- }
- }
- /* FALLTHRU */
- default:
- if (!lvalue_p (unfolded_lhs))
- lhs = non_lvalue (lhs);
- if (compare && !c_parser_next_token_is (parser, CPP_EQ))
- {
- c_parser_error (parser, "expected %<=%>");
- goto saw_error;
- }
- switch (c_parser_peek_token (parser)->type)
- {
- case CPP_MULT_EQ:
- opcode = MULT_EXPR;
- break;
- case CPP_DIV_EQ:
- opcode = TRUNC_DIV_EXPR;
- break;
- case CPP_PLUS_EQ:
- opcode = PLUS_EXPR;
- break;
- case CPP_MINUS_EQ:
- opcode = MINUS_EXPR;
- break;
- case CPP_LSHIFT_EQ:
- opcode = LSHIFT_EXPR;
- break;
- case CPP_RSHIFT_EQ:
- opcode = RSHIFT_EXPR;
- break;
- case CPP_AND_EQ:
- opcode = BIT_AND_EXPR;
- break;
- case CPP_OR_EQ:
- opcode = BIT_IOR_EXPR;
- break;
- case CPP_XOR_EQ:
- opcode = BIT_XOR_EXPR;
- break;
- case CPP_EQ:
- c_parser_consume_token (parser);
- eloc = c_parser_peek_token (parser)->location;
- expr = c_parser_expr_no_commas (parser, NULL, unfolded_lhs);
- rhs1 = expr.value;
- switch (TREE_CODE (rhs1))
- {
- case MULT_EXPR:
- case TRUNC_DIV_EXPR:
- case RDIV_EXPR:
- case PLUS_EXPR:
- case MINUS_EXPR:
- case LSHIFT_EXPR:
- case RSHIFT_EXPR:
- case BIT_AND_EXPR:
- case BIT_IOR_EXPR:
- case BIT_XOR_EXPR:
- if (compare)
- break;
- if (c_tree_equal (TREE_OPERAND (rhs1, 0), unfolded_lhs))
- {
- opcode = TREE_CODE (rhs1);
- rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
- true);
- rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL,
- true);
- goto stmt_done;
- }
- if (c_tree_equal (TREE_OPERAND (rhs1, 1), unfolded_lhs))
- {
- opcode = TREE_CODE (rhs1);
- rhs = c_fully_fold (TREE_OPERAND (rhs1, 0), false, NULL,
- true);
- rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
- true);
- swapped = !commutative_tree_code (opcode);
- goto stmt_done;
- }
- break;
- case COND_EXPR:
- if (!compare)
- break;
- if (TREE_CODE (TREE_OPERAND (rhs1, 0)) != GT_EXPR
- && TREE_CODE (TREE_OPERAND (rhs1, 0)) != LT_EXPR
- && TREE_CODE (TREE_OPERAND (rhs1, 0)) != EQ_EXPR)
- break;
- if (!TREE_OPERAND (rhs1, 1))
- break;
- if (!c_tree_equal (TREE_OPERAND (rhs1, 2), unfolded_lhs))
- break;
- if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0),
- unfolded_lhs))
- {
- if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == EQ_EXPR)
- {
- opcode = COND_EXPR;
- rhs = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
- 0), 1),
- false, NULL, true);
- rhs1 = c_fully_fold (TREE_OPERAND (rhs1, 1), false,
- NULL, true);
- goto stmt_done;
- }
- if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1),
- TREE_OPERAND (rhs1, 1)))
- {
- opcode = (TREE_CODE (TREE_OPERAND (rhs1, 0)) == GT_EXPR
- ? MIN_EXPR : MAX_EXPR);
- rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
- true);
- rhs1 = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
- 0), 0),
- false, NULL, true);
- goto stmt_done;
- }
- }
- else if (TREE_CODE (TREE_OPERAND (rhs1, 0)) == EQ_EXPR)
- break;
- else if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 1),
- unfolded_lhs))
- {
- if (c_tree_equal (TREE_OPERAND (TREE_OPERAND (rhs1, 0), 0),
- TREE_OPERAND (rhs1, 1)))
- {
- opcode = (TREE_CODE (TREE_OPERAND (rhs1, 0)) == GT_EXPR
- ? MAX_EXPR : MIN_EXPR);
- rhs = c_fully_fold (TREE_OPERAND (rhs1, 1), false, NULL,
- true);
- rhs1 = c_fully_fold (TREE_OPERAND (TREE_OPERAND (rhs1,
- 0), 1),
- false, NULL, true);
- goto stmt_done;
- }
- }
- break;
- case EQ_EXPR:
- if (!compare
- || code != OMP_ATOMIC_CAPTURE_NEW
- || !structured_block
- || v
- || r)
- break;
- if (c_parser_next_token_is (parser, CPP_SEMICOLON)
- && c_parser_peek_2nd_token (parser)->keyword == RID_IF)
- {
- r = lhs;
- lhs = NULL_TREE;
- c_parser_consume_token (parser);
- goto restart;
- }
- break;
- case ERROR_MARK:
- goto saw_error;
- default:
- break;
- }
- if (c_parser_peek_token (parser)->type == CPP_SEMICOLON)
- {
- if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW)
- {
- code = OMP_ATOMIC_CAPTURE_OLD;
- v = lhs;
- lhs = NULL_TREE;
- expr = default_function_array_read_conversion (eloc, expr);
- unfolded_lhs1 = expr.value;
- lhs1 = c_fully_fold (unfolded_lhs1, false, NULL, true);
- rhs1 = NULL_TREE;
- c_parser_consume_token (parser);
- goto restart;
- }
- if (structured_block && !compare)
- {
- opcode = NOP_EXPR;
- expr = default_function_array_read_conversion (eloc, expr);
- rhs = c_fully_fold (expr.value, false, NULL, true);
- rhs1 = NULL_TREE;
- goto stmt_done;
- }
- }
- c_parser_error (parser, "invalid form of %<#pragma omp atomic%>");
- goto saw_error;
- default:
- c_parser_error (parser,
- "invalid operator for %<#pragma omp atomic%>");
- goto saw_error;
- }
-
- /* Arrange to pass the location of the assignment operator to
- c_finish_omp_atomic. */
- loc = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
- eloc = c_parser_peek_token (parser)->location;
- expr = c_parser_expression (parser);
- expr = default_function_array_read_conversion (eloc, expr);
- rhs = expr.value;
- rhs = c_fully_fold (rhs, false, NULL, true);
- break;
- }
-stmt_done:
- if (structured_block && code == OMP_ATOMIC_CAPTURE_NEW && r == NULL_TREE)
- {
- if (!no_semicolon
- && !c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
- goto saw_error;
- no_semicolon = false;
- v = c_parser_cast_expression (parser, NULL).value;
- non_lvalue_p = !lvalue_p (v);
- v = c_fully_fold (v, false, NULL, true);
- if (v == error_mark_node)
- goto saw_error;
- if (non_lvalue_p)
- v = non_lvalue (v);
- if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
- goto saw_error;
- eloc = c_parser_peek_token (parser)->location;
- expr = c_parser_cast_expression (parser, NULL);
- lhs1 = expr.value;
- expr = default_function_array_read_conversion (eloc, expr);
- unfolded_lhs1 = expr.value;
- lhs1 = c_fully_fold (lhs1, false, NULL, true);
- if (lhs1 == error_mark_node)
- goto saw_error;
- if (!lvalue_p (unfolded_lhs1))
- lhs1 = non_lvalue (lhs1);
- }
- if (structured_block)
- {
- if (!no_semicolon)
- c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
- c_parser_require (parser, CPP_CLOSE_BRACE, "expected %<}%>");
- }
-done:
- if (weak && opcode != COND_EXPR)
- {
- error_at (loc, "%<weak%> clause requires atomic equality comparison");
- weak = false;
- }
- if (unfolded_lhs && unfolded_lhs1
- && !c_tree_equal (unfolded_lhs, unfolded_lhs1))
- {
- error ("%<#pragma omp atomic capture%> uses two different "
- "expressions for memory");
- stmt = error_mark_node;
- }
- else
- stmt = c_finish_omp_atomic (loc, code, opcode, lhs, rhs, v, lhs1, rhs1, r,
- swapped, memory_order, weak);
- if (stmt != error_mark_node)
- add_stmt (stmt);
-
- if (!structured_block && !no_semicolon)
- c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-}
-
-
-/* OpenMP 2.5:
- # pragma omp barrier new-line
-*/
-
-static void
-c_parser_omp_barrier (c_parser *parser)
-{
- location_t loc = c_parser_peek_token (parser)->location;
- c_parser_consume_pragma (parser);
- c_parser_skip_to_pragma_eol (parser);
-
- c_finish_omp_barrier (loc);
-}
-
-/* OpenMP 2.5:
- # pragma omp critical [(name)] new-line
- structured-block
-
- OpenMP 4.5:
- # pragma omp critical [(name) [hint(expression)]] new-line
-
- LOC is the location of the #pragma itself. */
-
-#define OMP_CRITICAL_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_HINT) )
-
-static tree
-c_parser_omp_critical (location_t loc, c_parser *parser, bool *if_p)
-{
- tree stmt, name = NULL_TREE, clauses = NULL_TREE;
-
- if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
- {
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- name = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>");
- }
- else
- c_parser_error (parser, "expected identifier");
-
- if (c_parser_next_token_is (parser, CPP_COMMA)
- && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
- c_parser_consume_token (parser);
- }
- clauses = c_parser_omp_all_clauses (parser, OMP_CRITICAL_CLAUSE_MASK,
- "#pragma omp critical");
- stmt = c_parser_omp_structured_block (parser, if_p);
- return c_finish_omp_critical (loc, stmt, name, clauses);
-}
-
-/* OpenMP 5.0:
- # pragma omp depobj ( depobj ) depobj-clause new-line
-
- depobj-clause:
- depend (dependence-type : locator)
- destroy
- update (dependence-type)
-
- dependence-type:
- in
- out
- inout
- mutexinout */
-
-static void
-c_parser_omp_depobj (c_parser *parser)
-{
- location_t loc = c_parser_peek_token (parser)->location;
- c_parser_consume_pragma (parser);
- matching_parens parens;
- if (!parens.require_open (parser))
- {
- c_parser_skip_to_pragma_eol (parser);
- return;
- }
-
- tree depobj = c_parser_expr_no_commas (parser, NULL).value;
- if (depobj != error_mark_node)
- {
- if (!lvalue_p (depobj))
- {
- error_at (EXPR_LOC_OR_LOC (depobj, loc),
- "%<depobj%> expression is not lvalue expression");
- depobj = error_mark_node;
- }
- else
- {
- tree addr = build_unary_op (EXPR_LOC_OR_LOC (depobj, loc), ADDR_EXPR,
- depobj, false);
- if (addr == error_mark_node)
- depobj = error_mark_node;
- else
- depobj = build_indirect_ref (EXPR_LOC_OR_LOC (depobj, loc),
- addr, RO_UNARY_STAR);
- }
- }
-
- parens.skip_until_found_close (parser);
- tree clause = NULL_TREE;
- enum omp_clause_depend_kind kind = OMP_CLAUSE_DEPEND_SOURCE;
- location_t c_loc = c_parser_peek_token (parser)->location;
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-
- c_parser_consume_token (parser);
- if (!strcmp ("depend", p))
- {
- clause = c_parser_omp_clause_depend (parser, NULL_TREE);
- clause = c_finish_omp_clauses (clause, C_ORT_OMP);
- if (!clause)
- clause = error_mark_node;
- }
- else if (!strcmp ("destroy", p))
- kind = OMP_CLAUSE_DEPEND_LAST;
- else if (!strcmp ("update", p))
- {
- matching_parens c_parens;
- if (c_parens.require_open (parser))
- {
- location_t c2_loc = c_parser_peek_token (parser)->location;
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p2
- = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-
- c_parser_consume_token (parser);
- if (!strcmp ("in", p2))
- kind = OMP_CLAUSE_DEPEND_IN;
- else if (!strcmp ("out", p2))
- kind = OMP_CLAUSE_DEPEND_OUT;
- else if (!strcmp ("inout", p2))
- kind = OMP_CLAUSE_DEPEND_INOUT;
- else if (!strcmp ("mutexinoutset", p2))
- kind = OMP_CLAUSE_DEPEND_MUTEXINOUTSET;
- }
- if (kind == OMP_CLAUSE_DEPEND_SOURCE)
- {
- clause = error_mark_node;
- error_at (c2_loc, "expected %<in%>, %<out%>, %<inout%> or "
- "%<mutexinoutset%>");
- }
- c_parens.skip_until_found_close (parser);
- }
- else
- clause = error_mark_node;
- }
- }
- if (!clause && kind == OMP_CLAUSE_DEPEND_SOURCE)
- {
- clause = error_mark_node;
- error_at (c_loc, "expected %<depend%>, %<destroy%> or %<update%> clause");
- }
- c_parser_skip_to_pragma_eol (parser);
-
- c_finish_omp_depobj (loc, depobj, kind, clause);
-}
-
-
-/* OpenMP 2.5:
- # pragma omp flush flush-vars[opt] new-line
-
- flush-vars:
- ( variable-list )
-
- OpenMP 5.0:
- # pragma omp flush memory-order-clause new-line */
-
-static void
-c_parser_omp_flush (c_parser *parser)
-{
- location_t loc = c_parser_peek_token (parser)->location;
- c_parser_consume_pragma (parser);
- enum memmodel mo = MEMMODEL_LAST;
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p
- = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-
- if (!strcmp (p, "seq_cst"))
- mo = MEMMODEL_SEQ_CST;
- else if (!strcmp (p, "acq_rel"))
- mo = MEMMODEL_ACQ_REL;
- else if (!strcmp (p, "release"))
- mo = MEMMODEL_RELEASE;
- else if (!strcmp (p, "acquire"))
- mo = MEMMODEL_ACQUIRE;
- else
- error_at (c_parser_peek_token (parser)->location,
- "expected %<seq_cst%>, %<acq_rel%>, %<release%> or "
- "%<acquire%>");
- c_parser_consume_token (parser);
- }
- if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
- {
- if (mo != MEMMODEL_LAST)
- error_at (c_parser_peek_token (parser)->location,
- "%<flush%> list specified together with memory order "
- "clause");
- c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
- }
- else if (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
- c_parser_error (parser, "expected %<(%> or end of line");
- c_parser_skip_to_pragma_eol (parser);
-
- c_finish_omp_flush (loc, mo);
-}
-
-/* Parse an OpenMP structured block sequence. KIND is the corresponding
- separating directive. */
-
-static tree
-c_parser_omp_structured_block_sequence (c_parser *parser,
- enum pragma_kind kind)
-{
- tree stmt = push_stmt_list ();
- c_parser_statement (parser, NULL);
- do
- {
- if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
- break;
- if (c_parser_next_token_is (parser, CPP_EOF))
- break;
-
- if (kind != PRAGMA_NONE
- && c_parser_peek_token (parser)->pragma_kind == kind)
- break;
- c_parser_statement (parser, NULL);
- }
- while (1);
- return pop_stmt_list (stmt);
-}
-
-/* OpenMP 5.0:
-
- scan-loop-body:
- { structured-block scan-directive structured-block } */
-
-static void
-c_parser_omp_scan_loop_body (c_parser *parser, bool open_brace_parsed)
-{
- tree substmt;
- location_t loc;
- tree clauses = NULL_TREE;
-
- loc = c_parser_peek_token (parser)->location;
- if (!open_brace_parsed
- && !c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
- {
- /* Avoid skipping until the end of the block. */
- parser->error = false;
- return;
- }
-
- substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_OMP_SCAN);
- substmt = build2 (OMP_SCAN, void_type_node, substmt, NULL_TREE);
- SET_EXPR_LOCATION (substmt, loc);
- add_stmt (substmt);
-
- loc = c_parser_peek_token (parser)->location;
- if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SCAN)
- {
- enum omp_clause_code clause = OMP_CLAUSE_ERROR;
-
- c_parser_consume_pragma (parser);
-
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p
- = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (strcmp (p, "inclusive") == 0)
- clause = OMP_CLAUSE_INCLUSIVE;
- else if (strcmp (p, "exclusive") == 0)
- clause = OMP_CLAUSE_EXCLUSIVE;
- }
- if (clause != OMP_CLAUSE_ERROR)
- {
- c_parser_consume_token (parser);
- clauses = c_parser_omp_var_list_parens (parser, clause, NULL_TREE);
- }
- else
- c_parser_error (parser, "expected %<inclusive%> or "
- "%<exclusive%> clause");
- c_parser_skip_to_pragma_eol (parser);
- }
- else
- error ("expected %<#pragma omp scan%>");
-
- clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
- substmt = c_parser_omp_structured_block_sequence (parser, PRAGMA_NONE);
- substmt = build2 (OMP_SCAN, void_type_node, substmt, clauses);
- SET_EXPR_LOCATION (substmt, loc);
- add_stmt (substmt);
-
- c_parser_skip_until_found (parser, CPP_CLOSE_BRACE,
- "expected %<}%>");
-}
-
-/* Parse the restricted form of loop statements allowed by OpenACC and OpenMP.
- The real trick here is to determine the loop control variable early
- so that we can push a new decl if necessary to make it private.
- LOC is the location of the "acc" or "omp" in "#pragma acc" or "#pragma omp",
- respectively. */
-
-static tree
-c_parser_omp_for_loop (location_t loc, c_parser *parser, enum tree_code code,
- tree clauses, tree *cclauses, bool *if_p)
-{
- tree decl, cond, incr, body, init, stmt, cl;
- unsigned char save_in_statement;
- tree declv, condv, incrv, initv, ret = NULL_TREE;
- tree pre_body = NULL_TREE, this_pre_body;
- tree ordered_cl = NULL_TREE;
- bool fail = false, open_brace_parsed = false;
- int i, collapse = 1, ordered = 0, count, nbraces = 0;
- location_t for_loc;
- bool tiling = false;
- bool inscan = false;
- vec<tree, va_gc> *for_block = make_tree_vector ();
-
- for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
- if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
- collapse = tree_to_shwi (OMP_CLAUSE_COLLAPSE_EXPR (cl));
- else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_TILE)
- {
- tiling = true;
- collapse = list_length (OMP_CLAUSE_TILE_LIST (cl));
- }
- else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_ORDERED
- && OMP_CLAUSE_ORDERED_EXPR (cl))
- {
- ordered_cl = cl;
- ordered = tree_to_shwi (OMP_CLAUSE_ORDERED_EXPR (cl));
- }
- else if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_REDUCTION
- && OMP_CLAUSE_REDUCTION_INSCAN (cl)
- && (code == OMP_SIMD || code == OMP_FOR))
- inscan = true;
-
- if (ordered && ordered < collapse)
- {
- error_at (OMP_CLAUSE_LOCATION (ordered_cl),
- "%<ordered%> clause parameter is less than %<collapse%>");
- OMP_CLAUSE_ORDERED_EXPR (ordered_cl)
- = build_int_cst (NULL_TREE, collapse);
- ordered = collapse;
- }
- if (ordered)
- {
- for (tree *pc = &clauses; *pc; )
- if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_LINEAR)
- {
- error_at (OMP_CLAUSE_LOCATION (*pc),
- "%<linear%> clause may not be specified together "
- "with %<ordered%> clause with a parameter");
- *pc = OMP_CLAUSE_CHAIN (*pc);
- }
- else
- pc = &OMP_CLAUSE_CHAIN (*pc);
- }
-
- gcc_assert (tiling || (collapse >= 1 && ordered >= 0));
- count = ordered ? ordered : collapse;
-
- declv = make_tree_vec (count);
- initv = make_tree_vec (count);
- condv = make_tree_vec (count);
- incrv = make_tree_vec (count);
-
- if (!c_parser_next_token_is_keyword (parser, RID_FOR))
- {
- c_parser_error (parser, "for statement expected");
- return NULL;
- }
- for_loc = c_parser_peek_token (parser)->location;
- c_parser_consume_token (parser);
-
- /* Forbid break/continue in the loop initializer, condition, and
- increment expressions. */
- save_in_statement = in_statement;
- in_statement = IN_OMP_BLOCK;
-
- for (i = 0; i < count; i++)
- {
- int bracecount = 0;
-
- matching_parens parens;
- if (!parens.require_open (parser))
- goto pop_scopes;
-
- /* Parse the initialization declaration or expression. */
- if (c_parser_next_tokens_start_declaration (parser))
- {
- if (i > 0)
- vec_safe_push (for_block, c_begin_compound_stmt (true));
- this_pre_body = push_stmt_list ();
- c_in_omp_for = true;
- c_parser_declaration_or_fndef (parser, true, true, true, true, true);
- c_in_omp_for = false;
- if (this_pre_body)
- {
- this_pre_body = pop_stmt_list (this_pre_body);
- if (pre_body)
- {
- tree t = pre_body;
- pre_body = push_stmt_list ();
- add_stmt (t);
- add_stmt (this_pre_body);
- pre_body = pop_stmt_list (pre_body);
- }
- else
- pre_body = this_pre_body;
- }
- decl = check_for_loop_decls (for_loc, flag_isoc99);
- if (decl == NULL)
- goto error_init;
- if (DECL_INITIAL (decl) == error_mark_node)
- decl = error_mark_node;
- init = decl;
- }
- else if (c_parser_next_token_is (parser, CPP_NAME)
- && c_parser_peek_2nd_token (parser)->type == CPP_EQ)
- {
- struct c_expr decl_exp;
- struct c_expr init_exp;
- location_t init_loc;
-
- decl_exp = c_parser_postfix_expression (parser);
- decl = decl_exp.value;
-
- c_parser_require (parser, CPP_EQ, "expected %<=%>");
-
- init_loc = c_parser_peek_token (parser)->location;
- init_exp = c_parser_expr_no_commas (parser, NULL);
- init_exp = default_function_array_read_conversion (init_loc,
- init_exp);
- c_in_omp_for = true;
- init = build_modify_expr (init_loc, decl, decl_exp.original_type,
- NOP_EXPR, init_loc, init_exp.value,
- init_exp.original_type);
- c_in_omp_for = false;
- init = c_process_expr_stmt (init_loc, init);
-
- c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
- }
- else
- {
- error_init:
- c_parser_error (parser,
- "expected iteration declaration or initialization");
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
- "expected %<)%>");
- fail = true;
- goto parse_next;
- }
-
- /* Parse the loop condition. */
- cond = NULL_TREE;
- if (c_parser_next_token_is_not (parser, CPP_SEMICOLON))
- {
- location_t cond_loc = c_parser_peek_token (parser)->location;
- c_in_omp_for = true;
- struct c_expr cond_expr
- = c_parser_binary_expression (parser, NULL, NULL_TREE);
- c_in_omp_for = false;
-
- cond = cond_expr.value;
- cond = c_objc_common_truthvalue_conversion (cond_loc, cond);
- switch (cond_expr.original_code)
- {
- case GT_EXPR:
- case GE_EXPR:
- case LT_EXPR:
- case LE_EXPR:
- break;
- case NE_EXPR:
- if (code != OACC_LOOP)
- break;
- /* FALLTHRU. */
- default:
- /* Can't be cond = error_mark_node, because we want to preserve
- the location until c_finish_omp_for. */
- cond = build1 (NOP_EXPR, boolean_type_node, error_mark_node);
- break;
- }
- protected_set_expr_location (cond, cond_loc);
- }
- c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
-
- /* Parse the increment expression. */
- incr = NULL_TREE;
- if (c_parser_next_token_is_not (parser, CPP_CLOSE_PAREN))
- {
- location_t incr_loc = c_parser_peek_token (parser)->location;
-
- incr = c_process_expr_stmt (incr_loc,
- c_parser_expression (parser).value);
- }
- parens.skip_until_found_close (parser);
-
- if (decl == NULL || decl == error_mark_node || init == error_mark_node)
- fail = true;
- else
- {
- TREE_VEC_ELT (declv, i) = decl;
- TREE_VEC_ELT (initv, i) = init;
- TREE_VEC_ELT (condv, i) = cond;
- TREE_VEC_ELT (incrv, i) = incr;
- }
-
- parse_next:
- if (i == count - 1)
- break;
-
- /* FIXME: OpenMP 3.0 draft isn't very clear on what exactly is allowed
- in between the collapsed for loops to be still considered perfectly
- nested. Hopefully the final version clarifies this.
- For now handle (multiple) {'s and empty statements. */
- do
- {
- if (c_parser_next_token_is_keyword (parser, RID_FOR))
- {
- c_parser_consume_token (parser);
- break;
- }
- else if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
- {
- c_parser_consume_token (parser);
- bracecount++;
- }
- else if (bracecount
- && c_parser_next_token_is (parser, CPP_SEMICOLON))
- c_parser_consume_token (parser);
- else
- {
- c_parser_error (parser, "not enough perfectly nested loops");
- if (bracecount)
- {
- open_brace_parsed = true;
- bracecount--;
- }
- fail = true;
- count = 0;
- break;
- }
- }
- while (1);
-
- nbraces += bracecount;
- }
-
- if (nbraces)
- if_p = NULL;
-
- in_statement = IN_OMP_FOR;
- body = push_stmt_list ();
-
- if (inscan)
- c_parser_omp_scan_loop_body (parser, open_brace_parsed);
- else if (open_brace_parsed)
- {
- location_t here = c_parser_peek_token (parser)->location;
- stmt = c_begin_compound_stmt (true);
- c_parser_compound_statement_nostart (parser);
- add_stmt (c_end_compound_stmt (here, stmt, true));
- }
- else
- add_stmt (c_parser_c99_block_statement (parser, if_p));
-
- body = pop_stmt_list (body);
- in_statement = save_in_statement;
-
- while (nbraces)
- {
- if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
- {
- c_parser_consume_token (parser);
- nbraces--;
- }
- else if (c_parser_next_token_is (parser, CPP_SEMICOLON))
- c_parser_consume_token (parser);
- else
- {
- c_parser_error (parser, "collapsed loops not perfectly nested");
- while (nbraces)
- {
- location_t here = c_parser_peek_token (parser)->location;
- stmt = c_begin_compound_stmt (true);
- add_stmt (body);
- c_parser_compound_statement_nostart (parser);
- body = c_end_compound_stmt (here, stmt, true);
- nbraces--;
- }
- goto pop_scopes;
- }
- }
-
- /* Only bother calling c_finish_omp_for if we haven't already generated
- an error from the initialization parsing. */
- if (!fail)
- {
- c_in_omp_for = true;
- stmt = c_finish_omp_for (loc, code, declv, NULL, initv, condv,
- incrv, body, pre_body, true);
- c_in_omp_for = false;
-
- /* Check for iterators appearing in lb, b or incr expressions. */
- if (stmt && !c_omp_check_loop_iv (stmt, declv, NULL))
- stmt = NULL_TREE;
-
- if (stmt)
- {
- add_stmt (stmt);
-
- for (i = 0; i < TREE_VEC_LENGTH (OMP_FOR_INIT (stmt)); i++)
- {
- tree init = TREE_VEC_ELT (OMP_FOR_INIT (stmt), i);
- gcc_assert (TREE_CODE (init) == MODIFY_EXPR);
- tree decl = TREE_OPERAND (init, 0);
- tree cond = TREE_VEC_ELT (OMP_FOR_COND (stmt), i);
- gcc_assert (COMPARISON_CLASS_P (cond));
- gcc_assert (TREE_OPERAND (cond, 0) == decl);
-
- tree op0 = TREE_OPERAND (init, 1);
- if (!OMP_FOR_NON_RECTANGULAR (stmt)
- || TREE_CODE (op0) != TREE_VEC)
- TREE_OPERAND (init, 1) = c_fully_fold (op0, false, NULL);
- else
- {
- TREE_VEC_ELT (op0, 1)
- = c_fully_fold (TREE_VEC_ELT (op0, 1), false, NULL);
- TREE_VEC_ELT (op0, 2)
- = c_fully_fold (TREE_VEC_ELT (op0, 2), false, NULL);
- }
-
- tree op1 = TREE_OPERAND (cond, 1);
- if (!OMP_FOR_NON_RECTANGULAR (stmt)
- || TREE_CODE (op1) != TREE_VEC)
- TREE_OPERAND (cond, 1) = c_fully_fold (op1, false, NULL);
- else
- {
- TREE_VEC_ELT (op1, 1)
- = c_fully_fold (TREE_VEC_ELT (op1, 1), false, NULL);
- TREE_VEC_ELT (op1, 2)
- = c_fully_fold (TREE_VEC_ELT (op1, 2), false, NULL);
- }
- }
-
- if (cclauses != NULL
- && cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL] != NULL)
- {
- tree *c;
- for (c = &cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL]; *c ; )
- if (OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_FIRSTPRIVATE
- && OMP_CLAUSE_CODE (*c) != OMP_CLAUSE_LASTPRIVATE)
- c = &OMP_CLAUSE_CHAIN (*c);
- else
- {
- for (i = 0; i < count; i++)
- if (TREE_VEC_ELT (declv, i) == OMP_CLAUSE_DECL (*c))
- break;
- if (i == count)
- c = &OMP_CLAUSE_CHAIN (*c);
- else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE)
- {
- error_at (loc,
- "iteration variable %qD should not be firstprivate",
- OMP_CLAUSE_DECL (*c));
- *c = OMP_CLAUSE_CHAIN (*c);
- }
- else
- {
- /* Move lastprivate (decl) clause to OMP_FOR_CLAUSES. */
- tree l = *c;
- *c = OMP_CLAUSE_CHAIN (*c);
- if (code == OMP_SIMD)
- {
- OMP_CLAUSE_CHAIN (l)
- = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
- cclauses[C_OMP_CLAUSE_SPLIT_FOR] = l;
- }
- else
- {
- OMP_CLAUSE_CHAIN (l) = clauses;
- clauses = l;
- }
- }
- }
- }
- OMP_FOR_CLAUSES (stmt) = clauses;
- }
- ret = stmt;
- }
-pop_scopes:
- while (!for_block->is_empty ())
- {
- /* FIXME diagnostics: LOC below should be the actual location of
- this particular for block. We need to build a list of
- locations to go along with FOR_BLOCK. */
- stmt = c_end_compound_stmt (loc, for_block->pop (), true);
- add_stmt (stmt);
- }
- release_tree_vector (for_block);
- return ret;
-}
-
-/* Helper function for OpenMP parsing, split clauses and call
- finish_omp_clauses on each of the set of clauses afterwards. */
-
-static void
-omp_split_clauses (location_t loc, enum tree_code code,
- omp_clause_mask mask, tree clauses, tree *cclauses)
-{
- int i;
- c_omp_split_clauses (loc, code, mask, clauses, cclauses);
- for (i = 0; i < C_OMP_CLAUSE_SPLIT_COUNT; i++)
- if (cclauses[i])
- cclauses[i] = c_finish_omp_clauses (cclauses[i],
- i == C_OMP_CLAUSE_SPLIT_TARGET
- ? C_ORT_OMP_TARGET : C_ORT_OMP);
-}
-
-/* OpenMP 5.0:
- #pragma omp loop loop-clause[optseq] new-line
- for-loop
-
- LOC is the location of the #pragma token.
-*/
-
-#define OMP_LOOP_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_BIND) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
-
-static tree
-c_parser_omp_loop (location_t loc, c_parser *parser,
- char *p_name, omp_clause_mask mask, tree *cclauses,
- bool *if_p)
-{
- tree block, clauses, ret;
-
- strcat (p_name, " loop");
- mask |= OMP_LOOP_CLAUSE_MASK;
-
- clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
- if (cclauses)
- {
- omp_split_clauses (loc, OMP_LOOP, mask, clauses, cclauses);
- clauses = cclauses[C_OMP_CLAUSE_SPLIT_LOOP];
- }
-
- block = c_begin_compound_stmt (true);
- ret = c_parser_omp_for_loop (loc, parser, OMP_LOOP, clauses, cclauses, if_p);
- block = c_end_compound_stmt (loc, block, true);
- add_stmt (block);
-
- return ret;
-}
-
-/* OpenMP 4.0:
- #pragma omp simd simd-clause[optseq] new-line
- for-loop
-
- LOC is the location of the #pragma token.
-*/
-
-#define OMP_SIMD_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SAFELEN) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NONTEMPORAL) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
-
-static tree
-c_parser_omp_simd (location_t loc, c_parser *parser,
- char *p_name, omp_clause_mask mask, tree *cclauses,
- bool *if_p)
-{
- tree block, clauses, ret;
-
- strcat (p_name, " simd");
- mask |= OMP_SIMD_CLAUSE_MASK;
-
- clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
- if (cclauses)
- {
- omp_split_clauses (loc, OMP_SIMD, mask, clauses, cclauses);
- clauses = cclauses[C_OMP_CLAUSE_SPLIT_SIMD];
- tree c = omp_find_clause (cclauses[C_OMP_CLAUSE_SPLIT_FOR],
- OMP_CLAUSE_ORDERED);
- if (c && OMP_CLAUSE_ORDERED_EXPR (c))
- {
- error_at (OMP_CLAUSE_LOCATION (c),
- "%<ordered%> clause with parameter may not be specified "
- "on %qs construct", p_name);
- OMP_CLAUSE_ORDERED_EXPR (c) = NULL_TREE;
- }
- }
-
- block = c_begin_compound_stmt (true);
- ret = c_parser_omp_for_loop (loc, parser, OMP_SIMD, clauses, cclauses, if_p);
- block = c_end_compound_stmt (loc, block, true);
- add_stmt (block);
-
- return ret;
-}
-
-/* OpenMP 2.5:
- #pragma omp for for-clause[optseq] new-line
- for-loop
-
- OpenMP 4.0:
- #pragma omp for simd for-simd-clause[optseq] new-line
- for-loop
-
- LOC is the location of the #pragma token.
-*/
-
-#define OMP_FOR_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SCHEDULE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
-
-static tree
-c_parser_omp_for (location_t loc, c_parser *parser,
- char *p_name, omp_clause_mask mask, tree *cclauses,
- bool *if_p)
-{
- tree block, clauses, ret;
-
- strcat (p_name, " for");
- mask |= OMP_FOR_CLAUSE_MASK;
- /* parallel for{, simd} disallows nowait clause, but for
- target {teams distribute ,}parallel for{, simd} it should be accepted. */
- if (cclauses && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) == 0)
- mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
- /* Composite distribute parallel for{, simd} disallows ordered clause. */
- if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
- mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDERED);
-
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-
- if (strcmp (p, "simd") == 0)
- {
- tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
- if (cclauses == NULL)
- cclauses = cclauses_buf;
-
- c_parser_consume_token (parser);
- if (!flag_openmp) /* flag_openmp_simd */
- return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
- if_p);
- block = c_begin_compound_stmt (true);
- ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses, if_p);
- block = c_end_compound_stmt (loc, block, true);
- if (ret == NULL_TREE)
- return ret;
- ret = make_node (OMP_FOR);
- TREE_TYPE (ret) = void_type_node;
- OMP_FOR_BODY (ret) = block;
- OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
- SET_EXPR_LOCATION (ret, loc);
- add_stmt (ret);
- return ret;
- }
- }
- if (!flag_openmp) /* flag_openmp_simd */
- {
- c_parser_skip_to_pragma_eol (parser, false);
- return NULL_TREE;
- }
-
- /* Composite distribute parallel for disallows linear clause. */
- if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
- mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR);
-
- clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
- if (cclauses)
- {
- omp_split_clauses (loc, OMP_FOR, mask, clauses, cclauses);
- clauses = cclauses[C_OMP_CLAUSE_SPLIT_FOR];
- }
-
- block = c_begin_compound_stmt (true);
- ret = c_parser_omp_for_loop (loc, parser, OMP_FOR, clauses, cclauses, if_p);
- block = c_end_compound_stmt (loc, block, true);
- add_stmt (block);
-
- return ret;
-}
-
-static tree c_parser_omp_taskloop (location_t, c_parser *, char *,
- omp_clause_mask, tree *, bool *);
-
-/* OpenMP 2.5:
- # pragma omp master new-line
- structured-block
-
- LOC is the location of the #pragma token.
-*/
-
-static tree
-c_parser_omp_master (location_t loc, c_parser *parser,
- char *p_name, omp_clause_mask mask, tree *cclauses,
- bool *if_p)
-{
- tree block, clauses, ret;
-
- strcat (p_name, " master");
-
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-
- if (strcmp (p, "taskloop") == 0)
- {
- tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
- if (cclauses == NULL)
- cclauses = cclauses_buf;
-
- c_parser_consume_token (parser);
- if (!flag_openmp) /* flag_openmp_simd */
- return c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
- if_p);
- block = c_begin_compound_stmt (true);
- ret = c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
- if_p);
- block = c_end_compound_stmt (loc, block, true);
- if (ret == NULL_TREE)
- return ret;
- ret = c_finish_omp_master (loc, block);
- OMP_MASTER_COMBINED (ret) = 1;
- return ret;
- }
- }
- if (!flag_openmp) /* flag_openmp_simd */
- {
- c_parser_skip_to_pragma_eol (parser, false);
- return NULL_TREE;
- }
-
- if (cclauses)
- {
- clauses = c_parser_omp_all_clauses (parser, mask, p_name, false);
- omp_split_clauses (loc, OMP_MASTER, mask, clauses, cclauses);
- }
- else
- c_parser_skip_to_pragma_eol (parser);
-
- return c_finish_omp_master (loc, c_parser_omp_structured_block (parser,
- if_p));
-}
-
-/* OpenMP 5.1:
- # pragma omp masked masked-clauses new-line
- structured-block
-
- LOC is the location of the #pragma token.
-*/
-
-#define OMP_MASKED_CLAUSE_MASK \
- (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FILTER)
-
-static tree
-c_parser_omp_masked (location_t loc, c_parser *parser,
- char *p_name, omp_clause_mask mask, tree *cclauses,
- bool *if_p)
-{
- tree block, clauses, ret;
-
- strcat (p_name, " masked");
- mask |= OMP_MASKED_CLAUSE_MASK;
-
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-
- if (strcmp (p, "taskloop") == 0)
- {
- tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
- if (cclauses == NULL)
- cclauses = cclauses_buf;
-
- c_parser_consume_token (parser);
- if (!flag_openmp) /* flag_openmp_simd */
- return c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
- if_p);
- block = c_begin_compound_stmt (true);
- ret = c_parser_omp_taskloop (loc, parser, p_name, mask, cclauses,
- if_p);
- block = c_end_compound_stmt (loc, block, true);
- if (ret == NULL_TREE)
- return ret;
- ret = c_finish_omp_masked (loc, block,
- cclauses[C_OMP_CLAUSE_SPLIT_MASKED]);
- OMP_MASKED_COMBINED (ret) = 1;
- return ret;
- }
- }
- if (!flag_openmp) /* flag_openmp_simd */
- {
- c_parser_skip_to_pragma_eol (parser, false);
- return NULL_TREE;
- }
-
- clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
- if (cclauses)
- {
- omp_split_clauses (loc, OMP_MASKED, mask, clauses, cclauses);
- clauses = cclauses[C_OMP_CLAUSE_SPLIT_MASKED];
- }
-
- return c_finish_omp_masked (loc, c_parser_omp_structured_block (parser,
- if_p),
- clauses);
-}
-
-/* OpenMP 2.5:
- # pragma omp ordered new-line
- structured-block
-
- OpenMP 4.5:
- # pragma omp ordered ordered-clauses new-line
- structured-block
-
- # pragma omp ordered depend-clauses new-line */
-
-#define OMP_ORDERED_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREADS) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMD))
-
-#define OMP_ORDERED_DEPEND_CLAUSE_MASK \
- (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND)
-
-static bool
-c_parser_omp_ordered (c_parser *parser, enum pragma_context context,
- bool *if_p)
-{
- location_t loc = c_parser_peek_token (parser)->location;
- c_parser_consume_pragma (parser);
-
- if (context != pragma_stmt && context != pragma_compound)
- {
- c_parser_error (parser, "expected declaration specifiers");
- c_parser_skip_to_pragma_eol (parser, false);
- return false;
- }
-
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-
- if (!strcmp ("depend", p))
- {
- if (!flag_openmp) /* flag_openmp_simd */
- {
- c_parser_skip_to_pragma_eol (parser, false);
- return false;
- }
- if (context == pragma_stmt)
- {
- error_at (loc,
- "%<#pragma omp ordered%> with %<depend%> clause may "
- "only be used in compound statements");
- c_parser_skip_to_pragma_eol (parser, false);
- return true;
- }
-
- tree clauses
- = c_parser_omp_all_clauses (parser,
- OMP_ORDERED_DEPEND_CLAUSE_MASK,
- "#pragma omp ordered");
- c_finish_omp_ordered (loc, clauses, NULL_TREE);
- return false;
- }
- }
-
- tree clauses = c_parser_omp_all_clauses (parser, OMP_ORDERED_CLAUSE_MASK,
- "#pragma omp ordered");
-
- if (!flag_openmp /* flag_openmp_simd */
- && omp_find_clause (clauses, OMP_CLAUSE_SIMD) == NULL_TREE)
- return false;
-
- c_finish_omp_ordered (loc, clauses,
- c_parser_omp_structured_block (parser, if_p));
- return true;
-}
-
-/* OpenMP 2.5:
-
- section-scope:
- { section-sequence }
-
- section-sequence:
- section-directive[opt] structured-block
- section-sequence section-directive structured-block
-
- OpenMP 5.1 allows structured-block-sequence instead of structured-block.
-
- SECTIONS_LOC is the location of the #pragma omp sections. */
-
-static tree
-c_parser_omp_sections_scope (location_t sections_loc, c_parser *parser)
-{
- tree stmt, substmt;
- bool error_suppress = false;
- location_t loc;
-
- loc = c_parser_peek_token (parser)->location;
- if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
- {
- /* Avoid skipping until the end of the block. */
- parser->error = false;
- return NULL_TREE;
- }
-
- stmt = push_stmt_list ();
-
- if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_SECTION)
- {
- substmt = c_parser_omp_structured_block_sequence (parser,
- PRAGMA_OMP_SECTION);
- substmt = build1 (OMP_SECTION, void_type_node, substmt);
- SET_EXPR_LOCATION (substmt, loc);
- add_stmt (substmt);
- }
-
- while (1)
- {
- if (c_parser_next_token_is (parser, CPP_CLOSE_BRACE))
- break;
- if (c_parser_next_token_is (parser, CPP_EOF))
- break;
-
- loc = c_parser_peek_token (parser)->location;
- if (c_parser_peek_token (parser)->pragma_kind == PRAGMA_OMP_SECTION)
- {
- c_parser_consume_pragma (parser);
- c_parser_skip_to_pragma_eol (parser);
- error_suppress = false;
- }
- else if (!error_suppress)
- {
- error_at (loc, "expected %<#pragma omp section%> or %<}%>");
- error_suppress = true;
- }
-
- substmt = c_parser_omp_structured_block_sequence (parser,
- PRAGMA_OMP_SECTION);
- substmt = build1 (OMP_SECTION, void_type_node, substmt);
- SET_EXPR_LOCATION (substmt, loc);
- add_stmt (substmt);
- }
- c_parser_skip_until_found (parser, CPP_CLOSE_BRACE,
- "expected %<#pragma omp section%> or %<}%>");
-
- substmt = pop_stmt_list (stmt);
-
- stmt = make_node (OMP_SECTIONS);
- SET_EXPR_LOCATION (stmt, sections_loc);
- TREE_TYPE (stmt) = void_type_node;
- OMP_SECTIONS_BODY (stmt) = substmt;
-
- return add_stmt (stmt);
-}
-
-/* OpenMP 2.5:
- # pragma omp sections sections-clause[optseq] newline
- sections-scope
-
- LOC is the location of the #pragma token.
-*/
-
-#define OMP_SECTIONS_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
-
-static tree
-c_parser_omp_sections (location_t loc, c_parser *parser,
- char *p_name, omp_clause_mask mask, tree *cclauses)
-{
- tree block, clauses, ret;
-
- strcat (p_name, " sections");
- mask |= OMP_SECTIONS_CLAUSE_MASK;
- if (cclauses)
- mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT);
-
- clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
- if (cclauses)
- {
- omp_split_clauses (loc, OMP_SECTIONS, mask, clauses, cclauses);
- clauses = cclauses[C_OMP_CLAUSE_SPLIT_SECTIONS];
- }
-
- block = c_begin_compound_stmt (true);
- ret = c_parser_omp_sections_scope (loc, parser);
- if (ret)
- OMP_SECTIONS_CLAUSES (ret) = clauses;
- block = c_end_compound_stmt (loc, block, true);
- add_stmt (block);
-
- return ret;
-}
-
-/* OpenMP 2.5:
- # pragma omp parallel parallel-clause[optseq] new-line
- structured-block
- # pragma omp parallel for parallel-for-clause[optseq] new-line
- structured-block
- # pragma omp parallel sections parallel-sections-clause[optseq] new-line
- structured-block
-
- OpenMP 4.0:
- # pragma omp parallel for simd parallel-for-simd-clause[optseq] new-line
- structured-block
-
- LOC is the location of the #pragma token.
-*/
-
-#define OMP_PARALLEL_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PROC_BIND))
-
-static tree
-c_parser_omp_parallel (location_t loc, c_parser *parser,
- char *p_name, omp_clause_mask mask, tree *cclauses,
- bool *if_p)
-{
- tree stmt, clauses, block;
-
- strcat (p_name, " parallel");
- mask |= OMP_PARALLEL_CLAUSE_MASK;
- /* #pragma omp target parallel{, for, for simd} disallow copyin clause. */
- if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP)) != 0
- && (mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) == 0)
- mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYIN);
-
- if (c_parser_next_token_is_keyword (parser, RID_FOR))
- {
- tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
- if (cclauses == NULL)
- cclauses = cclauses_buf;
-
- c_parser_consume_token (parser);
- if (!flag_openmp) /* flag_openmp_simd */
- return c_parser_omp_for (loc, parser, p_name, mask, cclauses, if_p);
- block = c_begin_omp_parallel ();
- tree ret = c_parser_omp_for (loc, parser, p_name, mask, cclauses, if_p);
- stmt
- = c_finish_omp_parallel (loc, cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
- block);
- if (ret == NULL_TREE)
- return ret;
- OMP_PARALLEL_COMBINED (stmt) = 1;
- return stmt;
- }
- /* When combined with distribute, parallel has to be followed by for.
- #pragma omp target parallel is allowed though. */
- else if (cclauses
- && (mask & (OMP_CLAUSE_MASK_1
- << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)) != 0)
- {
- error_at (loc, "expected %<for%> after %qs", p_name);
- c_parser_skip_to_pragma_eol (parser);
- return NULL_TREE;
- }
- else if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (cclauses == NULL && strcmp (p, "masked") == 0)
- {
- tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
- cclauses = cclauses_buf;
-
- c_parser_consume_token (parser);
- if (!flag_openmp) /* flag_openmp_simd */
- return c_parser_omp_masked (loc, parser, p_name, mask, cclauses,
- if_p);
- block = c_begin_omp_parallel ();
- tree ret = c_parser_omp_masked (loc, parser, p_name, mask, cclauses,
- if_p);
- stmt = c_finish_omp_parallel (loc,
- cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
- block);
- if (ret == NULL)
- return ret;
- /* masked does have just filter clause, but during gimplification
- isn't represented by a gimplification omp context, so for
- #pragma omp parallel masked don't set OMP_PARALLEL_COMBINED,
- so that
- #pragma omp parallel masked
- #pragma omp taskloop simd lastprivate (x)
- isn't confused with
- #pragma omp parallel masked taskloop simd lastprivate (x) */
- if (OMP_MASKED_COMBINED (ret))
- OMP_PARALLEL_COMBINED (stmt) = 1;
- return stmt;
- }
- else if (cclauses == NULL && strcmp (p, "master") == 0)
- {
- tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
- cclauses = cclauses_buf;
-
- c_parser_consume_token (parser);
- if (!flag_openmp) /* flag_openmp_simd */
- return c_parser_omp_master (loc, parser, p_name, mask, cclauses,
- if_p);
- block = c_begin_omp_parallel ();
- tree ret = c_parser_omp_master (loc, parser, p_name, mask, cclauses,
- if_p);
- stmt = c_finish_omp_parallel (loc,
- cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
- block);
- if (ret == NULL)
- return ret;
- /* master doesn't have any clauses and during gimplification
- isn't represented by a gimplification omp context, so for
- #pragma omp parallel master don't set OMP_PARALLEL_COMBINED,
- so that
- #pragma omp parallel master
- #pragma omp taskloop simd lastprivate (x)
- isn't confused with
- #pragma omp parallel master taskloop simd lastprivate (x) */
- if (OMP_MASTER_COMBINED (ret))
- OMP_PARALLEL_COMBINED (stmt) = 1;
- return stmt;
- }
- else if (strcmp (p, "loop") == 0)
- {
- tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
- if (cclauses == NULL)
- cclauses = cclauses_buf;
-
- c_parser_consume_token (parser);
- if (!flag_openmp) /* flag_openmp_simd */
- return c_parser_omp_loop (loc, parser, p_name, mask, cclauses,
- if_p);
- block = c_begin_omp_parallel ();
- tree ret = c_parser_omp_loop (loc, parser, p_name, mask, cclauses,
- if_p);
- stmt
- = c_finish_omp_parallel (loc,
- cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
- block);
- if (ret == NULL_TREE)
- return ret;
- OMP_PARALLEL_COMBINED (stmt) = 1;
- return stmt;
- }
- else if (!flag_openmp) /* flag_openmp_simd */
- {
- c_parser_skip_to_pragma_eol (parser, false);
- return NULL_TREE;
- }
- else if (cclauses == NULL && strcmp (p, "sections") == 0)
- {
- tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
- cclauses = cclauses_buf;
-
- c_parser_consume_token (parser);
- block = c_begin_omp_parallel ();
- c_parser_omp_sections (loc, parser, p_name, mask, cclauses);
- stmt = c_finish_omp_parallel (loc,
- cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL],
- block);
- OMP_PARALLEL_COMBINED (stmt) = 1;
- return stmt;
- }
- }
- else if (!flag_openmp) /* flag_openmp_simd */
- {
- c_parser_skip_to_pragma_eol (parser, false);
- return NULL_TREE;
- }
-
- clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
- if (cclauses)
- {
- omp_split_clauses (loc, OMP_PARALLEL, mask, clauses, cclauses);
- clauses = cclauses[C_OMP_CLAUSE_SPLIT_PARALLEL];
- }
-
- block = c_begin_omp_parallel ();
- c_parser_statement (parser, if_p);
- stmt = c_finish_omp_parallel (loc, clauses, block);
-
- return stmt;
-}
-
-/* OpenMP 2.5:
- # pragma omp single single-clause[optseq] new-line
- structured-block
-
- LOC is the location of the #pragma.
-*/
-
-#define OMP_SINGLE_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COPYPRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
-
-static tree
-c_parser_omp_single (location_t loc, c_parser *parser, bool *if_p)
-{
- tree stmt = make_node (OMP_SINGLE);
- SET_EXPR_LOCATION (stmt, loc);
- TREE_TYPE (stmt) = void_type_node;
-
- OMP_SINGLE_CLAUSES (stmt)
- = c_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK,
- "#pragma omp single");
- OMP_SINGLE_BODY (stmt) = c_parser_omp_structured_block (parser, if_p);
-
- return add_stmt (stmt);
-}
-
-/* OpenMP 5.1:
- # pragma omp scope scope-clause[optseq] new-line
- structured-block
-
- LOC is the location of the #pragma.
-*/
-
-#define OMP_SCOPE_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
-
-static tree
-c_parser_omp_scope (location_t loc, c_parser *parser, bool *if_p)
-{
- tree stmt = make_node (OMP_SCOPE);
- SET_EXPR_LOCATION (stmt, loc);
- TREE_TYPE (stmt) = void_type_node;
-
- OMP_SCOPE_CLAUSES (stmt)
- = c_parser_omp_all_clauses (parser, OMP_SCOPE_CLAUSE_MASK,
- "#pragma omp scope");
- OMP_SCOPE_BODY (stmt) = c_parser_omp_structured_block (parser, if_p);
-
- return add_stmt (stmt);
-}
-
-/* OpenMP 3.0:
- # pragma omp task task-clause[optseq] new-line
-
- LOC is the location of the #pragma.
-*/
-
-#define OMP_TASK_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DETACH) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_AFFINITY))
-
-static tree
-c_parser_omp_task (location_t loc, c_parser *parser, bool *if_p)
-{
- tree clauses, block;
-
- clauses = c_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK,
- "#pragma omp task");
-
- block = c_begin_omp_task ();
- c_parser_statement (parser, if_p);
- return c_finish_omp_task (loc, clauses, block);
-}
-
-/* OpenMP 3.0:
- # pragma omp taskwait new-line
-
- OpenMP 5.0:
- # pragma omp taskwait taskwait-clause[optseq] new-line
-*/
-
-#define OMP_TASKWAIT_CLAUSE_MASK \
- (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND)
-
-static void
-c_parser_omp_taskwait (c_parser *parser)
-{
- location_t loc = c_parser_peek_token (parser)->location;
- c_parser_consume_pragma (parser);
-
- tree clauses
- = c_parser_omp_all_clauses (parser, OMP_TASKWAIT_CLAUSE_MASK,
- "#pragma omp taskwait");
-
- if (clauses)
- {
- tree stmt = make_node (OMP_TASK);
- TREE_TYPE (stmt) = void_node;
- OMP_TASK_CLAUSES (stmt) = clauses;
- OMP_TASK_BODY (stmt) = NULL_TREE;
- SET_EXPR_LOCATION (stmt, loc);
- add_stmt (stmt);
- }
- else
- c_finish_omp_taskwait (loc);
-}
-
-/* OpenMP 3.1:
- # pragma omp taskyield new-line
-*/
-
-static void
-c_parser_omp_taskyield (c_parser *parser)
-{
- location_t loc = c_parser_peek_token (parser)->location;
- c_parser_consume_pragma (parser);
- c_parser_skip_to_pragma_eol (parser);
-
- c_finish_omp_taskyield (loc);
-}
-
-/* OpenMP 4.0:
- # pragma omp taskgroup new-line
-
- OpenMP 5.0:
- # pragma omp taskgroup taskgroup-clause[optseq] new-line
-*/
-
-#define OMP_TASKGROUP_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASK_REDUCTION))
-
-static tree
-c_parser_omp_taskgroup (location_t loc, c_parser *parser, bool *if_p)
-{
- tree clauses = c_parser_omp_all_clauses (parser, OMP_TASKGROUP_CLAUSE_MASK,
- "#pragma omp taskgroup");
-
- tree body = c_parser_omp_structured_block (parser, if_p);
- return c_finish_omp_taskgroup (loc, body, clauses);
-}
-
-/* OpenMP 4.0:
- # pragma omp cancel cancel-clause[optseq] new-line
-
- LOC is the location of the #pragma.
-*/
-
-#define OMP_CANCEL_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF))
-
-static void
-c_parser_omp_cancel (c_parser *parser)
-{
- location_t loc = c_parser_peek_token (parser)->location;
-
- c_parser_consume_pragma (parser);
- tree clauses = c_parser_omp_all_clauses (parser, OMP_CANCEL_CLAUSE_MASK,
- "#pragma omp cancel");
-
- c_finish_omp_cancel (loc, clauses);
-}
-
-/* OpenMP 4.0:
- # pragma omp cancellation point cancelpt-clause[optseq] new-line
-
- LOC is the location of the #pragma.
-*/
-
-#define OMP_CANCELLATION_POINT_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PARALLEL) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FOR) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SECTIONS) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TASKGROUP))
-
-static bool
-c_parser_omp_cancellation_point (c_parser *parser, enum pragma_context context)
-{
- location_t loc = c_parser_peek_token (parser)->location;
- tree clauses;
- bool point_seen = false;
-
- c_parser_consume_pragma (parser);
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (strcmp (p, "point") == 0)
- {
- c_parser_consume_token (parser);
- point_seen = true;
- }
- }
- if (!point_seen)
- {
- c_parser_error (parser, "expected %<point%>");
- c_parser_skip_to_pragma_eol (parser);
- return false;
- }
-
- if (context != pragma_compound)
- {
- if (context == pragma_stmt)
- error_at (loc,
- "%<#pragma %s%> may only be used in compound statements",
- "omp cancellation point");
- else
- c_parser_error (parser, "expected declaration specifiers");
- c_parser_skip_to_pragma_eol (parser, false);
- return true;
- }
-
- clauses
- = c_parser_omp_all_clauses (parser, OMP_CANCELLATION_POINT_CLAUSE_MASK,
- "#pragma omp cancellation point");
-
- c_finish_omp_cancellation_point (loc, clauses);
- return true;
-}
-
-/* OpenMP 4.0:
- #pragma omp distribute distribute-clause[optseq] new-line
- for-loop */
-
-#define OMP_DISTRIBUTE_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DIST_SCHEDULE)\
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ORDER))
-
-static tree
-c_parser_omp_distribute (location_t loc, c_parser *parser,
- char *p_name, omp_clause_mask mask, tree *cclauses,
- bool *if_p)
-{
- tree clauses, block, ret;
-
- strcat (p_name, " distribute");
- mask |= OMP_DISTRIBUTE_CLAUSE_MASK;
-
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- bool simd = false;
- bool parallel = false;
-
- if (strcmp (p, "simd") == 0)
- simd = true;
- else
- parallel = strcmp (p, "parallel") == 0;
- if (parallel || simd)
- {
- tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
- if (cclauses == NULL)
- cclauses = cclauses_buf;
- c_parser_consume_token (parser);
- if (!flag_openmp) /* flag_openmp_simd */
- {
- if (simd)
- return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
- if_p);
- else
- return c_parser_omp_parallel (loc, parser, p_name, mask,
- cclauses, if_p);
- }
- block = c_begin_compound_stmt (true);
- if (simd)
- ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
- if_p);
- else
- ret = c_parser_omp_parallel (loc, parser, p_name, mask, cclauses,
- if_p);
- block = c_end_compound_stmt (loc, block, true);
- if (ret == NULL)
- return ret;
- ret = make_node (OMP_DISTRIBUTE);
- TREE_TYPE (ret) = void_type_node;
- OMP_FOR_BODY (ret) = block;
- OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
- SET_EXPR_LOCATION (ret, loc);
- add_stmt (ret);
- return ret;
- }
- }
- if (!flag_openmp) /* flag_openmp_simd */
- {
- c_parser_skip_to_pragma_eol (parser, false);
- return NULL_TREE;
- }
-
- clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
- if (cclauses)
- {
- omp_split_clauses (loc, OMP_DISTRIBUTE, mask, clauses, cclauses);
- clauses = cclauses[C_OMP_CLAUSE_SPLIT_DISTRIBUTE];
- }
-
- block = c_begin_compound_stmt (true);
- ret = c_parser_omp_for_loop (loc, parser, OMP_DISTRIBUTE, clauses, NULL,
- if_p);
- block = c_end_compound_stmt (loc, block, true);
- add_stmt (block);
-
- return ret;
-}
-
-/* OpenMP 4.0:
- # pragma omp teams teams-clause[optseq] new-line
- structured-block */
-
-#define OMP_TEAMS_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TEAMS) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT))
-
-static tree
-c_parser_omp_teams (location_t loc, c_parser *parser,
- char *p_name, omp_clause_mask mask, tree *cclauses,
- bool *if_p)
-{
- tree clauses, block, ret;
-
- strcat (p_name, " teams");
- mask |= OMP_TEAMS_CLAUSE_MASK;
-
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (strcmp (p, "distribute") == 0)
- {
- tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
- if (cclauses == NULL)
- cclauses = cclauses_buf;
-
- c_parser_consume_token (parser);
- if (!flag_openmp) /* flag_openmp_simd */
- return c_parser_omp_distribute (loc, parser, p_name, mask,
- cclauses, if_p);
- block = c_begin_omp_parallel ();
- ret = c_parser_omp_distribute (loc, parser, p_name, mask, cclauses,
- if_p);
- block = c_end_compound_stmt (loc, block, true);
- if (ret == NULL)
- return ret;
- clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
- ret = make_node (OMP_TEAMS);
- TREE_TYPE (ret) = void_type_node;
- OMP_TEAMS_CLAUSES (ret) = clauses;
- OMP_TEAMS_BODY (ret) = block;
- OMP_TEAMS_COMBINED (ret) = 1;
- SET_EXPR_LOCATION (ret, loc);
- return add_stmt (ret);
- }
- else if (strcmp (p, "loop") == 0)
- {
- tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
- if (cclauses == NULL)
- cclauses = cclauses_buf;
-
- c_parser_consume_token (parser);
- if (!flag_openmp) /* flag_openmp_simd */
- return c_parser_omp_loop (loc, parser, p_name, mask, cclauses,
- if_p);
- block = c_begin_omp_parallel ();
- ret = c_parser_omp_loop (loc, parser, p_name, mask, cclauses, if_p);
- block = c_end_compound_stmt (loc, block, true);
- if (ret == NULL)
- return ret;
- clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
- ret = make_node (OMP_TEAMS);
- TREE_TYPE (ret) = void_type_node;
- OMP_TEAMS_CLAUSES (ret) = clauses;
- OMP_TEAMS_BODY (ret) = block;
- OMP_TEAMS_COMBINED (ret) = 1;
- SET_EXPR_LOCATION (ret, loc);
- return add_stmt (ret);
- }
- }
- if (!flag_openmp) /* flag_openmp_simd */
- {
- c_parser_skip_to_pragma_eol (parser, false);
- return NULL_TREE;
- }
-
- clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
- if (cclauses)
- {
- omp_split_clauses (loc, OMP_TEAMS, mask, clauses, cclauses);
- clauses = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
- }
-
- tree stmt = make_node (OMP_TEAMS);
- TREE_TYPE (stmt) = void_type_node;
- OMP_TEAMS_CLAUSES (stmt) = clauses;
- block = c_begin_omp_parallel ();
- add_stmt (c_parser_omp_structured_block (parser, if_p));
- OMP_TEAMS_BODY (stmt) = c_end_compound_stmt (loc, block, true);
- SET_EXPR_LOCATION (stmt, loc);
-
- return add_stmt (stmt);
-}
-
-/* OpenMP 4.0:
- # pragma omp target data target-data-clause[optseq] new-line
- structured-block */
-
-#define OMP_TARGET_DATA_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_PTR) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_USE_DEVICE_ADDR))
-
-static tree
-c_parser_omp_target_data (location_t loc, c_parser *parser, bool *if_p)
-{
- tree clauses
- = c_parser_omp_all_clauses (parser, OMP_TARGET_DATA_CLAUSE_MASK,
- "#pragma omp target data");
- c_omp_adjust_map_clauses (clauses, false);
- int map_seen = 0;
- for (tree *pc = &clauses; *pc;)
- {
- if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
- switch (OMP_CLAUSE_MAP_KIND (*pc))
- {
- 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:
- map_seen = 3;
- break;
- case GOMP_MAP_FIRSTPRIVATE_POINTER:
- case GOMP_MAP_ALWAYS_POINTER:
- case GOMP_MAP_ATTACH_DETACH:
- break;
- default:
- map_seen |= 1;
- error_at (OMP_CLAUSE_LOCATION (*pc),
- "%<#pragma omp target data%> with map-type other "
- "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> "
- "on %<map%> clause");
- *pc = OMP_CLAUSE_CHAIN (*pc);
- continue;
- }
- else if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_PTR
- || OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_USE_DEVICE_ADDR)
- map_seen = 3;
- pc = &OMP_CLAUSE_CHAIN (*pc);
- }
-
- if (map_seen != 3)
- {
- if (map_seen == 0)
- error_at (loc,
- "%<#pragma omp target data%> must contain at least "
- "one %<map%>, %<use_device_ptr%> or %<use_device_addr%> "
- "clause");
- return NULL_TREE;
- }
-
- tree stmt = make_node (OMP_TARGET_DATA);
- TREE_TYPE (stmt) = void_type_node;
- OMP_TARGET_DATA_CLAUSES (stmt) = clauses;
- keep_next_level ();
- tree block = c_begin_compound_stmt (true);
- add_stmt (c_parser_omp_structured_block (parser, if_p));
- OMP_TARGET_DATA_BODY (stmt) = c_end_compound_stmt (loc, block, true);
-
- SET_EXPR_LOCATION (stmt, loc);
- return add_stmt (stmt);
-}
-
-/* OpenMP 4.0:
- # pragma omp target update target-update-clause[optseq] new-line */
-
-#define OMP_TARGET_UPDATE_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FROM) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
-
-static bool
-c_parser_omp_target_update (location_t loc, c_parser *parser,
- enum pragma_context context)
-{
- if (context == pragma_stmt)
- {
- error_at (loc, "%<#pragma %s%> may only be used in compound statements",
- "omp target update");
- c_parser_skip_to_pragma_eol (parser, false);
- return true;
- }
-
- tree clauses
- = c_parser_omp_all_clauses (parser, OMP_TARGET_UPDATE_CLAUSE_MASK,
- "#pragma omp target update");
- if (omp_find_clause (clauses, OMP_CLAUSE_TO) == NULL_TREE
- && omp_find_clause (clauses, OMP_CLAUSE_FROM) == NULL_TREE)
- {
- error_at (loc,
- "%<#pragma omp target update%> must contain at least one "
- "%<from%> or %<to%> clauses");
- return false;
- }
-
- tree stmt = make_node (OMP_TARGET_UPDATE);
- TREE_TYPE (stmt) = void_type_node;
- OMP_TARGET_UPDATE_CLAUSES (stmt) = clauses;
- SET_EXPR_LOCATION (stmt, loc);
- add_stmt (stmt);
- return false;
-}
-
-/* OpenMP 4.5:
- # pragma omp target enter data target-data-clause[optseq] new-line */
-
-#define OMP_TARGET_ENTER_DATA_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
-
-static bool
-c_parser_omp_target_enter_data (location_t loc, c_parser *parser,
- enum pragma_context context)
-{
- bool data_seen = false;
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (strcmp (p, "data") == 0)
- {
- c_parser_consume_token (parser);
- data_seen = true;
- }
- }
- if (!data_seen)
- {
- c_parser_error (parser, "expected %<data%>");
- c_parser_skip_to_pragma_eol (parser);
- return false;
- }
-
- if (context == pragma_stmt)
- {
- error_at (loc, "%<#pragma %s%> may only be used in compound statements",
- "omp target enter data");
- c_parser_skip_to_pragma_eol (parser, false);
- return true;
- }
-
- tree clauses
- = c_parser_omp_all_clauses (parser, OMP_TARGET_ENTER_DATA_CLAUSE_MASK,
- "#pragma omp target enter data");
- c_omp_adjust_map_clauses (clauses, false);
- int map_seen = 0;
- for (tree *pc = &clauses; *pc;)
- {
- if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
- switch (OMP_CLAUSE_MAP_KIND (*pc))
- {
- case GOMP_MAP_TO:
- case GOMP_MAP_ALWAYS_TO:
- case GOMP_MAP_ALLOC:
- map_seen = 3;
- break;
- case GOMP_MAP_FIRSTPRIVATE_POINTER:
- case GOMP_MAP_ALWAYS_POINTER:
- case GOMP_MAP_ATTACH_DETACH:
- break;
- default:
- map_seen |= 1;
- error_at (OMP_CLAUSE_LOCATION (*pc),
- "%<#pragma omp target enter data%> with map-type other "
- "than %<to%> or %<alloc%> on %<map%> clause");
- *pc = OMP_CLAUSE_CHAIN (*pc);
- continue;
- }
- pc = &OMP_CLAUSE_CHAIN (*pc);
- }
-
- if (map_seen != 3)
- {
- if (map_seen == 0)
- error_at (loc,
- "%<#pragma omp target enter data%> must contain at least "
- "one %<map%> clause");
- return true;
- }
-
- tree stmt = make_node (OMP_TARGET_ENTER_DATA);
- TREE_TYPE (stmt) = void_type_node;
- OMP_TARGET_ENTER_DATA_CLAUSES (stmt) = clauses;
- SET_EXPR_LOCATION (stmt, loc);
- add_stmt (stmt);
- return true;
-}
-
-/* OpenMP 4.5:
- # pragma omp target exit data target-data-clause[optseq] new-line */
-
-#define OMP_TARGET_EXIT_DATA_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT))
-
-static bool
-c_parser_omp_target_exit_data (location_t loc, c_parser *parser,
- enum pragma_context context)
-{
- bool data_seen = false;
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (strcmp (p, "data") == 0)
- {
- c_parser_consume_token (parser);
- data_seen = true;
- }
- }
- if (!data_seen)
- {
- c_parser_error (parser, "expected %<data%>");
- c_parser_skip_to_pragma_eol (parser);
- return false;
- }
-
- if (context == pragma_stmt)
- {
- error_at (loc, "%<#pragma %s%> may only be used in compound statements",
- "omp target exit data");
- c_parser_skip_to_pragma_eol (parser, false);
- return true;
- }
-
- tree clauses
- = c_parser_omp_all_clauses (parser, OMP_TARGET_EXIT_DATA_CLAUSE_MASK,
- "#pragma omp target exit data");
- c_omp_adjust_map_clauses (clauses, false);
- int map_seen = 0;
- for (tree *pc = &clauses; *pc;)
- {
- if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
- switch (OMP_CLAUSE_MAP_KIND (*pc))
- {
- case GOMP_MAP_FROM:
- case GOMP_MAP_ALWAYS_FROM:
- case GOMP_MAP_RELEASE:
- case GOMP_MAP_DELETE:
- map_seen = 3;
- break;
- case GOMP_MAP_FIRSTPRIVATE_POINTER:
- case GOMP_MAP_ALWAYS_POINTER:
- case GOMP_MAP_ATTACH_DETACH:
- break;
- default:
- map_seen |= 1;
- error_at (OMP_CLAUSE_LOCATION (*pc),
- "%<#pragma omp target exit data%> with map-type other "
- "than %<from%>, %<release%> or %<delete%> on %<map%>"
- " clause");
- *pc = OMP_CLAUSE_CHAIN (*pc);
- continue;
- }
- pc = &OMP_CLAUSE_CHAIN (*pc);
- }
-
- if (map_seen != 3)
- {
- if (map_seen == 0)
- error_at (loc,
- "%<#pragma omp target exit data%> must contain at least one "
- "%<map%> clause");
- return true;
- }
-
- tree stmt = make_node (OMP_TARGET_EXIT_DATA);
- TREE_TYPE (stmt) = void_type_node;
- OMP_TARGET_EXIT_DATA_CLAUSES (stmt) = clauses;
- SET_EXPR_LOCATION (stmt, loc);
- add_stmt (stmt);
- return true;
-}
-
-/* OpenMP 4.0:
- # pragma omp target target-clause[optseq] new-line
- structured-block */
-
-#define OMP_TARGET_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MAP) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEPEND) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOWAIT) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULTMAP) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_THREAD_LIMIT) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IS_DEVICE_PTR))
-
-static bool
-c_parser_omp_target (c_parser *parser, enum pragma_context context, bool *if_p)
-{
- location_t loc = c_parser_peek_token (parser)->location;
- c_parser_consume_pragma (parser);
- tree *pc = NULL, stmt, block;
-
- if (context != pragma_stmt && context != pragma_compound)
- {
- c_parser_error (parser, "expected declaration specifiers");
- c_parser_skip_to_pragma_eol (parser);
- return false;
- }
-
- if (flag_openmp)
- omp_requires_mask
- = (enum omp_requires) (omp_requires_mask | OMP_REQUIRES_TARGET_USED);
-
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- enum tree_code ccode = ERROR_MARK;
-
- if (strcmp (p, "teams") == 0)
- ccode = OMP_TEAMS;
- else if (strcmp (p, "parallel") == 0)
- ccode = OMP_PARALLEL;
- else if (strcmp (p, "simd") == 0)
- ccode = OMP_SIMD;
- if (ccode != ERROR_MARK)
- {
- tree cclauses[C_OMP_CLAUSE_SPLIT_COUNT];
- char p_name[sizeof ("#pragma omp target teams distribute "
- "parallel for simd")];
-
- c_parser_consume_token (parser);
- strcpy (p_name, "#pragma omp target");
- if (!flag_openmp) /* flag_openmp_simd */
- {
- tree stmt;
- switch (ccode)
- {
- case OMP_TEAMS:
- stmt = c_parser_omp_teams (loc, parser, p_name,
- OMP_TARGET_CLAUSE_MASK,
- cclauses, if_p);
- break;
- case OMP_PARALLEL:
- stmt = c_parser_omp_parallel (loc, parser, p_name,
- OMP_TARGET_CLAUSE_MASK,
- cclauses, if_p);
- break;
- case OMP_SIMD:
- stmt = c_parser_omp_simd (loc, parser, p_name,
- OMP_TARGET_CLAUSE_MASK,
- cclauses, if_p);
- break;
- default:
- gcc_unreachable ();
- }
- return stmt != NULL_TREE;
- }
- keep_next_level ();
- tree block = c_begin_compound_stmt (true), ret;
- switch (ccode)
- {
- case OMP_TEAMS:
- ret = c_parser_omp_teams (loc, parser, p_name,
- OMP_TARGET_CLAUSE_MASK, cclauses,
- if_p);
- break;
- case OMP_PARALLEL:
- ret = c_parser_omp_parallel (loc, parser, p_name,
- OMP_TARGET_CLAUSE_MASK, cclauses,
- if_p);
- break;
- case OMP_SIMD:
- ret = c_parser_omp_simd (loc, parser, p_name,
- OMP_TARGET_CLAUSE_MASK, cclauses,
- if_p);
- break;
- default:
- gcc_unreachable ();
- }
- block = c_end_compound_stmt (loc, block, true);
- if (ret == NULL_TREE)
- return false;
- if (ccode == OMP_TEAMS)
- /* For combined target teams, ensure the num_teams and
- thread_limit clause expressions are evaluated on the host,
- before entering the target construct. */
- for (tree c = cclauses[C_OMP_CLAUSE_SPLIT_TEAMS];
- c; c = OMP_CLAUSE_CHAIN (c))
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS
- || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_THREAD_LIMIT)
- for (int i = 0;
- i <= (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_NUM_TEAMS); ++i)
- if (OMP_CLAUSE_OPERAND (c, i)
- && TREE_CODE (OMP_CLAUSE_OPERAND (c, i)) != INTEGER_CST)
- {
- tree expr = OMP_CLAUSE_OPERAND (c, i);
- tree tmp = create_tmp_var_raw (TREE_TYPE (expr));
- expr = build4 (TARGET_EXPR, TREE_TYPE (expr), tmp,
- expr, NULL_TREE, NULL_TREE);
- add_stmt (expr);
- OMP_CLAUSE_OPERAND (c, i) = expr;
- tree tc = build_omp_clause (OMP_CLAUSE_LOCATION (c),
- OMP_CLAUSE_FIRSTPRIVATE);
- OMP_CLAUSE_DECL (tc) = tmp;
- OMP_CLAUSE_CHAIN (tc)
- = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
- cclauses[C_OMP_CLAUSE_SPLIT_TARGET] = tc;
- }
- tree stmt = make_node (OMP_TARGET);
- TREE_TYPE (stmt) = void_type_node;
- OMP_TARGET_CLAUSES (stmt) = cclauses[C_OMP_CLAUSE_SPLIT_TARGET];
- c_omp_adjust_map_clauses (OMP_TARGET_CLAUSES (stmt), true);
- OMP_TARGET_BODY (stmt) = block;
- OMP_TARGET_COMBINED (stmt) = 1;
- SET_EXPR_LOCATION (stmt, loc);
- add_stmt (stmt);
- pc = &OMP_TARGET_CLAUSES (stmt);
- goto check_clauses;
- }
- else if (!flag_openmp) /* flag_openmp_simd */
- {
- c_parser_skip_to_pragma_eol (parser, false);
- return false;
- }
- else if (strcmp (p, "data") == 0)
- {
- c_parser_consume_token (parser);
- c_parser_omp_target_data (loc, parser, if_p);
- return true;
- }
- else if (strcmp (p, "enter") == 0)
- {
- c_parser_consume_token (parser);
- return c_parser_omp_target_enter_data (loc, parser, context);
- }
- else if (strcmp (p, "exit") == 0)
- {
- c_parser_consume_token (parser);
- return c_parser_omp_target_exit_data (loc, parser, context);
- }
- else if (strcmp (p, "update") == 0)
- {
- c_parser_consume_token (parser);
- return c_parser_omp_target_update (loc, parser, context);
- }
- }
- if (!flag_openmp) /* flag_openmp_simd */
- {
- c_parser_skip_to_pragma_eol (parser, false);
- return false;
- }
-
- stmt = make_node (OMP_TARGET);
- TREE_TYPE (stmt) = void_type_node;
-
- OMP_TARGET_CLAUSES (stmt)
- = c_parser_omp_all_clauses (parser, OMP_TARGET_CLAUSE_MASK,
- "#pragma omp target", false);
- for (tree c = OMP_TARGET_CLAUSES (stmt); c; c = OMP_CLAUSE_CHAIN (c))
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_IN_REDUCTION)
- {
- tree nc = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP);
- OMP_CLAUSE_DECL (nc) = OMP_CLAUSE_DECL (c);
- OMP_CLAUSE_SET_MAP_KIND (nc, GOMP_MAP_ALWAYS_TOFROM);
- OMP_CLAUSE_CHAIN (nc) = OMP_CLAUSE_CHAIN (c);
- OMP_CLAUSE_CHAIN (c) = nc;
- }
- OMP_TARGET_CLAUSES (stmt)
- = c_finish_omp_clauses (OMP_TARGET_CLAUSES (stmt), C_ORT_OMP_TARGET);
- c_omp_adjust_map_clauses (OMP_TARGET_CLAUSES (stmt), true);
-
- pc = &OMP_TARGET_CLAUSES (stmt);
- keep_next_level ();
- block = c_begin_compound_stmt (true);
- add_stmt (c_parser_omp_structured_block (parser, if_p));
- OMP_TARGET_BODY (stmt) = c_end_compound_stmt (loc, block, true);
-
- SET_EXPR_LOCATION (stmt, loc);
- add_stmt (stmt);
-
-check_clauses:
- while (*pc)
- {
- if (OMP_CLAUSE_CODE (*pc) == OMP_CLAUSE_MAP)
- switch (OMP_CLAUSE_MAP_KIND (*pc))
- {
- 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_ALWAYS_POINTER:
- case GOMP_MAP_ATTACH_DETACH:
- break;
- default:
- error_at (OMP_CLAUSE_LOCATION (*pc),
- "%<#pragma omp target%> with map-type other "
- "than %<to%>, %<from%>, %<tofrom%> or %<alloc%> "
- "on %<map%> clause");
- *pc = OMP_CLAUSE_CHAIN (*pc);
- continue;
- }
- pc = &OMP_CLAUSE_CHAIN (*pc);
- }
- cfun->has_omp_target = true;
- return true;
-}
-
-/* OpenMP 4.0:
- # pragma omp declare simd declare-simd-clauses[optseq] new-line
-
- OpenMP 5.0:
- # pragma omp declare variant (identifier) match(context-selector) new-line
- */
-
-#define OMP_DECLARE_SIMD_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SIMDLEN) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINEAR) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALIGNED) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNIFORM) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_INBRANCH) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOTINBRANCH))
-
-static void
-c_parser_omp_declare_simd (c_parser *parser, enum pragma_context context)
-{
- c_token *token = c_parser_peek_token (parser);
- gcc_assert (token->type == CPP_NAME);
- tree kind = token->value;
- gcc_assert (strcmp (IDENTIFIER_POINTER (kind), "simd") == 0
- || strcmp (IDENTIFIER_POINTER (kind), "variant") == 0);
-
- auto_vec<c_token> clauses;
- while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
- {
- c_token *token = c_parser_peek_token (parser);
- if (token->type == CPP_EOF)
- {
- c_parser_skip_to_pragma_eol (parser);
- return;
- }
- clauses.safe_push (*token);
- c_parser_consume_token (parser);
- }
- clauses.safe_push (*c_parser_peek_token (parser));
- c_parser_skip_to_pragma_eol (parser);
-
- while (c_parser_next_token_is (parser, CPP_PRAGMA))
- {
- if (c_parser_peek_token (parser)->pragma_kind != PRAGMA_OMP_DECLARE
- || c_parser_peek_2nd_token (parser)->type != CPP_NAME
- || c_parser_peek_2nd_token (parser)->value != kind)
- {
- error ("%<#pragma omp declare %s%> must be followed by "
- "function declaration or definition or another "
- "%<#pragma omp declare %s%>",
- IDENTIFIER_POINTER (kind), IDENTIFIER_POINTER (kind));
- return;
- }
- c_parser_consume_pragma (parser);
- while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
- {
- c_token *token = c_parser_peek_token (parser);
- if (token->type == CPP_EOF)
- {
- c_parser_skip_to_pragma_eol (parser);
- return;
- }
- clauses.safe_push (*token);
- c_parser_consume_token (parser);
- }
- clauses.safe_push (*c_parser_peek_token (parser));
- c_parser_skip_to_pragma_eol (parser);
- }
-
- /* Make sure nothing tries to read past the end of the tokens. */
- c_token eof_token;
- memset (&eof_token, 0, sizeof (eof_token));
- eof_token.type = CPP_EOF;
- clauses.safe_push (eof_token);
- clauses.safe_push (eof_token);
-
- switch (context)
- {
- case pragma_external:
- if (c_parser_next_token_is (parser, CPP_KEYWORD)
- && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
- {
- int ext = disable_extension_diagnostics ();
- do
- c_parser_consume_token (parser);
- while (c_parser_next_token_is (parser, CPP_KEYWORD)
- && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
- c_parser_declaration_or_fndef (parser, true, true, true, false, true,
- NULL, &clauses);
- restore_extension_diagnostics (ext);
- }
- else
- c_parser_declaration_or_fndef (parser, true, true, true, false, true,
- NULL, &clauses);
- break;
- case pragma_struct:
- case pragma_param:
- case pragma_stmt:
- error ("%<#pragma omp declare %s%> must be followed by "
- "function declaration or definition",
- IDENTIFIER_POINTER (kind));
- break;
- case pragma_compound:
- if (c_parser_next_token_is (parser, CPP_KEYWORD)
- && c_parser_peek_token (parser)->keyword == RID_EXTENSION)
- {
- int ext = disable_extension_diagnostics ();
- do
- c_parser_consume_token (parser);
- while (c_parser_next_token_is (parser, CPP_KEYWORD)
- && c_parser_peek_token (parser)->keyword == RID_EXTENSION);
- if (c_parser_next_tokens_start_declaration (parser))
- {
- c_parser_declaration_or_fndef (parser, true, true, true, true,
- true, NULL, &clauses);
- restore_extension_diagnostics (ext);
- break;
- }
- restore_extension_diagnostics (ext);
- }
- else if (c_parser_next_tokens_start_declaration (parser))
- {
- c_parser_declaration_or_fndef (parser, true, true, true, true, true,
- NULL, &clauses);
- break;
- }
- error ("%<#pragma omp declare %s%> must be followed by "
- "function declaration or definition",
- IDENTIFIER_POINTER (kind));
- break;
- default:
- gcc_unreachable ();
- }
-}
-
-static const char *const omp_construct_selectors[] = {
- "simd", "target", "teams", "parallel", "for", NULL };
-static const char *const omp_device_selectors[] = {
- "kind", "isa", "arch", NULL };
-static const char *const omp_implementation_selectors[] = {
- "vendor", "extension", "atomic_default_mem_order", "unified_address",
- "unified_shared_memory", "dynamic_allocators", "reverse_offload", NULL };
-static const char *const omp_user_selectors[] = {
- "condition", NULL };
-
-/* OpenMP 5.0:
-
- trait-selector:
- trait-selector-name[([trait-score:]trait-property[,trait-property[,...]])]
-
- trait-score:
- score(score-expression) */
-
-static tree
-c_parser_omp_context_selector (c_parser *parser, tree set, tree parms)
-{
- tree ret = NULL_TREE;
- do
- {
- tree selector;
- if (c_parser_next_token_is (parser, CPP_KEYWORD)
- || c_parser_next_token_is (parser, CPP_NAME))
- selector = c_parser_peek_token (parser)->value;
- else
- {
- c_parser_error (parser, "expected trait selector name");
- return error_mark_node;
- }
-
- tree properties = NULL_TREE;
- const char *const *selectors = NULL;
- bool allow_score = true;
- bool allow_user = false;
- int property_limit = 0;
- enum { CTX_PROPERTY_NONE, CTX_PROPERTY_USER, CTX_PROPERTY_NAME_LIST,
- CTX_PROPERTY_ID, CTX_PROPERTY_EXPR,
- CTX_PROPERTY_SIMD } property_kind = CTX_PROPERTY_NONE;
- switch (IDENTIFIER_POINTER (set)[0])
- {
- case 'c': /* construct */
- selectors = omp_construct_selectors;
- allow_score = false;
- property_limit = 1;
- property_kind = CTX_PROPERTY_SIMD;
- break;
- case 'd': /* device */
- selectors = omp_device_selectors;
- allow_score = false;
- allow_user = true;
- property_limit = 3;
- property_kind = CTX_PROPERTY_NAME_LIST;
- break;
- case 'i': /* implementation */
- selectors = omp_implementation_selectors;
- allow_user = true;
- property_limit = 3;
- property_kind = CTX_PROPERTY_NAME_LIST;
- break;
- case 'u': /* user */
- selectors = omp_user_selectors;
- property_limit = 1;
- property_kind = CTX_PROPERTY_EXPR;
- break;
- default:
- gcc_unreachable ();
- }
- for (int i = 0; ; i++)
- {
- if (selectors[i] == NULL)
- {
- if (allow_user)
- {
- property_kind = CTX_PROPERTY_USER;
- break;
- }
- else
- {
- error_at (c_parser_peek_token (parser)->location,
- "selector %qs not allowed for context selector "
- "set %qs", IDENTIFIER_POINTER (selector),
- IDENTIFIER_POINTER (set));
- c_parser_consume_token (parser);
- return error_mark_node;
- }
- }
- if (i == property_limit)
- property_kind = CTX_PROPERTY_NONE;
- if (strcmp (selectors[i], IDENTIFIER_POINTER (selector)) == 0)
- break;
- }
- if (property_kind == CTX_PROPERTY_NAME_LIST
- && IDENTIFIER_POINTER (set)[0] == 'i'
- && strcmp (IDENTIFIER_POINTER (selector),
- "atomic_default_mem_order") == 0)
- property_kind = CTX_PROPERTY_ID;
-
- c_parser_consume_token (parser);
-
- if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
- {
- if (property_kind == CTX_PROPERTY_NONE)
- {
- error_at (c_parser_peek_token (parser)->location,
- "selector %qs does not accept any properties",
- IDENTIFIER_POINTER (selector));
- return error_mark_node;
- }
-
- matching_parens parens;
- parens.require_open (parser);
-
- c_token *token = c_parser_peek_token (parser);
- if (allow_score
- && c_parser_next_token_is (parser, CPP_NAME)
- && strcmp (IDENTIFIER_POINTER (token->value), "score") == 0
- && c_parser_peek_2nd_token (parser)->type == CPP_OPEN_PAREN)
- {
- c_parser_consume_token (parser);
-
- matching_parens parens2;
- parens2.require_open (parser);
- tree score = c_parser_expr_no_commas (parser, NULL).value;
- parens2.skip_until_found_close (parser);
- c_parser_require (parser, CPP_COLON, "expected %<:%>");
- if (score != error_mark_node)
- {
- mark_exp_read (score);
- score = c_fully_fold (score, false, NULL);
- if (!INTEGRAL_TYPE_P (TREE_TYPE (score))
- || TREE_CODE (score) != INTEGER_CST)
- error_at (token->location, "score argument must be "
- "constant integer expression");
- else if (tree_int_cst_sgn (score) < 0)
- error_at (token->location, "score argument must be "
- "non-negative");
- else
- properties = tree_cons (get_identifier (" score"),
- score, properties);
- }
- token = c_parser_peek_token (parser);
- }
-
- switch (property_kind)
- {
- tree t;
- case CTX_PROPERTY_USER:
- do
- {
- t = c_parser_expr_no_commas (parser, NULL).value;
- if (TREE_CODE (t) == STRING_CST)
- properties = tree_cons (NULL_TREE, t, properties);
- else if (t != error_mark_node)
- {
- mark_exp_read (t);
- t = c_fully_fold (t, false, NULL);
- if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
- || !tree_fits_shwi_p (t))
- error_at (token->location, "property must be "
- "constant integer expression or string "
- "literal");
- else
- properties = tree_cons (NULL_TREE, t, properties);
- }
- else
- return error_mark_node;
-
- if (c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
- else
- break;
- }
- while (1);
- break;
- case CTX_PROPERTY_ID:
- if (c_parser_next_token_is (parser, CPP_KEYWORD)
- || c_parser_next_token_is (parser, CPP_NAME))
- {
- tree prop = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- properties = tree_cons (prop, NULL_TREE, properties);
- }
- else
- {
- c_parser_error (parser, "expected identifier");
- return error_mark_node;
- }
- break;
- case CTX_PROPERTY_NAME_LIST:
- do
- {
- tree prop = NULL_TREE, value = NULL_TREE;
- if (c_parser_next_token_is (parser, CPP_KEYWORD)
- || c_parser_next_token_is (parser, CPP_NAME))
- {
- prop = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
- }
- else if (c_parser_next_token_is (parser, CPP_STRING))
- value = c_parser_string_literal (parser, false,
- false).value;
- else
- {
- c_parser_error (parser, "expected identifier or "
- "string literal");
- return error_mark_node;
- }
-
- properties = tree_cons (prop, value, properties);
-
- if (c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
- else
- break;
- }
- while (1);
- break;
- case CTX_PROPERTY_EXPR:
- t = c_parser_expr_no_commas (parser, NULL).value;
- if (t != error_mark_node)
- {
- mark_exp_read (t);
- t = c_fully_fold (t, false, NULL);
- if (!INTEGRAL_TYPE_P (TREE_TYPE (t))
- || !tree_fits_shwi_p (t))
- error_at (token->location, "property must be "
- "constant integer expression");
- else
- properties = tree_cons (NULL_TREE, t, properties);
- }
- else
- return error_mark_node;
- break;
- case CTX_PROPERTY_SIMD:
- if (parms == NULL_TREE)
- {
- error_at (token->location, "properties for %<simd%> "
- "selector may not be specified in "
- "%<metadirective%>");
- return error_mark_node;
- }
- tree c;
- c = c_parser_omp_all_clauses (parser,
- OMP_DECLARE_SIMD_CLAUSE_MASK,
- "simd", true, 2);
- c = c_omp_declare_simd_clauses_to_numbers (parms
- == error_mark_node
- ? NULL_TREE : parms,
- c);
- properties = c;
- break;
- default:
- gcc_unreachable ();
- }
-
- parens.skip_until_found_close (parser);
- properties = nreverse (properties);
- }
- else if (property_kind == CTX_PROPERTY_NAME_LIST
- || property_kind == CTX_PROPERTY_ID
- || property_kind == CTX_PROPERTY_EXPR)
- {
- c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>");
- return error_mark_node;
- }
-
- ret = tree_cons (selector, properties, ret);
-
- if (c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
- else
- break;
- }
- while (1);
-
- return nreverse (ret);
-}
-
-/* OpenMP 5.0:
-
- trait-set-selector[,trait-set-selector[,...]]
-
- trait-set-selector:
- trait-set-selector-name = { trait-selector[, trait-selector[, ...]] }
-
- trait-set-selector-name:
- constructor
- device
- implementation
- user */
-
-static tree
-c_parser_omp_context_selector_specification (c_parser *parser, tree parms)
-{
- tree ret = NULL_TREE;
- do
- {
- const char *setp = "";
- if (c_parser_next_token_is (parser, CPP_NAME))
- setp = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- switch (setp[0])
- {
- case 'c':
- if (strcmp (setp, "construct") == 0)
- setp = NULL;
- break;
- case 'd':
- if (strcmp (setp, "device") == 0)
- setp = NULL;
- break;
- case 'i':
- if (strcmp (setp, "implementation") == 0)
- setp = NULL;
- break;
- case 'u':
- if (strcmp (setp, "user") == 0)
- setp = NULL;
- break;
- default:
- break;
- }
- if (setp)
- {
- c_parser_error (parser, "expected %<construct%>, %<device%>, "
- "%<implementation%> or %<user%>");
- return error_mark_node;
- }
-
- tree set = c_parser_peek_token (parser)->value;
- c_parser_consume_token (parser);
-
- if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
- return error_mark_node;
-
- matching_braces braces;
- if (!braces.require_open (parser))
- return error_mark_node;
-
- tree selectors = c_parser_omp_context_selector (parser, set, parms);
- if (selectors == error_mark_node)
- ret = error_mark_node;
- else if (ret != error_mark_node)
- ret = tree_cons (set, selectors, ret);
-
- braces.skip_until_found_close (parser);
-
- if (c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
- else
- break;
- }
- while (1);
-
- if (ret == error_mark_node)
- return ret;
- return nreverse (ret);
-}
-
-/* Finalize #pragma omp declare variant after FNDECL has been parsed, and put
- that into "omp declare variant base" attribute. */
-
-static void
-c_finish_omp_declare_variant (c_parser *parser, tree fndecl, tree parms)
-{
- matching_parens parens;
- if (!parens.require_open (parser))
- {
- fail:
- c_parser_skip_to_pragma_eol (parser, false);
- return;
- }
-
- if (c_parser_next_token_is_not (parser, CPP_NAME)
- || c_parser_peek_token (parser)->id_kind != C_ID_ID)
- {
- c_parser_error (parser, "expected identifier");
- goto fail;
- }
-
- c_token *token = c_parser_peek_token (parser);
- tree variant = lookup_name (token->value);
-
- if (variant == NULL_TREE)
- {
- undeclared_variable (token->location, token->value);
- variant = error_mark_node;
- }
-
- c_parser_consume_token (parser);
-
- parens.require_close (parser);
-
- const char *clause = "";
- location_t match_loc = c_parser_peek_token (parser)->location;
- if (c_parser_next_token_is (parser, CPP_NAME))
- clause = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (strcmp (clause, "match"))
- {
- c_parser_error (parser, "expected %<match%>");
- goto fail;
- }
-
- c_parser_consume_token (parser);
-
- if (!parens.require_open (parser))
- goto fail;
-
- if (parms == NULL_TREE)
- parms = error_mark_node;
-
- tree ctx = c_parser_omp_context_selector_specification (parser, parms);
- if (ctx == error_mark_node)
- goto fail;
- ctx = omp_check_context_selector (match_loc, ctx);
- if (ctx != error_mark_node && variant != error_mark_node)
- {
- if (TREE_CODE (variant) != FUNCTION_DECL)
- {
- error_at (token->location, "variant %qD is not a function", variant);
- variant = error_mark_node;
- }
- else if (omp_get_context_selector (ctx, "construct", "simd") == NULL_TREE
- && !comptypes (TREE_TYPE (fndecl), TREE_TYPE (variant)))
- {
- error_at (token->location, "variant %qD and base %qD have "
- "incompatible types", variant, fndecl);
- variant = error_mark_node;
- }
- else if (fndecl_built_in_p (variant)
- && (strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
- "__builtin_", strlen ("__builtin_")) == 0
- || strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
- "__sync_", strlen ("__sync_")) == 0
- || strncmp (IDENTIFIER_POINTER (DECL_NAME (variant)),
- "__atomic_", strlen ("__atomic_")) == 0))
- {
- error_at (token->location, "variant %qD is a built-in", variant);
- variant = error_mark_node;
- }
- if (variant != error_mark_node)
- {
- C_DECL_USED (variant) = 1;
- tree construct = omp_get_context_selector (ctx, "construct", NULL);
- omp_mark_declare_variant (match_loc, variant, construct);
- if (omp_context_selector_matches (ctx))
- {
- tree attr
- = tree_cons (get_identifier ("omp declare variant base"),
- build_tree_list (variant, ctx),
- DECL_ATTRIBUTES (fndecl));
- DECL_ATTRIBUTES (fndecl) = attr;
- }
- }
- }
-
- parens.require_close (parser);
- c_parser_skip_to_pragma_eol (parser);
-}
-
-/* Finalize #pragma omp declare simd or #pragma omp declare variant
- clauses after FNDECL has been parsed, and put that into "omp declare simd"
- or "omp declare variant base" attribute. */
-
-static void
-c_finish_omp_declare_simd (c_parser *parser, tree fndecl, tree parms,
- vec<c_token> *pclauses)
-{
- vec<c_token> &clauses = *pclauses;
-
- /* Normally first token is CPP_NAME "simd" or "variant". CPP_EOF there
- indicates error has been reported and CPP_PRAGMA that
- c_finish_omp_declare_simd has already processed the tokens. */
- if (clauses.exists () && clauses[0].type == CPP_EOF)
- return;
- const char *kind = "simd";
- if (clauses.exists ()
- && (clauses[0].type == CPP_NAME || clauses[0].type == CPP_PRAGMA))
- kind = IDENTIFIER_POINTER (clauses[0].value);
- gcc_assert (strcmp (kind, "simd") == 0 || strcmp (kind, "variant") == 0);
- if (fndecl == NULL_TREE || TREE_CODE (fndecl) != FUNCTION_DECL)
- {
- error ("%<#pragma omp declare %s%> not immediately followed by "
- "a function declaration or definition", kind);
- clauses[0].type = CPP_EOF;
- return;
- }
- if (clauses.exists () && clauses[0].type != CPP_NAME)
- {
- error_at (DECL_SOURCE_LOCATION (fndecl),
- "%<#pragma omp declare %s%> not immediately followed by "
- "a single function declaration or definition", kind);
- clauses[0].type = CPP_EOF;
- return;
- }
-
- if (parms == NULL_TREE)
- parms = DECL_ARGUMENTS (fndecl);
-
- unsigned int tokens_avail = parser->tokens_avail;
- gcc_assert (parser->tokens == &parser->tokens_buf[0]);
-
- parser->tokens = clauses.address ();
- parser->tokens_avail = clauses.length ();
-
- /* c_parser_omp_declare_simd pushed 2 extra CPP_EOF tokens at the end. */
- while (parser->tokens_avail > 3)
- {
- c_token *token = c_parser_peek_token (parser);
- gcc_assert (token->type == CPP_NAME
- && strcmp (IDENTIFIER_POINTER (token->value), kind) == 0);
- c_parser_consume_token (parser);
- parser->in_pragma = true;
-
- if (strcmp (kind, "simd") == 0)
- {
- tree c;
- c = c_parser_omp_all_clauses (parser, OMP_DECLARE_SIMD_CLAUSE_MASK,
- "#pragma omp declare simd");
- c = c_omp_declare_simd_clauses_to_numbers (parms, c);
- if (c != NULL_TREE)
- c = tree_cons (NULL_TREE, c, NULL_TREE);
- c = build_tree_list (get_identifier ("omp declare simd"), c);
- TREE_CHAIN (c) = DECL_ATTRIBUTES (fndecl);
- DECL_ATTRIBUTES (fndecl) = c;
- }
- else
- {
- gcc_assert (strcmp (kind, "variant") == 0);
- c_finish_omp_declare_variant (parser, fndecl, parms);
- }
- }
-
- parser->tokens = &parser->tokens_buf[0];
- parser->tokens_avail = tokens_avail;
- if (clauses.exists ())
- clauses[0].type = CPP_PRAGMA;
-}
-
-
-/* OpenMP 4.0:
- # pragma omp declare target new-line
- declarations and definitions
- # pragma omp end declare target new-line
-
- OpenMP 4.5:
- # pragma omp declare target ( extended-list ) new-line
-
- # pragma omp declare target declare-target-clauses[seq] new-line */
-
-#define OMP_DECLARE_TARGET_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_TO) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LINK) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEVICE_TYPE))
-
-static void
-c_parser_omp_declare_target (c_parser *parser)
-{
- tree clauses = NULL_TREE;
- int device_type = 0;
- bool only_device_type = true;
- if (c_parser_next_token_is (parser, CPP_NAME))
- clauses = c_parser_omp_all_clauses (parser, OMP_DECLARE_TARGET_CLAUSE_MASK,
- "#pragma omp declare target");
- else if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
- {
- clauses = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_TO_DECLARE,
- clauses);
- clauses = c_finish_omp_clauses (clauses, C_ORT_OMP);
- c_parser_skip_to_pragma_eol (parser);
- }
- else
- {
- c_parser_skip_to_pragma_eol (parser);
- current_omp_declare_target_attribute++;
- return;
- }
- for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE)
- device_type |= OMP_CLAUSE_DEVICE_TYPE_KIND (c);
- for (tree c = clauses; c; c = OMP_CLAUSE_CHAIN (c))
- {
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEVICE_TYPE)
- continue;
- tree t = OMP_CLAUSE_DECL (c), id;
- tree at1 = lookup_attribute ("omp declare target", DECL_ATTRIBUTES (t));
- tree at2 = lookup_attribute ("omp declare target link",
- DECL_ATTRIBUTES (t));
- only_device_type = false;
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LINK)
- {
- id = get_identifier ("omp declare target link");
- std::swap (at1, at2);
- }
- else
- id = get_identifier ("omp declare target");
- if (at2)
- {
- error_at (OMP_CLAUSE_LOCATION (c),
- "%qD specified both in declare target %<link%> and %<to%>"
- " clauses", t);
- continue;
- }
- if (!at1)
- {
- DECL_ATTRIBUTES (t) = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
- if (TREE_CODE (t) != FUNCTION_DECL && !is_global_var (t))
- continue;
-
- symtab_node *node = symtab_node::get (t);
- if (node != NULL)
- {
- node->offloadable = 1;
- if (ENABLE_OFFLOADING)
- {
- g->have_offload = true;
- if (is_a <varpool_node *> (node))
- vec_safe_push (offload_vars, t);
- }
- }
- }
- if (TREE_CODE (t) != FUNCTION_DECL)
- continue;
- if ((device_type & OMP_CLAUSE_DEVICE_TYPE_HOST) != 0)
- {
- tree at3 = lookup_attribute ("omp declare target host",
- DECL_ATTRIBUTES (t));
- if (at3 == NULL_TREE)
- {
- id = get_identifier ("omp declare target host");
- DECL_ATTRIBUTES (t)
- = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
- }
- }
- if ((device_type & OMP_CLAUSE_DEVICE_TYPE_NOHOST) != 0)
- {
- tree at3 = lookup_attribute ("omp declare target nohost",
- DECL_ATTRIBUTES (t));
- if (at3 == NULL_TREE)
- {
- id = get_identifier ("omp declare target nohost");
- DECL_ATTRIBUTES (t)
- = tree_cons (id, NULL_TREE, DECL_ATTRIBUTES (t));
- }
- }
- }
- if (device_type && only_device_type)
- warning_at (OMP_CLAUSE_LOCATION (clauses), 0,
- "directive with only %<device_type%> clauses ignored");
-}
-
-static void
-c_parser_omp_end_declare_target (c_parser *parser)
-{
- location_t loc = c_parser_peek_token (parser)->location;
- c_parser_consume_pragma (parser);
- if (c_parser_next_token_is (parser, CPP_NAME)
- && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
- "declare") == 0)
- {
- c_parser_consume_token (parser);
- if (c_parser_next_token_is (parser, CPP_NAME)
- && strcmp (IDENTIFIER_POINTER (c_parser_peek_token (parser)->value),
- "target") == 0)
- c_parser_consume_token (parser);
- else
- {
- c_parser_error (parser, "expected %<target%>");
- c_parser_skip_to_pragma_eol (parser);
- return;
- }
- }
- else
- {
- c_parser_error (parser, "expected %<declare%>");
- c_parser_skip_to_pragma_eol (parser);
- return;
- }
- c_parser_skip_to_pragma_eol (parser);
- if (!current_omp_declare_target_attribute)
- error_at (loc, "%<#pragma omp end declare target%> without corresponding "
- "%<#pragma omp declare target%>");
- else
- current_omp_declare_target_attribute--;
-}
-
-
-/* OpenMP 4.0
- #pragma omp declare reduction (reduction-id : typename-list : expression) \
- initializer-clause[opt] new-line
-
- initializer-clause:
- initializer (omp_priv = initializer)
- initializer (function-name (argument-list)) */
-
-static void
-c_parser_omp_declare_reduction (c_parser *parser, enum pragma_context context)
-{
- unsigned int tokens_avail = 0, i;
- vec<tree> types = vNULL;
- vec<c_token> clauses = vNULL;
- enum tree_code reduc_code = ERROR_MARK;
- tree reduc_id = NULL_TREE;
- tree type;
- location_t rloc = c_parser_peek_token (parser)->location;
-
- if (context == pragma_struct || context == pragma_param)
- {
- error ("%<#pragma omp declare reduction%> not at file or block scope");
- goto fail;
- }
-
- if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
- goto fail;
-
- switch (c_parser_peek_token (parser)->type)
- {
- case CPP_PLUS:
- reduc_code = PLUS_EXPR;
- break;
- case CPP_MULT:
- reduc_code = MULT_EXPR;
- break;
- case CPP_MINUS:
- reduc_code = MINUS_EXPR;
- break;
- case CPP_AND:
- reduc_code = BIT_AND_EXPR;
- break;
- case CPP_XOR:
- reduc_code = BIT_XOR_EXPR;
- break;
- case CPP_OR:
- reduc_code = BIT_IOR_EXPR;
- break;
- case CPP_AND_AND:
- reduc_code = TRUTH_ANDIF_EXPR;
- break;
- case CPP_OR_OR:
- reduc_code = TRUTH_ORIF_EXPR;
- break;
- case CPP_NAME:
- const char *p;
- p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (strcmp (p, "min") == 0)
- {
- reduc_code = MIN_EXPR;
- break;
- }
- if (strcmp (p, "max") == 0)
- {
- reduc_code = MAX_EXPR;
- break;
- }
- reduc_id = c_parser_peek_token (parser)->value;
- break;
- default:
- c_parser_error (parser,
- "expected %<+%>, %<*%>, %<-%>, %<&%>, "
- "%<^%>, %<|%>, %<&&%>, %<||%> or identifier");
- goto fail;
- }
-
- tree orig_reduc_id, reduc_decl;
- orig_reduc_id = reduc_id;
- reduc_id = c_omp_reduction_id (reduc_code, reduc_id);
- reduc_decl = c_omp_reduction_decl (reduc_id);
- c_parser_consume_token (parser);
-
- if (!c_parser_require (parser, CPP_COLON, "expected %<:%>"))
- goto fail;
-
- while (true)
- {
- location_t loc = c_parser_peek_token (parser)->location;
- struct c_type_name *ctype = c_parser_type_name (parser);
- if (ctype != NULL)
- {
- type = groktypename (ctype, NULL, NULL);
- if (type == error_mark_node)
- ;
- else if ((INTEGRAL_TYPE_P (type)
- || TREE_CODE (type) == REAL_TYPE
- || TREE_CODE (type) == COMPLEX_TYPE)
- && orig_reduc_id == NULL_TREE)
- error_at (loc, "predeclared arithmetic type in "
- "%<#pragma omp declare reduction%>");
- else if (TREE_CODE (type) == FUNCTION_TYPE
- || TREE_CODE (type) == ARRAY_TYPE)
- error_at (loc, "function or array type in "
- "%<#pragma omp declare reduction%>");
- else if (TYPE_ATOMIC (type))
- error_at (loc, "%<_Atomic%> qualified type in "
- "%<#pragma omp declare reduction%>");
- else if (TYPE_QUALS_NO_ADDR_SPACE (type))
- error_at (loc, "const, volatile or restrict qualified type in "
- "%<#pragma omp declare reduction%>");
- else
- {
- tree t;
- for (t = DECL_INITIAL (reduc_decl); t; t = TREE_CHAIN (t))
- if (comptypes (TREE_PURPOSE (t), type))
- {
- error_at (loc, "redeclaration of %qs "
- "%<#pragma omp declare reduction%> for "
- "type %qT",
- IDENTIFIER_POINTER (reduc_id)
- + sizeof ("omp declare reduction ") - 1,
- type);
- location_t ploc
- = DECL_SOURCE_LOCATION (TREE_VEC_ELT (TREE_VALUE (t),
- 0));
- error_at (ploc, "previous %<#pragma omp declare "
- "reduction%>");
- break;
- }
- if (t == NULL_TREE)
- types.safe_push (type);
- }
- if (c_parser_next_token_is (parser, CPP_COMMA))
- c_parser_consume_token (parser);
- else
- break;
- }
- else
- break;
- }
-
- if (!c_parser_require (parser, CPP_COLON, "expected %<:%>")
- || types.is_empty ())
- {
- fail:
- clauses.release ();
- types.release ();
- while (true)
- {
- c_token *token = c_parser_peek_token (parser);
- if (token->type == CPP_EOF || token->type == CPP_PRAGMA_EOL)
- break;
- c_parser_consume_token (parser);
- }
- c_parser_skip_to_pragma_eol (parser);
- return;
- }
-
- if (types.length () > 1)
- {
- while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
- {
- c_token *token = c_parser_peek_token (parser);
- if (token->type == CPP_EOF)
- goto fail;
- clauses.safe_push (*token);
- c_parser_consume_token (parser);
- }
- clauses.safe_push (*c_parser_peek_token (parser));
- c_parser_skip_to_pragma_eol (parser);
-
- /* Make sure nothing tries to read past the end of the tokens. */
- c_token eof_token;
- memset (&eof_token, 0, sizeof (eof_token));
- eof_token.type = CPP_EOF;
- clauses.safe_push (eof_token);
- clauses.safe_push (eof_token);
- }
-
- int errs = errorcount;
- FOR_EACH_VEC_ELT (types, i, type)
- {
- tokens_avail = parser->tokens_avail;
- gcc_assert (parser->tokens == &parser->tokens_buf[0]);
- if (!clauses.is_empty ())
- {
- parser->tokens = clauses.address ();
- parser->tokens_avail = clauses.length ();
- parser->in_pragma = true;
- }
-
- bool nested = current_function_decl != NULL_TREE;
- if (nested)
- c_push_function_context ();
- tree fndecl = build_decl (BUILTINS_LOCATION, FUNCTION_DECL,
- reduc_id, default_function_type);
- current_function_decl = fndecl;
- allocate_struct_function (fndecl, true);
- push_scope ();
- tree stmt = push_stmt_list ();
- /* Intentionally BUILTINS_LOCATION, so that -Wshadow doesn't
- warn about these. */
- tree omp_out = build_decl (BUILTINS_LOCATION, VAR_DECL,
- get_identifier ("omp_out"), type);
- DECL_ARTIFICIAL (omp_out) = 1;
- DECL_CONTEXT (omp_out) = fndecl;
- pushdecl (omp_out);
- tree omp_in = build_decl (BUILTINS_LOCATION, VAR_DECL,
- get_identifier ("omp_in"), type);
- DECL_ARTIFICIAL (omp_in) = 1;
- DECL_CONTEXT (omp_in) = fndecl;
- pushdecl (omp_in);
- struct c_expr combiner = c_parser_expression (parser);
- struct c_expr initializer;
- tree omp_priv = NULL_TREE, omp_orig = NULL_TREE;
- bool bad = false;
- initializer.set_error ();
- if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
- bad = true;
- else if (c_parser_next_token_is (parser, CPP_NAME)
- && strcmp (IDENTIFIER_POINTER
- (c_parser_peek_token (parser)->value),
- "initializer") == 0)
- {
- c_parser_consume_token (parser);
- pop_scope ();
- push_scope ();
- omp_priv = build_decl (BUILTINS_LOCATION, VAR_DECL,
- get_identifier ("omp_priv"), type);
- DECL_ARTIFICIAL (omp_priv) = 1;
- DECL_INITIAL (omp_priv) = error_mark_node;
- DECL_CONTEXT (omp_priv) = fndecl;
- pushdecl (omp_priv);
- omp_orig = build_decl (BUILTINS_LOCATION, VAR_DECL,
- get_identifier ("omp_orig"), type);
- DECL_ARTIFICIAL (omp_orig) = 1;
- DECL_CONTEXT (omp_orig) = fndecl;
- pushdecl (omp_orig);
- if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
- bad = true;
- else if (!c_parser_next_token_is (parser, CPP_NAME))
- {
- c_parser_error (parser, "expected %<omp_priv%> or "
- "function-name");
- bad = true;
- }
- else if (strcmp (IDENTIFIER_POINTER
- (c_parser_peek_token (parser)->value),
- "omp_priv") != 0)
- {
- if (c_parser_peek_2nd_token (parser)->type != CPP_OPEN_PAREN
- || c_parser_peek_token (parser)->id_kind != C_ID_ID)
- {
- c_parser_error (parser, "expected function-name %<(%>");
- bad = true;
- }
- else
- initializer = c_parser_postfix_expression (parser);
- if (initializer.value
- && TREE_CODE (initializer.value) == CALL_EXPR)
- {
- int j;
- tree c = initializer.value;
- for (j = 0; j < call_expr_nargs (c); j++)
- {
- tree a = CALL_EXPR_ARG (c, j);
- STRIP_NOPS (a);
- if (TREE_CODE (a) == ADDR_EXPR
- && TREE_OPERAND (a, 0) == omp_priv)
- break;
- }
- if (j == call_expr_nargs (c))
- error ("one of the initializer call arguments should be "
- "%<&omp_priv%>");
- }
- }
- else
- {
- c_parser_consume_token (parser);
- if (!c_parser_require (parser, CPP_EQ, "expected %<=%>"))
- bad = true;
- else
- {
- tree st = push_stmt_list ();
- location_t loc = c_parser_peek_token (parser)->location;
- rich_location richloc (line_table, loc);
- start_init (omp_priv, NULL_TREE, 0, &richloc);
- struct c_expr init = c_parser_initializer (parser);
- finish_init ();
- finish_decl (omp_priv, loc, init.value,
- init.original_type, NULL_TREE);
- pop_stmt_list (st);
- }
- }
- if (!bad
- && !c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
- bad = true;
- }
-
- if (!bad)
- {
- c_parser_skip_to_pragma_eol (parser);
-
- tree t = tree_cons (type, make_tree_vec (omp_priv ? 6 : 3),
- DECL_INITIAL (reduc_decl));
- DECL_INITIAL (reduc_decl) = t;
- DECL_SOURCE_LOCATION (omp_out) = rloc;
- TREE_VEC_ELT (TREE_VALUE (t), 0) = omp_out;
- TREE_VEC_ELT (TREE_VALUE (t), 1) = omp_in;
- TREE_VEC_ELT (TREE_VALUE (t), 2) = combiner.value;
- walk_tree (&combiner.value, c_check_omp_declare_reduction_r,
- &TREE_VEC_ELT (TREE_VALUE (t), 0), NULL);
- if (omp_priv)
- {
- DECL_SOURCE_LOCATION (omp_priv) = rloc;
- TREE_VEC_ELT (TREE_VALUE (t), 3) = omp_priv;
- TREE_VEC_ELT (TREE_VALUE (t), 4) = omp_orig;
- TREE_VEC_ELT (TREE_VALUE (t), 5) = initializer.value;
- walk_tree (&initializer.value, c_check_omp_declare_reduction_r,
- &TREE_VEC_ELT (TREE_VALUE (t), 3), NULL);
- walk_tree (&DECL_INITIAL (omp_priv),
- c_check_omp_declare_reduction_r,
- &TREE_VEC_ELT (TREE_VALUE (t), 3), NULL);
- }
- }
-
- pop_stmt_list (stmt);
- pop_scope ();
- if (cfun->language != NULL)
- {
- ggc_free (cfun->language);
- cfun->language = NULL;
- }
- set_cfun (NULL);
- current_function_decl = NULL_TREE;
- if (nested)
- c_pop_function_context ();
-
- if (!clauses.is_empty ())
- {
- parser->tokens = &parser->tokens_buf[0];
- parser->tokens_avail = tokens_avail;
- }
- if (bad)
- goto fail;
- if (errs != errorcount)
- break;
- }
-
- clauses.release ();
- types.release ();
-}
-
-
-/* OpenMP 4.0
- #pragma omp declare simd declare-simd-clauses[optseq] new-line
- #pragma omp declare reduction (reduction-id : typename-list : expression) \
- initializer-clause[opt] new-line
- #pragma omp declare target new-line
-
- OpenMP 5.0
- #pragma omp declare variant (identifier) match (context-selector) */
-
-static bool
-c_parser_omp_declare (c_parser *parser, enum pragma_context context)
-{
- c_parser_consume_pragma (parser);
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- if (strcmp (p, "simd") == 0)
- {
- /* c_parser_consume_token (parser); done in
- c_parser_omp_declare_simd. */
- c_parser_omp_declare_simd (parser, context);
- return true;
- }
- if (strcmp (p, "reduction") == 0)
- {
- c_parser_consume_token (parser);
- c_parser_omp_declare_reduction (parser, context);
- return false;
- }
- if (!flag_openmp) /* flag_openmp_simd */
- {
- c_parser_skip_to_pragma_eol (parser, false);
- return false;
- }
- if (strcmp (p, "target") == 0)
- {
- c_parser_consume_token (parser);
- c_parser_omp_declare_target (parser);
- return false;
- }
- if (strcmp (p, "variant") == 0)
- {
- /* c_parser_consume_token (parser); done in
- c_parser_omp_declare_simd. */
- c_parser_omp_declare_simd (parser, context);
- return true;
- }
- }
-
- c_parser_error (parser, "expected %<simd%>, %<reduction%>, "
- "%<target%> or %<variant%>");
- c_parser_skip_to_pragma_eol (parser);
- return false;
-}
-
-/* OpenMP 5.0
- #pragma omp requires clauses[optseq] new-line */
-
-static void
-c_parser_omp_requires (c_parser *parser)
-{
- bool first = true;
- enum omp_requires new_req = (enum omp_requires) 0;
-
- c_parser_consume_pragma (parser);
-
- location_t loc = c_parser_peek_token (parser)->location;
- while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
- {
- if (!first
- && c_parser_next_token_is (parser, CPP_COMMA)
- && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
- c_parser_consume_token (parser);
-
- first = false;
-
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p
- = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- location_t cloc = c_parser_peek_token (parser)->location;
- enum omp_requires this_req = (enum omp_requires) 0;
-
- if (!strcmp (p, "unified_address"))
- this_req = OMP_REQUIRES_UNIFIED_ADDRESS;
- else if (!strcmp (p, "unified_shared_memory"))
- this_req = OMP_REQUIRES_UNIFIED_SHARED_MEMORY;
- else if (!strcmp (p, "dynamic_allocators"))
- this_req = OMP_REQUIRES_DYNAMIC_ALLOCATORS;
- else if (!strcmp (p, "reverse_offload"))
- this_req = OMP_REQUIRES_REVERSE_OFFLOAD;
- else if (!strcmp (p, "atomic_default_mem_order"))
- {
- c_parser_consume_token (parser);
-
- matching_parens parens;
- if (parens.require_open (parser))
- {
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- tree v = c_parser_peek_token (parser)->value;
- p = IDENTIFIER_POINTER (v);
-
- if (!strcmp (p, "seq_cst"))
- this_req
- = (enum omp_requires) OMP_MEMORY_ORDER_SEQ_CST;
- else if (!strcmp (p, "relaxed"))
- this_req
- = (enum omp_requires) OMP_MEMORY_ORDER_RELAXED;
- else if (!strcmp (p, "acq_rel"))
- this_req
- = (enum omp_requires) OMP_MEMORY_ORDER_ACQ_REL;
- }
- if (this_req == 0)
- {
- error_at (c_parser_peek_token (parser)->location,
- "expected %<seq_cst%>, %<relaxed%> or "
- "%<acq_rel%>");
- switch (c_parser_peek_token (parser)->type)
- {
- case CPP_EOF:
- case CPP_PRAGMA_EOL:
- case CPP_CLOSE_PAREN:
- break;
- default:
- if (c_parser_peek_2nd_token (parser)->type
- == CPP_CLOSE_PAREN)
- c_parser_consume_token (parser);
- break;
- }
- }
- else
- c_parser_consume_token (parser);
-
- parens.skip_until_found_close (parser);
- if (this_req == 0)
- {
- c_parser_skip_to_pragma_eol (parser, false);
- return;
- }
- }
- p = NULL;
- }
- else
- {
- error_at (cloc, "expected %<unified_address%>, "
- "%<unified_shared_memory%>, "
- "%<dynamic_allocators%>, "
- "%<reverse_offload%> "
- "or %<atomic_default_mem_order%> clause");
- c_parser_skip_to_pragma_eol (parser, false);
- return;
- }
- if (p && this_req != OMP_REQUIRES_DYNAMIC_ALLOCATORS)
- sorry_at (cloc, "%qs clause on %<requires%> directive not "
- "supported yet", p);
- if (p)
- c_parser_consume_token (parser);
- if (this_req)
- {
- if ((this_req & ~OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
- {
- if ((this_req & new_req) != 0)
- error_at (cloc, "too many %qs clauses", p);
- if (this_req != OMP_REQUIRES_DYNAMIC_ALLOCATORS
- && (omp_requires_mask & OMP_REQUIRES_TARGET_USED) != 0)
- error_at (cloc, "%qs clause used lexically after first "
- "target construct or offloading API", p);
- }
- else if ((new_req & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
- {
- error_at (cloc, "too many %qs clauses",
- "atomic_default_mem_order");
- this_req = (enum omp_requires) 0;
- }
- else if ((omp_requires_mask
- & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER) != 0)
- {
- error_at (cloc, "more than one %<atomic_default_mem_order%>"
- " clause in a single compilation unit");
- this_req
- = (enum omp_requires)
- (omp_requires_mask
- & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER);
- }
- else if ((omp_requires_mask
- & OMP_REQUIRES_ATOMIC_DEFAULT_MEM_ORDER_USED) != 0)
- error_at (cloc, "%<atomic_default_mem_order%> clause used "
- "lexically after first %<atomic%> construct "
- "without memory order clause");
- new_req = (enum omp_requires) (new_req | this_req);
- omp_requires_mask
- = (enum omp_requires) (omp_requires_mask | this_req);
- continue;
- }
- }
- break;
- }
- c_parser_skip_to_pragma_eol (parser);
-
- if (new_req == 0)
- error_at (loc, "%<pragma omp requires%> requires at least one clause");
-}
-
-/* Helper function for c_parser_omp_taskloop.
- Disallow zero sized or potentially zero sized task reductions. */
-
-static tree
-c_finish_taskloop_clauses (tree clauses)
-{
- tree *pc = &clauses;
- for (tree c = clauses; c; c = *pc)
- {
- bool remove = false;
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
- {
- tree type = strip_array_types (TREE_TYPE (OMP_CLAUSE_DECL (c)));
- if (integer_zerop (TYPE_SIZE_UNIT (type)))
- {
- error_at (OMP_CLAUSE_LOCATION (c),
- "zero sized type %qT in %<reduction%> clause", type);
- remove = true;
- }
- else if (TREE_CODE (TYPE_SIZE_UNIT (type)) != INTEGER_CST)
- {
- error_at (OMP_CLAUSE_LOCATION (c),
- "variable sized type %qT in %<reduction%> clause",
- type);
- remove = true;
- }
- }
- if (remove)
- *pc = OMP_CLAUSE_CHAIN (c);
- else
- pc = &OMP_CLAUSE_CHAIN (c);
- }
- return clauses;
-}
-
-/* OpenMP 4.5:
- #pragma omp taskloop taskloop-clause[optseq] new-line
- for-loop
-
- #pragma omp taskloop simd taskloop-simd-clause[optseq] new-line
- for-loop */
-
-#define OMP_TASKLOOP_CLAUSE_MASK \
- ( (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_SHARED) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_LASTPRIVATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_DEFAULT) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_GRAINSIZE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_TASKS) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_COLLAPSE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_UNTIED) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IF) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_FINAL) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_MERGEABLE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NOGROUP) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_PRIORITY) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_ALLOCATE) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_REDUCTION) \
- | (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION))
-
-static tree
-c_parser_omp_taskloop (location_t loc, c_parser *parser,
- char *p_name, omp_clause_mask mask, tree *cclauses,
- bool *if_p)
-{
- tree clauses, block, ret;
-
- strcat (p_name, " taskloop");
- mask |= OMP_TASKLOOP_CLAUSE_MASK;
- /* #pragma omp parallel master taskloop{, simd} disallow in_reduction
- clause. */
- if ((mask & (OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_NUM_THREADS)) != 0)
- mask &= ~(OMP_CLAUSE_MASK_1 << PRAGMA_OMP_CLAUSE_IN_REDUCTION);
-
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- const char *p = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
-
- if (strcmp (p, "simd") == 0)
- {
- tree cclauses_buf[C_OMP_CLAUSE_SPLIT_COUNT];
- if (cclauses == NULL)
- cclauses = cclauses_buf;
- c_parser_consume_token (parser);
- if (!flag_openmp) /* flag_openmp_simd */
- return c_parser_omp_simd (loc, parser, p_name, mask, cclauses,
- if_p);
- block = c_begin_compound_stmt (true);
- ret = c_parser_omp_simd (loc, parser, p_name, mask, cclauses, if_p);
- block = c_end_compound_stmt (loc, block, true);
- if (ret == NULL)
- return ret;
- ret = make_node (OMP_TASKLOOP);
- TREE_TYPE (ret) = void_type_node;
- OMP_FOR_BODY (ret) = block;
- OMP_FOR_CLAUSES (ret) = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
- OMP_FOR_CLAUSES (ret)
- = c_finish_taskloop_clauses (OMP_FOR_CLAUSES (ret));
- SET_EXPR_LOCATION (ret, loc);
- add_stmt (ret);
- return ret;
- }
- }
- if (!flag_openmp) /* flag_openmp_simd */
- {
- c_parser_skip_to_pragma_eol (parser, false);
- return NULL_TREE;
- }
-
- clauses = c_parser_omp_all_clauses (parser, mask, p_name, cclauses == NULL);
- if (cclauses)
- {
- omp_split_clauses (loc, OMP_TASKLOOP, mask, clauses, cclauses);
- clauses = cclauses[C_OMP_CLAUSE_SPLIT_TASKLOOP];
- }
-
- clauses = c_finish_taskloop_clauses (clauses);
- block = c_begin_compound_stmt (true);
- ret = c_parser_omp_for_loop (loc, parser, OMP_TASKLOOP, clauses, NULL, if_p);
- block = c_end_compound_stmt (loc, block, true);
- add_stmt (block);
-
- return ret;
-}
-
-/* OpenMP 5.1
- #pragma omp nothing new-line */
-
-static void
-c_parser_omp_nothing (c_parser *parser)
-{
- c_parser_consume_pragma (parser);
- c_parser_skip_to_pragma_eol (parser);
-}
-
-/* OpenMP 5.1
- #pragma omp error clauses[optseq] new-line */
-
-static bool
-c_parser_omp_error (c_parser *parser, enum pragma_context context)
-{
- int at_compilation = -1;
- int severity_fatal = -1;
- tree message = NULL_TREE;
- bool first = true;
- bool bad = false;
- location_t loc = c_parser_peek_token (parser)->location;
-
- c_parser_consume_pragma (parser);
-
- while (c_parser_next_token_is_not (parser, CPP_PRAGMA_EOL))
- {
- if (!first
- && c_parser_next_token_is (parser, CPP_COMMA)
- && c_parser_peek_2nd_token (parser)->type == CPP_NAME)
- c_parser_consume_token (parser);
-
- first = false;
-
- if (!c_parser_next_token_is (parser, CPP_NAME))
- break;
-
- const char *p
- = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
- location_t cloc = c_parser_peek_token (parser)->location;
- static const char *args[] = {
- "execution", "compilation", "warning", "fatal"
- };
- int *v = NULL;
- int idx = 0, n = -1;
- tree m = NULL_TREE;
-
- if (!strcmp (p, "at"))
- v = &at_compilation;
- else if (!strcmp (p, "severity"))
- {
- v = &severity_fatal;
- idx += 2;
- }
- else if (strcmp (p, "message"))
- {
- error_at (cloc,
- "expected %<at%>, %<severity%> or %<message%> clause");
- c_parser_skip_to_pragma_eol (parser, false);
- return false;
- }
-
- c_parser_consume_token (parser);
-
- matching_parens parens;
- if (parens.require_open (parser))
- {
- if (v == NULL)
- {
- location_t expr_loc = c_parser_peek_token (parser)->location;
- c_expr expr = c_parser_expr_no_commas (parser, NULL);
- expr = convert_lvalue_to_rvalue (expr_loc, expr, true, true);
- m = convert (const_string_type_node, expr.value);
- m = c_fully_fold (m, false, NULL);
- }
- else
- {
- if (c_parser_next_token_is (parser, CPP_NAME))
- {
- tree val = c_parser_peek_token (parser)->value;
- const char *q = IDENTIFIER_POINTER (val);
-
- if (!strcmp (q, args[idx]))
- n = 0;
- else if (!strcmp (q, args[idx + 1]))
- n = 1;
- }
- if (n == -1)
- {
- error_at (c_parser_peek_token (parser)->location,
- "expected %qs or %qs", args[idx], args[idx + 1]);
- bad = true;
- switch (c_parser_peek_token (parser)->type)
- {
- case CPP_EOF:
- case CPP_PRAGMA_EOL:
- case CPP_CLOSE_PAREN:
- break;
- default:
- if (c_parser_peek_2nd_token (parser)->type
- == CPP_CLOSE_PAREN)
- c_parser_consume_token (parser);
- break;
- }
- }
- else
- c_parser_consume_token (parser);
- }
-
- parens.skip_until_found_close (parser);
-
- if (v == NULL)
- {
- if (message)
- {
- error_at (cloc, "too many %qs clauses", p);
- bad = true;
- }
- else
- message = m;
- }
- else if (n != -1)
- {
- if (*v != -1)
- {
- error_at (cloc, "too many %qs clauses", p);
- bad = true;
- }
- else
- *v = n;
- }
- }
- else
- bad = true;
- }
- c_parser_skip_to_pragma_eol (parser);
- if (bad)
- return true;
-
- if (at_compilation == -1)
- at_compilation = 1;
- if (severity_fatal == -1)
- severity_fatal = 1;
- if (!at_compilation)
- {
- if (context != pragma_compound)
- {
- error_at (loc, "%<#pragma omp error%> with %<at(execution)%> clause "
- "may only be used in compound statements");
- return true;
- }
- tree fndecl
- = builtin_decl_explicit (severity_fatal ? BUILT_IN_GOMP_ERROR
- : BUILT_IN_GOMP_WARNING);
- if (!message)
- message = build_zero_cst (const_string_type_node);
- tree stmt = build_call_expr_loc (loc, fndecl, 2, message,
- build_all_ones_cst (size_type_node));
- add_stmt (stmt);
- return true;
- }
- const char *msg = NULL;
- if (message)
- {
- msg = c_getstr (message);
- if (msg == NULL)
- msg = _("<message unknown at compile time>");
- }
- if (msg)
- emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0,
- "%<pragma omp error%> encountered: %s", msg);
- else
- emit_diagnostic (severity_fatal ? DK_ERROR : DK_WARNING, loc, 0,
- "%<pragma omp error%> encountered");
- return false;
-}
-
-/* Main entry point to parsing most OpenMP pragmas. */
-
-static void
-c_parser_omp_construct (c_parser *parser, bool *if_p)
-{
- enum pragma_kind p_kind;
- location_t loc;
- tree stmt;
- char p_name[sizeof "#pragma omp teams distribute parallel for simd"];
- omp_clause_mask mask (0);
-
- loc = c_parser_peek_token (parser)->location;
- p_kind = c_parser_peek_token (parser)->pragma_kind;
- c_parser_consume_pragma (parser);
-
- switch (p_kind)
- {
- case PRAGMA_OACC_ATOMIC:
- c_parser_omp_atomic (loc, parser, true);
- return;
- case PRAGMA_OACC_CACHE:
- strcpy (p_name, "#pragma acc");
- stmt = c_parser_oacc_cache (loc, parser);
- break;
- case PRAGMA_OACC_DATA:
- stmt = c_parser_oacc_data (loc, parser, if_p);
- break;
- case PRAGMA_OACC_HOST_DATA:
- stmt = c_parser_oacc_host_data (loc, parser, if_p);
- break;
- case PRAGMA_OACC_KERNELS:
- case PRAGMA_OACC_PARALLEL:
- case PRAGMA_OACC_SERIAL:
- strcpy (p_name, "#pragma acc");
- stmt = c_parser_oacc_compute (loc, parser, p_kind, p_name, if_p);
- break;
- case PRAGMA_OACC_LOOP:
- strcpy (p_name, "#pragma acc");
- stmt = c_parser_oacc_loop (loc, parser, p_name, mask, NULL, if_p);
- break;
- case PRAGMA_OACC_WAIT:
- strcpy (p_name, "#pragma wait");
- stmt = c_parser_oacc_wait (loc, parser, p_name);
- break;
- case PRAGMA_OMP_ALLOCATE:
- c_parser_omp_allocate (loc, parser);
- return;
- case PRAGMA_OMP_ATOMIC:
- c_parser_omp_atomic (loc, parser, false);
- return;
- case PRAGMA_OMP_CRITICAL:
- stmt = c_parser_omp_critical (loc, parser, if_p);
- break;
- case PRAGMA_OMP_DISTRIBUTE:
- strcpy (p_name, "#pragma omp");
- stmt = c_parser_omp_distribute (loc, parser, p_name, mask, NULL, if_p);
- break;
- case PRAGMA_OMP_FOR:
- strcpy (p_name, "#pragma omp");
- stmt = c_parser_omp_for (loc, parser, p_name, mask, NULL, if_p);
- break;
- case PRAGMA_OMP_LOOP:
- strcpy (p_name, "#pragma omp");
- stmt = c_parser_omp_loop (loc, parser, p_name, mask, NULL, if_p);
- break;
- case PRAGMA_OMP_MASKED:
- strcpy (p_name, "#pragma omp");
- stmt = c_parser_omp_masked (loc, parser, p_name, mask, NULL, if_p);
- break;
- case PRAGMA_OMP_MASTER:
- strcpy (p_name, "#pragma omp");
- stmt = c_parser_omp_master (loc, parser, p_name, mask, NULL, if_p);
- break;
- case PRAGMA_OMP_PARALLEL:
- strcpy (p_name, "#pragma omp");
- stmt = c_parser_omp_parallel (loc, parser, p_name, mask, NULL, if_p);
- break;
- case PRAGMA_OMP_SCOPE:
- stmt = c_parser_omp_scope (loc, parser, if_p);
- break;
- case PRAGMA_OMP_SECTIONS:
- strcpy (p_name, "#pragma omp");
- stmt = c_parser_omp_sections (loc, parser, p_name, mask, NULL);
- break;
- case PRAGMA_OMP_SIMD:
- strcpy (p_name, "#pragma omp");
- stmt = c_parser_omp_simd (loc, parser, p_name, mask, NULL, if_p);
- break;
- case PRAGMA_OMP_SINGLE:
- stmt = c_parser_omp_single (loc, parser, if_p);
- break;
- case PRAGMA_OMP_TASK:
- stmt = c_parser_omp_task (loc, parser, if_p);
- break;
- case PRAGMA_OMP_TASKGROUP:
- stmt = c_parser_omp_taskgroup (loc, parser, if_p);
- break;
- case PRAGMA_OMP_TASKLOOP:
- strcpy (p_name, "#pragma omp");
- stmt = c_parser_omp_taskloop (loc, parser, p_name, mask, NULL, if_p);
- break;
- case PRAGMA_OMP_TEAMS:
- strcpy (p_name, "#pragma omp");
- stmt = c_parser_omp_teams (loc, parser, p_name, mask, NULL, if_p);
- break;
- default:
- gcc_unreachable ();
- }
-
- if (stmt && stmt != error_mark_node)
- gcc_assert (EXPR_LOCATION (stmt) != UNKNOWN_LOCATION);
-}
-
-
-/* OpenMP 2.5:
- # pragma omp threadprivate (variable-list) */
-
-static void
-c_parser_omp_threadprivate (c_parser *parser)
-{
- tree vars, t;
- location_t loc;
-
- c_parser_consume_pragma (parser);
- loc = c_parser_peek_token (parser)->location;
- vars = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_ERROR, NULL);
-
- /* Mark every variable in VARS to be assigned thread local storage. */
- for (t = vars; t; t = TREE_CHAIN (t))
- {
- tree v = TREE_PURPOSE (t);
-
- /* FIXME diagnostics: Ideally we should keep individual
- locations for all the variables in the var list to make the
- following errors more precise. Perhaps
- c_parser_omp_var_list_parens() should construct a list of
- locations to go along with the var list. */
-
- /* If V had already been marked threadprivate, it doesn't matter
- whether it had been used prior to this point. */
- if (!VAR_P (v))
- error_at (loc, "%qD is not a variable", v);
- else if (TREE_USED (v) && !C_DECL_THREADPRIVATE_P (v))
- error_at (loc, "%qE declared %<threadprivate%> after first use", v);
- else if (! is_global_var (v))
- error_at (loc, "automatic variable %qE cannot be %<threadprivate%>", v);
- else if (TREE_TYPE (v) == error_mark_node)
- ;
- else if (! COMPLETE_TYPE_P (TREE_TYPE (v)))
- error_at (loc, "%<threadprivate%> %qE has incomplete type", v);
- else
- {
- if (! DECL_THREAD_LOCAL_P (v))
- {
- 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);
- }
- C_DECL_THREADPRIVATE_P (v) = 1;
- }
- }
-
- c_parser_skip_to_pragma_eol (parser);
-}
-
-/* Parse a transaction attribute (GCC Extension).
-
- transaction-attribute:
- gnu-attributes
- attribute-specifier
-*/
-
-static tree
-c_parser_transaction_attributes (c_parser *parser)
-{
- if (c_parser_next_token_is_keyword (parser, RID_ATTRIBUTE))
- return c_parser_gnu_attributes (parser);
-
- if (!c_parser_next_token_is (parser, CPP_OPEN_SQUARE))
- return NULL_TREE;
- return c_parser_std_attribute_specifier (parser, true);
-}
-
-/* Parse a __transaction_atomic or __transaction_relaxed statement
- (GCC Extension).
-
- transaction-statement:
- __transaction_atomic transaction-attribute[opt] compound-statement
- __transaction_relaxed compound-statement
-
- Note that the only valid attribute is: "outer".
-*/
-
-static tree
-c_parser_transaction (c_parser *parser, enum rid keyword)
-{
- unsigned int old_in = parser->in_transaction;
- unsigned int this_in = 1, new_in;
- location_t loc = c_parser_peek_token (parser)->location;
- tree stmt, attrs;
-
- gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
- || keyword == RID_TRANSACTION_RELAXED)
- && c_parser_next_token_is_keyword (parser, keyword));
- c_parser_consume_token (parser);
-
- if (keyword == RID_TRANSACTION_RELAXED)
- this_in |= TM_STMT_ATTR_RELAXED;
- else
- {
- attrs = c_parser_transaction_attributes (parser);
- if (attrs)
- this_in |= parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER);
- }
-
- /* Keep track if we're in the lexical scope of an outer transaction. */
- new_in = this_in | (old_in & TM_STMT_ATTR_OUTER);
-
- parser->in_transaction = new_in;
- stmt = c_parser_compound_statement (parser);
- parser->in_transaction = old_in;
-
- if (flag_tm)
- stmt = c_finish_transaction (loc, stmt, this_in);
- else
- error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
- "%<__transaction_atomic%> without transactional memory support enabled"
- : "%<__transaction_relaxed %> "
- "without transactional memory support enabled"));
-
- return stmt;
-}
-
-/* Parse a __transaction_atomic or __transaction_relaxed expression
- (GCC Extension).
-
- transaction-expression:
- __transaction_atomic ( expression )
- __transaction_relaxed ( expression )
-*/
-
-static struct c_expr
-c_parser_transaction_expression (c_parser *parser, enum rid keyword)
-{
- struct c_expr ret;
- unsigned int old_in = parser->in_transaction;
- unsigned int this_in = 1;
- location_t loc = c_parser_peek_token (parser)->location;
- tree attrs;
-
- gcc_assert ((keyword == RID_TRANSACTION_ATOMIC
- || keyword == RID_TRANSACTION_RELAXED)
- && c_parser_next_token_is_keyword (parser, keyword));
- c_parser_consume_token (parser);
-
- if (keyword == RID_TRANSACTION_RELAXED)
- this_in |= TM_STMT_ATTR_RELAXED;
- else
- {
- attrs = c_parser_transaction_attributes (parser);
- if (attrs)
- this_in |= parse_tm_stmt_attr (attrs, 0);
- }
-
- parser->in_transaction = this_in;
- matching_parens parens;
- if (parens.require_open (parser))
- {
- tree expr = c_parser_expression (parser).value;
- ret.original_type = TREE_TYPE (expr);
- ret.value = build1 (TRANSACTION_EXPR, ret.original_type, expr);
- if (this_in & TM_STMT_ATTR_RELAXED)
- TRANSACTION_EXPR_RELAXED (ret.value) = 1;
- SET_EXPR_LOCATION (ret.value, loc);
- ret.original_code = TRANSACTION_EXPR;
- if (!parens.require_close (parser))
- {
- c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, NULL);
- goto error;
- }
- }
- else
- {
- error:
- ret.set_error ();
- ret.original_code = ERROR_MARK;
- ret.original_type = NULL;
- }
- parser->in_transaction = old_in;
-
- if (!flag_tm)
- error_at (loc, (keyword == RID_TRANSACTION_ATOMIC ?
- "%<__transaction_atomic%> without transactional memory support enabled"
- : "%<__transaction_relaxed %> "
- "without transactional memory support enabled"));
-
- set_c_expr_source_range (&ret, loc, loc);
-
- return ret;
-}
-
-/* Parse a __transaction_cancel statement (GCC Extension).
-
- transaction-cancel-statement:
- __transaction_cancel transaction-attribute[opt] ;
-
- Note that the only valid attribute is "outer".
-*/
-
-static tree
-c_parser_transaction_cancel (c_parser *parser)
-{
- location_t loc = c_parser_peek_token (parser)->location;
- tree attrs;
- bool is_outer = false;
-
- gcc_assert (c_parser_next_token_is_keyword (parser, RID_TRANSACTION_CANCEL));
- c_parser_consume_token (parser);
-
- attrs = c_parser_transaction_attributes (parser);
- if (attrs)
- is_outer = (parse_tm_stmt_attr (attrs, TM_STMT_ATTR_OUTER) != 0);
-
- if (!flag_tm)
- {
- error_at (loc, "%<__transaction_cancel%> without "
- "transactional memory support enabled");
- goto ret_error;
- }
- else if (parser->in_transaction & TM_STMT_ATTR_RELAXED)
- {
- error_at (loc, "%<__transaction_cancel%> within a "
- "%<__transaction_relaxed%>");
- goto ret_error;
- }
- else if (is_outer)
- {
- if ((parser->in_transaction & TM_STMT_ATTR_OUTER) == 0
- && !is_tm_may_cancel_outer (current_function_decl))
- {
- error_at (loc, "outer %<__transaction_cancel%> not "
- "within outer %<__transaction_atomic%> or "
- "a %<transaction_may_cancel_outer%> function");
- goto ret_error;
- }
- }
- else if (parser->in_transaction == 0)
- {
- error_at (loc, "%<__transaction_cancel%> not within "
- "%<__transaction_atomic%>");
- goto ret_error;
- }
-
- return add_stmt (build_tm_abort_call (loc, is_outer));
-
- ret_error:
- return build1 (NOP_EXPR, void_type_node, error_mark_node);
-}
-
-/* Parse a single source file. */
-
-void
-c_parse_file (void)
-{
- /* Use local storage to begin. If the first token is a pragma, parse it.
- If it is #pragma GCC pch_preprocess, then this will load a PCH file
- which will cause garbage collection. */
- c_parser tparser;
-
- memset (&tparser, 0, sizeof tparser);
- tparser.translate_strings_p = true;
- tparser.tokens = &tparser.tokens_buf[0];
- the_parser = &tparser;
-
- if (c_parser_peek_token (&tparser)->pragma_kind == PRAGMA_GCC_PCH_PREPROCESS)
- c_parser_pragma_pch_preprocess (&tparser);
- else
- c_common_no_more_pch ();
-
- the_parser = ggc_alloc<c_parser> ();
- *the_parser = tparser;
- if (tparser.tokens == &tparser.tokens_buf[0])
- the_parser->tokens = &the_parser->tokens_buf[0];
-
- /* Initialize EH, if we've been told to do so. */
- if (flag_exceptions)
- using_eh_for_cleanups ();
-
- c_parser_translation_unit (the_parser);
- the_parser = NULL;
-}
-
-/* Parse the body of a function declaration marked with "__RTL".
-
- The RTL parser works on the level of characters read from a
- FILE *, whereas c_parser works at the level of tokens.
- Square this circle by consuming all of the tokens up to and
- including the closing brace, recording the start/end of the RTL
- fragment, and reopening the file and re-reading the relevant
- lines within the RTL parser.
-
- This requires the opening and closing braces of the C function
- to be on separate lines from the RTL they wrap.
-
- Take ownership of START_WITH_PASS, if non-NULL. */
-
-location_t
-c_parser_parse_rtl_body (c_parser *parser, char *start_with_pass)
-{
- if (!c_parser_require (parser, CPP_OPEN_BRACE, "expected %<{%>"))
- {
- free (start_with_pass);
- return c_parser_peek_token (parser)->location;
- }
-
- location_t start_loc = c_parser_peek_token (parser)->location;
-
- /* Consume all tokens, up to the closing brace, handling
- matching pairs of braces in the rtl dump. */
- int num_open_braces = 1;
- while (1)
- {
- switch (c_parser_peek_token (parser)->type)
- {
- case CPP_OPEN_BRACE:
- num_open_braces++;
- break;
- case CPP_CLOSE_BRACE:
- if (--num_open_braces == 0)
- goto found_closing_brace;
- break;
- case CPP_EOF:
- error_at (start_loc, "no closing brace");
- free (start_with_pass);
- return c_parser_peek_token (parser)->location;
- default:
- break;
- }
- c_parser_consume_token (parser);
- }
-
- found_closing_brace:
- /* At the closing brace; record its location. */
- location_t end_loc = c_parser_peek_token (parser)->location;
-
- /* Consume the closing brace. */
- c_parser_consume_token (parser);
-
- /* Invoke the RTL parser. */
- if (!read_rtl_function_body_from_file_range (start_loc, end_loc))
- {
- free (start_with_pass);
- return end_loc;
- }
-
- /* Run the backend on the cfun created above, transferring ownership of
- START_WITH_PASS. */
- run_rtl_passes (start_with_pass);
- return end_loc;
-}
-
-#include "gt-c-c-parser.h"