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/gcov.cc | |
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/gcov.cc')
-rw-r--r-- | gcc/gcov.cc | 3262 |
1 files changed, 3262 insertions, 0 deletions
diff --git a/gcc/gcov.cc b/gcc/gcov.cc new file mode 100644 index 0000000..73bdfc7 --- /dev/null +++ b/gcc/gcov.cc @@ -0,0 +1,3262 @@ +/* Gcov.c: prepend line execution counts and branch probabilities to a + source file. + Copyright (C) 1990-2022 Free Software Foundation, Inc. + Contributed by James E. Wilson of Cygnus Support. + Mangled by Bob Manson of Cygnus Support. + Mangled further by Nathan Sidwell <nathan@codesourcery.com> + +Gcov 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. + +Gcov 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 Gcov; see the file COPYING3. If not see +<http://www.gnu.org/licenses/>. */ + +/* ??? Print a list of the ten blocks with the highest execution counts, + and list the line numbers corresponding to those blocks. Also, perhaps + list the line numbers with the highest execution counts, only printing + the first if there are several which are all listed in the same block. */ + +/* ??? Should have an option to print the number of basic blocks, and the + percent of them that are covered. */ + +/* Need an option to show individual block counts, and show + probabilities of fall through arcs. */ + +#include "config.h" +#define INCLUDE_ALGORITHM +#define INCLUDE_VECTOR +#define INCLUDE_STRING +#define INCLUDE_MAP +#define INCLUDE_SET +#include "system.h" +#include "coretypes.h" +#include "tm.h" +#include "intl.h" +#include "diagnostic.h" +#include "version.h" +#include "demangle.h" +#include "color-macros.h" +#include "pretty-print.h" +#include "json.h" + +#include <zlib.h> +#include <getopt.h> + +#include "md5.h" + +using namespace std; + +#define IN_GCOV 1 +#include "gcov-io.h" +#include "gcov-io.c" + +/* The gcno file is generated by -ftest-coverage option. The gcda file is + generated by a program compiled with -fprofile-arcs. Their formats + are documented in gcov-io.h. */ + +/* The functions in this file for creating and solution program flow graphs + are very similar to functions in the gcc source file profile.c. In + some places we make use of the knowledge of how profile.c works to + select particular algorithms here. */ + +/* The code validates that the profile information read in corresponds + to the code currently being compiled. Rather than checking for + identical files, the code below compares a checksum on the CFG + (based on the order of basic blocks and the arcs in the CFG). If + the CFG checksum in the gcda file match the CFG checksum in the + gcno file, the profile data will be used. */ + +/* This is the size of the buffer used to read in source file lines. */ + +class function_info; +class block_info; +class source_info; + +/* Describes an arc between two basic blocks. */ + +struct arc_info +{ + /* source and destination blocks. */ + class block_info *src; + class block_info *dst; + + /* transition counts. */ + gcov_type count; + /* used in cycle search, so that we do not clobber original counts. */ + gcov_type cs_count; + + unsigned int count_valid : 1; + unsigned int on_tree : 1; + unsigned int fake : 1; + unsigned int fall_through : 1; + + /* Arc to a catch handler. */ + unsigned int is_throw : 1; + + /* Arc is for a function that abnormally returns. */ + unsigned int is_call_non_return : 1; + + /* Arc is for catch/setjmp. */ + unsigned int is_nonlocal_return : 1; + + /* Is an unconditional branch. */ + unsigned int is_unconditional : 1; + + /* Loop making arc. */ + unsigned int cycle : 1; + + /* Links to next arc on src and dst lists. */ + struct arc_info *succ_next; + struct arc_info *pred_next; +}; + +/* Describes which locations (lines and files) are associated with + a basic block. */ + +class block_location_info +{ +public: + block_location_info (unsigned _source_file_idx): + source_file_idx (_source_file_idx) + {} + + unsigned source_file_idx; + vector<unsigned> lines; +}; + +/* Describes a basic block. Contains lists of arcs to successor and + predecessor blocks. */ + +class block_info +{ +public: + /* Constructor. */ + block_info (); + + /* Chain of exit and entry arcs. */ + arc_info *succ; + arc_info *pred; + + /* Number of unprocessed exit and entry arcs. */ + gcov_type num_succ; + gcov_type num_pred; + + unsigned id; + + /* Block execution count. */ + gcov_type count; + unsigned count_valid : 1; + unsigned valid_chain : 1; + unsigned invalid_chain : 1; + unsigned exceptional : 1; + + /* Block is a call instrumenting site. */ + unsigned is_call_site : 1; /* Does the call. */ + unsigned is_call_return : 1; /* Is the return. */ + + /* Block is a landing pad for longjmp or throw. */ + unsigned is_nonlocal_return : 1; + + vector<block_location_info> locations; + + struct + { + /* Single line graph cycle workspace. Used for all-blocks + mode. */ + arc_info *arc; + unsigned ident; + } cycle; /* Used in all-blocks mode, after blocks are linked onto + lines. */ + + /* Temporary chain for solving graph, and for chaining blocks on one + line. */ + class block_info *chain; + +}; + +block_info::block_info (): succ (NULL), pred (NULL), num_succ (0), num_pred (0), + id (0), count (0), count_valid (0), valid_chain (0), invalid_chain (0), + exceptional (0), is_call_site (0), is_call_return (0), is_nonlocal_return (0), + locations (), chain (NULL) +{ + cycle.arc = NULL; +} + +/* Describes a single line of source. Contains a chain of basic blocks + with code on it. */ + +class line_info +{ +public: + /* Default constructor. */ + line_info (); + + /* Return true when NEEDLE is one of basic blocks the line belongs to. */ + bool has_block (block_info *needle); + + /* Execution count. */ + gcov_type count; + + /* Branches from blocks that end on this line. */ + vector<arc_info *> branches; + + /* blocks which start on this line. Used in all-blocks mode. */ + vector<block_info *> blocks; + + unsigned exists : 1; + unsigned unexceptional : 1; + unsigned has_unexecuted_block : 1; +}; + +line_info::line_info (): count (0), branches (), blocks (), exists (false), + unexceptional (0), has_unexecuted_block (0) +{ +} + +bool +line_info::has_block (block_info *needle) +{ + return std::find (blocks.begin (), blocks.end (), needle) != blocks.end (); +} + +/* Output demangled function names. */ + +static int flag_demangled_names = 0; + +/* Describes a single function. Contains an array of basic blocks. */ + +class function_info +{ +public: + function_info (); + ~function_info (); + + /* Return true when line N belongs to the function in source file SRC_IDX. + The line must be defined in body of the function, can't be inlined. */ + bool group_line_p (unsigned n, unsigned src_idx); + + /* Function filter based on function_info::artificial variable. */ + + static inline bool + is_artificial (function_info *fn) + { + return fn->artificial; + } + + /* Name of function. */ + char *m_name; + char *m_demangled_name; + unsigned ident; + unsigned lineno_checksum; + unsigned cfg_checksum; + + /* The graph contains at least one fake incoming edge. */ + unsigned has_catch : 1; + + /* True when the function is artificial and does not exist + in a source file. */ + unsigned artificial : 1; + + /* True when multiple functions start at a line in a source file. */ + unsigned is_group : 1; + + /* Array of basic blocks. Like in GCC, the entry block is + at blocks[0] and the exit block is at blocks[1]. */ +#define ENTRY_BLOCK (0) +#define EXIT_BLOCK (1) + vector<block_info> blocks; + unsigned blocks_executed; + + /* Raw arc coverage counts. */ + vector<gcov_type> counts; + + /* First line number. */ + unsigned start_line; + + /* First line column. */ + unsigned start_column; + + /* Last line number. */ + unsigned end_line; + + /* Last line column. */ + unsigned end_column; + + /* Index of source file where the function is defined. */ + unsigned src; + + /* Vector of line information (used only for group functions). */ + vector<line_info> lines; + + /* Next function. */ + class function_info *next; + + /* Get demangled name of a function. The demangled name + is converted when it is used for the first time. */ + char *get_demangled_name () + { + if (m_demangled_name == NULL) + { + m_demangled_name = cplus_demangle (m_name, DMGL_PARAMS); + if (!m_demangled_name) + m_demangled_name = m_name; + } + + return m_demangled_name; + } + + /* Get name of the function based on flag_demangled_names. */ + char *get_name () + { + return flag_demangled_names ? get_demangled_name () : m_name; + } + + /* Return number of basic blocks (without entry and exit block). */ + unsigned get_block_count () + { + return blocks.size () - 2; + } +}; + +/* Function info comparer that will sort functions according to starting + line. */ + +struct function_line_start_cmp +{ + inline bool operator() (const function_info *lhs, + const function_info *rhs) + { + return (lhs->start_line == rhs->start_line + ? lhs->start_column < rhs->start_column + : lhs->start_line < rhs->start_line); + } +}; + +/* Describes coverage of a file or function. */ + +struct coverage_info +{ + int lines; + int lines_executed; + + int branches; + int branches_executed; + int branches_taken; + + int calls; + int calls_executed; + + char *name; +}; + +/* Describes a file mentioned in the block graph. Contains an array + of line info. */ + +class source_info +{ +public: + /* Default constructor. */ + source_info (); + + vector<function_info *> *get_functions_at_location (unsigned line_num) const; + + /* Register a new function. */ + void add_function (function_info *fn); + + /* Debug the source file. */ + void debug (); + + /* Index of the source_info in sources vector. */ + unsigned index; + + /* Canonical name of source file. */ + char *name; + time_t file_time; + + /* Vector of line information. */ + vector<line_info> lines; + + coverage_info coverage; + + /* Maximum line count in the source file. */ + unsigned int maximum_count; + + /* Functions in this source file. These are in ascending line + number order. */ + vector<function_info *> functions; + + /* Line number to functions map. */ + vector<vector<function_info *> *> line_to_function_map; +}; + +source_info::source_info (): index (0), name (NULL), file_time (), + lines (), coverage (), maximum_count (0), functions () +{ +} + +/* Register a new function. */ +void +source_info::add_function (function_info *fn) +{ + functions.push_back (fn); + + if (fn->start_line >= line_to_function_map.size ()) + line_to_function_map.resize (fn->start_line + 1); + + vector<function_info *> **slot = &line_to_function_map[fn->start_line]; + if (*slot == NULL) + *slot = new vector<function_info *> (); + + (*slot)->push_back (fn); +} + +vector<function_info *> * +source_info::get_functions_at_location (unsigned line_num) const +{ + if (line_num >= line_to_function_map.size ()) + return NULL; + + vector<function_info *> *slot = line_to_function_map[line_num]; + if (slot != NULL) + std::sort (slot->begin (), slot->end (), function_line_start_cmp ()); + + return slot; +} + +void source_info::debug () +{ + fprintf (stderr, "source_info: %s\n", name); + for (vector<function_info *>::iterator it = functions.begin (); + it != functions.end (); it++) + { + function_info *fn = *it; + fprintf (stderr, " function_info: %s\n", fn->get_name ()); + for (vector<block_info>::iterator bit = fn->blocks.begin (); + bit != fn->blocks.end (); bit++) + { + fprintf (stderr, " block_info id=%d, count=%" PRId64 " \n", + bit->id, bit->count); + } + } + + for (unsigned lineno = 1; lineno < lines.size (); ++lineno) + { + line_info &line = lines[lineno]; + fprintf (stderr, " line_info=%d, count=%" PRId64 "\n", lineno, line.count); + } + + fprintf (stderr, "\n"); +} + +class name_map +{ +public: + name_map () + { + } + + name_map (char *_name, unsigned _src): name (_name), src (_src) + { + } + + bool operator== (const name_map &rhs) const + { +#if HAVE_DOS_BASED_FILE_SYSTEM + return strcasecmp (this->name, rhs.name) == 0; +#else + return strcmp (this->name, rhs.name) == 0; +#endif + } + + bool operator< (const name_map &rhs) const + { +#if HAVE_DOS_BASED_FILE_SYSTEM + return strcasecmp (this->name, rhs.name) < 0; +#else + return strcmp (this->name, rhs.name) < 0; +#endif + } + + const char *name; /* Source file name */ + unsigned src; /* Source file */ +}; + +/* Vector of all functions. */ +static vector<function_info *> functions; + +/* Function ident to function_info * map. */ +static map<unsigned, function_info *> ident_to_fn; + +/* Vector of source files. */ +static vector<source_info> sources; + +/* Mapping of file names to sources */ +static vector<name_map> names; + +/* Record all processed files in order to warn about + a file being read multiple times. */ +static vector<char *> processed_files; + +/* This holds data summary information. */ + +static unsigned object_runs; + +static unsigned total_lines; +static unsigned total_executed; + +/* Modification time of graph file. */ + +static time_t bbg_file_time; + +/* Name of the notes (gcno) output file. The "bbg" prefix is for + historical reasons, when the notes file contained only the + basic block graph notes. */ + +static char *bbg_file_name; + +/* Stamp of the bbg file */ +static unsigned bbg_stamp; + +/* Supports has_unexecuted_blocks functionality. */ +static unsigned bbg_supports_has_unexecuted_blocks; + +/* Working directory in which a TU was compiled. */ +static const char *bbg_cwd; + +/* Name and file pointer of the input file for the count data (gcda). */ + +static char *da_file_name; + +/* Data file is missing. */ + +static int no_data_file; + +/* If there is several input files, compute and display results after + reading all data files. This way if two or more gcda file refer to + the same source file (eg inline subprograms in a .h file), the + counts are added. */ + +static int multiple_files = 0; + +/* Output branch probabilities. */ + +static int flag_branches = 0; + +/* Show unconditional branches too. */ +static int flag_unconditional = 0; + +/* Output a gcov file if this is true. This is on by default, and can + be turned off by the -n option. */ + +static int flag_gcov_file = 1; + +/* Output to stdout instead to a gcov file. */ + +static int flag_use_stdout = 0; + +/* Output progress indication if this is true. This is off by default + and can be turned on by the -d option. */ + +static int flag_display_progress = 0; + +/* Output *.gcov file in JSON intermediate format used by consumers. */ + +static int flag_json_format = 0; + +/* For included files, make the gcov output file name include the name + of the input source file. For example, if x.h is included in a.c, + then the output file name is a.c##x.h.gcov instead of x.h.gcov. */ + +static int flag_long_names = 0; + +/* For situations when a long name can potentially hit filesystem path limit, + let's calculate md5sum of the path and append it to a file name. */ + +static int flag_hash_filenames = 0; + +/* Print verbose informations. */ + +static int flag_verbose = 0; + +/* Print colored output. */ + +static int flag_use_colors = 0; + +/* Use perf-like colors to indicate hot lines. */ + +static int flag_use_hotness_colors = 0; + +/* Output count information for every basic block, not merely those + that contain line number information. */ + +static int flag_all_blocks = 0; + +/* Output human readable numbers. */ + +static int flag_human_readable_numbers = 0; + +/* Output summary info for each function. */ + +static int flag_function_summary = 0; + +/* Print debugging dumps. */ + +static int flag_debug = 0; + +/* Object directory file prefix. This is the directory/file where the + graph and data files are looked for, if nonzero. */ + +static char *object_directory = 0; + +/* Source directory prefix. This is removed from source pathnames + that match, when generating the output file name. */ + +static char *source_prefix = 0; +static size_t source_length = 0; + +/* Only show data for sources with relative pathnames. Absolute ones + usually indicate a system header file, which although it may + contain inline functions, is usually uninteresting. */ +static int flag_relative_only = 0; + +/* Preserve all pathname components. Needed when object files and + source files are in subdirectories. '/' is mangled as '#', '.' is + elided and '..' mangled to '^'. */ + +static int flag_preserve_paths = 0; + +/* Output the number of times a branch was taken as opposed to the percentage + of times it was taken. */ + +static int flag_counts = 0; + +/* Return code of the tool invocation. */ +static int return_code = 0; + +/* Forward declarations. */ +static int process_args (int, char **); +static void print_usage (int) ATTRIBUTE_NORETURN; +static void print_version (void) ATTRIBUTE_NORETURN; +static void process_file (const char *); +static void process_all_functions (void); +static void generate_results (const char *); +static void create_file_names (const char *); +static char *canonicalize_name (const char *); +static unsigned find_source (const char *); +static void read_graph_file (void); +static int read_count_file (void); +static void solve_flow_graph (function_info *); +static void find_exception_blocks (function_info *); +static void add_branch_counts (coverage_info *, const arc_info *); +static void add_line_counts (coverage_info *, function_info *); +static void executed_summary (unsigned, unsigned); +static void function_summary (const coverage_info *); +static void file_summary (const coverage_info *); +static const char *format_gcov (gcov_type, gcov_type, int); +static void accumulate_line_counts (source_info *); +static void output_gcov_file (const char *, source_info *); +static int output_branch_count (FILE *, int, const arc_info *); +static void output_lines (FILE *, const source_info *); +static string make_gcov_file_name (const char *, const char *); +static char *mangle_name (const char *); +static void release_structures (void); +extern int main (int, char **); + +function_info::function_info (): m_name (NULL), m_demangled_name (NULL), + ident (0), lineno_checksum (0), cfg_checksum (0), has_catch (0), + artificial (0), is_group (0), + blocks (), blocks_executed (0), counts (), + start_line (0), start_column (0), end_line (0), end_column (0), + src (0), lines (), next (NULL) +{ +} + +function_info::~function_info () +{ + for (int i = blocks.size () - 1; i >= 0; i--) + { + arc_info *arc, *arc_n; + + for (arc = blocks[i].succ; arc; arc = arc_n) + { + arc_n = arc->succ_next; + free (arc); + } + } + if (m_demangled_name != m_name) + free (m_demangled_name); + free (m_name); +} + +bool function_info::group_line_p (unsigned n, unsigned src_idx) +{ + return is_group && src == src_idx && start_line <= n && n <= end_line; +} + +/* Cycle detection! + There are a bajillion algorithms that do this. Boost's function is named + hawick_cycles, so I used the algorithm by K. A. Hawick and H. A. James in + "Enumerating Circuits and Loops in Graphs with Self-Arcs and Multiple-Arcs" + (url at <http://complexity.massey.ac.nz/cstn/013/cstn-013.pdf>). + + The basic algorithm is simple: effectively, we're finding all simple paths + in a subgraph (that shrinks every iteration). Duplicates are filtered by + "blocking" a path when a node is added to the path (this also prevents non- + simple paths)--the node is unblocked only when it participates in a cycle. + */ + +typedef vector<arc_info *> arc_vector_t; +typedef vector<const block_info *> block_vector_t; + +/* Handle cycle identified by EDGES, where the function finds minimum cs_count + and subtract the value from all counts. The subtracted value is added + to COUNT. Returns type of loop. */ + +static void +handle_cycle (const arc_vector_t &edges, int64_t &count) +{ + /* Find the minimum edge of the cycle, and reduce all nodes in the cycle by + that amount. */ + int64_t cycle_count = INTTYPE_MAXIMUM (int64_t); + for (unsigned i = 0; i < edges.size (); i++) + { + int64_t ecount = edges[i]->cs_count; + if (cycle_count > ecount) + cycle_count = ecount; + } + count += cycle_count; + for (unsigned i = 0; i < edges.size (); i++) + edges[i]->cs_count -= cycle_count; + + gcc_assert (cycle_count > 0); +} + +/* Unblock a block U from BLOCKED. Apart from that, iterate all blocks + blocked by U in BLOCK_LISTS. */ + +static void +unblock (const block_info *u, block_vector_t &blocked, + vector<block_vector_t > &block_lists) +{ + block_vector_t::iterator it = find (blocked.begin (), blocked.end (), u); + if (it == blocked.end ()) + return; + + unsigned index = it - blocked.begin (); + blocked.erase (it); + + block_vector_t to_unblock (block_lists[index]); + + block_lists.erase (block_lists.begin () + index); + + for (block_vector_t::iterator it = to_unblock.begin (); + it != to_unblock.end (); it++) + unblock (*it, blocked, block_lists); +} + +/* Return true when PATH contains a zero cycle arc count. */ + +static bool +path_contains_zero_or_negative_cycle_arc (arc_vector_t &path) +{ + for (unsigned i = 0; i < path.size (); i++) + if (path[i]->cs_count <= 0) + return true; + return false; +} + +/* Find circuit going to block V, PATH is provisional seen cycle. + BLOCKED is vector of blocked vertices, BLOCK_LISTS contains vertices + blocked by a block. COUNT is accumulated count of the current LINE. + Returns what type of loop it contains. */ + +static bool +circuit (block_info *v, arc_vector_t &path, block_info *start, + block_vector_t &blocked, vector<block_vector_t> &block_lists, + line_info &linfo, int64_t &count) +{ + bool loop_found = false; + + /* Add v to the block list. */ + gcc_assert (find (blocked.begin (), blocked.end (), v) == blocked.end ()); + blocked.push_back (v); + block_lists.push_back (block_vector_t ()); + + for (arc_info *arc = v->succ; arc; arc = arc->succ_next) + { + block_info *w = arc->dst; + if (w < start + || arc->cs_count <= 0 + || !linfo.has_block (w)) + continue; + + path.push_back (arc); + if (w == start) + { + /* Cycle has been found. */ + handle_cycle (path, count); + loop_found = true; + } + else if (!path_contains_zero_or_negative_cycle_arc (path) + && find (blocked.begin (), blocked.end (), w) == blocked.end ()) + loop_found |= circuit (w, path, start, blocked, block_lists, linfo, + count); + + path.pop_back (); + } + + if (loop_found) + unblock (v, blocked, block_lists); + else + for (arc_info *arc = v->succ; arc; arc = arc->succ_next) + { + block_info *w = arc->dst; + if (w < start + || arc->cs_count <= 0 + || !linfo.has_block (w)) + continue; + + size_t index + = find (blocked.begin (), blocked.end (), w) - blocked.begin (); + gcc_assert (index < blocked.size ()); + block_vector_t &list = block_lists[index]; + if (find (list.begin (), list.end (), v) == list.end ()) + list.push_back (v); + } + + return loop_found; +} + +/* Find cycles for a LINFO. */ + +static gcov_type +get_cycles_count (line_info &linfo) +{ + /* Note that this algorithm works even if blocks aren't in sorted order. + Each iteration of the circuit detection is completely independent + (except for reducing counts, but that shouldn't matter anyways). + Therefore, operating on a permuted order (i.e., non-sorted) only + has the effect of permuting the output cycles. */ + + gcov_type count = 0; + for (vector<block_info *>::iterator it = linfo.blocks.begin (); + it != linfo.blocks.end (); it++) + { + arc_vector_t path; + block_vector_t blocked; + vector<block_vector_t > block_lists; + circuit (*it, path, *it, blocked, block_lists, linfo, count); + } + + return count; +} + +int +main (int argc, char **argv) +{ + int argno; + int first_arg; + const char *p; + + p = argv[0] + strlen (argv[0]); + while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1])) + --p; + progname = p; + + xmalloc_set_program_name (progname); + + /* Unlock the stdio streams. */ + unlock_std_streams (); + + gcc_init_libintl (); + + diagnostic_initialize (global_dc, 0); + + /* Handle response files. */ + expandargv (&argc, &argv); + + argno = process_args (argc, argv); + if (optind == argc) + print_usage (true); + + if (argc - argno > 1) + multiple_files = 1; + + first_arg = argno; + + for (; argno != argc; argno++) + { + if (flag_display_progress) + printf ("Processing file %d out of %d\n", argno - first_arg + 1, + argc - first_arg); + process_file (argv[argno]); + + if (flag_json_format || argno == argc - 1) + { + process_all_functions (); + generate_results (argv[argno]); + release_structures (); + } + } + + if (!flag_use_stdout) + executed_summary (total_lines, total_executed); + + return return_code; +} + +/* Print a usage message and exit. If ERROR_P is nonzero, this is an error, + otherwise the output of --help. */ + +static void +print_usage (int error_p) +{ + FILE *file = error_p ? stderr : stdout; + int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE; + + fnotice (file, "Usage: gcov [OPTION...] SOURCE|OBJ...\n\n"); + fnotice (file, "Print code coverage information.\n\n"); + fnotice (file, " -a, --all-blocks Show information for every basic block\n"); + fnotice (file, " -b, --branch-probabilities Include branch probabilities in output\n"); + fnotice (file, " -c, --branch-counts Output counts of branches taken\n\ + rather than percentages\n"); + fnotice (file, " -d, --display-progress Display progress information\n"); + fnotice (file, " -D, --debug Display debugging dumps\n"); + fnotice (file, " -f, --function-summaries Output summaries for each function\n"); + fnotice (file, " -h, --help Print this help, then exit\n"); + fnotice (file, " -j, --json-format Output JSON intermediate format\n\ + into .gcov.json.gz file\n"); + fnotice (file, " -H, --human-readable Output human readable numbers\n"); + fnotice (file, " -k, --use-colors Emit colored output\n"); + fnotice (file, " -l, --long-file-names Use long output file names for included\n\ + source files\n"); + fnotice (file, " -m, --demangled-names Output demangled function names\n"); + fnotice (file, " -n, --no-output Do not create an output file\n"); + fnotice (file, " -o, --object-directory DIR|FILE Search for object files in DIR or called FILE\n"); + fnotice (file, " -p, --preserve-paths Preserve all pathname components\n"); + fnotice (file, " -q, --use-hotness-colors Emit perf-like colored output for hot lines\n"); + fnotice (file, " -r, --relative-only Only show data for relative sources\n"); + fnotice (file, " -s, --source-prefix DIR Source prefix to elide\n"); + fnotice (file, " -t, --stdout Output to stdout instead of a file\n"); + fnotice (file, " -u, --unconditional-branches Show unconditional branch counts too\n"); + fnotice (file, " -v, --version Print version number, then exit\n"); + fnotice (file, " -w, --verbose Print verbose informations\n"); + fnotice (file, " -x, --hash-filenames Hash long pathnames\n"); + fnotice (file, "\nObsolete options:\n"); + fnotice (file, " -i, --json-format Replaced with -j, --json-format\n"); + fnotice (file, " -j, --human-readable Replaced with -H, --human-readable\n"); + fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n", + bug_report_url); + exit (status); +} + +/* Print version information and exit. */ + +static void +print_version (void) +{ + fnotice (stdout, "gcov %s%s\n", pkgversion_string, version_string); + fprintf (stdout, "Copyright %s 2022 Free Software Foundation, Inc.\n", + _("(C)")); + fnotice (stdout, + _("This is free software; see the source for copying conditions. There is NO\n\ +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n")); + exit (SUCCESS_EXIT_CODE); +} + +static const struct option options[] = +{ + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, 'v' }, + { "verbose", no_argument, NULL, 'w' }, + { "all-blocks", no_argument, NULL, 'a' }, + { "branch-probabilities", no_argument, NULL, 'b' }, + { "branch-counts", no_argument, NULL, 'c' }, + { "json-format", no_argument, NULL, 'j' }, + { "human-readable", no_argument, NULL, 'H' }, + { "no-output", no_argument, NULL, 'n' }, + { "long-file-names", no_argument, NULL, 'l' }, + { "function-summaries", no_argument, NULL, 'f' }, + { "demangled-names", no_argument, NULL, 'm' }, + { "preserve-paths", no_argument, NULL, 'p' }, + { "relative-only", no_argument, NULL, 'r' }, + { "object-directory", required_argument, NULL, 'o' }, + { "object-file", required_argument, NULL, 'o' }, + { "source-prefix", required_argument, NULL, 's' }, + { "stdout", no_argument, NULL, 't' }, + { "unconditional-branches", no_argument, NULL, 'u' }, + { "display-progress", no_argument, NULL, 'd' }, + { "hash-filenames", no_argument, NULL, 'x' }, + { "use-colors", no_argument, NULL, 'k' }, + { "use-hotness-colors", no_argument, NULL, 'q' }, + { "debug", no_argument, NULL, 'D' }, + { 0, 0, 0, 0 } +}; + +/* Process args, return index to first non-arg. */ + +static int +process_args (int argc, char **argv) +{ + int opt; + + const char *opts = "abcdDfhHijklmno:pqrs:tuvwx"; + while ((opt = getopt_long (argc, argv, opts, options, NULL)) != -1) + { + switch (opt) + { + case 'a': + flag_all_blocks = 1; + break; + case 'b': + flag_branches = 1; + break; + case 'c': + flag_counts = 1; + break; + case 'f': + flag_function_summary = 1; + break; + case 'h': + print_usage (false); + /* print_usage will exit. */ + case 'l': + flag_long_names = 1; + break; + case 'H': + flag_human_readable_numbers = 1; + break; + case 'k': + flag_use_colors = 1; + break; + case 'q': + flag_use_hotness_colors = 1; + break; + case 'm': + flag_demangled_names = 1; + break; + case 'n': + flag_gcov_file = 0; + break; + case 'o': + object_directory = optarg; + break; + case 's': + source_prefix = optarg; + source_length = strlen (source_prefix); + break; + case 'r': + flag_relative_only = 1; + break; + case 'p': + flag_preserve_paths = 1; + break; + case 'u': + flag_unconditional = 1; + break; + case 'i': + case 'j': + flag_json_format = 1; + flag_gcov_file = 1; + break; + case 'd': + flag_display_progress = 1; + break; + case 'x': + flag_hash_filenames = 1; + break; + case 'w': + flag_verbose = 1; + break; + case 't': + flag_use_stdout = 1; + break; + case 'D': + flag_debug = 1; + break; + case 'v': + print_version (); + /* print_version will exit. */ + default: + print_usage (true); + /* print_usage will exit. */ + } + } + + return optind; +} + +/* Output intermediate LINE sitting on LINE_NUM to JSON OBJECT. + Add FUNCTION_NAME to the LINE. */ + +static void +output_intermediate_json_line (json::array *object, + line_info *line, unsigned line_num, + const char *function_name) +{ + if (!line->exists) + return; + + json::object *lineo = new json::object (); + lineo->set ("line_number", new json::integer_number (line_num)); + if (function_name != NULL) + lineo->set ("function_name", new json::string (function_name)); + lineo->set ("count", new json::integer_number (line->count)); + lineo->set ("unexecuted_block", + new json::literal (line->has_unexecuted_block)); + + json::array *branches = new json::array (); + lineo->set ("branches", branches); + + vector<arc_info *>::const_iterator it; + if (flag_branches) + for (it = line->branches.begin (); it != line->branches.end (); + it++) + { + if (!(*it)->is_unconditional && !(*it)->is_call_non_return) + { + json::object *branch = new json::object (); + branch->set ("count", new json::integer_number ((*it)->count)); + branch->set ("throw", new json::literal ((*it)->is_throw)); + branch->set ("fallthrough", + new json::literal ((*it)->fall_through)); + branches->append (branch); + } + } + + object->append (lineo); +} + +/* Strip filename extension in STR. */ + +static string +strip_extention (string str) +{ + string::size_type pos = str.rfind ('.'); + if (pos != string::npos) + str = str.substr (0, pos); + + return str; +} + +/* Calcualte md5sum for INPUT string and return it in hex string format. */ + +static string +get_md5sum (const char *input) +{ + md5_ctx ctx; + char md5sum[16]; + string str; + + md5_init_ctx (&ctx); + md5_process_bytes (input, strlen (input), &ctx); + md5_finish_ctx (&ctx, md5sum); + + for (unsigned i = 0; i < 16; i++) + { + char b[3]; + sprintf (b, "%02x", (unsigned char)md5sum[i]); + str += b; + } + + return str; +} + +/* Get the name of the gcov file. The return value must be free'd. + + It appends the '.gcov' extension to the *basename* of the file. + The resulting file name will be in PWD. + + e.g., + input: foo.da, output: foo.da.gcov + input: a/b/foo.cc, output: foo.cc.gcov */ + +static string +get_gcov_intermediate_filename (const char *input_file_name) +{ + string base = basename (input_file_name); + string str = strip_extention (base); + + if (flag_hash_filenames) + { + str += "##"; + str += get_md5sum (input_file_name); + } + else if (flag_preserve_paths && base != input_file_name) + { + str += "##"; + str += mangle_path (input_file_name); + str = strip_extention (str); + } + + str += ".gcov.json.gz"; + return str.c_str (); +} + +/* Output the result in JSON intermediate format. + Source info SRC is dumped into JSON_FILES which is JSON array. */ + +static void +output_json_intermediate_file (json::array *json_files, source_info *src) +{ + json::object *root = new json::object (); + json_files->append (root); + + root->set ("file", new json::string (src->name)); + + json::array *functions = new json::array (); + root->set ("functions", functions); + + std::sort (src->functions.begin (), src->functions.end (), + function_line_start_cmp ()); + for (vector<function_info *>::iterator it = src->functions.begin (); + it != src->functions.end (); it++) + { + json::object *function = new json::object (); + function->set ("name", new json::string ((*it)->m_name)); + function->set ("demangled_name", + new json::string ((*it)->get_demangled_name ())); + function->set ("start_line", + new json::integer_number ((*it)->start_line)); + function->set ("start_column", + new json::integer_number ((*it)->start_column)); + function->set ("end_line", new json::integer_number ((*it)->end_line)); + function->set ("end_column", + new json::integer_number ((*it)->end_column)); + function->set ("blocks", + new json::integer_number ((*it)->get_block_count ())); + function->set ("blocks_executed", + new json::integer_number ((*it)->blocks_executed)); + function->set ("execution_count", + new json::integer_number ((*it)->blocks[0].count)); + + functions->append (function); + } + + json::array *lineso = new json::array (); + root->set ("lines", lineso); + + vector<function_info *> last_non_group_fns; + + for (unsigned line_num = 1; line_num <= src->lines.size (); line_num++) + { + vector<function_info *> *fns = src->get_functions_at_location (line_num); + + if (fns != NULL) + /* Print info for all group functions that begin on the line. */ + for (vector<function_info *>::iterator it2 = fns->begin (); + it2 != fns->end (); it2++) + { + if (!(*it2)->is_group) + last_non_group_fns.push_back (*it2); + + vector<line_info> &lines = (*it2)->lines; + /* The LINES array is allocated only for group functions. */ + for (unsigned i = 0; i < lines.size (); i++) + { + line_info *line = &lines[i]; + output_intermediate_json_line (lineso, line, line_num + i, + (*it2)->m_name); + } + } + + /* Follow with lines associated with the source file. */ + if (line_num < src->lines.size ()) + { + unsigned size = last_non_group_fns.size (); + function_info *last_fn = size > 0 ? last_non_group_fns[size - 1] : NULL; + const char *fname = last_fn ? last_fn->m_name : NULL; + output_intermediate_json_line (lineso, &src->lines[line_num], line_num, + fname); + + /* Pop ending function from stack. */ + if (last_fn != NULL && last_fn->end_line == line_num) + last_non_group_fns.pop_back (); + } + } +} + +/* Function start pair. */ +struct function_start +{ + unsigned source_file_idx; + unsigned start_line; +}; + +/* Traits class for function start hash maps below. */ + +struct function_start_pair_hash : typed_noop_remove <function_start> +{ + typedef function_start value_type; + typedef function_start compare_type; + + static hashval_t + hash (const function_start &ref) + { + inchash::hash hstate (0); + hstate.add_int (ref.source_file_idx); + hstate.add_int (ref.start_line); + return hstate.end (); + } + + static bool + equal (const function_start &ref1, const function_start &ref2) + { + return (ref1.source_file_idx == ref2.source_file_idx + && ref1.start_line == ref2.start_line); + } + + static void + mark_deleted (function_start &ref) + { + ref.start_line = ~1U; + } + + static const bool empty_zero_p = false; + + static void + mark_empty (function_start &ref) + { + ref.start_line = ~2U; + } + + static bool + is_deleted (const function_start &ref) + { + return ref.start_line == ~1U; + } + + static bool + is_empty (const function_start &ref) + { + return ref.start_line == ~2U; + } +}; + +/* Process a single input file. */ + +static void +process_file (const char *file_name) +{ + create_file_names (file_name); + + for (unsigned i = 0; i < processed_files.size (); i++) + if (strcmp (da_file_name, processed_files[i]) == 0) + { + fnotice (stderr, "'%s' file is already processed\n", + file_name); + return; + } + + processed_files.push_back (xstrdup (da_file_name)); + + read_graph_file (); + read_count_file (); +} + +/* Process all functions in all files. */ + +static void +process_all_functions (void) +{ + hash_map<function_start_pair_hash, function_info *> fn_map; + + /* Identify group functions. */ + for (vector<function_info *>::iterator it = functions.begin (); + it != functions.end (); it++) + if (!(*it)->artificial) + { + function_start needle; + needle.source_file_idx = (*it)->src; + needle.start_line = (*it)->start_line; + + function_info **slot = fn_map.get (needle); + if (slot) + { + (*slot)->is_group = 1; + (*it)->is_group = 1; + } + else + fn_map.put (needle, *it); + } + + /* Remove all artificial function. */ + functions.erase (remove_if (functions.begin (), functions.end (), + function_info::is_artificial), functions.end ()); + + for (vector<function_info *>::iterator it = functions.begin (); + it != functions.end (); it++) + { + function_info *fn = *it; + unsigned src = fn->src; + + if (!fn->counts.empty () || no_data_file) + { + source_info *s = &sources[src]; + s->add_function (fn); + + /* Mark last line in files touched by function. */ + for (unsigned block_no = 0; block_no != fn->blocks.size (); + block_no++) + { + block_info *block = &fn->blocks[block_no]; + for (unsigned i = 0; i < block->locations.size (); i++) + { + /* Sort lines of locations. */ + sort (block->locations[i].lines.begin (), + block->locations[i].lines.end ()); + + if (!block->locations[i].lines.empty ()) + { + s = &sources[block->locations[i].source_file_idx]; + unsigned last_line + = block->locations[i].lines.back (); + + /* Record new lines for the function. */ + if (last_line >= s->lines.size ()) + { + s = &sources[block->locations[i].source_file_idx]; + unsigned last_line + = block->locations[i].lines.back (); + + /* Record new lines for the function. */ + if (last_line >= s->lines.size ()) + { + /* Record new lines for a source file. */ + s->lines.resize (last_line + 1); + } + } + } + } + } + + /* Allocate lines for group function, following start_line + and end_line information of the function. */ + if (fn->is_group) + fn->lines.resize (fn->end_line - fn->start_line + 1); + + solve_flow_graph (fn); + if (fn->has_catch) + find_exception_blocks (fn); + } + else + { + /* The function was not in the executable -- some other + instance must have been selected. */ + } + } +} + +static void +output_gcov_file (const char *file_name, source_info *src) +{ + string gcov_file_name_str + = make_gcov_file_name (file_name, src->coverage.name); + const char *gcov_file_name = gcov_file_name_str.c_str (); + + if (src->coverage.lines) + { + FILE *gcov_file = fopen (gcov_file_name, "w"); + if (gcov_file) + { + fnotice (stdout, "Creating '%s'\n", gcov_file_name); + output_lines (gcov_file, src); + if (ferror (gcov_file)) + { + fnotice (stderr, "Error writing output file '%s'\n", + gcov_file_name); + return_code = 6; + } + fclose (gcov_file); + } + else + { + fnotice (stderr, "Could not open output file '%s'\n", gcov_file_name); + return_code = 6; + } + } + else + { + unlink (gcov_file_name); + fnotice (stdout, "Removing '%s'\n", gcov_file_name); + } +} + +static void +generate_results (const char *file_name) +{ + string gcov_intermediate_filename; + + for (vector<function_info *>::iterator it = functions.begin (); + it != functions.end (); it++) + { + function_info *fn = *it; + coverage_info coverage; + + memset (&coverage, 0, sizeof (coverage)); + coverage.name = fn->get_name (); + add_line_counts (flag_function_summary ? &coverage : NULL, fn); + if (flag_function_summary) + { + function_summary (&coverage); + fnotice (stdout, "\n"); + } + } + + name_map needle; + needle.name = file_name; + vector<name_map>::iterator it + = std::find (names.begin (), names.end (), needle); + if (it != names.end ()) + file_name = sources[it->src].coverage.name; + else + file_name = canonicalize_name (file_name); + + gcov_intermediate_filename = get_gcov_intermediate_filename (file_name); + + json::object *root = new json::object (); + root->set ("format_version", new json::string ("1")); + root->set ("gcc_version", new json::string (version_string)); + + if (bbg_cwd != NULL) + root->set ("current_working_directory", new json::string (bbg_cwd)); + root->set ("data_file", new json::string (file_name)); + + json::array *json_files = new json::array (); + root->set ("files", json_files); + + for (vector<source_info>::iterator it = sources.begin (); + it != sources.end (); it++) + { + source_info *src = &(*it); + if (flag_relative_only) + { + /* Ignore this source, if it is an absolute path (after + source prefix removal). */ + char first = src->coverage.name[0]; + +#if HAVE_DOS_BASED_FILE_SYSTEM + if (first && src->coverage.name[1] == ':') + first = src->coverage.name[2]; +#endif + if (IS_DIR_SEPARATOR (first)) + continue; + } + + accumulate_line_counts (src); + if (flag_debug) + src->debug (); + + if (!flag_use_stdout) + file_summary (&src->coverage); + total_lines += src->coverage.lines; + total_executed += src->coverage.lines_executed; + if (flag_gcov_file) + { + if (flag_json_format) + { + output_json_intermediate_file (json_files, src); + if (!flag_use_stdout) + fnotice (stdout, "\n"); + } + else + { + if (flag_use_stdout) + { + if (src->coverage.lines) + output_lines (stdout, src); + } + else + { + output_gcov_file (file_name, src); + fnotice (stdout, "\n"); + } + } + } + } + + if (flag_gcov_file && flag_json_format) + { + if (flag_use_stdout) + { + root->dump (stdout); + printf ("\n"); + } + else + { + pretty_printer pp; + root->print (&pp); + pp_formatted_text (&pp); + + fnotice (stdout, "Creating '%s'\n", + gcov_intermediate_filename.c_str ()); + gzFile output = gzopen (gcov_intermediate_filename.c_str (), "w"); + if (output == NULL) + { + fnotice (stderr, "Cannot open JSON output file %s\n", + gcov_intermediate_filename.c_str ()); + return_code = 6; + return; + } + + if (gzputs (output, pp_formatted_text (&pp)) == EOF + || gzclose (output)) + { + fnotice (stderr, "Error writing JSON output file %s\n", + gcov_intermediate_filename.c_str ()); + return_code = 6; + return; + } + } + } +} + +/* Release all memory used. */ + +static void +release_structures (void) +{ + for (vector<function_info *>::iterator it = functions.begin (); + it != functions.end (); it++) + delete (*it); + + sources.resize (0); + names.resize (0); + functions.resize (0); + ident_to_fn.clear (); +} + +/* Generate the names of the graph and data files. If OBJECT_DIRECTORY + is not specified, these are named from FILE_NAME sans extension. If + OBJECT_DIRECTORY is specified and is a directory, the files are in that + directory, but named from the basename of the FILE_NAME, sans extension. + Otherwise OBJECT_DIRECTORY is taken to be the name of the object *file* + and the data files are named from that. */ + +static void +create_file_names (const char *file_name) +{ + char *cptr; + char *name; + int length = strlen (file_name); + int base; + + /* Free previous file names. */ + free (bbg_file_name); + free (da_file_name); + da_file_name = bbg_file_name = NULL; + bbg_file_time = 0; + bbg_stamp = 0; + + if (object_directory && object_directory[0]) + { + struct stat status; + + length += strlen (object_directory) + 2; + name = XNEWVEC (char, length); + name[0] = 0; + + base = !stat (object_directory, &status) && S_ISDIR (status.st_mode); + strcat (name, object_directory); + if (base && (!IS_DIR_SEPARATOR (name[strlen (name) - 1]))) + strcat (name, "/"); + } + else + { + name = XNEWVEC (char, length + 1); + strcpy (name, file_name); + base = 0; + } + + if (base) + { + /* Append source file name. */ + const char *cptr = lbasename (file_name); + strcat (name, cptr ? cptr : file_name); + } + + /* Remove the extension. */ + cptr = strrchr (CONST_CAST (char *, lbasename (name)), '.'); + if (cptr) + *cptr = 0; + + length = strlen (name); + + bbg_file_name = XNEWVEC (char, length + strlen (GCOV_NOTE_SUFFIX) + 1); + strcpy (bbg_file_name, name); + strcpy (bbg_file_name + length, GCOV_NOTE_SUFFIX); + + da_file_name = XNEWVEC (char, length + strlen (GCOV_DATA_SUFFIX) + 1); + strcpy (da_file_name, name); + strcpy (da_file_name + length, GCOV_DATA_SUFFIX); + + free (name); + return; +} + +/* Find or create a source file structure for FILE_NAME. Copies + FILE_NAME on creation */ + +static unsigned +find_source (const char *file_name) +{ + char *canon; + unsigned idx; + struct stat status; + + if (!file_name) + file_name = "<unknown>"; + + name_map needle; + needle.name = file_name; + + vector<name_map>::iterator it = std::find (names.begin (), names.end (), + needle); + if (it != names.end ()) + { + idx = it->src; + goto check_date; + } + + /* Not found, try the canonical name. */ + canon = canonicalize_name (file_name); + needle.name = canon; + it = std::find (names.begin (), names.end (), needle); + if (it == names.end ()) + { + /* Not found with canonical name, create a new source. */ + source_info *src; + + idx = sources.size (); + needle = name_map (canon, idx); + names.push_back (needle); + + sources.push_back (source_info ()); + src = &sources.back (); + src->name = canon; + src->coverage.name = src->name; + src->index = idx; + if (source_length +#if HAVE_DOS_BASED_FILE_SYSTEM + /* You lose if separators don't match exactly in the + prefix. */ + && !strncasecmp (source_prefix, src->coverage.name, source_length) +#else + && !strncmp (source_prefix, src->coverage.name, source_length) +#endif + && IS_DIR_SEPARATOR (src->coverage.name[source_length])) + src->coverage.name += source_length + 1; + if (!stat (src->name, &status)) + src->file_time = status.st_mtime; + } + else + idx = it->src; + + needle.name = file_name; + if (std::find (names.begin (), names.end (), needle) == names.end ()) + { + /* Append the non-canonical name. */ + names.push_back (name_map (xstrdup (file_name), idx)); + } + + /* Resort the name map. */ + std::sort (names.begin (), names.end ()); + + check_date: + if (sources[idx].file_time > bbg_file_time) + { + static int info_emitted; + + fnotice (stderr, "%s:source file is newer than notes file '%s'\n", + file_name, bbg_file_name); + if (!info_emitted) + { + fnotice (stderr, + "(the message is displayed only once per source file)\n"); + info_emitted = 1; + } + sources[idx].file_time = 0; + } + + return idx; +} + +/* Read the notes file. Save functions to FUNCTIONS global vector. */ + +static void +read_graph_file (void) +{ + unsigned version; + unsigned current_tag = 0; + unsigned tag; + + if (!gcov_open (bbg_file_name, 1)) + { + fnotice (stderr, "%s:cannot open notes file\n", bbg_file_name); + return_code = 1; + return; + } + bbg_file_time = gcov_time (); + if (!gcov_magic (gcov_read_unsigned (), GCOV_NOTE_MAGIC)) + { + fnotice (stderr, "%s:not a gcov notes file\n", bbg_file_name); + return_code = 2; + gcov_close (); + return; + } + + version = gcov_read_unsigned (); + if (version != GCOV_VERSION) + { + char v[4], e[4]; + + GCOV_UNSIGNED2STRING (v, version); + GCOV_UNSIGNED2STRING (e, GCOV_VERSION); + + fnotice (stderr, "%s:version '%.4s', prefer '%.4s'\n", + bbg_file_name, v, e); + return_code = 3; + } + bbg_stamp = gcov_read_unsigned (); + /* Read checksum. */ + gcov_read_unsigned (); + bbg_cwd = xstrdup (gcov_read_string ()); + bbg_supports_has_unexecuted_blocks = gcov_read_unsigned (); + + function_info *fn = NULL; + while ((tag = gcov_read_unsigned ())) + { + unsigned length = gcov_read_unsigned (); + gcov_position_t base = gcov_position (); + + if (tag == GCOV_TAG_FUNCTION) + { + char *function_name; + unsigned ident; + unsigned lineno_checksum, cfg_checksum; + + ident = gcov_read_unsigned (); + lineno_checksum = gcov_read_unsigned (); + cfg_checksum = gcov_read_unsigned (); + function_name = xstrdup (gcov_read_string ()); + unsigned artificial = gcov_read_unsigned (); + unsigned src_idx = find_source (gcov_read_string ()); + unsigned start_line = gcov_read_unsigned (); + unsigned start_column = gcov_read_unsigned (); + unsigned end_line = gcov_read_unsigned (); + unsigned end_column = gcov_read_unsigned (); + + fn = new function_info (); + functions.push_back (fn); + ident_to_fn[ident] = fn; + + fn->m_name = function_name; + fn->ident = ident; + fn->lineno_checksum = lineno_checksum; + fn->cfg_checksum = cfg_checksum; + fn->src = src_idx; + fn->start_line = start_line; + fn->start_column = start_column; + fn->end_line = end_line; + fn->end_column = end_column; + fn->artificial = artificial; + + current_tag = tag; + } + else if (fn && tag == GCOV_TAG_BLOCKS) + { + if (!fn->blocks.empty ()) + fnotice (stderr, "%s:already seen blocks for '%s'\n", + bbg_file_name, fn->get_name ()); + else + fn->blocks.resize (gcov_read_unsigned ()); + } + else if (fn && tag == GCOV_TAG_ARCS) + { + unsigned src = gcov_read_unsigned (); + fn->blocks[src].id = src; + unsigned num_dests = GCOV_TAG_ARCS_NUM (length); + block_info *src_blk = &fn->blocks[src]; + unsigned mark_catches = 0; + struct arc_info *arc; + + if (src >= fn->blocks.size () || fn->blocks[src].succ) + goto corrupt; + + while (num_dests--) + { + unsigned dest = gcov_read_unsigned (); + unsigned flags = gcov_read_unsigned (); + + if (dest >= fn->blocks.size ()) + goto corrupt; + arc = XCNEW (arc_info); + + arc->dst = &fn->blocks[dest]; + /* Set id in order to find EXIT_BLOCK. */ + arc->dst->id = dest; + arc->src = src_blk; + + arc->count = 0; + arc->count_valid = 0; + arc->on_tree = !!(flags & GCOV_ARC_ON_TREE); + arc->fake = !!(flags & GCOV_ARC_FAKE); + arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH); + + arc->succ_next = src_blk->succ; + src_blk->succ = arc; + src_blk->num_succ++; + + arc->pred_next = fn->blocks[dest].pred; + fn->blocks[dest].pred = arc; + fn->blocks[dest].num_pred++; + + if (arc->fake) + { + if (src) + { + /* Exceptional exit from this function, the + source block must be a call. */ + fn->blocks[src].is_call_site = 1; + arc->is_call_non_return = 1; + mark_catches = 1; + } + else + { + /* Non-local return from a callee of this + function. The destination block is a setjmp. */ + arc->is_nonlocal_return = 1; + fn->blocks[dest].is_nonlocal_return = 1; + } + } + + if (!arc->on_tree) + fn->counts.push_back (0); + } + + if (mark_catches) + { + /* We have a fake exit from this block. The other + non-fall through exits must be to catch handlers. + Mark them as catch arcs. */ + + for (arc = src_blk->succ; arc; arc = arc->succ_next) + if (!arc->fake && !arc->fall_through) + { + arc->is_throw = 1; + fn->has_catch = 1; + } + } + } + else if (fn && tag == GCOV_TAG_LINES) + { + unsigned blockno = gcov_read_unsigned (); + block_info *block = &fn->blocks[blockno]; + + if (blockno >= fn->blocks.size ()) + goto corrupt; + + while (true) + { + unsigned lineno = gcov_read_unsigned (); + + if (lineno) + block->locations.back ().lines.push_back (lineno); + else + { + const char *file_name = gcov_read_string (); + + if (!file_name) + break; + block->locations.push_back (block_location_info + (find_source (file_name))); + } + } + } + else if (current_tag && !GCOV_TAG_IS_SUBTAG (current_tag, tag)) + { + fn = NULL; + current_tag = 0; + } + gcov_sync (base, length); + if (gcov_is_error ()) + { + corrupt:; + fnotice (stderr, "%s:corrupted\n", bbg_file_name); + return_code = 4; + break; + } + } + gcov_close (); + + if (functions.empty ()) + fnotice (stderr, "%s:no functions found\n", bbg_file_name); +} + +/* Reads profiles from the count file and attach to each + function. Return nonzero if fatal error. */ + +static int +read_count_file (void) +{ + unsigned ix; + unsigned version; + unsigned tag; + function_info *fn = NULL; + int error = 0; + map<unsigned, function_info *>::iterator it; + + if (!gcov_open (da_file_name, 1)) + { + fnotice (stderr, "%s:cannot open data file, assuming not executed\n", + da_file_name); + no_data_file = 1; + return 0; + } + if (!gcov_magic (gcov_read_unsigned (), GCOV_DATA_MAGIC)) + { + fnotice (stderr, "%s:not a gcov data file\n", da_file_name); + return_code = 2; + cleanup:; + gcov_close (); + return 1; + } + version = gcov_read_unsigned (); + if (version != GCOV_VERSION) + { + char v[4], e[4]; + + GCOV_UNSIGNED2STRING (v, version); + GCOV_UNSIGNED2STRING (e, GCOV_VERSION); + + fnotice (stderr, "%s:version '%.4s', prefer version '%.4s'\n", + da_file_name, v, e); + return_code = 3; + } + tag = gcov_read_unsigned (); + if (tag != bbg_stamp) + { + fnotice (stderr, "%s:stamp mismatch with notes file\n", da_file_name); + return_code = 5; + goto cleanup; + } + + /* Read checksum. */ + gcov_read_unsigned (); + + while ((tag = gcov_read_unsigned ())) + { + unsigned length = gcov_read_unsigned (); + int read_length = (int)length; + unsigned long base = gcov_position (); + + if (tag == GCOV_TAG_OBJECT_SUMMARY) + { + struct gcov_summary summary; + gcov_read_summary (&summary); + object_runs = summary.runs; + } + else if (tag == GCOV_TAG_FUNCTION && !length) + ; /* placeholder */ + else if (tag == GCOV_TAG_FUNCTION && length == GCOV_TAG_FUNCTION_LENGTH) + { + unsigned ident; + ident = gcov_read_unsigned (); + fn = NULL; + it = ident_to_fn.find (ident); + if (it != ident_to_fn.end ()) + fn = it->second; + + if (!fn) + ; + else if (gcov_read_unsigned () != fn->lineno_checksum + || gcov_read_unsigned () != fn->cfg_checksum) + { + mismatch:; + fnotice (stderr, "%s:profile mismatch for '%s'\n", + da_file_name, fn->get_name ()); + goto cleanup; + } + } + else if (tag == GCOV_TAG_FOR_COUNTER (GCOV_COUNTER_ARCS) && fn) + { + length = abs (read_length); + if (length != GCOV_TAG_COUNTER_LENGTH (fn->counts.size ())) + goto mismatch; + + if (read_length > 0) + for (ix = 0; ix != fn->counts.size (); ix++) + fn->counts[ix] += gcov_read_counter (); + } + if (read_length < 0) + read_length = 0; + gcov_sync (base, read_length); + if ((error = gcov_is_error ())) + { + fnotice (stderr, + error < 0 + ? N_("%s:overflowed\n") + : N_("%s:corrupted\n"), + da_file_name); + return_code = 4; + goto cleanup; + } + } + + gcov_close (); + return 0; +} + +/* Solve the flow graph. Propagate counts from the instrumented arcs + to the blocks and the uninstrumented arcs. */ + +static void +solve_flow_graph (function_info *fn) +{ + unsigned ix; + arc_info *arc; + gcov_type *count_ptr = &fn->counts.front (); + block_info *blk; + block_info *valid_blocks = NULL; /* valid, but unpropagated blocks. */ + block_info *invalid_blocks = NULL; /* invalid, but inferable blocks. */ + + /* The arcs were built in reverse order. Fix that now. */ + for (ix = fn->blocks.size (); ix--;) + { + arc_info *arc_p, *arc_n; + + for (arc_p = NULL, arc = fn->blocks[ix].succ; arc; + arc_p = arc, arc = arc_n) + { + arc_n = arc->succ_next; + arc->succ_next = arc_p; + } + fn->blocks[ix].succ = arc_p; + + for (arc_p = NULL, arc = fn->blocks[ix].pred; arc; + arc_p = arc, arc = arc_n) + { + arc_n = arc->pred_next; + arc->pred_next = arc_p; + } + fn->blocks[ix].pred = arc_p; + } + + if (fn->blocks.size () < 2) + fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n", + bbg_file_name, fn->get_name ()); + else + { + if (fn->blocks[ENTRY_BLOCK].num_pred) + fnotice (stderr, "%s:'%s' has arcs to entry block\n", + bbg_file_name, fn->get_name ()); + else + /* We can't deduce the entry block counts from the lack of + predecessors. */ + fn->blocks[ENTRY_BLOCK].num_pred = ~(unsigned)0; + + if (fn->blocks[EXIT_BLOCK].num_succ) + fnotice (stderr, "%s:'%s' has arcs from exit block\n", + bbg_file_name, fn->get_name ()); + else + /* Likewise, we can't deduce exit block counts from the lack + of its successors. */ + fn->blocks[EXIT_BLOCK].num_succ = ~(unsigned)0; + } + + /* Propagate the measured counts, this must be done in the same + order as the code in profile.c */ + for (unsigned i = 0; i < fn->blocks.size (); i++) + { + blk = &fn->blocks[i]; + block_info const *prev_dst = NULL; + int out_of_order = 0; + int non_fake_succ = 0; + + for (arc = blk->succ; arc; arc = arc->succ_next) + { + if (!arc->fake) + non_fake_succ++; + + if (!arc->on_tree) + { + if (count_ptr) + arc->count = *count_ptr++; + arc->count_valid = 1; + blk->num_succ--; + arc->dst->num_pred--; + } + if (prev_dst && prev_dst > arc->dst) + out_of_order = 1; + prev_dst = arc->dst; + } + if (non_fake_succ == 1) + { + /* If there is only one non-fake exit, it is an + unconditional branch. */ + for (arc = blk->succ; arc; arc = arc->succ_next) + if (!arc->fake) + { + arc->is_unconditional = 1; + /* If this block is instrumenting a call, it might be + an artificial block. It is not artificial if it has + a non-fallthrough exit, or the destination of this + arc has more than one entry. Mark the destination + block as a return site, if none of those conditions + hold. */ + if (blk->is_call_site && arc->fall_through + && arc->dst->pred == arc && !arc->pred_next) + arc->dst->is_call_return = 1; + } + } + + /* Sort the successor arcs into ascending dst order. profile.c + normally produces arcs in the right order, but sometimes with + one or two out of order. We're not using a particularly + smart sort. */ + if (out_of_order) + { + arc_info *start = blk->succ; + unsigned changes = 1; + + while (changes) + { + arc_info *arc, *arc_p, *arc_n; + + changes = 0; + for (arc_p = NULL, arc = start; (arc_n = arc->succ_next);) + { + if (arc->dst > arc_n->dst) + { + changes = 1; + if (arc_p) + arc_p->succ_next = arc_n; + else + start = arc_n; + arc->succ_next = arc_n->succ_next; + arc_n->succ_next = arc; + arc_p = arc_n; + } + else + { + arc_p = arc; + arc = arc_n; + } + } + } + blk->succ = start; + } + + /* Place it on the invalid chain, it will be ignored if that's + wrong. */ + blk->invalid_chain = 1; + blk->chain = invalid_blocks; + invalid_blocks = blk; + } + + while (invalid_blocks || valid_blocks) + { + while ((blk = invalid_blocks)) + { + gcov_type total = 0; + const arc_info *arc; + + invalid_blocks = blk->chain; + blk->invalid_chain = 0; + if (!blk->num_succ) + for (arc = blk->succ; arc; arc = arc->succ_next) + total += arc->count; + else if (!blk->num_pred) + for (arc = blk->pred; arc; arc = arc->pred_next) + total += arc->count; + else + continue; + + blk->count = total; + blk->count_valid = 1; + blk->chain = valid_blocks; + blk->valid_chain = 1; + valid_blocks = blk; + } + while ((blk = valid_blocks)) + { + gcov_type total; + arc_info *arc, *inv_arc; + + valid_blocks = blk->chain; + blk->valid_chain = 0; + if (blk->num_succ == 1) + { + block_info *dst; + + total = blk->count; + inv_arc = NULL; + for (arc = blk->succ; arc; arc = arc->succ_next) + { + total -= arc->count; + if (!arc->count_valid) + inv_arc = arc; + } + dst = inv_arc->dst; + inv_arc->count_valid = 1; + inv_arc->count = total; + blk->num_succ--; + dst->num_pred--; + if (dst->count_valid) + { + if (dst->num_pred == 1 && !dst->valid_chain) + { + dst->chain = valid_blocks; + dst->valid_chain = 1; + valid_blocks = dst; + } + } + else + { + if (!dst->num_pred && !dst->invalid_chain) + { + dst->chain = invalid_blocks; + dst->invalid_chain = 1; + invalid_blocks = dst; + } + } + } + if (blk->num_pred == 1) + { + block_info *src; + + total = blk->count; + inv_arc = NULL; + for (arc = blk->pred; arc; arc = arc->pred_next) + { + total -= arc->count; + if (!arc->count_valid) + inv_arc = arc; + } + src = inv_arc->src; + inv_arc->count_valid = 1; + inv_arc->count = total; + blk->num_pred--; + src->num_succ--; + if (src->count_valid) + { + if (src->num_succ == 1 && !src->valid_chain) + { + src->chain = valid_blocks; + src->valid_chain = 1; + valid_blocks = src; + } + } + else + { + if (!src->num_succ && !src->invalid_chain) + { + src->chain = invalid_blocks; + src->invalid_chain = 1; + invalid_blocks = src; + } + } + } + } + } + + /* If the graph has been correctly solved, every block will have a + valid count. */ + for (unsigned i = 0; ix < fn->blocks.size (); i++) + if (!fn->blocks[i].count_valid) + { + fnotice (stderr, "%s:graph is unsolvable for '%s'\n", + bbg_file_name, fn->get_name ()); + break; + } +} + +/* Mark all the blocks only reachable via an incoming catch. */ + +static void +find_exception_blocks (function_info *fn) +{ + unsigned ix; + block_info **queue = XALLOCAVEC (block_info *, fn->blocks.size ()); + + /* First mark all blocks as exceptional. */ + for (ix = fn->blocks.size (); ix--;) + fn->blocks[ix].exceptional = 1; + + /* Now mark all the blocks reachable via non-fake edges */ + queue[0] = &fn->blocks[0]; + queue[0]->exceptional = 0; + for (ix = 1; ix;) + { + block_info *block = queue[--ix]; + const arc_info *arc; + + for (arc = block->succ; arc; arc = arc->succ_next) + if (!arc->fake && !arc->is_throw && arc->dst->exceptional) + { + arc->dst->exceptional = 0; + queue[ix++] = arc->dst; + } + } +} + + +/* Increment totals in COVERAGE according to arc ARC. */ + +static void +add_branch_counts (coverage_info *coverage, const arc_info *arc) +{ + if (arc->is_call_non_return) + { + coverage->calls++; + if (arc->src->count) + coverage->calls_executed++; + } + else if (!arc->is_unconditional) + { + coverage->branches++; + if (arc->src->count) + coverage->branches_executed++; + if (arc->count) + coverage->branches_taken++; + } +} + +/* Format COUNT, if flag_human_readable_numbers is set, return it human + readable format. */ + +static char const * +format_count (gcov_type count) +{ + static char buffer[64]; + const char *units = " kMGTPEZY"; + + if (count < 1000 || !flag_human_readable_numbers) + { + sprintf (buffer, "%" PRId64, count); + return buffer; + } + + unsigned i; + gcov_type divisor = 1; + for (i = 0; units[i+1]; i++, divisor *= 1000) + { + if (count + divisor / 2 < 1000 * divisor) + break; + } + float r = 1.0f * count / divisor; + sprintf (buffer, "%.1f%c", r, units[i]); + return buffer; +} + +/* Format a GCOV_TYPE integer as either a percent ratio, or absolute + count. If DECIMAL_PLACES >= 0, format TOP/BOTTOM * 100 to DECIMAL_PLACES. + If DECIMAL_PLACES is zero, no decimal point is printed. Only print 100% when + TOP==BOTTOM and only print 0% when TOP=0. If DECIMAL_PLACES < 0, then simply + format TOP. Return pointer to a static string. */ + +static char const * +format_gcov (gcov_type top, gcov_type bottom, int decimal_places) +{ + static char buffer[20]; + + if (decimal_places >= 0) + { + float ratio = bottom ? 100.0f * top / bottom: 0; + + /* Round up to 1% if there's a small non-zero value. */ + if (ratio > 0.0f && ratio < 0.5f && decimal_places == 0) + ratio = 1.0f; + sprintf (buffer, "%.*f%%", decimal_places, ratio); + } + else + return format_count (top); + + return buffer; +} + +/* Summary of execution */ + +static void +executed_summary (unsigned lines, unsigned executed) +{ + if (lines) + fnotice (stdout, "Lines executed:%s of %d\n", + format_gcov (executed, lines, 2), lines); + else + fnotice (stdout, "No executable lines\n"); +} + +/* Output summary info for a function. */ + +static void +function_summary (const coverage_info *coverage) +{ + fnotice (stdout, "%s '%s'\n", "Function", coverage->name); + executed_summary (coverage->lines, coverage->lines_executed); +} + +/* Output summary info for a file. */ + +static void +file_summary (const coverage_info *coverage) +{ + fnotice (stdout, "%s '%s'\n", "File", coverage->name); + executed_summary (coverage->lines, coverage->lines_executed); + + if (flag_branches) + { + if (coverage->branches) + { + fnotice (stdout, "Branches executed:%s of %d\n", + format_gcov (coverage->branches_executed, + coverage->branches, 2), + coverage->branches); + fnotice (stdout, "Taken at least once:%s of %d\n", + format_gcov (coverage->branches_taken, + coverage->branches, 2), + coverage->branches); + } + else + fnotice (stdout, "No branches\n"); + if (coverage->calls) + fnotice (stdout, "Calls executed:%s of %d\n", + format_gcov (coverage->calls_executed, coverage->calls, 2), + coverage->calls); + else + fnotice (stdout, "No calls\n"); + } +} + +/* Canonicalize the filename NAME by canonicalizing directory + separators, eliding . components and resolving .. components + appropriately. Always returns a unique string. */ + +static char * +canonicalize_name (const char *name) +{ + /* The canonical name cannot be longer than the incoming name. */ + char *result = XNEWVEC (char, strlen (name) + 1); + const char *base = name, *probe; + char *ptr = result; + char *dd_base; + int slash = 0; + +#if HAVE_DOS_BASED_FILE_SYSTEM + if (base[0] && base[1] == ':') + { + result[0] = base[0]; + result[1] = ':'; + base += 2; + ptr += 2; + } +#endif + for (dd_base = ptr; *base; base = probe) + { + size_t len; + + for (probe = base; *probe; probe++) + if (IS_DIR_SEPARATOR (*probe)) + break; + + len = probe - base; + if (len == 1 && base[0] == '.') + /* Elide a '.' directory */ + ; + else if (len == 2 && base[0] == '.' && base[1] == '.') + { + /* '..', we can only elide it and the previous directory, if + we're not a symlink. */ + struct stat ATTRIBUTE_UNUSED buf; + + *ptr = 0; + if (dd_base == ptr +#if defined (S_ISLNK) + /* S_ISLNK is not POSIX.1-1996. */ + || stat (result, &buf) || S_ISLNK (buf.st_mode) +#endif + ) + { + /* Cannot elide, or unreadable or a symlink. */ + dd_base = ptr + 2 + slash; + goto regular; + } + while (ptr != dd_base && *ptr != '/') + ptr--; + slash = ptr != result; + } + else + { + regular: + /* Regular pathname component. */ + if (slash) + *ptr++ = '/'; + memcpy (ptr, base, len); + ptr += len; + slash = 1; + } + + for (; IS_DIR_SEPARATOR (*probe); probe++) + continue; + } + *ptr = 0; + + return result; +} + +/* Generate an output file name. INPUT_NAME is the canonicalized main + input file and SRC_NAME is the canonicalized file name. + LONG_OUTPUT_NAMES and PRESERVE_PATHS affect name generation. With + long_output_names we prepend the processed name of the input file + to each output name (except when the current source file is the + input file, so you don't get a double concatenation). The two + components are separated by '##'. With preserve_paths we create a + filename from all path components of the source file, replacing '/' + with '#', and .. with '^', without it we simply take the basename + component. (Remember, the canonicalized name will already have + elided '.' components and converted \\ separators.) */ + +static string +make_gcov_file_name (const char *input_name, const char *src_name) +{ + string str; + + /* When hashing filenames, we shorten them by only using the filename + component and appending a hash of the full (mangled) pathname. */ + if (flag_hash_filenames) + str = (string (mangle_name (src_name)) + "##" + + get_md5sum (src_name) + ".gcov"); + else + { + if (flag_long_names && input_name && strcmp (src_name, input_name) != 0) + { + str += mangle_name (input_name); + str += "##"; + } + + str += mangle_name (src_name); + str += ".gcov"; + } + + return str; +} + +/* Mangle BASE name, copy it at the beginning of PTR buffer and + return address of the \0 character of the buffer. */ + +static char * +mangle_name (char const *base) +{ + /* Generate the source filename part. */ + if (!flag_preserve_paths) + return xstrdup (lbasename (base)); + else + return mangle_path (base); +} + +/* Scan through the bb_data for each line in the block, increment + the line number execution count indicated by the execution count of + the appropriate basic block. */ + +static void +add_line_counts (coverage_info *coverage, function_info *fn) +{ + bool has_any_line = false; + /* Scan each basic block. */ + for (unsigned ix = 0; ix != fn->blocks.size (); ix++) + { + line_info *line = NULL; + block_info *block = &fn->blocks[ix]; + if (block->count && ix && ix + 1 != fn->blocks.size ()) + fn->blocks_executed++; + for (unsigned i = 0; i < block->locations.size (); i++) + { + unsigned src_idx = block->locations[i].source_file_idx; + vector<unsigned> &lines = block->locations[i].lines; + + block->cycle.arc = NULL; + block->cycle.ident = ~0U; + + for (unsigned j = 0; j < lines.size (); j++) + { + unsigned ln = lines[j]; + + /* Line belongs to a function that is in a group. */ + if (fn->group_line_p (ln, src_idx)) + { + gcc_assert (lines[j] - fn->start_line < fn->lines.size ()); + line = &(fn->lines[lines[j] - fn->start_line]); + line->exists = 1; + if (!block->exceptional) + { + line->unexceptional = 1; + if (block->count == 0) + line->has_unexecuted_block = 1; + } + line->count += block->count; + } + else + { + gcc_assert (ln < sources[src_idx].lines.size ()); + line = &(sources[src_idx].lines[ln]); + if (coverage) + { + if (!line->exists) + coverage->lines++; + if (!line->count && block->count) + coverage->lines_executed++; + } + line->exists = 1; + if (!block->exceptional) + { + line->unexceptional = 1; + if (block->count == 0) + line->has_unexecuted_block = 1; + } + line->count += block->count; + } + } + + has_any_line = true; + + if (!ix || ix + 1 == fn->blocks.size ()) + /* Entry or exit block. */; + else if (line != NULL) + { + line->blocks.push_back (block); + + if (flag_branches) + { + arc_info *arc; + + for (arc = block->succ; arc; arc = arc->succ_next) + line->branches.push_back (arc); + } + } + } + } + + if (!has_any_line) + fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, + fn->get_name ()); +} + +/* Accumulate info for LINE that belongs to SRC source file. If ADD_COVERAGE + is set to true, update source file summary. */ + +static void accumulate_line_info (line_info *line, source_info *src, + bool add_coverage) +{ + if (add_coverage) + for (vector<arc_info *>::iterator it = line->branches.begin (); + it != line->branches.end (); it++) + add_branch_counts (&src->coverage, *it); + + if (!line->blocks.empty ()) + { + /* The user expects the line count to be the number of times + a line has been executed. Simply summing the block count + will give an artificially high number. The Right Thing + is to sum the entry counts to the graph of blocks on this + line, then find the elementary cycles of the local graph + and add the transition counts of those cycles. */ + gcov_type count = 0; + + /* Cycle detection. */ + for (vector<block_info *>::iterator it = line->blocks.begin (); + it != line->blocks.end (); it++) + { + for (arc_info *arc = (*it)->pred; arc; arc = arc->pred_next) + if (!line->has_block (arc->src)) + count += arc->count; + for (arc_info *arc = (*it)->succ; arc; arc = arc->succ_next) + arc->cs_count = arc->count; + } + + /* Now, add the count of loops entirely on this line. */ + count += get_cycles_count (*line); + line->count = count; + + if (line->count > src->maximum_count) + src->maximum_count = line->count; + } + + if (line->exists && add_coverage) + { + src->coverage.lines++; + if (line->count) + src->coverage.lines_executed++; + } +} + +/* Accumulate the line counts of a file. */ + +static void +accumulate_line_counts (source_info *src) +{ + /* First work on group functions. */ + for (vector<function_info *>::iterator it = src->functions.begin (); + it != src->functions.end (); it++) + { + function_info *fn = *it; + + if (fn->src != src->index || !fn->is_group) + continue; + + for (vector<line_info>::iterator it2 = fn->lines.begin (); + it2 != fn->lines.end (); it2++) + { + line_info *line = &(*it2); + accumulate_line_info (line, src, false); + } + } + + /* Work on global lines that line in source file SRC. */ + for (vector<line_info>::iterator it = src->lines.begin (); + it != src->lines.end (); it++) + accumulate_line_info (&(*it), src, true); + + /* If not using intermediate mode, sum lines of group functions and + add them to lines that live in a source file. */ + if (!flag_json_format) + for (vector<function_info *>::iterator it = src->functions.begin (); + it != src->functions.end (); it++) + { + function_info *fn = *it; + + if (fn->src != src->index || !fn->is_group) + continue; + + for (unsigned i = 0; i < fn->lines.size (); i++) + { + line_info *fn_line = &fn->lines[i]; + if (fn_line->exists) + { + unsigned ln = fn->start_line + i; + line_info *src_line = &src->lines[ln]; + + if (!src_line->exists) + src->coverage.lines++; + if (!src_line->count && fn_line->count) + src->coverage.lines_executed++; + + src_line->count += fn_line->count; + src_line->exists = 1; + + if (fn_line->has_unexecuted_block) + src_line->has_unexecuted_block = 1; + + if (fn_line->unexceptional) + src_line->unexceptional = 1; + } + } + } +} + +/* Output information about ARC number IX. Returns nonzero if + anything is output. */ + +static int +output_branch_count (FILE *gcov_file, int ix, const arc_info *arc) +{ + if (arc->is_call_non_return) + { + if (arc->src->count) + { + fnotice (gcov_file, "call %2d returned %s\n", ix, + format_gcov (arc->src->count - arc->count, + arc->src->count, -flag_counts)); + } + else + fnotice (gcov_file, "call %2d never executed\n", ix); + } + else if (!arc->is_unconditional) + { + if (arc->src->count) + fnotice (gcov_file, "branch %2d taken %s%s", ix, + format_gcov (arc->count, arc->src->count, -flag_counts), + arc->fall_through ? " (fallthrough)" + : arc->is_throw ? " (throw)" : ""); + else + fnotice (gcov_file, "branch %2d never executed", ix); + + if (flag_verbose) + fnotice (gcov_file, " (BB %d)", arc->dst->id); + + fnotice (gcov_file, "\n"); + } + else if (flag_unconditional && !arc->dst->is_call_return) + { + if (arc->src->count) + fnotice (gcov_file, "unconditional %2d taken %s\n", ix, + format_gcov (arc->count, arc->src->count, -flag_counts)); + else + fnotice (gcov_file, "unconditional %2d never executed\n", ix); + } + else + return 0; + return 1; +} + +static const char * +read_line (FILE *file) +{ + static char *string; + static size_t string_len; + size_t pos = 0; + + if (!string_len) + { + string_len = 200; + string = XNEWVEC (char, string_len); + } + + while (fgets (string + pos, string_len - pos, file)) + { + size_t len = strlen (string + pos); + + if (len && string[pos + len - 1] == '\n') + { + string[pos + len - 1] = 0; + return string; + } + pos += len; + /* If the file contains NUL characters or an incomplete + last line, which can happen more than once in one run, + we have to avoid doubling the STRING_LEN unnecessarily. */ + if (pos > string_len / 2) + { + string_len *= 2; + string = XRESIZEVEC (char, string, string_len); + } + } + + return pos ? string : NULL; +} + +/* Pad string S with spaces from left to have total width equal to 9. */ + +static void +pad_count_string (string &s) +{ + if (s.size () < 9) + s.insert (0, 9 - s.size (), ' '); +} + +/* Print GCOV line beginning to F stream. If EXISTS is set to true, the + line exists in source file. UNEXCEPTIONAL indicated that it's not in + an exceptional statement. The output is printed for LINE_NUM of given + COUNT of executions. EXCEPTIONAL_STRING and UNEXCEPTIONAL_STRING are + used to indicate non-executed blocks. */ + +static void +output_line_beginning (FILE *f, bool exists, bool unexceptional, + bool has_unexecuted_block, + gcov_type count, unsigned line_num, + const char *exceptional_string, + const char *unexceptional_string, + unsigned int maximum_count) +{ + string s; + if (exists) + { + if (count > 0) + { + s = format_gcov (count, 0, -1); + if (has_unexecuted_block + && bbg_supports_has_unexecuted_blocks) + { + if (flag_use_colors) + { + pad_count_string (s); + s.insert (0, SGR_SEQ (COLOR_BG_MAGENTA + COLOR_SEPARATOR COLOR_FG_WHITE)); + s += SGR_RESET; + } + else + s += "*"; + } + pad_count_string (s); + } + else + { + if (flag_use_colors) + { + s = "0"; + pad_count_string (s); + if (unexceptional) + s.insert (0, SGR_SEQ (COLOR_BG_RED + COLOR_SEPARATOR COLOR_FG_WHITE)); + else + s.insert (0, SGR_SEQ (COLOR_BG_CYAN + COLOR_SEPARATOR COLOR_FG_WHITE)); + s += SGR_RESET; + } + else + { + s = unexceptional ? unexceptional_string : exceptional_string; + pad_count_string (s); + } + } + } + else + { + s = "-"; + pad_count_string (s); + } + + /* Format line number in output. */ + char buffer[16]; + sprintf (buffer, "%5u", line_num); + string linestr (buffer); + + if (flag_use_hotness_colors && maximum_count) + { + if (count * 2 > maximum_count) /* > 50%. */ + linestr.insert (0, SGR_SEQ (COLOR_BG_RED)); + else if (count * 5 > maximum_count) /* > 20%. */ + linestr.insert (0, SGR_SEQ (COLOR_BG_YELLOW)); + else if (count * 10 > maximum_count) /* > 10%. */ + linestr.insert (0, SGR_SEQ (COLOR_BG_GREEN)); + linestr += SGR_RESET; + } + + fprintf (f, "%s:%s", s.c_str (), linestr.c_str ()); +} + +static void +print_source_line (FILE *f, const vector<const char *> &source_lines, + unsigned line) +{ + gcc_assert (line >= 1); + gcc_assert (line <= source_lines.size ()); + + fprintf (f, ":%s\n", source_lines[line - 1]); +} + +/* Output line details for LINE and print it to F file. LINE lives on + LINE_NUM. */ + +static void +output_line_details (FILE *f, const line_info *line, unsigned line_num) +{ + if (flag_all_blocks) + { + arc_info *arc; + int ix, jx; + + ix = jx = 0; + for (vector<block_info *>::const_iterator it = line->blocks.begin (); + it != line->blocks.end (); it++) + { + if (!(*it)->is_call_return) + { + output_line_beginning (f, line->exists, + (*it)->exceptional, false, + (*it)->count, line_num, + "%%%%%", "$$$$$", 0); + fprintf (f, "-block %2d", ix++); + if (flag_verbose) + fprintf (f, " (BB %u)", (*it)->id); + fprintf (f, "\n"); + } + if (flag_branches) + for (arc = (*it)->succ; arc; arc = arc->succ_next) + jx += output_branch_count (f, jx, arc); + } + } + else if (flag_branches) + { + int ix; + + ix = 0; + for (vector<arc_info *>::const_iterator it = line->branches.begin (); + it != line->branches.end (); it++) + ix += output_branch_count (f, ix, (*it)); + } +} + +/* Output detail statistics about function FN to file F. */ + +static void +output_function_details (FILE *f, function_info *fn) +{ + if (!flag_branches) + return; + + arc_info *arc = fn->blocks[EXIT_BLOCK].pred; + gcov_type return_count = fn->blocks[EXIT_BLOCK].count; + gcov_type called_count = fn->blocks[ENTRY_BLOCK].count; + + for (; arc; arc = arc->pred_next) + if (arc->fake) + return_count -= arc->count; + + fprintf (f, "function %s", fn->get_name ()); + fprintf (f, " called %s", + format_gcov (called_count, 0, -1)); + fprintf (f, " returned %s", + format_gcov (return_count, called_count, 0)); + fprintf (f, " blocks executed %s", + format_gcov (fn->blocks_executed, fn->get_block_count (), 0)); + fprintf (f, "\n"); +} + +/* Read in the source file one line at a time, and output that line to + the gcov file preceded by its execution count and other + information. */ + +static void +output_lines (FILE *gcov_file, const source_info *src) +{ +#define DEFAULT_LINE_START " -: 0:" +#define FN_SEPARATOR "------------------\n" + + FILE *source_file; + const char *retval; + + /* Print colorization legend. */ + if (flag_use_colors) + fprintf (gcov_file, "%s", + DEFAULT_LINE_START "Colorization: profile count: " \ + SGR_SEQ (COLOR_BG_CYAN) "zero coverage (exceptional)" SGR_RESET \ + " " \ + SGR_SEQ (COLOR_BG_RED) "zero coverage (unexceptional)" SGR_RESET \ + " " \ + SGR_SEQ (COLOR_BG_MAGENTA) "unexecuted block" SGR_RESET "\n"); + + if (flag_use_hotness_colors) + fprintf (gcov_file, "%s", + DEFAULT_LINE_START "Colorization: line numbers: hotness: " \ + SGR_SEQ (COLOR_BG_RED) "> 50%" SGR_RESET " " \ + SGR_SEQ (COLOR_BG_YELLOW) "> 20%" SGR_RESET " " \ + SGR_SEQ (COLOR_BG_GREEN) "> 10%" SGR_RESET "\n"); + + fprintf (gcov_file, DEFAULT_LINE_START "Source:%s\n", src->coverage.name); + if (!multiple_files) + { + fprintf (gcov_file, DEFAULT_LINE_START "Graph:%s\n", bbg_file_name); + fprintf (gcov_file, DEFAULT_LINE_START "Data:%s\n", + no_data_file ? "-" : da_file_name); + fprintf (gcov_file, DEFAULT_LINE_START "Runs:%u\n", object_runs); + } + + source_file = fopen (src->name, "r"); + if (!source_file) + fnotice (stderr, "Cannot open source file %s\n", src->name); + else if (src->file_time == 0) + fprintf (gcov_file, DEFAULT_LINE_START "Source is newer than graph\n"); + + vector<const char *> source_lines; + if (source_file) + while ((retval = read_line (source_file)) != NULL) + source_lines.push_back (xstrdup (retval)); + + unsigned line_start_group = 0; + vector<function_info *> *fns; + + for (unsigned line_num = 1; line_num <= source_lines.size (); line_num++) + { + if (line_num >= src->lines.size ()) + { + fprintf (gcov_file, "%9s:%5u", "-", line_num); + print_source_line (gcov_file, source_lines, line_num); + continue; + } + + const line_info *line = &src->lines[line_num]; + + if (line_start_group == 0) + { + fns = src->get_functions_at_location (line_num); + if (fns != NULL && fns->size () > 1) + { + /* It's possible to have functions that partially overlap, + thus take the maximum end_line of functions starting + at LINE_NUM. */ + for (unsigned i = 0; i < fns->size (); i++) + if ((*fns)[i]->end_line > line_start_group) + line_start_group = (*fns)[i]->end_line; + } + else if (fns != NULL && fns->size () == 1) + { + function_info *fn = (*fns)[0]; + output_function_details (gcov_file, fn); + } + } + + /* For lines which don't exist in the .bb file, print '-' before + the source line. For lines which exist but were never + executed, print '#####' or '=====' before the source line. + Otherwise, print the execution count before the source line. + There are 16 spaces of indentation added before the source + line so that tabs won't be messed up. */ + output_line_beginning (gcov_file, line->exists, line->unexceptional, + line->has_unexecuted_block, line->count, + line_num, "=====", "#####", src->maximum_count); + + print_source_line (gcov_file, source_lines, line_num); + output_line_details (gcov_file, line, line_num); + + if (line_start_group == line_num) + { + for (vector<function_info *>::iterator it = fns->begin (); + it != fns->end (); it++) + { + function_info *fn = *it; + vector<line_info> &lines = fn->lines; + + fprintf (gcov_file, FN_SEPARATOR); + + string fn_name = fn->get_name (); + if (flag_use_colors) + { + fn_name.insert (0, SGR_SEQ (COLOR_FG_CYAN)); + fn_name += SGR_RESET; + } + + fprintf (gcov_file, "%s:\n", fn_name.c_str ()); + + output_function_details (gcov_file, fn); + + /* Print all lines covered by the function. */ + for (unsigned i = 0; i < lines.size (); i++) + { + line_info *line = &lines[i]; + unsigned l = fn->start_line + i; + + /* For lines which don't exist in the .bb file, print '-' + before the source line. For lines which exist but + were never executed, print '#####' or '=====' before + the source line. Otherwise, print the execution count + before the source line. + There are 16 spaces of indentation added before the source + line so that tabs won't be messed up. */ + output_line_beginning (gcov_file, line->exists, + line->unexceptional, + line->has_unexecuted_block, + line->count, + l, "=====", "#####", + src->maximum_count); + + print_source_line (gcov_file, source_lines, l); + output_line_details (gcov_file, line, l); + } + } + + fprintf (gcov_file, FN_SEPARATOR); + line_start_group = 0; + } + } + + if (source_file) + fclose (source_file); +} |