diff options
author | Martin Liska <mliska@suse.cz> | 2022-01-14 16:56:44 +0100 |
---|---|---|
committer | Martin Liska <mliska@suse.cz> | 2022-01-17 22:12:04 +0100 |
commit | 5c69acb32329d49e58c26fa41ae74229a52b9106 (patch) | |
tree | ddb05f9d73afb6f998457d2ac4b720e3b3b60483 /gcc/c/c-parser.c | |
parent | 490e23032baaece71f2ec09fa1805064b150fbc2 (diff) | |
download | gcc-5c69acb32329d49e58c26fa41ae74229a52b9106.zip gcc-5c69acb32329d49e58c26fa41ae74229a52b9106.tar.gz gcc-5c69acb32329d49e58c26fa41ae74229a52b9106.tar.bz2 |
Rename .c files to .cc files.
gcc/ada/ChangeLog:
* adadecode.c: Moved to...
* adadecode.cc: ...here.
* affinity.c: Moved to...
* affinity.cc: ...here.
* argv-lynxos178-raven-cert.c: Moved to...
* argv-lynxos178-raven-cert.cc: ...here.
* argv.c: Moved to...
* argv.cc: ...here.
* aux-io.c: Moved to...
* aux-io.cc: ...here.
* cio.c: Moved to...
* cio.cc: ...here.
* cstreams.c: Moved to...
* cstreams.cc: ...here.
* env.c: Moved to...
* env.cc: ...here.
* exit.c: Moved to...
* exit.cc: ...here.
* expect.c: Moved to...
* expect.cc: ...here.
* final.c: Moved to...
* final.cc: ...here.
* gcc-interface/cuintp.c: Moved to...
* gcc-interface/cuintp.cc: ...here.
* gcc-interface/decl.c: Moved to...
* gcc-interface/decl.cc: ...here.
* gcc-interface/misc.c: Moved to...
* gcc-interface/misc.cc: ...here.
* gcc-interface/targtyps.c: Moved to...
* gcc-interface/targtyps.cc: ...here.
* gcc-interface/trans.c: Moved to...
* gcc-interface/trans.cc: ...here.
* gcc-interface/utils.c: Moved to...
* gcc-interface/utils.cc: ...here.
* gcc-interface/utils2.c: Moved to...
* gcc-interface/utils2.cc: ...here.
* init.c: Moved to...
* init.cc: ...here.
* initialize.c: Moved to...
* initialize.cc: ...here.
* libgnarl/thread.c: Moved to...
* libgnarl/thread.cc: ...here.
* link.c: Moved to...
* link.cc: ...here.
* locales.c: Moved to...
* locales.cc: ...here.
* mkdir.c: Moved to...
* mkdir.cc: ...here.
* raise.c: Moved to...
* raise.cc: ...here.
* rtfinal.c: Moved to...
* rtfinal.cc: ...here.
* rtinit.c: Moved to...
* rtinit.cc: ...here.
* seh_init.c: Moved to...
* seh_init.cc: ...here.
* sigtramp-armdroid.c: Moved to...
* sigtramp-armdroid.cc: ...here.
* sigtramp-ios.c: Moved to...
* sigtramp-ios.cc: ...here.
* sigtramp-qnx.c: Moved to...
* sigtramp-qnx.cc: ...here.
* sigtramp-vxworks.c: Moved to...
* sigtramp-vxworks.cc: ...here.
* socket.c: Moved to...
* socket.cc: ...here.
* tracebak.c: Moved to...
* tracebak.cc: ...here.
* version.c: Moved to...
* version.cc: ...here.
* vx_stack_info.c: Moved to...
* vx_stack_info.cc: ...here.
gcc/ChangeLog:
* adjust-alignment.c: Moved to...
* adjust-alignment.cc: ...here.
* alias.c: Moved to...
* alias.cc: ...here.
* alloc-pool.c: Moved to...
* alloc-pool.cc: ...here.
* asan.c: Moved to...
* asan.cc: ...here.
* attribs.c: Moved to...
* attribs.cc: ...here.
* auto-inc-dec.c: Moved to...
* auto-inc-dec.cc: ...here.
* auto-profile.c: Moved to...
* auto-profile.cc: ...here.
* bb-reorder.c: Moved to...
* bb-reorder.cc: ...here.
* bitmap.c: Moved to...
* bitmap.cc: ...here.
* btfout.c: Moved to...
* btfout.cc: ...here.
* builtins.c: Moved to...
* builtins.cc: ...here.
* caller-save.c: Moved to...
* caller-save.cc: ...here.
* calls.c: Moved to...
* calls.cc: ...here.
* ccmp.c: Moved to...
* ccmp.cc: ...here.
* cfg.c: Moved to...
* cfg.cc: ...here.
* cfganal.c: Moved to...
* cfganal.cc: ...here.
* cfgbuild.c: Moved to...
* cfgbuild.cc: ...here.
* cfgcleanup.c: Moved to...
* cfgcleanup.cc: ...here.
* cfgexpand.c: Moved to...
* cfgexpand.cc: ...here.
* cfghooks.c: Moved to...
* cfghooks.cc: ...here.
* cfgloop.c: Moved to...
* cfgloop.cc: ...here.
* cfgloopanal.c: Moved to...
* cfgloopanal.cc: ...here.
* cfgloopmanip.c: Moved to...
* cfgloopmanip.cc: ...here.
* cfgrtl.c: Moved to...
* cfgrtl.cc: ...here.
* cgraph.c: Moved to...
* cgraph.cc: ...here.
* cgraphbuild.c: Moved to...
* cgraphbuild.cc: ...here.
* cgraphclones.c: Moved to...
* cgraphclones.cc: ...here.
* cgraphunit.c: Moved to...
* cgraphunit.cc: ...here.
* collect-utils.c: Moved to...
* collect-utils.cc: ...here.
* collect2-aix.c: Moved to...
* collect2-aix.cc: ...here.
* collect2.c: Moved to...
* collect2.cc: ...here.
* combine-stack-adj.c: Moved to...
* combine-stack-adj.cc: ...here.
* combine.c: Moved to...
* combine.cc: ...here.
* common/common-targhooks.c: Moved to...
* common/common-targhooks.cc: ...here.
* common/config/aarch64/aarch64-common.c: Moved to...
* common/config/aarch64/aarch64-common.cc: ...here.
* common/config/alpha/alpha-common.c: Moved to...
* common/config/alpha/alpha-common.cc: ...here.
* common/config/arc/arc-common.c: Moved to...
* common/config/arc/arc-common.cc: ...here.
* common/config/arm/arm-common.c: Moved to...
* common/config/arm/arm-common.cc: ...here.
* common/config/avr/avr-common.c: Moved to...
* common/config/avr/avr-common.cc: ...here.
* common/config/bfin/bfin-common.c: Moved to...
* common/config/bfin/bfin-common.cc: ...here.
* common/config/bpf/bpf-common.c: Moved to...
* common/config/bpf/bpf-common.cc: ...here.
* common/config/c6x/c6x-common.c: Moved to...
* common/config/c6x/c6x-common.cc: ...here.
* common/config/cr16/cr16-common.c: Moved to...
* common/config/cr16/cr16-common.cc: ...here.
* common/config/cris/cris-common.c: Moved to...
* common/config/cris/cris-common.cc: ...here.
* common/config/csky/csky-common.c: Moved to...
* common/config/csky/csky-common.cc: ...here.
* common/config/default-common.c: Moved to...
* common/config/default-common.cc: ...here.
* common/config/epiphany/epiphany-common.c: Moved to...
* common/config/epiphany/epiphany-common.cc: ...here.
* common/config/fr30/fr30-common.c: Moved to...
* common/config/fr30/fr30-common.cc: ...here.
* common/config/frv/frv-common.c: Moved to...
* common/config/frv/frv-common.cc: ...here.
* common/config/gcn/gcn-common.c: Moved to...
* common/config/gcn/gcn-common.cc: ...here.
* common/config/h8300/h8300-common.c: Moved to...
* common/config/h8300/h8300-common.cc: ...here.
* common/config/i386/i386-common.c: Moved to...
* common/config/i386/i386-common.cc: ...here.
* common/config/ia64/ia64-common.c: Moved to...
* common/config/ia64/ia64-common.cc: ...here.
* common/config/iq2000/iq2000-common.c: Moved to...
* common/config/iq2000/iq2000-common.cc: ...here.
* common/config/lm32/lm32-common.c: Moved to...
* common/config/lm32/lm32-common.cc: ...here.
* common/config/m32r/m32r-common.c: Moved to...
* common/config/m32r/m32r-common.cc: ...here.
* common/config/m68k/m68k-common.c: Moved to...
* common/config/m68k/m68k-common.cc: ...here.
* common/config/mcore/mcore-common.c: Moved to...
* common/config/mcore/mcore-common.cc: ...here.
* common/config/microblaze/microblaze-common.c: Moved to...
* common/config/microblaze/microblaze-common.cc: ...here.
* common/config/mips/mips-common.c: Moved to...
* common/config/mips/mips-common.cc: ...here.
* common/config/mmix/mmix-common.c: Moved to...
* common/config/mmix/mmix-common.cc: ...here.
* common/config/mn10300/mn10300-common.c: Moved to...
* common/config/mn10300/mn10300-common.cc: ...here.
* common/config/msp430/msp430-common.c: Moved to...
* common/config/msp430/msp430-common.cc: ...here.
* common/config/nds32/nds32-common.c: Moved to...
* common/config/nds32/nds32-common.cc: ...here.
* common/config/nios2/nios2-common.c: Moved to...
* common/config/nios2/nios2-common.cc: ...here.
* common/config/nvptx/nvptx-common.c: Moved to...
* common/config/nvptx/nvptx-common.cc: ...here.
* common/config/or1k/or1k-common.c: Moved to...
* common/config/or1k/or1k-common.cc: ...here.
* common/config/pa/pa-common.c: Moved to...
* common/config/pa/pa-common.cc: ...here.
* common/config/pdp11/pdp11-common.c: Moved to...
* common/config/pdp11/pdp11-common.cc: ...here.
* common/config/pru/pru-common.c: Moved to...
* common/config/pru/pru-common.cc: ...here.
* common/config/riscv/riscv-common.c: Moved to...
* common/config/riscv/riscv-common.cc: ...here.
* common/config/rs6000/rs6000-common.c: Moved to...
* common/config/rs6000/rs6000-common.cc: ...here.
* common/config/rx/rx-common.c: Moved to...
* common/config/rx/rx-common.cc: ...here.
* common/config/s390/s390-common.c: Moved to...
* common/config/s390/s390-common.cc: ...here.
* common/config/sh/sh-common.c: Moved to...
* common/config/sh/sh-common.cc: ...here.
* common/config/sparc/sparc-common.c: Moved to...
* common/config/sparc/sparc-common.cc: ...here.
* common/config/tilegx/tilegx-common.c: Moved to...
* common/config/tilegx/tilegx-common.cc: ...here.
* common/config/tilepro/tilepro-common.c: Moved to...
* common/config/tilepro/tilepro-common.cc: ...here.
* common/config/v850/v850-common.c: Moved to...
* common/config/v850/v850-common.cc: ...here.
* common/config/vax/vax-common.c: Moved to...
* common/config/vax/vax-common.cc: ...here.
* common/config/visium/visium-common.c: Moved to...
* common/config/visium/visium-common.cc: ...here.
* common/config/xstormy16/xstormy16-common.c: Moved to...
* common/config/xstormy16/xstormy16-common.cc: ...here.
* common/config/xtensa/xtensa-common.c: Moved to...
* common/config/xtensa/xtensa-common.cc: ...here.
* compare-elim.c: Moved to...
* compare-elim.cc: ...here.
* config/aarch64/aarch64-bti-insert.c: Moved to...
* config/aarch64/aarch64-bti-insert.cc: ...here.
* config/aarch64/aarch64-builtins.c: Moved to...
* config/aarch64/aarch64-builtins.cc: ...here.
* config/aarch64/aarch64-c.c: Moved to...
* config/aarch64/aarch64-c.cc: ...here.
* config/aarch64/aarch64-d.c: Moved to...
* config/aarch64/aarch64-d.cc: ...here.
* config/aarch64/aarch64.c: Moved to...
* config/aarch64/aarch64.cc: ...here.
* config/aarch64/cortex-a57-fma-steering.c: Moved to...
* config/aarch64/cortex-a57-fma-steering.cc: ...here.
* config/aarch64/driver-aarch64.c: Moved to...
* config/aarch64/driver-aarch64.cc: ...here.
* config/aarch64/falkor-tag-collision-avoidance.c: Moved to...
* config/aarch64/falkor-tag-collision-avoidance.cc: ...here.
* config/aarch64/host-aarch64-darwin.c: Moved to...
* config/aarch64/host-aarch64-darwin.cc: ...here.
* config/alpha/alpha.c: Moved to...
* config/alpha/alpha.cc: ...here.
* config/alpha/driver-alpha.c: Moved to...
* config/alpha/driver-alpha.cc: ...here.
* config/arc/arc-c.c: Moved to...
* config/arc/arc-c.cc: ...here.
* config/arc/arc.c: Moved to...
* config/arc/arc.cc: ...here.
* config/arc/driver-arc.c: Moved to...
* config/arc/driver-arc.cc: ...here.
* config/arm/aarch-common.c: Moved to...
* config/arm/aarch-common.cc: ...here.
* config/arm/arm-builtins.c: Moved to...
* config/arm/arm-builtins.cc: ...here.
* config/arm/arm-c.c: Moved to...
* config/arm/arm-c.cc: ...here.
* config/arm/arm-d.c: Moved to...
* config/arm/arm-d.cc: ...here.
* config/arm/arm.c: Moved to...
* config/arm/arm.cc: ...here.
* config/arm/driver-arm.c: Moved to...
* config/arm/driver-arm.cc: ...here.
* config/avr/avr-c.c: Moved to...
* config/avr/avr-c.cc: ...here.
* config/avr/avr-devices.c: Moved to...
* config/avr/avr-devices.cc: ...here.
* config/avr/avr-log.c: Moved to...
* config/avr/avr-log.cc: ...here.
* config/avr/avr.c: Moved to...
* config/avr/avr.cc: ...here.
* config/avr/driver-avr.c: Moved to...
* config/avr/driver-avr.cc: ...here.
* config/avr/gen-avr-mmcu-specs.c: Moved to...
* config/avr/gen-avr-mmcu-specs.cc: ...here.
* config/avr/gen-avr-mmcu-texi.c: Moved to...
* config/avr/gen-avr-mmcu-texi.cc: ...here.
* config/bfin/bfin.c: Moved to...
* config/bfin/bfin.cc: ...here.
* config/bpf/bpf.c: Moved to...
* config/bpf/bpf.cc: ...here.
* config/bpf/coreout.c: Moved to...
* config/bpf/coreout.cc: ...here.
* config/c6x/c6x.c: Moved to...
* config/c6x/c6x.cc: ...here.
* config/cr16/cr16.c: Moved to...
* config/cr16/cr16.cc: ...here.
* config/cris/cris.c: Moved to...
* config/cris/cris.cc: ...here.
* config/csky/csky.c: Moved to...
* config/csky/csky.cc: ...here.
* config/darwin-c.c: Moved to...
* config/darwin-c.cc: ...here.
* config/darwin-d.c: Moved to...
* config/darwin-d.cc: ...here.
* config/darwin-driver.c: Moved to...
* config/darwin-driver.cc: ...here.
* config/darwin-f.c: Moved to...
* config/darwin-f.cc: ...here.
* config/darwin.c: Moved to...
* config/darwin.cc: ...here.
* config/default-c.c: Moved to...
* config/default-c.cc: ...here.
* config/default-d.c: Moved to...
* config/default-d.cc: ...here.
* config/dragonfly-d.c: Moved to...
* config/dragonfly-d.cc: ...here.
* config/epiphany/epiphany.c: Moved to...
* config/epiphany/epiphany.cc: ...here.
* config/epiphany/mode-switch-use.c: Moved to...
* config/epiphany/mode-switch-use.cc: ...here.
* config/epiphany/resolve-sw-modes.c: Moved to...
* config/epiphany/resolve-sw-modes.cc: ...here.
* config/fr30/fr30.c: Moved to...
* config/fr30/fr30.cc: ...here.
* config/freebsd-d.c: Moved to...
* config/freebsd-d.cc: ...here.
* config/frv/frv.c: Moved to...
* config/frv/frv.cc: ...here.
* config/ft32/ft32.c: Moved to...
* config/ft32/ft32.cc: ...here.
* config/gcn/driver-gcn.c: Moved to...
* config/gcn/driver-gcn.cc: ...here.
* config/gcn/gcn-run.c: Moved to...
* config/gcn/gcn-run.cc: ...here.
* config/gcn/gcn-tree.c: Moved to...
* config/gcn/gcn-tree.cc: ...here.
* config/gcn/gcn.c: Moved to...
* config/gcn/gcn.cc: ...here.
* config/gcn/mkoffload.c: Moved to...
* config/gcn/mkoffload.cc: ...here.
* config/glibc-c.c: Moved to...
* config/glibc-c.cc: ...here.
* config/glibc-d.c: Moved to...
* config/glibc-d.cc: ...here.
* config/h8300/h8300.c: Moved to...
* config/h8300/h8300.cc: ...here.
* config/host-darwin.c: Moved to...
* config/host-darwin.cc: ...here.
* config/host-hpux.c: Moved to...
* config/host-hpux.cc: ...here.
* config/host-linux.c: Moved to...
* config/host-linux.cc: ...here.
* config/host-netbsd.c: Moved to...
* config/host-netbsd.cc: ...here.
* config/host-openbsd.c: Moved to...
* config/host-openbsd.cc: ...here.
* config/host-solaris.c: Moved to...
* config/host-solaris.cc: ...here.
* config/i386/djgpp.c: Moved to...
* config/i386/djgpp.cc: ...here.
* config/i386/driver-i386.c: Moved to...
* config/i386/driver-i386.cc: ...here.
* config/i386/driver-mingw32.c: Moved to...
* config/i386/driver-mingw32.cc: ...here.
* config/i386/gnu-property.c: Moved to...
* config/i386/gnu-property.cc: ...here.
* config/i386/host-cygwin.c: Moved to...
* config/i386/host-cygwin.cc: ...here.
* config/i386/host-i386-darwin.c: Moved to...
* config/i386/host-i386-darwin.cc: ...here.
* config/i386/host-mingw32.c: Moved to...
* config/i386/host-mingw32.cc: ...here.
* config/i386/i386-builtins.c: Moved to...
* config/i386/i386-builtins.cc: ...here.
* config/i386/i386-c.c: Moved to...
* config/i386/i386-c.cc: ...here.
* config/i386/i386-d.c: Moved to...
* config/i386/i386-d.cc: ...here.
* config/i386/i386-expand.c: Moved to...
* config/i386/i386-expand.cc: ...here.
* config/i386/i386-features.c: Moved to...
* config/i386/i386-features.cc: ...here.
* config/i386/i386-options.c: Moved to...
* config/i386/i386-options.cc: ...here.
* config/i386/i386.c: Moved to...
* config/i386/i386.cc: ...here.
* config/i386/intelmic-mkoffload.c: Moved to...
* config/i386/intelmic-mkoffload.cc: ...here.
* config/i386/msformat-c.c: Moved to...
* config/i386/msformat-c.cc: ...here.
* config/i386/winnt-cxx.c: Moved to...
* config/i386/winnt-cxx.cc: ...here.
* config/i386/winnt-d.c: Moved to...
* config/i386/winnt-d.cc: ...here.
* config/i386/winnt-stubs.c: Moved to...
* config/i386/winnt-stubs.cc: ...here.
* config/i386/winnt.c: Moved to...
* config/i386/winnt.cc: ...here.
* config/i386/x86-tune-sched-atom.c: Moved to...
* config/i386/x86-tune-sched-atom.cc: ...here.
* config/i386/x86-tune-sched-bd.c: Moved to...
* config/i386/x86-tune-sched-bd.cc: ...here.
* config/i386/x86-tune-sched-core.c: Moved to...
* config/i386/x86-tune-sched-core.cc: ...here.
* config/i386/x86-tune-sched.c: Moved to...
* config/i386/x86-tune-sched.cc: ...here.
* config/ia64/ia64-c.c: Moved to...
* config/ia64/ia64-c.cc: ...here.
* config/ia64/ia64.c: Moved to...
* config/ia64/ia64.cc: ...here.
* config/iq2000/iq2000.c: Moved to...
* config/iq2000/iq2000.cc: ...here.
* config/linux.c: Moved to...
* config/linux.cc: ...here.
* config/lm32/lm32.c: Moved to...
* config/lm32/lm32.cc: ...here.
* config/m32c/m32c-pragma.c: Moved to...
* config/m32c/m32c-pragma.cc: ...here.
* config/m32c/m32c.c: Moved to...
* config/m32c/m32c.cc: ...here.
* config/m32r/m32r.c: Moved to...
* config/m32r/m32r.cc: ...here.
* config/m68k/m68k.c: Moved to...
* config/m68k/m68k.cc: ...here.
* config/mcore/mcore.c: Moved to...
* config/mcore/mcore.cc: ...here.
* config/microblaze/microblaze-c.c: Moved to...
* config/microblaze/microblaze-c.cc: ...here.
* config/microblaze/microblaze.c: Moved to...
* config/microblaze/microblaze.cc: ...here.
* config/mips/driver-native.c: Moved to...
* config/mips/driver-native.cc: ...here.
* config/mips/frame-header-opt.c: Moved to...
* config/mips/frame-header-opt.cc: ...here.
* config/mips/mips-d.c: Moved to...
* config/mips/mips-d.cc: ...here.
* config/mips/mips.c: Moved to...
* config/mips/mips.cc: ...here.
* config/mmix/mmix.c: Moved to...
* config/mmix/mmix.cc: ...here.
* config/mn10300/mn10300.c: Moved to...
* config/mn10300/mn10300.cc: ...here.
* config/moxie/moxie.c: Moved to...
* config/moxie/moxie.cc: ...here.
* config/msp430/driver-msp430.c: Moved to...
* config/msp430/driver-msp430.cc: ...here.
* config/msp430/msp430-c.c: Moved to...
* config/msp430/msp430-c.cc: ...here.
* config/msp430/msp430-devices.c: Moved to...
* config/msp430/msp430-devices.cc: ...here.
* config/msp430/msp430.c: Moved to...
* config/msp430/msp430.cc: ...here.
* config/nds32/nds32-cost.c: Moved to...
* config/nds32/nds32-cost.cc: ...here.
* config/nds32/nds32-fp-as-gp.c: Moved to...
* config/nds32/nds32-fp-as-gp.cc: ...here.
* config/nds32/nds32-intrinsic.c: Moved to...
* config/nds32/nds32-intrinsic.cc: ...here.
* config/nds32/nds32-isr.c: Moved to...
* config/nds32/nds32-isr.cc: ...here.
* config/nds32/nds32-md-auxiliary.c: Moved to...
* config/nds32/nds32-md-auxiliary.cc: ...here.
* config/nds32/nds32-memory-manipulation.c: Moved to...
* config/nds32/nds32-memory-manipulation.cc: ...here.
* config/nds32/nds32-pipelines-auxiliary.c: Moved to...
* config/nds32/nds32-pipelines-auxiliary.cc: ...here.
* config/nds32/nds32-predicates.c: Moved to...
* config/nds32/nds32-predicates.cc: ...here.
* config/nds32/nds32-relax-opt.c: Moved to...
* config/nds32/nds32-relax-opt.cc: ...here.
* config/nds32/nds32-utils.c: Moved to...
* config/nds32/nds32-utils.cc: ...here.
* config/nds32/nds32.c: Moved to...
* config/nds32/nds32.cc: ...here.
* config/netbsd-d.c: Moved to...
* config/netbsd-d.cc: ...here.
* config/netbsd.c: Moved to...
* config/netbsd.cc: ...here.
* config/nios2/nios2.c: Moved to...
* config/nios2/nios2.cc: ...here.
* config/nvptx/mkoffload.c: Moved to...
* config/nvptx/mkoffload.cc: ...here.
* config/nvptx/nvptx-c.c: Moved to...
* config/nvptx/nvptx-c.cc: ...here.
* config/nvptx/nvptx.c: Moved to...
* config/nvptx/nvptx.cc: ...here.
* config/openbsd-d.c: Moved to...
* config/openbsd-d.cc: ...here.
* config/or1k/or1k.c: Moved to...
* config/or1k/or1k.cc: ...here.
* config/pa/pa-d.c: Moved to...
* config/pa/pa-d.cc: ...here.
* config/pa/pa.c: Moved to...
* config/pa/pa.cc: ...here.
* config/pdp11/pdp11.c: Moved to...
* config/pdp11/pdp11.cc: ...here.
* config/pru/pru-passes.c: Moved to...
* config/pru/pru-passes.cc: ...here.
* config/pru/pru-pragma.c: Moved to...
* config/pru/pru-pragma.cc: ...here.
* config/pru/pru.c: Moved to...
* config/pru/pru.cc: ...here.
* config/riscv/riscv-builtins.c: Moved to...
* config/riscv/riscv-builtins.cc: ...here.
* config/riscv/riscv-c.c: Moved to...
* config/riscv/riscv-c.cc: ...here.
* config/riscv/riscv-d.c: Moved to...
* config/riscv/riscv-d.cc: ...here.
* config/riscv/riscv-shorten-memrefs.c: Moved to...
* config/riscv/riscv-shorten-memrefs.cc: ...here.
* config/riscv/riscv-sr.c: Moved to...
* config/riscv/riscv-sr.cc: ...here.
* config/riscv/riscv.c: Moved to...
* config/riscv/riscv.cc: ...here.
* config/rl78/rl78-c.c: Moved to...
* config/rl78/rl78-c.cc: ...here.
* config/rl78/rl78.c: Moved to...
* config/rl78/rl78.cc: ...here.
* config/rs6000/driver-rs6000.c: Moved to...
* config/rs6000/driver-rs6000.cc: ...here.
* config/rs6000/host-darwin.c: Moved to...
* config/rs6000/host-darwin.cc: ...here.
* config/rs6000/host-ppc64-darwin.c: Moved to...
* config/rs6000/host-ppc64-darwin.cc: ...here.
* config/rs6000/rbtree.c: Moved to...
* config/rs6000/rbtree.cc: ...here.
* config/rs6000/rs6000-c.c: Moved to...
* config/rs6000/rs6000-c.cc: ...here.
* config/rs6000/rs6000-call.c: Moved to...
* config/rs6000/rs6000-call.cc: ...here.
* config/rs6000/rs6000-d.c: Moved to...
* config/rs6000/rs6000-d.cc: ...here.
* config/rs6000/rs6000-gen-builtins.c: Moved to...
* config/rs6000/rs6000-gen-builtins.cc: ...here.
* config/rs6000/rs6000-linux.c: Moved to...
* config/rs6000/rs6000-linux.cc: ...here.
* config/rs6000/rs6000-logue.c: Moved to...
* config/rs6000/rs6000-logue.cc: ...here.
* config/rs6000/rs6000-p8swap.c: Moved to...
* config/rs6000/rs6000-p8swap.cc: ...here.
* config/rs6000/rs6000-pcrel-opt.c: Moved to...
* config/rs6000/rs6000-pcrel-opt.cc: ...here.
* config/rs6000/rs6000-string.c: Moved to...
* config/rs6000/rs6000-string.cc: ...here.
* config/rs6000/rs6000.c: Moved to...
* config/rs6000/rs6000.cc: ...here.
* config/rx/rx.c: Moved to...
* config/rx/rx.cc: ...here.
* config/s390/driver-native.c: Moved to...
* config/s390/driver-native.cc: ...here.
* config/s390/s390-c.c: Moved to...
* config/s390/s390-c.cc: ...here.
* config/s390/s390-d.c: Moved to...
* config/s390/s390-d.cc: ...here.
* config/s390/s390.c: Moved to...
* config/s390/s390.cc: ...here.
* config/sh/divtab-sh4-300.c: Moved to...
* config/sh/divtab-sh4-300.cc: ...here.
* config/sh/divtab-sh4.c: Moved to...
* config/sh/divtab-sh4.cc: ...here.
* config/sh/divtab.c: Moved to...
* config/sh/divtab.cc: ...here.
* config/sh/sh-c.c: Moved to...
* config/sh/sh-c.cc: ...here.
* config/sh/sh.c: Moved to...
* config/sh/sh.cc: ...here.
* config/sol2-c.c: Moved to...
* config/sol2-c.cc: ...here.
* config/sol2-cxx.c: Moved to...
* config/sol2-cxx.cc: ...here.
* config/sol2-d.c: Moved to...
* config/sol2-d.cc: ...here.
* config/sol2-stubs.c: Moved to...
* config/sol2-stubs.cc: ...here.
* config/sol2.c: Moved to...
* config/sol2.cc: ...here.
* config/sparc/driver-sparc.c: Moved to...
* config/sparc/driver-sparc.cc: ...here.
* config/sparc/sparc-c.c: Moved to...
* config/sparc/sparc-c.cc: ...here.
* config/sparc/sparc-d.c: Moved to...
* config/sparc/sparc-d.cc: ...here.
* config/sparc/sparc.c: Moved to...
* config/sparc/sparc.cc: ...here.
* config/stormy16/stormy16.c: Moved to...
* config/stormy16/stormy16.cc: ...here.
* config/tilegx/mul-tables.c: Moved to...
* config/tilegx/mul-tables.cc: ...here.
* config/tilegx/tilegx-c.c: Moved to...
* config/tilegx/tilegx-c.cc: ...here.
* config/tilegx/tilegx.c: Moved to...
* config/tilegx/tilegx.cc: ...here.
* config/tilepro/mul-tables.c: Moved to...
* config/tilepro/mul-tables.cc: ...here.
* config/tilepro/tilepro-c.c: Moved to...
* config/tilepro/tilepro-c.cc: ...here.
* config/tilepro/tilepro.c: Moved to...
* config/tilepro/tilepro.cc: ...here.
* config/v850/v850-c.c: Moved to...
* config/v850/v850-c.cc: ...here.
* config/v850/v850.c: Moved to...
* config/v850/v850.cc: ...here.
* config/vax/vax.c: Moved to...
* config/vax/vax.cc: ...here.
* config/visium/visium.c: Moved to...
* config/visium/visium.cc: ...here.
* config/vms/vms-c.c: Moved to...
* config/vms/vms-c.cc: ...here.
* config/vms/vms-f.c: Moved to...
* config/vms/vms-f.cc: ...here.
* config/vms/vms.c: Moved to...
* config/vms/vms.cc: ...here.
* config/vxworks-c.c: Moved to...
* config/vxworks-c.cc: ...here.
* config/vxworks.c: Moved to...
* config/vxworks.cc: ...here.
* config/winnt-c.c: Moved to...
* config/winnt-c.cc: ...here.
* config/xtensa/xtensa.c: Moved to...
* config/xtensa/xtensa.cc: ...here.
* context.c: Moved to...
* context.cc: ...here.
* convert.c: Moved to...
* convert.cc: ...here.
* coverage.c: Moved to...
* coverage.cc: ...here.
* cppbuiltin.c: Moved to...
* cppbuiltin.cc: ...here.
* cppdefault.c: Moved to...
* cppdefault.cc: ...here.
* cprop.c: Moved to...
* cprop.cc: ...here.
* cse.c: Moved to...
* cse.cc: ...here.
* cselib.c: Moved to...
* cselib.cc: ...here.
* ctfc.c: Moved to...
* ctfc.cc: ...here.
* ctfout.c: Moved to...
* ctfout.cc: ...here.
* data-streamer-in.c: Moved to...
* data-streamer-in.cc: ...here.
* data-streamer-out.c: Moved to...
* data-streamer-out.cc: ...here.
* data-streamer.c: Moved to...
* data-streamer.cc: ...here.
* dbgcnt.c: Moved to...
* dbgcnt.cc: ...here.
* dbxout.c: Moved to...
* dbxout.cc: ...here.
* dce.c: Moved to...
* dce.cc: ...here.
* ddg.c: Moved to...
* ddg.cc: ...here.
* debug.c: Moved to...
* debug.cc: ...here.
* df-core.c: Moved to...
* df-core.cc: ...here.
* df-problems.c: Moved to...
* df-problems.cc: ...here.
* df-scan.c: Moved to...
* df-scan.cc: ...here.
* dfp.c: Moved to...
* dfp.cc: ...here.
* diagnostic-color.c: Moved to...
* diagnostic-color.cc: ...here.
* diagnostic-show-locus.c: Moved to...
* diagnostic-show-locus.cc: ...here.
* diagnostic-spec.c: Moved to...
* diagnostic-spec.cc: ...here.
* diagnostic.c: Moved to...
* diagnostic.cc: ...here.
* dojump.c: Moved to...
* dojump.cc: ...here.
* dominance.c: Moved to...
* dominance.cc: ...here.
* domwalk.c: Moved to...
* domwalk.cc: ...here.
* double-int.c: Moved to...
* double-int.cc: ...here.
* dse.c: Moved to...
* dse.cc: ...here.
* dumpfile.c: Moved to...
* dumpfile.cc: ...here.
* dwarf2asm.c: Moved to...
* dwarf2asm.cc: ...here.
* dwarf2cfi.c: Moved to...
* dwarf2cfi.cc: ...here.
* dwarf2ctf.c: Moved to...
* dwarf2ctf.cc: ...here.
* dwarf2out.c: Moved to...
* dwarf2out.cc: ...here.
* early-remat.c: Moved to...
* early-remat.cc: ...here.
* edit-context.c: Moved to...
* edit-context.cc: ...here.
* emit-rtl.c: Moved to...
* emit-rtl.cc: ...here.
* errors.c: Moved to...
* errors.cc: ...here.
* et-forest.c: Moved to...
* et-forest.cc: ...here.
* except.c: Moved to...
* except.cc: ...here.
* explow.c: Moved to...
* explow.cc: ...here.
* expmed.c: Moved to...
* expmed.cc: ...here.
* expr.c: Moved to...
* expr.cc: ...here.
* fibonacci_heap.c: Moved to...
* fibonacci_heap.cc: ...here.
* file-find.c: Moved to...
* file-find.cc: ...here.
* file-prefix-map.c: Moved to...
* file-prefix-map.cc: ...here.
* final.c: Moved to...
* final.cc: ...here.
* fixed-value.c: Moved to...
* fixed-value.cc: ...here.
* fold-const-call.c: Moved to...
* fold-const-call.cc: ...here.
* fold-const.c: Moved to...
* fold-const.cc: ...here.
* fp-test.c: Moved to...
* fp-test.cc: ...here.
* function-tests.c: Moved to...
* function-tests.cc: ...here.
* function.c: Moved to...
* function.cc: ...here.
* fwprop.c: Moved to...
* fwprop.cc: ...here.
* gcc-ar.c: Moved to...
* gcc-ar.cc: ...here.
* gcc-main.c: Moved to...
* gcc-main.cc: ...here.
* gcc-rich-location.c: Moved to...
* gcc-rich-location.cc: ...here.
* gcc.c: Moved to...
* gcc.cc: ...here.
* gcov-dump.c: Moved to...
* gcov-dump.cc: ...here.
* gcov-io.c: Moved to...
* gcov-io.cc: ...here.
* gcov-tool.c: Moved to...
* gcov-tool.cc: ...here.
* gcov.c: Moved to...
* gcov.cc: ...here.
* gcse-common.c: Moved to...
* gcse-common.cc: ...here.
* gcse.c: Moved to...
* gcse.cc: ...here.
* genattr-common.c: Moved to...
* genattr-common.cc: ...here.
* genattr.c: Moved to...
* genattr.cc: ...here.
* genattrtab.c: Moved to...
* genattrtab.cc: ...here.
* genautomata.c: Moved to...
* genautomata.cc: ...here.
* gencfn-macros.c: Moved to...
* gencfn-macros.cc: ...here.
* gencheck.c: Moved to...
* gencheck.cc: ...here.
* genchecksum.c: Moved to...
* genchecksum.cc: ...here.
* gencodes.c: Moved to...
* gencodes.cc: ...here.
* genconditions.c: Moved to...
* genconditions.cc: ...here.
* genconfig.c: Moved to...
* genconfig.cc: ...here.
* genconstants.c: Moved to...
* genconstants.cc: ...here.
* genemit.c: Moved to...
* genemit.cc: ...here.
* genenums.c: Moved to...
* genenums.cc: ...here.
* generic-match-head.c: Moved to...
* generic-match-head.cc: ...here.
* genextract.c: Moved to...
* genextract.cc: ...here.
* genflags.c: Moved to...
* genflags.cc: ...here.
* gengenrtl.c: Moved to...
* gengenrtl.cc: ...here.
* gengtype-parse.c: Moved to...
* gengtype-parse.cc: ...here.
* gengtype-state.c: Moved to...
* gengtype-state.cc: ...here.
* gengtype.c: Moved to...
* gengtype.cc: ...here.
* genhooks.c: Moved to...
* genhooks.cc: ...here.
* genmatch.c: Moved to...
* genmatch.cc: ...here.
* genmddeps.c: Moved to...
* genmddeps.cc: ...here.
* genmddump.c: Moved to...
* genmddump.cc: ...here.
* genmodes.c: Moved to...
* genmodes.cc: ...here.
* genopinit.c: Moved to...
* genopinit.cc: ...here.
* genoutput.c: Moved to...
* genoutput.cc: ...here.
* genpeep.c: Moved to...
* genpeep.cc: ...here.
* genpreds.c: Moved to...
* genpreds.cc: ...here.
* genrecog.c: Moved to...
* genrecog.cc: ...here.
* gensupport.c: Moved to...
* gensupport.cc: ...here.
* gentarget-def.c: Moved to...
* gentarget-def.cc: ...here.
* genversion.c: Moved to...
* genversion.cc: ...here.
* ggc-common.c: Moved to...
* ggc-common.cc: ...here.
* ggc-none.c: Moved to...
* ggc-none.cc: ...here.
* ggc-page.c: Moved to...
* ggc-page.cc: ...here.
* ggc-tests.c: Moved to...
* ggc-tests.cc: ...here.
* gimple-builder.c: Moved to...
* gimple-builder.cc: ...here.
* gimple-expr.c: Moved to...
* gimple-expr.cc: ...here.
* gimple-fold.c: Moved to...
* gimple-fold.cc: ...here.
* gimple-iterator.c: Moved to...
* gimple-iterator.cc: ...here.
* gimple-laddress.c: Moved to...
* gimple-laddress.cc: ...here.
* gimple-loop-jam.c: Moved to...
* gimple-loop-jam.cc: ...here.
* gimple-low.c: Moved to...
* gimple-low.cc: ...here.
* gimple-match-head.c: Moved to...
* gimple-match-head.cc: ...here.
* gimple-pretty-print.c: Moved to...
* gimple-pretty-print.cc: ...here.
* gimple-ssa-backprop.c: Moved to...
* gimple-ssa-backprop.cc: ...here.
* gimple-ssa-evrp-analyze.c: Moved to...
* gimple-ssa-evrp-analyze.cc: ...here.
* gimple-ssa-evrp.c: Moved to...
* gimple-ssa-evrp.cc: ...here.
* gimple-ssa-isolate-paths.c: Moved to...
* gimple-ssa-isolate-paths.cc: ...here.
* gimple-ssa-nonnull-compare.c: Moved to...
* gimple-ssa-nonnull-compare.cc: ...here.
* gimple-ssa-split-paths.c: Moved to...
* gimple-ssa-split-paths.cc: ...here.
* gimple-ssa-sprintf.c: Moved to...
* gimple-ssa-sprintf.cc: ...here.
* gimple-ssa-store-merging.c: Moved to...
* gimple-ssa-store-merging.cc: ...here.
* gimple-ssa-strength-reduction.c: Moved to...
* gimple-ssa-strength-reduction.cc: ...here.
* gimple-ssa-warn-alloca.c: Moved to...
* gimple-ssa-warn-alloca.cc: ...here.
* gimple-ssa-warn-restrict.c: Moved to...
* gimple-ssa-warn-restrict.cc: ...here.
* gimple-streamer-in.c: Moved to...
* gimple-streamer-in.cc: ...here.
* gimple-streamer-out.c: Moved to...
* gimple-streamer-out.cc: ...here.
* gimple-walk.c: Moved to...
* gimple-walk.cc: ...here.
* gimple-warn-recursion.c: Moved to...
* gimple-warn-recursion.cc: ...here.
* gimple.c: Moved to...
* gimple.cc: ...here.
* gimplify-me.c: Moved to...
* gimplify-me.cc: ...here.
* gimplify.c: Moved to...
* gimplify.cc: ...here.
* godump.c: Moved to...
* godump.cc: ...here.
* graph.c: Moved to...
* graph.cc: ...here.
* graphds.c: Moved to...
* graphds.cc: ...here.
* graphite-dependences.c: Moved to...
* graphite-dependences.cc: ...here.
* graphite-isl-ast-to-gimple.c: Moved to...
* graphite-isl-ast-to-gimple.cc: ...here.
* graphite-optimize-isl.c: Moved to...
* graphite-optimize-isl.cc: ...here.
* graphite-poly.c: Moved to...
* graphite-poly.cc: ...here.
* graphite-scop-detection.c: Moved to...
* graphite-scop-detection.cc: ...here.
* graphite-sese-to-poly.c: Moved to...
* graphite-sese-to-poly.cc: ...here.
* graphite.c: Moved to...
* graphite.cc: ...here.
* haifa-sched.c: Moved to...
* haifa-sched.cc: ...here.
* hash-map-tests.c: Moved to...
* hash-map-tests.cc: ...here.
* hash-set-tests.c: Moved to...
* hash-set-tests.cc: ...here.
* hash-table.c: Moved to...
* hash-table.cc: ...here.
* hooks.c: Moved to...
* hooks.cc: ...here.
* host-default.c: Moved to...
* host-default.cc: ...here.
* hw-doloop.c: Moved to...
* hw-doloop.cc: ...here.
* hwint.c: Moved to...
* hwint.cc: ...here.
* ifcvt.c: Moved to...
* ifcvt.cc: ...here.
* inchash.c: Moved to...
* inchash.cc: ...here.
* incpath.c: Moved to...
* incpath.cc: ...here.
* init-regs.c: Moved to...
* init-regs.cc: ...here.
* input.c: Moved to...
* input.cc: ...here.
* internal-fn.c: Moved to...
* internal-fn.cc: ...here.
* intl.c: Moved to...
* intl.cc: ...here.
* ipa-comdats.c: Moved to...
* ipa-comdats.cc: ...here.
* ipa-cp.c: Moved to...
* ipa-cp.cc: ...here.
* ipa-devirt.c: Moved to...
* ipa-devirt.cc: ...here.
* ipa-fnsummary.c: Moved to...
* ipa-fnsummary.cc: ...here.
* ipa-icf-gimple.c: Moved to...
* ipa-icf-gimple.cc: ...here.
* ipa-icf.c: Moved to...
* ipa-icf.cc: ...here.
* ipa-inline-analysis.c: Moved to...
* ipa-inline-analysis.cc: ...here.
* ipa-inline-transform.c: Moved to...
* ipa-inline-transform.cc: ...here.
* ipa-inline.c: Moved to...
* ipa-inline.cc: ...here.
* ipa-modref-tree.c: Moved to...
* ipa-modref-tree.cc: ...here.
* ipa-modref.c: Moved to...
* ipa-modref.cc: ...here.
* ipa-param-manipulation.c: Moved to...
* ipa-param-manipulation.cc: ...here.
* ipa-polymorphic-call.c: Moved to...
* ipa-polymorphic-call.cc: ...here.
* ipa-predicate.c: Moved to...
* ipa-predicate.cc: ...here.
* ipa-profile.c: Moved to...
* ipa-profile.cc: ...here.
* ipa-prop.c: Moved to...
* ipa-prop.cc: ...here.
* ipa-pure-const.c: Moved to...
* ipa-pure-const.cc: ...here.
* ipa-ref.c: Moved to...
* ipa-ref.cc: ...here.
* ipa-reference.c: Moved to...
* ipa-reference.cc: ...here.
* ipa-split.c: Moved to...
* ipa-split.cc: ...here.
* ipa-sra.c: Moved to...
* ipa-sra.cc: ...here.
* ipa-utils.c: Moved to...
* ipa-utils.cc: ...here.
* ipa-visibility.c: Moved to...
* ipa-visibility.cc: ...here.
* ipa.c: Moved to...
* ipa.cc: ...here.
* ira-build.c: Moved to...
* ira-build.cc: ...here.
* ira-color.c: Moved to...
* ira-color.cc: ...here.
* ira-conflicts.c: Moved to...
* ira-conflicts.cc: ...here.
* ira-costs.c: Moved to...
* ira-costs.cc: ...here.
* ira-emit.c: Moved to...
* ira-emit.cc: ...here.
* ira-lives.c: Moved to...
* ira-lives.cc: ...here.
* ira.c: Moved to...
* ira.cc: ...here.
* jump.c: Moved to...
* jump.cc: ...here.
* langhooks.c: Moved to...
* langhooks.cc: ...here.
* lcm.c: Moved to...
* lcm.cc: ...here.
* lists.c: Moved to...
* lists.cc: ...here.
* loop-doloop.c: Moved to...
* loop-doloop.cc: ...here.
* loop-init.c: Moved to...
* loop-init.cc: ...here.
* loop-invariant.c: Moved to...
* loop-invariant.cc: ...here.
* loop-iv.c: Moved to...
* loop-iv.cc: ...here.
* loop-unroll.c: Moved to...
* loop-unroll.cc: ...here.
* lower-subreg.c: Moved to...
* lower-subreg.cc: ...here.
* lra-assigns.c: Moved to...
* lra-assigns.cc: ...here.
* lra-coalesce.c: Moved to...
* lra-coalesce.cc: ...here.
* lra-constraints.c: Moved to...
* lra-constraints.cc: ...here.
* lra-eliminations.c: Moved to...
* lra-eliminations.cc: ...here.
* lra-lives.c: Moved to...
* lra-lives.cc: ...here.
* lra-remat.c: Moved to...
* lra-remat.cc: ...here.
* lra-spills.c: Moved to...
* lra-spills.cc: ...here.
* lra.c: Moved to...
* lra.cc: ...here.
* lto-cgraph.c: Moved to...
* lto-cgraph.cc: ...here.
* lto-compress.c: Moved to...
* lto-compress.cc: ...here.
* lto-opts.c: Moved to...
* lto-opts.cc: ...here.
* lto-section-in.c: Moved to...
* lto-section-in.cc: ...here.
* lto-section-out.c: Moved to...
* lto-section-out.cc: ...here.
* lto-streamer-in.c: Moved to...
* lto-streamer-in.cc: ...here.
* lto-streamer-out.c: Moved to...
* lto-streamer-out.cc: ...here.
* lto-streamer.c: Moved to...
* lto-streamer.cc: ...here.
* lto-wrapper.c: Moved to...
* lto-wrapper.cc: ...here.
* main.c: Moved to...
* main.cc: ...here.
* mcf.c: Moved to...
* mcf.cc: ...here.
* mode-switching.c: Moved to...
* mode-switching.cc: ...here.
* modulo-sched.c: Moved to...
* modulo-sched.cc: ...here.
* multiple_target.c: Moved to...
* multiple_target.cc: ...here.
* omp-expand.c: Moved to...
* omp-expand.cc: ...here.
* omp-general.c: Moved to...
* omp-general.cc: ...here.
* omp-low.c: Moved to...
* omp-low.cc: ...here.
* omp-offload.c: Moved to...
* omp-offload.cc: ...here.
* omp-simd-clone.c: Moved to...
* omp-simd-clone.cc: ...here.
* opt-suggestions.c: Moved to...
* opt-suggestions.cc: ...here.
* optabs-libfuncs.c: Moved to...
* optabs-libfuncs.cc: ...here.
* optabs-query.c: Moved to...
* optabs-query.cc: ...here.
* optabs-tree.c: Moved to...
* optabs-tree.cc: ...here.
* optabs.c: Moved to...
* optabs.cc: ...here.
* opts-common.c: Moved to...
* opts-common.cc: ...here.
* opts-global.c: Moved to...
* opts-global.cc: ...here.
* opts.c: Moved to...
* opts.cc: ...here.
* passes.c: Moved to...
* passes.cc: ...here.
* plugin.c: Moved to...
* plugin.cc: ...here.
* postreload-gcse.c: Moved to...
* postreload-gcse.cc: ...here.
* postreload.c: Moved to...
* postreload.cc: ...here.
* predict.c: Moved to...
* predict.cc: ...here.
* prefix.c: Moved to...
* prefix.cc: ...here.
* pretty-print.c: Moved to...
* pretty-print.cc: ...here.
* print-rtl-function.c: Moved to...
* print-rtl-function.cc: ...here.
* print-rtl.c: Moved to...
* print-rtl.cc: ...here.
* print-tree.c: Moved to...
* print-tree.cc: ...here.
* profile-count.c: Moved to...
* profile-count.cc: ...here.
* profile.c: Moved to...
* profile.cc: ...here.
* read-md.c: Moved to...
* read-md.cc: ...here.
* read-rtl-function.c: Moved to...
* read-rtl-function.cc: ...here.
* read-rtl.c: Moved to...
* read-rtl.cc: ...here.
* real.c: Moved to...
* real.cc: ...here.
* realmpfr.c: Moved to...
* realmpfr.cc: ...here.
* recog.c: Moved to...
* recog.cc: ...here.
* ree.c: Moved to...
* ree.cc: ...here.
* reg-stack.c: Moved to...
* reg-stack.cc: ...here.
* regcprop.c: Moved to...
* regcprop.cc: ...here.
* reginfo.c: Moved to...
* reginfo.cc: ...here.
* regrename.c: Moved to...
* regrename.cc: ...here.
* regstat.c: Moved to...
* regstat.cc: ...here.
* reload.c: Moved to...
* reload.cc: ...here.
* reload1.c: Moved to...
* reload1.cc: ...here.
* reorg.c: Moved to...
* reorg.cc: ...here.
* resource.c: Moved to...
* resource.cc: ...here.
* rtl-error.c: Moved to...
* rtl-error.cc: ...here.
* rtl-tests.c: Moved to...
* rtl-tests.cc: ...here.
* rtl.c: Moved to...
* rtl.cc: ...here.
* rtlanal.c: Moved to...
* rtlanal.cc: ...here.
* rtlhash.c: Moved to...
* rtlhash.cc: ...here.
* rtlhooks.c: Moved to...
* rtlhooks.cc: ...here.
* rtx-vector-builder.c: Moved to...
* rtx-vector-builder.cc: ...here.
* run-rtl-passes.c: Moved to...
* run-rtl-passes.cc: ...here.
* sancov.c: Moved to...
* sancov.cc: ...here.
* sanopt.c: Moved to...
* sanopt.cc: ...here.
* sbitmap.c: Moved to...
* sbitmap.cc: ...here.
* sched-deps.c: Moved to...
* sched-deps.cc: ...here.
* sched-ebb.c: Moved to...
* sched-ebb.cc: ...here.
* sched-rgn.c: Moved to...
* sched-rgn.cc: ...here.
* sel-sched-dump.c: Moved to...
* sel-sched-dump.cc: ...here.
* sel-sched-ir.c: Moved to...
* sel-sched-ir.cc: ...here.
* sel-sched.c: Moved to...
* sel-sched.cc: ...here.
* selftest-diagnostic.c: Moved to...
* selftest-diagnostic.cc: ...here.
* selftest-rtl.c: Moved to...
* selftest-rtl.cc: ...here.
* selftest-run-tests.c: Moved to...
* selftest-run-tests.cc: ...here.
* selftest.c: Moved to...
* selftest.cc: ...here.
* sese.c: Moved to...
* sese.cc: ...here.
* shrink-wrap.c: Moved to...
* shrink-wrap.cc: ...here.
* simplify-rtx.c: Moved to...
* simplify-rtx.cc: ...here.
* sparseset.c: Moved to...
* sparseset.cc: ...here.
* spellcheck-tree.c: Moved to...
* spellcheck-tree.cc: ...here.
* spellcheck.c: Moved to...
* spellcheck.cc: ...here.
* sreal.c: Moved to...
* sreal.cc: ...here.
* stack-ptr-mod.c: Moved to...
* stack-ptr-mod.cc: ...here.
* statistics.c: Moved to...
* statistics.cc: ...here.
* stmt.c: Moved to...
* stmt.cc: ...here.
* stor-layout.c: Moved to...
* stor-layout.cc: ...here.
* store-motion.c: Moved to...
* store-motion.cc: ...here.
* streamer-hooks.c: Moved to...
* streamer-hooks.cc: ...here.
* stringpool.c: Moved to...
* stringpool.cc: ...here.
* substring-locations.c: Moved to...
* substring-locations.cc: ...here.
* symtab.c: Moved to...
* symtab.cc: ...here.
* target-globals.c: Moved to...
* target-globals.cc: ...here.
* targhooks.c: Moved to...
* targhooks.cc: ...here.
* timevar.c: Moved to...
* timevar.cc: ...here.
* toplev.c: Moved to...
* toplev.cc: ...here.
* tracer.c: Moved to...
* tracer.cc: ...here.
* trans-mem.c: Moved to...
* trans-mem.cc: ...here.
* tree-affine.c: Moved to...
* tree-affine.cc: ...here.
* tree-call-cdce.c: Moved to...
* tree-call-cdce.cc: ...here.
* tree-cfg.c: Moved to...
* tree-cfg.cc: ...here.
* tree-cfgcleanup.c: Moved to...
* tree-cfgcleanup.cc: ...here.
* tree-chrec.c: Moved to...
* tree-chrec.cc: ...here.
* tree-complex.c: Moved to...
* tree-complex.cc: ...here.
* tree-data-ref.c: Moved to...
* tree-data-ref.cc: ...here.
* tree-dfa.c: Moved to...
* tree-dfa.cc: ...here.
* tree-diagnostic.c: Moved to...
* tree-diagnostic.cc: ...here.
* tree-dump.c: Moved to...
* tree-dump.cc: ...here.
* tree-eh.c: Moved to...
* tree-eh.cc: ...here.
* tree-emutls.c: Moved to...
* tree-emutls.cc: ...here.
* tree-if-conv.c: Moved to...
* tree-if-conv.cc: ...here.
* tree-inline.c: Moved to...
* tree-inline.cc: ...here.
* tree-into-ssa.c: Moved to...
* tree-into-ssa.cc: ...here.
* tree-iterator.c: Moved to...
* tree-iterator.cc: ...here.
* tree-loop-distribution.c: Moved to...
* tree-loop-distribution.cc: ...here.
* tree-nested.c: Moved to...
* tree-nested.cc: ...here.
* tree-nrv.c: Moved to...
* tree-nrv.cc: ...here.
* tree-object-size.c: Moved to...
* tree-object-size.cc: ...here.
* tree-outof-ssa.c: Moved to...
* tree-outof-ssa.cc: ...here.
* tree-parloops.c: Moved to...
* tree-parloops.cc: ...here.
* tree-phinodes.c: Moved to...
* tree-phinodes.cc: ...here.
* tree-predcom.c: Moved to...
* tree-predcom.cc: ...here.
* tree-pretty-print.c: Moved to...
* tree-pretty-print.cc: ...here.
* tree-profile.c: Moved to...
* tree-profile.cc: ...here.
* tree-scalar-evolution.c: Moved to...
* tree-scalar-evolution.cc: ...here.
* tree-sra.c: Moved to...
* tree-sra.cc: ...here.
* tree-ssa-address.c: Moved to...
* tree-ssa-address.cc: ...here.
* tree-ssa-alias.c: Moved to...
* tree-ssa-alias.cc: ...here.
* tree-ssa-ccp.c: Moved to...
* tree-ssa-ccp.cc: ...here.
* tree-ssa-coalesce.c: Moved to...
* tree-ssa-coalesce.cc: ...here.
* tree-ssa-copy.c: Moved to...
* tree-ssa-copy.cc: ...here.
* tree-ssa-dce.c: Moved to...
* tree-ssa-dce.cc: ...here.
* tree-ssa-dom.c: Moved to...
* tree-ssa-dom.cc: ...here.
* tree-ssa-dse.c: Moved to...
* tree-ssa-dse.cc: ...here.
* tree-ssa-forwprop.c: Moved to...
* tree-ssa-forwprop.cc: ...here.
* tree-ssa-ifcombine.c: Moved to...
* tree-ssa-ifcombine.cc: ...here.
* tree-ssa-live.c: Moved to...
* tree-ssa-live.cc: ...here.
* tree-ssa-loop-ch.c: Moved to...
* tree-ssa-loop-ch.cc: ...here.
* tree-ssa-loop-im.c: Moved to...
* tree-ssa-loop-im.cc: ...here.
* tree-ssa-loop-ivcanon.c: Moved to...
* tree-ssa-loop-ivcanon.cc: ...here.
* tree-ssa-loop-ivopts.c: Moved to...
* tree-ssa-loop-ivopts.cc: ...here.
* tree-ssa-loop-manip.c: Moved to...
* tree-ssa-loop-manip.cc: ...here.
* tree-ssa-loop-niter.c: Moved to...
* tree-ssa-loop-niter.cc: ...here.
* tree-ssa-loop-prefetch.c: Moved to...
* tree-ssa-loop-prefetch.cc: ...here.
* tree-ssa-loop-split.c: Moved to...
* tree-ssa-loop-split.cc: ...here.
* tree-ssa-loop-unswitch.c: Moved to...
* tree-ssa-loop-unswitch.cc: ...here.
* tree-ssa-loop.c: Moved to...
* tree-ssa-loop.cc: ...here.
* tree-ssa-math-opts.c: Moved to...
* tree-ssa-math-opts.cc: ...here.
* tree-ssa-operands.c: Moved to...
* tree-ssa-operands.cc: ...here.
* tree-ssa-phiopt.c: Moved to...
* tree-ssa-phiopt.cc: ...here.
* tree-ssa-phiprop.c: Moved to...
* tree-ssa-phiprop.cc: ...here.
* tree-ssa-pre.c: Moved to...
* tree-ssa-pre.cc: ...here.
* tree-ssa-propagate.c: Moved to...
* tree-ssa-propagate.cc: ...here.
* tree-ssa-reassoc.c: Moved to...
* tree-ssa-reassoc.cc: ...here.
* tree-ssa-sccvn.c: Moved to...
* tree-ssa-sccvn.cc: ...here.
* tree-ssa-scopedtables.c: Moved to...
* tree-ssa-scopedtables.cc: ...here.
* tree-ssa-sink.c: Moved to...
* tree-ssa-sink.cc: ...here.
* tree-ssa-strlen.c: Moved to...
* tree-ssa-strlen.cc: ...here.
* tree-ssa-structalias.c: Moved to...
* tree-ssa-structalias.cc: ...here.
* tree-ssa-tail-merge.c: Moved to...
* tree-ssa-tail-merge.cc: ...here.
* tree-ssa-ter.c: Moved to...
* tree-ssa-ter.cc: ...here.
* tree-ssa-threadbackward.c: Moved to...
* tree-ssa-threadbackward.cc: ...here.
* tree-ssa-threadedge.c: Moved to...
* tree-ssa-threadedge.cc: ...here.
* tree-ssa-threadupdate.c: Moved to...
* tree-ssa-threadupdate.cc: ...here.
* tree-ssa-uncprop.c: Moved to...
* tree-ssa-uncprop.cc: ...here.
* tree-ssa-uninit.c: Moved to...
* tree-ssa-uninit.cc: ...here.
* tree-ssa.c: Moved to...
* tree-ssa.cc: ...here.
* tree-ssanames.c: Moved to...
* tree-ssanames.cc: ...here.
* tree-stdarg.c: Moved to...
* tree-stdarg.cc: ...here.
* tree-streamer-in.c: Moved to...
* tree-streamer-in.cc: ...here.
* tree-streamer-out.c: Moved to...
* tree-streamer-out.cc: ...here.
* tree-streamer.c: Moved to...
* tree-streamer.cc: ...here.
* tree-switch-conversion.c: Moved to...
* tree-switch-conversion.cc: ...here.
* tree-tailcall.c: Moved to...
* tree-tailcall.cc: ...here.
* tree-vect-data-refs.c: Moved to...
* tree-vect-data-refs.cc: ...here.
* tree-vect-generic.c: Moved to...
* tree-vect-generic.cc: ...here.
* tree-vect-loop-manip.c: Moved to...
* tree-vect-loop-manip.cc: ...here.
* tree-vect-loop.c: Moved to...
* tree-vect-loop.cc: ...here.
* tree-vect-patterns.c: Moved to...
* tree-vect-patterns.cc: ...here.
* tree-vect-slp-patterns.c: Moved to...
* tree-vect-slp-patterns.cc: ...here.
* tree-vect-slp.c: Moved to...
* tree-vect-slp.cc: ...here.
* tree-vect-stmts.c: Moved to...
* tree-vect-stmts.cc: ...here.
* tree-vector-builder.c: Moved to...
* tree-vector-builder.cc: ...here.
* tree-vectorizer.c: Moved to...
* tree-vectorizer.cc: ...here.
* tree-vrp.c: Moved to...
* tree-vrp.cc: ...here.
* tree.c: Moved to...
* tree.cc: ...here.
* tsan.c: Moved to...
* tsan.cc: ...here.
* typed-splay-tree.c: Moved to...
* typed-splay-tree.cc: ...here.
* ubsan.c: Moved to...
* ubsan.cc: ...here.
* valtrack.c: Moved to...
* valtrack.cc: ...here.
* value-prof.c: Moved to...
* value-prof.cc: ...here.
* var-tracking.c: Moved to...
* var-tracking.cc: ...here.
* varasm.c: Moved to...
* varasm.cc: ...here.
* varpool.c: Moved to...
* varpool.cc: ...here.
* vec-perm-indices.c: Moved to...
* vec-perm-indices.cc: ...here.
* vec.c: Moved to...
* vec.cc: ...here.
* vmsdbgout.c: Moved to...
* vmsdbgout.cc: ...here.
* vr-values.c: Moved to...
* vr-values.cc: ...here.
* vtable-verify.c: Moved to...
* vtable-verify.cc: ...here.
* web.c: Moved to...
* web.cc: ...here.
* xcoffout.c: Moved to...
* xcoffout.cc: ...here.
gcc/c-family/ChangeLog:
* c-ada-spec.c: Moved to...
* c-ada-spec.cc: ...here.
* c-attribs.c: Moved to...
* c-attribs.cc: ...here.
* c-common.c: Moved to...
* c-common.cc: ...here.
* c-cppbuiltin.c: Moved to...
* c-cppbuiltin.cc: ...here.
* c-dump.c: Moved to...
* c-dump.cc: ...here.
* c-format.c: Moved to...
* c-format.cc: ...here.
* c-gimplify.c: Moved to...
* c-gimplify.cc: ...here.
* c-indentation.c: Moved to...
* c-indentation.cc: ...here.
* c-lex.c: Moved to...
* c-lex.cc: ...here.
* c-omp.c: Moved to...
* c-omp.cc: ...here.
* c-opts.c: Moved to...
* c-opts.cc: ...here.
* c-pch.c: Moved to...
* c-pch.cc: ...here.
* c-ppoutput.c: Moved to...
* c-ppoutput.cc: ...here.
* c-pragma.c: Moved to...
* c-pragma.cc: ...here.
* c-pretty-print.c: Moved to...
* c-pretty-print.cc: ...here.
* c-semantics.c: Moved to...
* c-semantics.cc: ...here.
* c-ubsan.c: Moved to...
* c-ubsan.cc: ...here.
* c-warn.c: Moved to...
* c-warn.cc: ...here.
* cppspec.c: Moved to...
* cppspec.cc: ...here.
* stub-objc.c: Moved to...
* stub-objc.cc: ...here.
gcc/c/ChangeLog:
* c-aux-info.c: Moved to...
* c-aux-info.cc: ...here.
* c-convert.c: Moved to...
* c-convert.cc: ...here.
* c-decl.c: Moved to...
* c-decl.cc: ...here.
* c-errors.c: Moved to...
* c-errors.cc: ...here.
* c-fold.c: Moved to...
* c-fold.cc: ...here.
* c-lang.c: Moved to...
* c-lang.cc: ...here.
* c-objc-common.c: Moved to...
* c-objc-common.cc: ...here.
* c-parser.c: Moved to...
* c-parser.cc: ...here.
* c-typeck.c: Moved to...
* c-typeck.cc: ...here.
* gccspec.c: Moved to...
* gccspec.cc: ...here.
* gimple-parser.c: Moved to...
* gimple-parser.cc: ...here.
gcc/cp/ChangeLog:
* call.c: Moved to...
* call.cc: ...here.
* class.c: Moved to...
* class.cc: ...here.
* constexpr.c: Moved to...
* constexpr.cc: ...here.
* cp-gimplify.c: Moved to...
* cp-gimplify.cc: ...here.
* cp-lang.c: Moved to...
* cp-lang.cc: ...here.
* cp-objcp-common.c: Moved to...
* cp-objcp-common.cc: ...here.
* cp-ubsan.c: Moved to...
* cp-ubsan.cc: ...here.
* cvt.c: Moved to...
* cvt.cc: ...here.
* cxx-pretty-print.c: Moved to...
* cxx-pretty-print.cc: ...here.
* decl.c: Moved to...
* decl.cc: ...here.
* decl2.c: Moved to...
* decl2.cc: ...here.
* dump.c: Moved to...
* dump.cc: ...here.
* error.c: Moved to...
* error.cc: ...here.
* except.c: Moved to...
* except.cc: ...here.
* expr.c: Moved to...
* expr.cc: ...here.
* friend.c: Moved to...
* friend.cc: ...here.
* g++spec.c: Moved to...
* g++spec.cc: ...here.
* init.c: Moved to...
* init.cc: ...here.
* lambda.c: Moved to...
* lambda.cc: ...here.
* lex.c: Moved to...
* lex.cc: ...here.
* mangle.c: Moved to...
* mangle.cc: ...here.
* method.c: Moved to...
* method.cc: ...here.
* name-lookup.c: Moved to...
* name-lookup.cc: ...here.
* optimize.c: Moved to...
* optimize.cc: ...here.
* parser.c: Moved to...
* parser.cc: ...here.
* pt.c: Moved to...
* pt.cc: ...here.
* ptree.c: Moved to...
* ptree.cc: ...here.
* rtti.c: Moved to...
* rtti.cc: ...here.
* search.c: Moved to...
* search.cc: ...here.
* semantics.c: Moved to...
* semantics.cc: ...here.
* tree.c: Moved to...
* tree.cc: ...here.
* typeck.c: Moved to...
* typeck.cc: ...here.
* typeck2.c: Moved to...
* typeck2.cc: ...here.
* vtable-class-hierarchy.c: Moved to...
* vtable-class-hierarchy.cc: ...here.
gcc/fortran/ChangeLog:
* arith.c: Moved to...
* arith.cc: ...here.
* array.c: Moved to...
* array.cc: ...here.
* bbt.c: Moved to...
* bbt.cc: ...here.
* check.c: Moved to...
* check.cc: ...here.
* class.c: Moved to...
* class.cc: ...here.
* constructor.c: Moved to...
* constructor.cc: ...here.
* convert.c: Moved to...
* convert.cc: ...here.
* cpp.c: Moved to...
* cpp.cc: ...here.
* data.c: Moved to...
* data.cc: ...here.
* decl.c: Moved to...
* decl.cc: ...here.
* dependency.c: Moved to...
* dependency.cc: ...here.
* dump-parse-tree.c: Moved to...
* dump-parse-tree.cc: ...here.
* error.c: Moved to...
* error.cc: ...here.
* expr.c: Moved to...
* expr.cc: ...here.
* f95-lang.c: Moved to...
* f95-lang.cc: ...here.
* frontend-passes.c: Moved to...
* frontend-passes.cc: ...here.
* gfortranspec.c: Moved to...
* gfortranspec.cc: ...here.
* interface.c: Moved to...
* interface.cc: ...here.
* intrinsic.c: Moved to...
* intrinsic.cc: ...here.
* io.c: Moved to...
* io.cc: ...here.
* iresolve.c: Moved to...
* iresolve.cc: ...here.
* match.c: Moved to...
* match.cc: ...here.
* matchexp.c: Moved to...
* matchexp.cc: ...here.
* misc.c: Moved to...
* misc.cc: ...here.
* module.c: Moved to...
* module.cc: ...here.
* openmp.c: Moved to...
* openmp.cc: ...here.
* options.c: Moved to...
* options.cc: ...here.
* parse.c: Moved to...
* parse.cc: ...here.
* primary.c: Moved to...
* primary.cc: ...here.
* resolve.c: Moved to...
* resolve.cc: ...here.
* scanner.c: Moved to...
* scanner.cc: ...here.
* simplify.c: Moved to...
* simplify.cc: ...here.
* st.c: Moved to...
* st.cc: ...here.
* symbol.c: Moved to...
* symbol.cc: ...here.
* target-memory.c: Moved to...
* target-memory.cc: ...here.
* trans-array.c: Moved to...
* trans-array.cc: ...here.
* trans-common.c: Moved to...
* trans-common.cc: ...here.
* trans-const.c: Moved to...
* trans-const.cc: ...here.
* trans-decl.c: Moved to...
* trans-decl.cc: ...here.
* trans-expr.c: Moved to...
* trans-expr.cc: ...here.
* trans-intrinsic.c: Moved to...
* trans-intrinsic.cc: ...here.
* trans-io.c: Moved to...
* trans-io.cc: ...here.
* trans-openmp.c: Moved to...
* trans-openmp.cc: ...here.
* trans-stmt.c: Moved to...
* trans-stmt.cc: ...here.
* trans-types.c: Moved to...
* trans-types.cc: ...here.
* trans.c: Moved to...
* trans.cc: ...here.
gcc/go/ChangeLog:
* go-backend.c: Moved to...
* go-backend.cc: ...here.
* go-lang.c: Moved to...
* go-lang.cc: ...here.
* gospec.c: Moved to...
* gospec.cc: ...here.
gcc/jit/ChangeLog:
* dummy-frontend.c: Moved to...
* dummy-frontend.cc: ...here.
* jit-builtins.c: Moved to...
* jit-builtins.cc: ...here.
* jit-logging.c: Moved to...
* jit-logging.cc: ...here.
* jit-playback.c: Moved to...
* jit-playback.cc: ...here.
* jit-recording.c: Moved to...
* jit-recording.cc: ...here.
* jit-result.c: Moved to...
* jit-result.cc: ...here.
* jit-spec.c: Moved to...
* jit-spec.cc: ...here.
* jit-tempdir.c: Moved to...
* jit-tempdir.cc: ...here.
* jit-w32.c: Moved to...
* jit-w32.cc: ...here.
* libgccjit.c: Moved to...
* libgccjit.cc: ...here.
gcc/lto/ChangeLog:
* common.c: Moved to...
* common.cc: ...here.
* lto-common.c: Moved to...
* lto-common.cc: ...here.
* lto-dump.c: Moved to...
* lto-dump.cc: ...here.
* lto-lang.c: Moved to...
* lto-lang.cc: ...here.
* lto-object.c: Moved to...
* lto-object.cc: ...here.
* lto-partition.c: Moved to...
* lto-partition.cc: ...here.
* lto-symtab.c: Moved to...
* lto-symtab.cc: ...here.
* lto.c: Moved to...
* lto.cc: ...here.
gcc/objc/ChangeLog:
* objc-act.c: Moved to...
* objc-act.cc: ...here.
* objc-encoding.c: Moved to...
* objc-encoding.cc: ...here.
* objc-gnu-runtime-abi-01.c: Moved to...
* objc-gnu-runtime-abi-01.cc: ...here.
* objc-lang.c: Moved to...
* objc-lang.cc: ...here.
* objc-map.c: Moved to...
* objc-map.cc: ...here.
* objc-next-runtime-abi-01.c: Moved to...
* objc-next-runtime-abi-01.cc: ...here.
* objc-next-runtime-abi-02.c: Moved to...
* objc-next-runtime-abi-02.cc: ...here.
* objc-runtime-shared-support.c: Moved to...
* objc-runtime-shared-support.cc: ...here.
gcc/objcp/ChangeLog:
* objcp-decl.c: Moved to...
* objcp-decl.cc: ...here.
* objcp-lang.c: Moved to...
* objcp-lang.cc: ...here.
libcpp/ChangeLog:
* charset.c: Moved to...
* charset.cc: ...here.
* directives.c: Moved to...
* directives.cc: ...here.
* errors.c: Moved to...
* errors.cc: ...here.
* expr.c: Moved to...
* expr.cc: ...here.
* files.c: Moved to...
* files.cc: ...here.
* identifiers.c: Moved to...
* identifiers.cc: ...here.
* init.c: Moved to...
* init.cc: ...here.
* lex.c: Moved to...
* lex.cc: ...here.
* line-map.c: Moved to...
* line-map.cc: ...here.
* macro.c: Moved to...
* macro.cc: ...here.
* makeucnid.c: Moved to...
* makeucnid.cc: ...here.
* mkdeps.c: Moved to...
* mkdeps.cc: ...here.
* pch.c: Moved to...
* pch.cc: ...here.
* symtab.c: Moved to...
* symtab.cc: ...here.
* traditional.c: Moved to...
* traditional.cc: ...here.
Diffstat (limited to 'gcc/c/c-parser.c')
-rw-r--r-- | gcc/c/c-parser.c | 23404 |
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" |